servo: Merge #16155 - stylo: Implement gecko glue for font-language-override (from chenpighead:gecko-glue-for-font-language-override); r=emilio

To be aligned with the implementation from Gecko side, we parse
font-language-override as Normal keyword or String. Then, we compute
and store it as a u32. So, as to the stylo glue, we can just pass the
u32 to Gecko.

The extra crate, byteorder, is used to simplify the computing and
serialization.

Since we now implement font-language-override for Gecko, we can remove
the additional branches for font-language-override in font shorthand.

ref: Gecko [Bug 1347821](https://bugzilla.mozilla.org/show_bug.cgi?id=1347821)

<!-- Please describe your changes on the following line: -->

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [ ] These changes fix #__ (github issue number if applicable).

<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because _____

<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

Source-Repo: https://github.com/servo/servo
Source-Revision: af243d5decde5663e2f6558eaa78c9022536c289

--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : a8af7077c4c7d662923ae8ccc854e06b53c590ea
This commit is contained in:
Jeremy Chen 2017-03-28 15:05:33 -05:00
Родитель b1aecb3f20
Коммит 1a65c22c50
6 изменённых файлов: 103 добавлений и 39 удалений

1
servo/Cargo.lock сгенерированный
Просмотреть файл

@ -2746,6 +2746,7 @@ dependencies = [
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bindgen 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
"encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",

Просмотреть файл

@ -25,6 +25,7 @@ testing = []
app_units = "0.4"
atomic_refcell = "0.1"
bitflags = "0.7"
byteorder = "1.0"
cfg-if = "0.1.0"
cssparser = "0.12"
encoding = {version = "0.2", optional = true}

Просмотреть файл

@ -41,6 +41,7 @@ extern crate app_units;
extern crate atomic_refcell;
#[macro_use]
extern crate bitflags;
#[allow(unused_extern_crates)] extern crate byteorder;
#[cfg(feature = "gecko")] #[macro_use] #[no_link] extern crate cfg_if;
#[macro_use] extern crate cssparser;
extern crate euclid;

Просмотреть файл

@ -1177,7 +1177,7 @@ fn static_assert() {
</%self:impl_trait>
<%self:impl_trait style_struct_name="Font"
skip_longhands="font-family font-size font-size-adjust font-weight font-synthesis -x-lang"
skip_longhands="font-family font-size font-size-adjust font-weight font-synthesis -x-lang font-language-override"
skip_additionals="*">
pub fn set_font_family(&mut self, v: longhands::font_family::computed_value::T) {
@ -1315,6 +1315,11 @@ fn static_assert() {
Gecko_nsStyleFont_CopyLangFrom(&mut self.gecko, &other.gecko);
}
}
pub fn set_font_language_override(&mut self, v: longhands::font_language_override::computed_value::T) {
self.gecko.mFont.languageOverride = v.0;
}
${impl_simple_copy('font_language_override', 'mFont.languageOverride')}
</%self:impl_trait>
<%def name="impl_copy_animation_or_transition_value(type, ident, gecko_ffi_name)">

Просмотреть файл

@ -954,40 +954,67 @@ ${helpers.single_keyword("font-variant-position",
}
</%helpers:longhand>
// https://www.w3.org/TR/css-fonts-3/#propdef-font-language-override
<%helpers:longhand name="font-language-override" products="none" animatable="False" extra_prefixes="moz"
<%helpers:longhand name="font-language-override" products="gecko" animatable="False" extra_prefixes="moz"
spec="https://drafts.csswg.org/css-fonts-3/#propdef-font-language-override">
use std::fmt;
use style_traits::ToCss;
use byteorder::{BigEndian, ByteOrder};
use values::HasViewportPercentage;
use values::computed::ComputedValueAsSpecified;
pub use self::computed_value::T as SpecifiedValue;
impl ComputedValueAsSpecified for SpecifiedValue {}
no_viewport_percentage!(SpecifiedValue);
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum SpecifiedValue {
Normal,
Override(String),
}
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
use cssparser;
match *self {
SpecifiedValue::Normal => dest.write_str("normal"),
SpecifiedValue::Override(ref lang) =>
cssparser::serialize_string(lang, dest),
}
}
}
pub mod computed_value {
use std::fmt;
use std::{fmt, str};
use style_traits::ToCss;
use byteorder::{BigEndian, ByteOrder};
use cssparser;
impl ToCss for T {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
T::Normal => dest.write_str("normal"),
T::Override(ref lang) => write!(dest, "\"{}\"", lang),
if self.0 == 0 {
return dest.write_str("normal")
}
let mut buf = [0; 4];
BigEndian::write_u32(&mut buf, self.0);
// Safe because we ensure it's ASCII during computing
let slice = if cfg!(debug_assertions) {
str::from_utf8(&buf).unwrap()
} else {
unsafe { str::from_utf8_unchecked(&buf) }
};
cssparser::serialize_string(slice.trim_right(), dest)
}
}
#[derive(Clone, Debug, PartialEq)]
// font-language-override can only have a single three-letter
// OpenType "language system" tag, so we should be able to compute
// it and store it as a 32-bit integer
// (see http://www.microsoft.com/typography/otspec/languagetags.htm).
#[derive(PartialEq, Clone, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum T {
Normal,
Override(String),
}
pub struct T(pub u32);
}
#[inline]
pub fn get_initial_value() -> computed_value::T {
computed_value::T::Normal
computed_value::T(0)
}
#[inline]
@ -995,6 +1022,45 @@ ${helpers.single_keyword("font-variant-position",
SpecifiedValue::Normal
}
impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T;
#[inline]
fn to_computed_value(&self, _: &Context) -> computed_value::T {
use std::ascii::AsciiExt;
match *self {
SpecifiedValue::Normal => computed_value::T(0),
SpecifiedValue::Override(ref lang) => {
if lang.is_empty() || lang.len() > 4 || !lang.is_ascii() {
return computed_value::T(0)
}
let mut computed_lang = lang.clone();
while computed_lang.len() < 4 {
computed_lang.push(' ');
}
let bytes = computed_lang.into_bytes();
computed_value::T(BigEndian::read_u32(&bytes))
}
}
}
#[inline]
fn from_computed_value(computed: &computed_value::T) -> Self {
if computed.0 == 0 {
return SpecifiedValue::Normal
}
let mut buf = [0; 4];
BigEndian::write_u32(&mut buf, computed.0);
SpecifiedValue::Override(
if cfg!(debug_assertions) {
String::from_utf8(buf.to_vec()).unwrap()
} else {
unsafe { String::from_utf8_unchecked(buf.to_vec()) }
}
)
}
}
/// normal | <string>
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
Ok(SpecifiedValue::Normal)

Просмотреть файл

@ -4,21 +4,20 @@
<%namespace name="helpers" file="/helpers.mako.rs" />
<%helpers:shorthand name="font" sub_properties="font-style font-variant font-weight font-stretch
font-size line-height font-family
${'font-size-adjust' if product == 'gecko' or data.testing else ''}
${'font-kerning' if product == 'gecko' or data.testing else ''}
${'font-variant-caps' if product == 'gecko' or data.testing else ''}
${'font-variant-position' if product == 'gecko' or data.testing else ''}
${'font-language-override' if data.testing else ''}"
<%helpers:shorthand name="font"
sub_properties="font-style font-variant font-weight font-stretch
font-size line-height font-family
${'font-size-adjust' if product == 'gecko' or data.testing else ''}
${'font-kerning' if product == 'gecko' or data.testing else ''}
${'font-variant-caps' if product == 'gecko' or data.testing else ''}
${'font-variant-position' if product == 'gecko' or data.testing else ''}
${'font-language-override' if product == 'gecko' or data.testing else ''}"
spec="https://drafts.csswg.org/css-fonts-3/#propdef-font">
use properties::longhands::{font_style, font_variant, font_weight, font_stretch};
use properties::longhands::{font_size, line_height};
% if product == "gecko" or data.testing:
use properties::longhands::{font_size_adjust, font_kerning, font_variant_caps, font_variant_position};
% endif
% if data.testing:
use properties::longhands::font_language_override;
use properties::longhands::{font_size_adjust, font_kerning, font_variant_caps, font_variant_position,
font_language_override};
% endif
use properties::longhands::font_family::SpecifiedValue as FontFamily;
@ -84,13 +83,10 @@
line_height: unwrap_or_initial!(line_height),
font_family: family,
% if product == "gecko" or data.testing:
% for name in "size_adjust kerning variant_caps variant_position".split():
% for name in "size_adjust kerning variant_caps variant_position language_override".split():
font_${name}: font_${name}::get_initial_specified_value(),
% endfor
% endif
% if data.testing:
font_language_override: font_language_override::get_initial_specified_value(),
% endif
})
}
@ -99,19 +95,13 @@
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
% if product == "gecko" or data.testing:
% for name in "size_adjust kerning variant_caps variant_position".split():
% for name in "size_adjust kerning variant_caps variant_position language_override".split():
if self.font_${name} != &font_${name}::get_initial_specified_value() {
return Ok(());
}
% endfor
% endif
% if data.testing:
if self.font_language_override != &font_language_override::get_initial_specified_value() {
return Ok(());
}
% endif
% for name in "style variant weight stretch".split():
self.font_${name}.to_css(dest)?;
dest.write_str(" ")?;