Skip to content

Commit

Permalink
Auto merge of #16155 - chenpighead:gecko-glue-for-font-language-overr…
Browse files Browse the repository at this point in the history
…ide, r=emilio

stylo: Implement gecko glue for font-language-override.

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. -->

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/16155)
<!-- Reviewable:end -->
  • Loading branch information
bors-servo committed Mar 28, 2017
2 parents f2cd9ef + a9e4b9c commit af243d5
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 39 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions components/style/Cargo.toml
Expand Up @@ -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}
Expand Down
1 change: 1 addition & 0 deletions components/style/lib.rs
Expand Up @@ -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;
Expand Down
7 changes: 6 additions & 1 deletion components/style/properties/gecko.mako.rs
Expand Up @@ -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) {
Expand Down Expand Up @@ -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)">
Expand Down
98 changes: 82 additions & 16 deletions components/style/properties/longhand/font.mako.rs
Expand Up @@ -954,47 +954,113 @@ ${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]
pub fn get_initial_specified_value() -> SpecifiedValue {
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)
Expand Down
34 changes: 12 additions & 22 deletions components/style/properties/shorthand/font.mako.rs
Expand Up @@ -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;

Expand Down Expand Up @@ -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
})
}

Expand All @@ -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(" ")?;
Expand Down

0 comments on commit af243d5

Please sign in to comment.