mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
Auto merge of #16187 - upsuper:bug1345696, r=Manishearth,heycam
Implement access to CSSFontFaceRule for stylo This is the Servo part of [bug 1345696](https://bugzilla.mozilla.org/show_bug.cgi?id=1345696) which has been reviewed on Bugzilla.
This commit is contained in:
commit
2084ee29c4
19 changed files with 4693 additions and 3374 deletions
|
@ -98,6 +98,7 @@ use servo_url::ServoUrl;
|
|||
use std::borrow::ToOwned;
|
||||
use std::collections::HashMap;
|
||||
use std::hash::BuildHasherDefault;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem as std_mem;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::process;
|
||||
|
@ -116,7 +117,7 @@ use style::parser::ParserContextExtraData;
|
|||
use style::servo::restyle_damage::{REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, REPOSITION, STORE_OVERFLOW};
|
||||
use style::shared_lock::{SharedRwLock, SharedRwLockReadGuard, StylesheetGuards};
|
||||
use style::stylesheets::{Origin, Stylesheet, UserAgentStylesheets};
|
||||
use style::stylist::Stylist;
|
||||
use style::stylist::{ExtraStyleData, Stylist};
|
||||
use style::thread_state;
|
||||
use style::timer::Timer;
|
||||
use style::traversal::{DomTraversal, TraversalDriver, TraversalFlags};
|
||||
|
@ -1078,11 +1079,15 @@ impl LayoutThread {
|
|||
author: &author_guard,
|
||||
ua_or_user: &ua_or_user_guard,
|
||||
};
|
||||
let mut extra_data = ExtraStyleData {
|
||||
marker: PhantomData,
|
||||
};
|
||||
let needs_dirtying = Arc::get_mut(&mut rw_data.stylist).unwrap().update(
|
||||
&data.document_stylesheets,
|
||||
&guards,
|
||||
Some(ua_stylesheets),
|
||||
data.stylesheets_changed);
|
||||
data.stylesheets_changed,
|
||||
&mut extra_data);
|
||||
let needs_reflow = viewport_size_changed && !needs_dirtying;
|
||||
if needs_dirtying {
|
||||
if let Some(mut d) = element.mutate_data() {
|
||||
|
|
|
@ -94,14 +94,13 @@ use std::time::{SystemTime, Instant};
|
|||
use style::attr::{AttrIdentifier, AttrValue, LengthOrPercentageOrAuto};
|
||||
use style::context::QuirksMode;
|
||||
use style::element_state::*;
|
||||
use style::font_face::FontFaceRule;
|
||||
use style::keyframes::Keyframe;
|
||||
use style::media_queries::MediaList;
|
||||
use style::properties::PropertyDeclarationBlock;
|
||||
use style::selector_parser::{PseudoElement, Snapshot};
|
||||
use style::shared_lock::{SharedRwLock as StyleSharedRwLock, Locked as StyleLocked};
|
||||
use style::stylesheets::{CssRules, KeyframesRule, MediaRule, NamespaceRule, StyleRule, ImportRule};
|
||||
use style::stylesheets::SupportsRule;
|
||||
use style::stylesheets::{CssRules, FontFaceRule, KeyframesRule, MediaRule};
|
||||
use style::stylesheets::{NamespaceRule, StyleRule, ImportRule, SupportsRule};
|
||||
use style::values::specified::Length;
|
||||
use style::viewport::ViewportRule;
|
||||
use time::Duration;
|
||||
|
|
|
@ -11,8 +11,8 @@ use dom::cssstylesheet::CSSStyleSheet;
|
|||
use dom::window::Window;
|
||||
use dom_struct::dom_struct;
|
||||
use std::sync::Arc;
|
||||
use style::font_face::FontFaceRule;
|
||||
use style::shared_lock::{Locked, ToCssWithGuard};
|
||||
use style::stylesheets::FontFaceRule;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct CSSFontFaceRule {
|
||||
|
|
|
@ -258,6 +258,7 @@ mod bindings {
|
|||
vars: true,
|
||||
..CodegenConfig::nothing()
|
||||
})
|
||||
.include(add_include("nsCSSPseudoClasses.h")) // servo/rust-bindgen#599
|
||||
.header(add_include("nsStyleStruct.h"))
|
||||
.include(add_include("mozilla/ServoPropPrefList.h"))
|
||||
.header(add_include("mozilla/StyleAnimationValue.h"))
|
||||
|
@ -270,6 +271,7 @@ mod bindings {
|
|||
.include(add_include("mozilla/dom/NameSpaceConstants.h"))
|
||||
.include(add_include("mozilla/LookAndFeel.h"))
|
||||
.include(add_include("mozilla/ServoBindings.h"))
|
||||
.include(add_include("nsCSSFontFaceRule.h"))
|
||||
.include(add_include("nsMediaFeatures.h"))
|
||||
.include(add_include("nsMediaList.h"))
|
||||
// FIXME(emilio): Incrementally remove these "pub use"s. Probably
|
||||
|
@ -336,6 +338,7 @@ mod bindings {
|
|||
"nsBorderColors",
|
||||
"nscolor",
|
||||
"nsChangeHint",
|
||||
"nsCSSFontFaceRule",
|
||||
"nsCSSKeyword",
|
||||
"nsCSSPropertyID",
|
||||
"nsCSSProps",
|
||||
|
@ -585,6 +588,7 @@ mod bindings {
|
|||
"RawGeckoElement",
|
||||
"RawGeckoKeyframeList",
|
||||
"RawGeckoComputedKeyframeValuesList",
|
||||
"RawGeckoFontFaceRuleList",
|
||||
"RawGeckoNode",
|
||||
"RawGeckoAnimationValueList",
|
||||
"RawServoAnimationValue",
|
||||
|
@ -608,9 +612,11 @@ mod bindings {
|
|||
"StyleBasicShape",
|
||||
"StyleBasicShapeType",
|
||||
"StyleShapeSource",
|
||||
"nsCSSFontFaceRule",
|
||||
"nsCSSKeyword",
|
||||
"nsCSSPropertyID",
|
||||
"nsCSSShadowArray",
|
||||
"nsCSSUnit",
|
||||
"nsCSSValue",
|
||||
"nsCSSValueSharedList",
|
||||
"nsChangeHint",
|
||||
|
@ -701,6 +707,7 @@ mod bindings {
|
|||
"RawGeckoAnimationValueList",
|
||||
"RawGeckoKeyframeList",
|
||||
"RawGeckoComputedKeyframeValuesList",
|
||||
"RawGeckoFontFaceRuleList",
|
||||
];
|
||||
for &ty in structs_types.iter() {
|
||||
builder = builder.hide_type(ty)
|
||||
|
|
|
@ -75,8 +75,8 @@ impl ToCss for UrlSource {
|
|||
///
|
||||
/// Note that the prelude parsing code lives in the `stylesheets` module.
|
||||
pub fn parse_font_face_block(context: &ParserContext, input: &mut Parser)
|
||||
-> Result<FontFaceRule, ()> {
|
||||
let mut rule = FontFaceRule::initial();
|
||||
-> Result<FontFaceData, ()> {
|
||||
let mut rule = FontFaceData::initial();
|
||||
{
|
||||
let parser = FontFaceRuleParser {
|
||||
context: context,
|
||||
|
@ -104,7 +104,7 @@ pub fn parse_font_face_block(context: &ParserContext, input: &mut Parser)
|
|||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||
pub struct EffectiveSources(Vec<Source>);
|
||||
|
||||
impl FontFaceRule {
|
||||
impl FontFaceData {
|
||||
/// Returns the list of effective sources for that font-face, that is the
|
||||
/// sources which don't list any format hint, or the ones which list at
|
||||
/// least "truetype" or "opentype".
|
||||
|
@ -134,7 +134,7 @@ impl iter::Iterator for EffectiveSources {
|
|||
|
||||
struct FontFaceRuleParser<'a, 'b: 'a> {
|
||||
context: &'a ParserContext<'b>,
|
||||
rule: &'a mut FontFaceRule,
|
||||
rule: &'a mut FontFaceData,
|
||||
missing: MissingDescriptors,
|
||||
}
|
||||
|
||||
|
@ -181,11 +181,11 @@ macro_rules! font_face_descriptors {
|
|||
$( #[$o_doc: meta] $o_name: tt $o_ident: ident: $o_ty: ty = $o_initial: expr, )*
|
||||
]
|
||||
) => {
|
||||
/// A `@font-face` rule.
|
||||
/// Data inside a `@font-face` rule.
|
||||
///
|
||||
/// https://drafts.csswg.org/css-fonts/#font-face-rule
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct FontFaceRule {
|
||||
pub struct FontFaceData {
|
||||
$(
|
||||
#[$m_doc]
|
||||
pub $m_ident: $m_ty,
|
||||
|
@ -218,9 +218,9 @@ macro_rules! font_face_descriptors {
|
|||
}
|
||||
}
|
||||
|
||||
impl FontFaceRule {
|
||||
impl FontFaceData {
|
||||
fn initial() -> Self {
|
||||
FontFaceRule {
|
||||
FontFaceData {
|
||||
$(
|
||||
$m_ident: $m_initial,
|
||||
)*
|
||||
|
@ -231,7 +231,7 @@ macro_rules! font_face_descriptors {
|
|||
}
|
||||
}
|
||||
|
||||
impl ToCssWithGuard for FontFaceRule {
|
||||
impl ToCssWithGuard for FontFaceData {
|
||||
// Serialization of FontFaceRule is not specced.
|
||||
fn to_css<W>(&self, _guard: &SharedRwLockReadGuard, dest: &mut W) -> fmt::Result
|
||||
where W: fmt::Write {
|
||||
|
|
|
@ -13,9 +13,9 @@ use gecko::values::{convert_rgba_to_nscolor, GeckoStyleCoordConvertible};
|
|||
use gecko_bindings::bindings::{Gecko_CreateGradient, Gecko_SetGradientImageValue, Gecko_SetUrlImageValue};
|
||||
use gecko_bindings::bindings::Gecko_InitializeImageCropRect;
|
||||
use gecko_bindings::structs::{nsStyleCoord_CalcValue, nsStyleImage};
|
||||
use gecko_bindings::structs::nsresult;
|
||||
use gecko_bindings::structs::{nsresult, SheetType};
|
||||
use gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordDataMut};
|
||||
use stylesheets::RulesMutateError;
|
||||
use stylesheets::{Origin, RulesMutateError};
|
||||
use values::computed::{CalcLengthOrPercentage, Gradient, Image, LengthOrPercentage, LengthOrPercentageOrAuto};
|
||||
|
||||
impl From<CalcLengthOrPercentage> for nsStyleCoord_CalcValue {
|
||||
|
@ -503,3 +503,13 @@ impl From<RulesMutateError> for nsresult {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Origin> for SheetType {
|
||||
fn from(other: Origin) -> Self {
|
||||
match other {
|
||||
Origin::UserAgent => SheetType::Agent,
|
||||
Origin::Author => SheetType::Doc,
|
||||
Origin::User => SheetType::User,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,12 +13,12 @@ use gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI};
|
|||
use media_queries::Device;
|
||||
use parking_lot::RwLock;
|
||||
use properties::ComputedValues;
|
||||
use shared_lock::{StylesheetGuards, SharedRwLockReadGuard};
|
||||
use shared_lock::{Locked, StylesheetGuards, SharedRwLockReadGuard};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use std::sync::mpsc::{Receiver, Sender, channel};
|
||||
use stylesheets::Stylesheet;
|
||||
use stylist::Stylist;
|
||||
use stylesheets::{FontFaceRule, Origin, Stylesheet};
|
||||
use stylist::{ExtraStyleData, Stylist};
|
||||
|
||||
/// The container for data that a Servo-backed Gecko document needs to style
|
||||
/// itself.
|
||||
|
@ -45,6 +45,9 @@ pub struct PerDocumentStyleDataImpl {
|
|||
/// Unused. Will go away when we actually implement transitions and
|
||||
/// animations properly.
|
||||
pub expired_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,
|
||||
|
||||
/// List of effective font face rules.
|
||||
pub font_faces: Vec<(Arc<Locked<FontFaceRule>>, Origin)>,
|
||||
}
|
||||
|
||||
/// The data itself is an `AtomicRefCell`, which guarantees the proper semantics
|
||||
|
@ -66,6 +69,7 @@ impl PerDocumentStyleData {
|
|||
new_animations_receiver: new_anims_receiver,
|
||||
running_animations: Arc::new(RwLock::new(HashMap::new())),
|
||||
expired_animations: Arc::new(RwLock::new(HashMap::new())),
|
||||
font_faces: vec![],
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -97,7 +101,11 @@ impl PerDocumentStyleDataImpl {
|
|||
pub fn flush_stylesheets(&mut self, guard: &SharedRwLockReadGuard) {
|
||||
if self.stylesheets_changed {
|
||||
let mut stylist = Arc::get_mut(&mut self.stylist).unwrap();
|
||||
stylist.update(&self.stylesheets, &StylesheetGuards::same(guard), None, true);
|
||||
let mut extra_data = ExtraStyleData {
|
||||
font_faces: &mut self.font_faces,
|
||||
};
|
||||
stylist.update(&self.stylesheets, &StylesheetGuards::same(guard),
|
||||
None, true, &mut extra_data);
|
||||
self.stylesheets_changed = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ pub mod data;
|
|||
pub mod global_style_data;
|
||||
pub mod media_queries;
|
||||
pub mod restyle_damage;
|
||||
pub mod rules;
|
||||
pub mod selector_parser;
|
||||
pub mod snapshot;
|
||||
pub mod snapshot_helpers;
|
||||
|
|
121
components/style/gecko/rules.rs
Normal file
121
components/style/gecko/rules.rs
Normal file
|
@ -0,0 +1,121 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
//! Bindings for CSS Rule objects
|
||||
|
||||
use font_face::{FontFaceData, Source};
|
||||
use gecko_bindings::bindings;
|
||||
use gecko_bindings::structs::{self, CSSFontFaceDescriptors, nsCSSFontFaceRule};
|
||||
use gecko_bindings::sugar::refptr::{RefPtr, UniqueRefPtr};
|
||||
use shared_lock::{ToCssWithGuard, SharedRwLockReadGuard};
|
||||
use std::fmt;
|
||||
|
||||
/// A @font-face rule
|
||||
pub type FontFaceRule = RefPtr<nsCSSFontFaceRule>;
|
||||
|
||||
fn set_font_face_descriptors(descriptors: &mut CSSFontFaceDescriptors,
|
||||
data: FontFaceData) {
|
||||
// font-family
|
||||
descriptors.mFamily.set_string_from_atom(&data.family.0);
|
||||
|
||||
macro_rules! map_enum {
|
||||
($target:ident = ($data:ident: $prop:ident) {
|
||||
$($servo:ident => $gecko:ident,)+
|
||||
}) => {{
|
||||
use computed_values::$prop::T;
|
||||
descriptors.$target.set_enum(match data.$data {
|
||||
$( T::$servo => structs::$gecko as i32, )+
|
||||
})
|
||||
}}
|
||||
}
|
||||
|
||||
// font-style
|
||||
map_enum!(mStyle = (style: font_style) {
|
||||
normal => NS_FONT_STYLE_NORMAL,
|
||||
italic => NS_FONT_STYLE_ITALIC,
|
||||
oblique => NS_FONT_STYLE_OBLIQUE,
|
||||
});
|
||||
|
||||
// font-weight
|
||||
descriptors.mWeight.set_integer(data.weight as i32);
|
||||
|
||||
// font-stretch
|
||||
map_enum!(mStretch = (stretch: font_stretch) {
|
||||
normal => NS_FONT_STRETCH_NORMAL,
|
||||
ultra_condensed => NS_FONT_STRETCH_ULTRA_CONDENSED,
|
||||
extra_condensed => NS_FONT_STRETCH_EXTRA_CONDENSED,
|
||||
condensed => NS_FONT_STRETCH_CONDENSED,
|
||||
semi_condensed => NS_FONT_STRETCH_SEMI_CONDENSED,
|
||||
semi_expanded => NS_FONT_STRETCH_SEMI_EXPANDED,
|
||||
expanded => NS_FONT_STRETCH_EXPANDED,
|
||||
extra_expanded => NS_FONT_STRETCH_EXTRA_EXPANDED,
|
||||
ultra_expanded => NS_FONT_STRETCH_ULTRA_EXPANDED,
|
||||
});
|
||||
|
||||
// src
|
||||
let src_len = data.sources.iter().fold(0, |acc, src| {
|
||||
acc + match *src {
|
||||
// Each format hint takes one position in the array of mSrc.
|
||||
Source::Url(ref url) => url.format_hints.len() + 1,
|
||||
Source::Local(_) => 1,
|
||||
}
|
||||
});
|
||||
let mut target_srcs =
|
||||
descriptors.mSrc.set_array(src_len as i32).as_mut_slice().iter_mut();
|
||||
macro_rules! next { () => {
|
||||
target_srcs.next().expect("Length of target_srcs should be enough")
|
||||
} }
|
||||
for src in data.sources.iter() {
|
||||
match *src {
|
||||
Source::Url(ref url) => {
|
||||
next!().set_url(&url.url);
|
||||
for hint in url.format_hints.iter() {
|
||||
next!().set_font_format(&hint);
|
||||
}
|
||||
}
|
||||
Source::Local(ref name) => {
|
||||
next!().set_local_font(&name.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
debug_assert!(target_srcs.next().is_none(), "Should have filled all slots");
|
||||
|
||||
// unicode-range
|
||||
let target_ranges = descriptors.mUnicodeRange
|
||||
.set_array((data.unicode_range.len() * 2) as i32)
|
||||
.as_mut_slice().chunks_mut(2);
|
||||
for (range, target) in data.unicode_range.iter().zip(target_ranges) {
|
||||
target[0].set_integer(range.start as i32);
|
||||
target[1].set_integer(range.end as i32);
|
||||
}
|
||||
|
||||
// The following three descriptors are not implemented yet.
|
||||
// font-feature-settings
|
||||
descriptors.mFontFeatureSettings.set_normal();
|
||||
// font-language-override
|
||||
descriptors.mFontLanguageOverride.set_normal();
|
||||
// font-display
|
||||
descriptors.mDisplay.set_enum(structs::NS_FONT_DISPLAY_AUTO as i32);
|
||||
}
|
||||
|
||||
impl From<FontFaceData> for FontFaceRule {
|
||||
fn from(data: FontFaceData) -> FontFaceRule {
|
||||
let mut result = unsafe {
|
||||
UniqueRefPtr::from_addrefed(bindings::Gecko_CSSFontFaceRule_Create())
|
||||
};
|
||||
set_font_face_descriptors(&mut result.mDecl.mDescriptors, data);
|
||||
result.get()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCssWithGuard for FontFaceRule {
|
||||
fn to_css<W>(&self, _guard: &SharedRwLockReadGuard, dest: &mut W) -> fmt::Result
|
||||
where W: fmt::Write {
|
||||
ns_auto_string!(css_text);
|
||||
unsafe {
|
||||
bindings::Gecko_CSSFontFaceRule_GetCssText(self.get(), &mut *css_text);
|
||||
}
|
||||
write!(dest, "{}", css_text)
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ use gecko_bindings::structs::RawGeckoDocument;
|
|||
use gecko_bindings::structs::RawGeckoElement;
|
||||
use gecko_bindings::structs::RawGeckoKeyframeList;
|
||||
use gecko_bindings::structs::RawGeckoComputedKeyframeValuesList;
|
||||
use gecko_bindings::structs::RawGeckoFontFaceRuleList;
|
||||
use gecko_bindings::structs::RawGeckoNode;
|
||||
use gecko_bindings::structs::RawGeckoAnimationValueList;
|
||||
use gecko_bindings::structs::RawServoAnimationValue;
|
||||
|
@ -31,9 +32,11 @@ use gecko_bindings::structs::SheetParsingMode;
|
|||
use gecko_bindings::structs::StyleBasicShape;
|
||||
use gecko_bindings::structs::StyleBasicShapeType;
|
||||
use gecko_bindings::structs::StyleShapeSource;
|
||||
use gecko_bindings::structs::nsCSSFontFaceRule;
|
||||
use gecko_bindings::structs::nsCSSKeyword;
|
||||
use gecko_bindings::structs::nsCSSPropertyID;
|
||||
use gecko_bindings::structs::nsCSSShadowArray;
|
||||
use gecko_bindings::structs::nsCSSUnit;
|
||||
use gecko_bindings::structs::nsCSSValue;
|
||||
use gecko_bindings::structs::nsCSSValueSharedList;
|
||||
use gecko_bindings::structs::nsChangeHint;
|
||||
|
@ -281,6 +284,10 @@ pub type RawGeckoComputedKeyframeValuesListBorrowed<'a> = &'a RawGeckoComputedKe
|
|||
pub type RawGeckoComputedKeyframeValuesListBorrowedOrNull<'a> = Option<&'a RawGeckoComputedKeyframeValuesList>;
|
||||
pub type RawGeckoComputedKeyframeValuesListBorrowedMut<'a> = &'a mut RawGeckoComputedKeyframeValuesList;
|
||||
pub type RawGeckoComputedKeyframeValuesListBorrowedMutOrNull<'a> = Option<&'a mut RawGeckoComputedKeyframeValuesList>;
|
||||
pub type RawGeckoFontFaceRuleListBorrowed<'a> = &'a RawGeckoFontFaceRuleList;
|
||||
pub type RawGeckoFontFaceRuleListBorrowedOrNull<'a> = Option<&'a RawGeckoFontFaceRuleList>;
|
||||
pub type RawGeckoFontFaceRuleListBorrowedMut<'a> = &'a mut RawGeckoFontFaceRuleList;
|
||||
pub type RawGeckoFontFaceRuleListBorrowedMutOrNull<'a> = Option<&'a mut RawGeckoFontFaceRuleList>;
|
||||
|
||||
extern "C" {
|
||||
pub fn Gecko_EnsureTArrayCapacity(aArray: *mut ::std::os::raw::c_void,
|
||||
|
@ -951,6 +958,9 @@ extern "C" {
|
|||
pub fn Gecko_CSSValue_SetAbsoluteLength(css_value: nsCSSValueBorrowedMut,
|
||||
len: nscoord);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_CSSValue_SetNormal(css_value: nsCSSValueBorrowedMut);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_CSSValue_SetNumber(css_value: nsCSSValueBorrowedMut,
|
||||
number: f32);
|
||||
|
@ -977,11 +987,13 @@ extern "C" {
|
|||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_CSSValue_SetString(css_value: nsCSSValueBorrowedMut,
|
||||
string: *const u8, len: u32);
|
||||
string: *const u8, len: u32,
|
||||
unit: nsCSSUnit);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_CSSValue_SetIdent(css_value: nsCSSValueBorrowedMut,
|
||||
string: *const u8, len: u32);
|
||||
pub fn Gecko_CSSValue_SetStringFromAtom(css_value: nsCSSValueBorrowedMut,
|
||||
atom: *mut nsIAtom,
|
||||
unit: nsCSSUnit);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_CSSValue_SetArray(css_value: nsCSSValueBorrowedMut,
|
||||
|
@ -992,12 +1004,8 @@ extern "C" {
|
|||
uri: ServoBundledURI);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_CSSValue_SetLocal(css_value: nsCSSValueBorrowedMut,
|
||||
family: nsString);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_CSSValue_SetInteger(css_value: nsCSSValueBorrowedMut,
|
||||
integer: i32);
|
||||
pub fn Gecko_CSSValue_SetInt(css_value: nsCSSValueBorrowedMut,
|
||||
integer: i32, unit: nsCSSUnit);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_CSSValue_Drop(css_value: nsCSSValueBorrowedMut);
|
||||
|
@ -1030,6 +1038,19 @@ extern "C" {
|
|||
extern "C" {
|
||||
pub fn Gecko_GetMediaFeatures() -> *const nsMediaFeature;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_CSSFontFaceRule_Create() -> *mut nsCSSFontFaceRule;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_CSSFontFaceRule_GetCssText(rule: *const nsCSSFontFaceRule,
|
||||
result: *mut nsAString);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_CSSFontFaceRule_AddRef(aPtr: *mut nsCSSFontFaceRule);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_CSSFontFaceRule_Release(aPtr: *mut nsCSSFontFaceRule);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_GetLookAndFeelSystemColor(color_id: i32,
|
||||
pres_context:
|
||||
|
@ -1440,6 +1461,11 @@ extern "C" {
|
|||
RawGeckoKeyframeListBorrowedMut)
|
||||
-> bool;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Servo_StyleSet_GetFontFaceRules(set: RawServoStyleSetBorrowed,
|
||||
list:
|
||||
RawGeckoFontFaceRuleListBorrowedMut);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Servo_CssRules_ListTypes(rules: ServoCssRulesBorrowed,
|
||||
result: nsTArrayBorrowed_uintptr_t);
|
||||
|
@ -1494,6 +1520,11 @@ extern "C" {
|
|||
pub fn Servo_NamespaceRule_GetCssText(rule: RawServoNamespaceRuleBorrowed,
|
||||
result: *mut nsAString);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Servo_CssRules_GetFontFaceRuleAt(rules: ServoCssRulesBorrowed,
|
||||
index: u32)
|
||||
-> *mut nsCSSFontFaceRule;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Servo_StyleRule_GetStyle(rule: RawServoStyleRuleBorrowed)
|
||||
-> RawServoDeclarationBlockStrong;
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -8,6 +8,7 @@ use app_units::Au;
|
|||
use gecko_bindings::bindings;
|
||||
use gecko_bindings::structs::{nsCSSValue, nsCSSUnit};
|
||||
use gecko_bindings::structs::{nsCSSValue_Array, nscolor};
|
||||
use gecko_string_cache::Atom;
|
||||
use std::mem;
|
||||
use std::ops::{Index, IndexMut};
|
||||
use std::slice;
|
||||
|
@ -100,14 +101,56 @@ impl nsCSSValue {
|
|||
}
|
||||
}
|
||||
|
||||
/// Set to a normal value
|
||||
pub fn set_normal(&mut self) {
|
||||
unsafe { bindings::Gecko_CSSValue_SetNormal(self) }
|
||||
}
|
||||
|
||||
fn set_string_internal(&mut self, s: &str, unit: nsCSSUnit) {
|
||||
unsafe { bindings::Gecko_CSSValue_SetString(self, s.as_ptr(), s.len() as u32, unit) }
|
||||
}
|
||||
|
||||
fn set_string_from_atom_internal(&mut self, s: &Atom, unit: nsCSSUnit) {
|
||||
unsafe { bindings::Gecko_CSSValue_SetStringFromAtom(self, s.as_ptr(), unit) }
|
||||
}
|
||||
|
||||
/// Set to a string value
|
||||
pub fn set_string(&mut self, s: &str) {
|
||||
unsafe { bindings::Gecko_CSSValue_SetString(self, s.as_ptr(), s.len() as u32) }
|
||||
self.set_string_internal(s, nsCSSUnit::eCSSUnit_String)
|
||||
}
|
||||
|
||||
/// Set to a string value from the given atom
|
||||
pub fn set_string_from_atom(&mut self, s: &Atom) {
|
||||
self.set_string_from_atom_internal(s, nsCSSUnit::eCSSUnit_String)
|
||||
}
|
||||
|
||||
/// Set to an identifier value
|
||||
pub fn set_ident(&mut self, s: &str) {
|
||||
unsafe { bindings::Gecko_CSSValue_SetIdent(self, s.as_ptr(), s.len() as u32) }
|
||||
self.set_string_internal(s, nsCSSUnit::eCSSUnit_Ident)
|
||||
}
|
||||
|
||||
/// Set to a font format
|
||||
pub fn set_font_format(&mut self, s: &str) {
|
||||
self.set_string_internal(s, nsCSSUnit::eCSSUnit_Font_Format);
|
||||
}
|
||||
|
||||
/// Set to a local font value
|
||||
pub fn set_local_font(&mut self, s: &Atom) {
|
||||
self.set_string_from_atom_internal(s, nsCSSUnit::eCSSUnit_Local_Font);
|
||||
}
|
||||
|
||||
fn set_int_internal(&mut self, value: i32, unit: nsCSSUnit) {
|
||||
unsafe { bindings::Gecko_CSSValue_SetInt(self, value, unit) }
|
||||
}
|
||||
|
||||
/// Set to an integer value
|
||||
pub fn set_integer(&mut self, value: i32) {
|
||||
self.set_int_internal(value, nsCSSUnit::eCSSUnit_Integer)
|
||||
}
|
||||
|
||||
/// Set to an enumerated value
|
||||
pub fn set_enum<T: Into<i32>>(&mut self, value: T) {
|
||||
self.set_int_internal(value.into(), nsCSSUnit::eCSSUnit_Enumerated);
|
||||
}
|
||||
|
||||
/// Set to a url value
|
||||
|
@ -116,8 +159,9 @@ impl nsCSSValue {
|
|||
}
|
||||
|
||||
/// Set to an array of given length
|
||||
pub fn set_array(&mut self, len: i32) {
|
||||
pub fn set_array(&mut self, len: i32) -> &mut nsCSSValue_Array {
|
||||
unsafe { bindings::Gecko_CSSValue_SetArray(self, len) }
|
||||
unsafe { self.mValue.mArray.as_mut().as_mut() }.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -235,10 +235,7 @@ impl<T: RefCounted> PartialEq for RefPtr<T> {
|
|||
unsafe impl<T: ThreadSafeRefCounted> Send for RefPtr<T> {}
|
||||
unsafe impl<T: ThreadSafeRefCounted> Sync for RefPtr<T> {}
|
||||
|
||||
// Companion of NS_DECL_THREADSAFE_FFI_REFCOUNTING.
|
||||
//
|
||||
// Gets you a free RefCounted impl implemented via FFI.
|
||||
macro_rules! impl_threadsafe_refcount {
|
||||
macro_rules! impl_refcount {
|
||||
($t:ty, $addref:ident, $release:ident) => (
|
||||
unsafe impl RefCounted for $t {
|
||||
fn addref(&self) {
|
||||
|
@ -248,6 +245,18 @@ macro_rules! impl_threadsafe_refcount {
|
|||
::gecko_bindings::bindings::$release(self as *const _ as *mut _)
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
impl_refcount!(::gecko_bindings::structs::nsCSSFontFaceRule,
|
||||
Gecko_CSSFontFaceRule_AddRef, Gecko_CSSFontFaceRule_Release);
|
||||
|
||||
// Companion of NS_DECL_THREADSAFE_FFI_REFCOUNTING.
|
||||
//
|
||||
// Gets you a free RefCounted impl implemented via FFI.
|
||||
macro_rules! impl_threadsafe_refcount {
|
||||
($t:ty, $addref:ident, $release:ident) => (
|
||||
impl_refcount!($t, $addref, $release);
|
||||
unsafe impl ThreadSafeRefCounted for $t {}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -57,7 +57,9 @@ extern crate log;
|
|||
#[allow(unused_extern_crates)]
|
||||
#[macro_use]
|
||||
extern crate matches;
|
||||
#[cfg(feature = "gecko")] extern crate nsstring_vendor as nsstring;
|
||||
#[cfg(feature = "gecko")]
|
||||
#[macro_use]
|
||||
extern crate nsstring_vendor as nsstring;
|
||||
#[cfg(feature = "gecko")] extern crate num_cpus;
|
||||
extern crate num_integer;
|
||||
extern crate num_traits;
|
||||
|
|
|
@ -11,7 +11,11 @@ use cssparser::{AtRuleParser, Parser, QualifiedRuleParser};
|
|||
use cssparser::{AtRuleType, RuleListParser, SourcePosition, Token, parse_one_rule};
|
||||
use cssparser::ToCss as ParserToCss;
|
||||
use error_reporting::ParseErrorReporter;
|
||||
use font_face::{FontFaceRule, parse_font_face_block};
|
||||
#[cfg(feature = "servo")]
|
||||
use font_face::FontFaceData;
|
||||
use font_face::parse_font_face_block;
|
||||
#[cfg(feature = "gecko")]
|
||||
pub use gecko::rules::FontFaceRule;
|
||||
use keyframes::{Keyframe, parse_keyframe_list};
|
||||
use media_queries::{Device, MediaList, parse_media_query_list};
|
||||
use parking_lot::RwLock;
|
||||
|
@ -551,6 +555,10 @@ impl ToCssWithGuard for StyleRule {
|
|||
}
|
||||
}
|
||||
|
||||
/// A @font-face rule
|
||||
#[cfg(feature = "servo")]
|
||||
pub type FontFaceRule = FontFaceData;
|
||||
|
||||
impl Stylesheet {
|
||||
/// Updates an empty stylesheet from a given string of text.
|
||||
pub fn update_from_str(existing: &Stylesheet,
|
||||
|
@ -1004,7 +1012,7 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
|
|||
match prelude {
|
||||
AtRulePrelude::FontFace => {
|
||||
Ok(CssRule::FontFace(Arc::new(self.shared_lock.wrap(
|
||||
try!(parse_font_face_block(self.context, input))))))
|
||||
parse_font_face_block(self.context, input)?.into()))))
|
||||
}
|
||||
AtRulePrelude::Media(media_queries) => {
|
||||
Ok(CssRule::Media(Arc::new(self.shared_lock.wrap(MediaRule {
|
||||
|
|
|
@ -34,9 +34,11 @@ use std::borrow::Borrow;
|
|||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
#[cfg(feature = "servo")]
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::Arc;
|
||||
use style_traits::viewport::ViewportConstraints;
|
||||
use stylesheets::{CssRule, Origin, StyleRule, Stylesheet, UserAgentStylesheets};
|
||||
use stylesheets::{CssRule, FontFaceRule, Origin, StyleRule, Stylesheet, UserAgentStylesheets};
|
||||
use thread_state;
|
||||
use viewport::{self, MaybeNew, ViewportRule};
|
||||
|
||||
|
@ -118,6 +120,37 @@ pub struct Stylist {
|
|||
non_common_style_affecting_attributes_selectors: Vec<Selector<SelectorImpl>>,
|
||||
}
|
||||
|
||||
/// This struct holds data which user of Stylist may want to extract
|
||||
/// from stylesheets which can be done at the same time as updating.
|
||||
pub struct ExtraStyleData<'a> {
|
||||
/// A list of effective font-face rules and their origin.
|
||||
#[cfg(feature = "gecko")]
|
||||
pub font_faces: &'a mut Vec<(Arc<Locked<FontFaceRule>>, Origin)>,
|
||||
|
||||
#[allow(missing_docs)]
|
||||
#[cfg(feature = "servo")]
|
||||
pub marker: PhantomData<&'a usize>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
impl<'a> ExtraStyleData<'a> {
|
||||
/// Clear the internal @font-face rule list.
|
||||
fn clear_font_faces(&mut self) {
|
||||
self.font_faces.clear();
|
||||
}
|
||||
|
||||
/// Add the given @font-face rule.
|
||||
fn add_font_face(&mut self, rule: &Arc<Locked<FontFaceRule>>, origin: Origin) {
|
||||
self.font_faces.push((rule.clone(), origin));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "servo")]
|
||||
impl<'a> ExtraStyleData<'a> {
|
||||
fn clear_font_faces(&mut self) {}
|
||||
fn add_font_face(&mut self, _: &Arc<Locked<FontFaceRule>>, _: Origin) {}
|
||||
}
|
||||
|
||||
impl Stylist {
|
||||
/// Construct a new `Stylist`, using a given `Device`.
|
||||
#[inline]
|
||||
|
@ -156,11 +189,12 @@ impl Stylist {
|
|||
/// This method resets all the style data each time the stylesheets change
|
||||
/// (which is indicated by the `stylesheets_changed` parameter), or the
|
||||
/// device is dirty, which means we need to re-evaluate media queries.
|
||||
pub fn update(&mut self,
|
||||
doc_stylesheets: &[Arc<Stylesheet>],
|
||||
guards: &StylesheetGuards,
|
||||
ua_stylesheets: Option<&UserAgentStylesheets>,
|
||||
stylesheets_changed: bool) -> bool {
|
||||
pub fn update<'a>(&mut self,
|
||||
doc_stylesheets: &[Arc<Stylesheet>],
|
||||
guards: &StylesheetGuards,
|
||||
ua_stylesheets: Option<&UserAgentStylesheets>,
|
||||
stylesheets_changed: bool,
|
||||
extra_data: &mut ExtraStyleData<'a>) -> bool {
|
||||
if !(self.is_device_dirty || stylesheets_changed) {
|
||||
return false;
|
||||
}
|
||||
|
@ -194,18 +228,21 @@ impl Stylist {
|
|||
self.sibling_affecting_selectors.clear();
|
||||
self.non_common_style_affecting_attributes_selectors.clear();
|
||||
|
||||
extra_data.clear_font_faces();
|
||||
|
||||
if let Some(ua_stylesheets) = ua_stylesheets {
|
||||
for stylesheet in &ua_stylesheets.user_or_user_agent_stylesheets {
|
||||
self.add_stylesheet(&stylesheet, guards.ua_or_user);
|
||||
self.add_stylesheet(&stylesheet, guards.ua_or_user, extra_data);
|
||||
}
|
||||
|
||||
if self.quirks_mode {
|
||||
self.add_stylesheet(&ua_stylesheets.quirks_mode_stylesheet, guards.ua_or_user);
|
||||
self.add_stylesheet(&ua_stylesheets.quirks_mode_stylesheet,
|
||||
guards.ua_or_user, extra_data);
|
||||
}
|
||||
}
|
||||
|
||||
for ref stylesheet in doc_stylesheets.iter() {
|
||||
self.add_stylesheet(stylesheet, guards.author);
|
||||
self.add_stylesheet(stylesheet, guards.author, extra_data);
|
||||
}
|
||||
|
||||
debug!("Stylist stats:");
|
||||
|
@ -230,7 +267,8 @@ impl Stylist {
|
|||
true
|
||||
}
|
||||
|
||||
fn add_stylesheet(&mut self, stylesheet: &Stylesheet, guard: &SharedRwLockReadGuard) {
|
||||
fn add_stylesheet<'a>(&mut self, stylesheet: &Stylesheet, guard: &SharedRwLockReadGuard,
|
||||
extra_data: &mut ExtraStyleData<'a>) {
|
||||
if stylesheet.disabled() || !stylesheet.is_effective_for_device(&self.device, guard) {
|
||||
return;
|
||||
}
|
||||
|
@ -274,7 +312,7 @@ impl Stylist {
|
|||
}
|
||||
CssRule::Import(ref import) => {
|
||||
let import = import.read_with(guard);
|
||||
self.add_stylesheet(&import.stylesheet, guard)
|
||||
self.add_stylesheet(&import.stylesheet, guard, extra_data)
|
||||
}
|
||||
CssRule::Keyframes(ref keyframes_rule) => {
|
||||
let keyframes_rule = keyframes_rule.read_with(guard);
|
||||
|
@ -284,6 +322,9 @@ impl Stylist {
|
|||
debug!("Found valid keyframe animation: {:?}", animation);
|
||||
self.animations.insert(keyframes_rule.name.clone(), animation);
|
||||
}
|
||||
CssRule::FontFace(ref rule) => {
|
||||
extra_data.add_font_face(&rule, stylesheet.origin);
|
||||
}
|
||||
// We don't care about any other rule.
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ use style::gecko_bindings::bindings::{nsACString, nsAString};
|
|||
use style::gecko_bindings::bindings::Gecko_AnimationAppendKeyframe;
|
||||
use style::gecko_bindings::bindings::RawGeckoComputedKeyframeValuesListBorrowedMut;
|
||||
use style::gecko_bindings::bindings::RawGeckoElementBorrowed;
|
||||
use style::gecko_bindings::bindings::RawGeckoFontFaceRuleListBorrowedMut;
|
||||
use style::gecko_bindings::bindings::RawServoAnimationValueBorrowed;
|
||||
use style::gecko_bindings::bindings::RawServoAnimationValueMapBorrowed;
|
||||
use style::gecko_bindings::bindings::RawServoAnimationValueStrong;
|
||||
|
@ -54,7 +55,7 @@ use style::gecko_bindings::bindings::nsTimingFunctionBorrowedMut;
|
|||
use style::gecko_bindings::structs;
|
||||
use style::gecko_bindings::structs::{SheetParsingMode, nsIAtom, nsCSSPropertyID};
|
||||
use style::gecko_bindings::structs::{ThreadSafePrincipalHolder, ThreadSafeURIHolder};
|
||||
use style::gecko_bindings::structs::{nsRestyleHint, nsChangeHint};
|
||||
use style::gecko_bindings::structs::{nsRestyleHint, nsChangeHint, nsCSSFontFaceRule};
|
||||
use style::gecko_bindings::structs::Loader;
|
||||
use style::gecko_bindings::structs::RawGeckoPresContextOwned;
|
||||
use style::gecko_bindings::structs::ServoStyleSheet;
|
||||
|
@ -602,6 +603,19 @@ impl_basic_rule_funcs! { (Namespace, NamespaceRule, RawServoNamespaceRule),
|
|||
to_css: Servo_NamespaceRule_GetCssText,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_CssRules_GetFontFaceRuleAt(rules: ServoCssRulesBorrowed, index: u32)
|
||||
-> *mut nsCSSFontFaceRule
|
||||
{
|
||||
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||
let guard = global_style_data.shared_lock.read();
|
||||
let rules = Locked::<CssRules>::as_arc(&rules).read_with(&guard);
|
||||
match rules.0[index as usize] {
|
||||
CssRule::FontFace(ref rule) => rule.read_with(&guard).get(),
|
||||
_ => unreachable!("Servo_CssRules_GetFontFaceRuleAt should only be called on a FontFace rule"),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_StyleRule_GetStyle(rule: RawServoStyleRuleBorrowed) -> RawServoDeclarationBlockStrong {
|
||||
read_locked_arc(rule, |rule: &StyleRule| {
|
||||
|
@ -1730,3 +1744,18 @@ pub extern "C" fn Servo_StyleSet_FillKeyframesForName(raw_data: RawServoStyleSet
|
|||
false
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_StyleSet_GetFontFaceRules(raw_data: RawServoStyleSetBorrowed,
|
||||
rules: RawGeckoFontFaceRuleListBorrowedMut) {
|
||||
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
||||
debug_assert!(rules.len() == 0);
|
||||
|
||||
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||
let guard = global_style_data.shared_lock.read();
|
||||
|
||||
unsafe { rules.set_len(data.font_faces.len() as u32) };
|
||||
for (src, dest) in data.font_faces.iter().zip(rules.iter_mut()) {
|
||||
dest.mRule = src.0.read_with(&guard).clone().forget();
|
||||
dest.mSheetType = src.1.into();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
use gfx::font_cache_thread::FontCacheThread;
|
||||
use ipc_channel::ipc;
|
||||
use style::computed_values::font_family::FamilyName;
|
||||
use style::font_face::{FontFaceRule, Source};
|
||||
use style::font_face::{FontFaceData, Source};
|
||||
|
||||
#[test]
|
||||
fn test_local_web_font() {
|
||||
|
@ -14,7 +14,7 @@ fn test_local_web_font() {
|
|||
let font_cache_thread = FontCacheThread::new(inp_chan, None);
|
||||
let family_name = FamilyName(From::from("test family"));
|
||||
let variant_name = FamilyName(From::from("test font face"));
|
||||
let font_face_rule = FontFaceRule {
|
||||
let font_face_rule = FontFaceData {
|
||||
family: family_name.clone(),
|
||||
sources: vec![Source::Local(variant_name)],
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue