Auto merge of #18222 - canaltinova:font-feature-values-lookup, r=emilo,xidorn

stylo: Implement font feature values lookup

This PR reviewed by emilio and xidorn on bugzilla

---
<!-- 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
- [X] These changes [Bug 1355721](https://bugzilla.mozilla.org/show_bug.cgi?id=1355721)

<!-- 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/18222)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2017-08-24 17:36:44 -05:00 committed by GitHub
commit 76e77be041
8 changed files with 1182 additions and 718 deletions

View file

@ -66,6 +66,7 @@ use gecko_bindings::structs::StyleBasicShape;
use gecko_bindings::structs::StyleBasicShapeType;
use gecko_bindings::structs::StyleShapeSource;
use gecko_bindings::structs::StyleTransition;
use gecko_bindings::structs::gfxFontFeatureValueSet;
use gecko_bindings::structs::nsBorderColors;
use gecko_bindings::structs::nsCSSCounterStyleRule;
use gecko_bindings::structs::nsCSSFontFaceRule;
@ -239,6 +240,7 @@ unsafe impl Send for nsStyleTransformMatrix::MatrixTransformOperator {}
unsafe impl Sync for nsStyleTransformMatrix::MatrixTransformOperator {}
use gecko_bindings::structs::RawGeckoGfxMatrix4x4;
pub type nsTArrayBorrowed_uintptr_t<'a> = &'a mut ::gecko_bindings::structs::nsTArray<usize>;
pub type nsTArrayBorrowed_uint32_t<'a> = &'a mut ::gecko_bindings::structs::nsTArray<u32>;
pub type RawServoStyleSetOwned = ::gecko_bindings::sugar::ownership::Owned<RawServoStyleSet>;
pub type RawServoStyleSetOwnedOrNull = ::gecko_bindings::sugar::ownership::OwnedOrNull<RawServoStyleSet>;
pub type RawServoStyleSetBorrowed<'a> = &'a RawServoStyleSet;
@ -910,6 +912,22 @@ extern "C" {
extern "C" {
pub fn Gecko_nsFont_Destroy(dst: *mut nsFont);
}
extern "C" {
pub fn Gecko_AppendFeatureValueHashEntry(value_set:
*mut gfxFontFeatureValueSet,
family: *mut nsIAtom,
alternate: u32,
name: *mut nsIAtom)
-> nsTArrayBorrowed_uint32_t;
}
extern "C" {
pub fn Gecko_nsFont_SetFontFeatureValuesLookup(font: *mut nsFont,
pres_context:
*const RawGeckoPresContext);
}
extern "C" {
pub fn Gecko_nsFont_ResetFontFeatureValuesLookup(font: *mut nsFont);
}
extern "C" {
pub fn Gecko_ClearAlternateValues(font: *mut nsFont, length: usize);
}
@ -2034,6 +2052,13 @@ extern "C" {
name: *mut nsIAtom)
-> *mut nsCSSCounterStyleRule;
}
extern "C" {
pub fn Servo_StyleSet_BuildFontFeatureValueSet(set:
RawServoStyleSetBorrowed,
list:
*mut gfxFontFeatureValueSet)
-> bool;
}
extern "C" {
pub fn Servo_StyleSet_ResolveForDeclarations(set:
RawServoStyleSetBorrowed,

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -2513,8 +2513,12 @@ fn static_assert() {
<% impl_simple_type_with_conversion("font_language_override", "mFont.languageOverride") %>
pub fn set_font_variant_alternates(&mut self, v: longhands::font_variant_alternates::computed_value::T) {
pub fn set_font_variant_alternates(&mut self,
v: longhands::font_variant_alternates::computed_value::T,
device: &Device) {
use gecko_bindings::bindings::{Gecko_ClearAlternateValues, Gecko_AppendAlternateValues};
use gecko_bindings::bindings::Gecko_nsFont_ResetFontFeatureValuesLookup;
use gecko_bindings::bindings::Gecko_nsFont_SetFontFeatureValuesLookup;
% for value in "normal swash stylistic ornaments annotation styleset character_variant historical".split():
use gecko_bindings::structs::NS_FONT_VARIANT_ALTERNATES_${value.upper()};
% endfor
@ -2526,6 +2530,8 @@ fn static_assert() {
if v.0.is_empty() {
self.gecko.mFont.variantAlternates = NS_FONT_VARIANT_ALTERNATES_NORMAL as u16;
unsafe { Gecko_nsFont_ResetFontFeatureValuesLookup(&mut self.gecko.mFont); }
return;
}
for val in v.0.iter() {
@ -2557,6 +2563,10 @@ fn static_assert() {
}
}
}
unsafe {
Gecko_nsFont_SetFontFeatureValuesLookup(&mut self.gecko.mFont, device.pres_context());
}
}
#[allow(non_snake_case)]

View file

@ -2722,12 +2722,13 @@ impl<'a> StyleBuilder<'a> {
&mut self,
value: longhands::${property.ident}::computed_value::T
) {
<% props_need_device = ["content", "list_style_type", "font_variant_alternates"] %>
self.${property.style_struct.ident}.mutate()
.set_${property.ident}(
value,
% if property.logical:
self.writing_mode,
% elif product == "gecko" and property.ident in ["content", "list_style_type"]:
% elif product == "gecko" and property.ident in props_need_device:
self.device,
% endif
);

View file

@ -11,6 +11,10 @@ use computed_values::font_family::FamilyName;
use cssparser::{AtRuleParser, AtRuleType, BasicParseError, DeclarationListParser, DeclarationParser, Parser};
use cssparser::{CowRcStr, RuleListParser, SourceLocation, QualifiedRuleParser, Token, serialize_identifier};
use error_reporting::{ContextualParseError, ParseErrorReporter};
#[cfg(feature = "gecko")]
use gecko_bindings::bindings::Gecko_AppendFeatureValueHashEntry;
#[cfg(feature = "gecko")]
use gecko_bindings::structs::{self, gfxFontFeatureValueSet, nsTArray};
use parser::{ParserContext, ParserErrorContext, Parse};
use selectors::parser::SelectorParseError;
use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
@ -41,6 +45,13 @@ impl<T: ToCss> ToCss for FFVDeclaration<T> {
}
}
/// A trait for @font-feature-values rule to gecko values conversion.
#[cfg(feature = "gecko")]
pub trait ToGeckoFontFeatureValues {
/// Sets the equivalent of declaration to gecko `nsTArray<u32>` array.
fn to_gecko_font_feature_values(&self, array: &mut nsTArray<u32>);
}
/// A @font-feature-values block declaration value that keeps one value.
#[derive(Clone, Debug, PartialEq)]
pub struct SingleValue(pub u32);
@ -61,6 +72,14 @@ impl ToCss for SingleValue {
}
}
#[cfg(feature = "gecko")]
impl ToGeckoFontFeatureValues for SingleValue {
fn to_gecko_font_feature_values(&self, array: &mut nsTArray<u32>) {
unsafe { array.set_len_pod(1); }
array[0] = self.0 as u32;
}
}
/// A @font-feature-values block declaration value that keeps one or two values.
#[derive(Clone, Debug, PartialEq)]
pub struct PairValues(pub u32, pub Option<u32>);
@ -94,6 +113,19 @@ impl ToCss for PairValues {
}
}
#[cfg(feature = "gecko")]
impl ToGeckoFontFeatureValues for PairValues {
fn to_gecko_font_feature_values(&self, array: &mut nsTArray<u32>) {
let len = if self.1.is_some() { 2 } else { 1 };
unsafe { array.set_len_pod(len); }
array[0] = self.0 as u32;
if let Some(second) = self.1 {
array[1] = second as u32;
};
}
}
/// A @font-feature-values block declaration value that keeps a list of values.
#[derive(Clone, Debug, PartialEq)]
pub struct VectorValues(pub Vec<u32>);
@ -136,6 +168,16 @@ impl ToCss for VectorValues {
}
}
#[cfg(feature = "gecko")]
impl ToGeckoFontFeatureValues for VectorValues {
fn to_gecko_font_feature_values(&self, array: &mut nsTArray<u32>) {
unsafe { array.set_len_pod(self.0.len() as u32); }
for (dest, value) in array.iter_mut().zip(self.0.iter()) {
*dest = *value;
}
}
}
/// Parses a list of `FamilyName`s.
pub fn parse_family_name_list<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Vec<FamilyName>, ParseError<'i>> {
@ -166,7 +208,7 @@ impl<'a, 'b, 'i, T> DeclarationParser<'i> for FFVDeclarationsParser<'a, 'b, T>
-> Result<(), ParseError<'i>> {
let value = input.parse_entirely(|i| T::parse(self.context, i))?;
let new = FFVDeclaration {
name: Atom::from(&*name),
name: Atom::from(&*name).to_ascii_lowercase(),
value: value,
};
update_or_push(&mut self.declarations, new);
@ -177,7 +219,7 @@ impl<'a, 'b, 'i, T> DeclarationParser<'i> for FFVDeclarationsParser<'a, 'b, T>
macro_rules! font_feature_values_blocks {
(
blocks = [
$( #[$doc: meta] $name: tt $ident: ident / $ident_camel: ident: $ty: ty, )*
$( #[$doc: meta] $name: tt $ident: ident / $ident_camel: ident / $gecko_enum: ident: $ty: ty, )*
]
) => {
/// The [`@font-feature-values`][font-feature-values] at-rule.
@ -262,6 +304,38 @@ macro_rules! font_feature_values_blocks {
)*
Ok(())
}
/// Returns length of all at-rules.
pub fn len(&self) -> usize {
let mut len = 0;
$(
len += self.$ident.len();
)*
len
}
/// Convert to Gecko gfxFontFeatureValueSet.
#[cfg(feature = "gecko")]
pub fn set_at_rules(&self, dest: *mut gfxFontFeatureValueSet) {
for ref family in self.family_names.iter() {
let family = family.name.to_ascii_lowercase();
$(
if self.$ident.len() > 0 {
for val in self.$ident.iter() {
let mut array = unsafe {
Gecko_AppendFeatureValueHashEntry(
dest,
family.as_ptr(),
structs::$gecko_enum,
val.name.as_ptr()
)
};
val.value.to_gecko_font_feature_values(&mut array);
}
}
)*
}
}
}
impl ToCssWithGuard for FontFeatureValuesRule {
@ -366,31 +440,32 @@ font_feature_values_blocks! {
#[doc = "A @swash blocksck. \
Specifies a feature name that will work with the swash() \
functional notation of font-variant-alternates."]
"swash" swash / Swash: SingleValue,
"swash" swash / Swash / NS_FONT_VARIANT_ALTERNATES_SWASH: SingleValue,
#[doc = "A @stylistic block. \
Specifies a feature name that will work with the annotation() \
functional notation of font-variant-alternates."]
"stylistic" stylistic / Stylistic: SingleValue,
"stylistic" stylistic / Stylistic / NS_FONT_VARIANT_ALTERNATES_STYLISTIC: SingleValue,
#[doc = "A @ornaments block. \
Specifies a feature name that will work with the ornaments() ] \
functional notation of font-variant-alternates."]
"ornaments" ornaments / Ornaments: SingleValue,
"ornaments" ornaments / Ornaments / NS_FONT_VARIANT_ALTERNATES_ORNAMENTS: SingleValue,
#[doc = "A @annotation block. \
Specifies a feature name that will work with the stylistic() \
functional notation of font-variant-alternates."]
"annotation" annotation / Annotation: SingleValue,
"annotation" annotation / Annotation / NS_FONT_VARIANT_ALTERNATES_ANNOTATION: SingleValue,
#[doc = "A @character-variant block. \
Specifies a feature name that will work with the styleset() \
functional notation of font-variant-alternates. The value can be a pair."]
"character-variant" character_variant / CharacterVariant: PairValues,
"character-variant" character_variant / CharacterVariant / NS_FONT_VARIANT_ALTERNATES_CHARACTER_VARIANT:
PairValues,
#[doc = "A @styleset block. \
Specifies a feature name that will work with the character-variant() \
functional notation of font-variant-alternates. The value can be a list."]
"styleset" styleset / Styleset: VectorValues,
"styleset" styleset / Styleset / NS_FONT_VARIANT_ALTERNATES_STYLESET: VectorValues,
]
}

View file

@ -40,7 +40,7 @@ use std::ops;
use style_traits::viewport::ViewportConstraints;
use stylesheet_set::{OriginValidity, SheetRebuildKind, StylesheetSet, StylesheetIterator, StylesheetFlusher};
#[cfg(feature = "gecko")]
use stylesheets::{CounterStyleRule, FontFaceRule};
use stylesheets::{CounterStyleRule, FontFaceRule, FontFeatureValuesRule};
use stylesheets::{CssRule, StyleRule};
use stylesheets::{StylesheetInDocument, Origin, OriginSet, PerOrigin, PerOriginIter};
use stylesheets::UserAgentStylesheets;
@ -338,13 +338,19 @@ impl DocumentCascadeData {
CssRule::FontFace(ref rule) => {
_extra_data
.borrow_mut_for_origin(&origin)
.add_font_face(&rule);
.add_font_face(rule);
}
#[cfg(feature = "gecko")]
CssRule::FontFeatureValues(ref rule) => {
_extra_data
.borrow_mut_for_origin(&origin)
.add_font_feature_values(rule);
}
#[cfg(feature = "gecko")]
CssRule::CounterStyle(ref rule) => {
_extra_data
.borrow_mut_for_origin(&origin)
.add_counter_style(guard, &rule);
.add_counter_style(guard, rule);
}
// We don't care about any other rule.
_ => {}
@ -1516,6 +1522,10 @@ pub struct ExtraStyleData {
#[cfg(feature = "gecko")]
pub font_faces: Vec<Arc<Locked<FontFaceRule>>>,
/// A list of effective font-feature-values rules.
#[cfg(feature = "gecko")]
pub font_feature_values: Vec<Arc<Locked<FontFeatureValuesRule>>>,
/// A map of effective counter-style rules.
#[cfg(feature = "gecko")]
pub counter_styles: PrecomputedHashMap<Atom, Arc<Locked<CounterStyleRule>>>,
@ -1528,6 +1538,11 @@ impl ExtraStyleData {
self.font_faces.push(rule.clone());
}
/// Add the given @font-feature-values rule.
fn add_font_feature_values(&mut self, rule: &Arc<Locked<FontFeatureValuesRule>>) {
self.font_feature_values.push(rule.clone());
}
/// Add the given @counter-style rule.
fn add_counter_style(
&mut self,
@ -1544,6 +1559,7 @@ impl ExtraStyleData {
#[cfg(feature = "gecko")]
{
self.font_faces.clear();
self.font_feature_values.clear();
self.counter_styles.clear();
}
}