зеркало из https://github.com/mozilla/gecko-dev.git
servo: Merge #16122 - stylo: Handle font-size keywords correctly (from Manishearth:stylo-font-size); r=heycam
r=heycam https://bugzilla.mozilla.org/show_bug.cgi?id=1341775 Source-Repo: https://github.com/servo/servo Source-Revision: 1584bbd3ecc2a86339f8fe2ccb88bd30fc462b1c --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : 2047c506f34dd7a2ea6e36b24008384212f8f737
This commit is contained in:
Родитель
8b6b8b09d0
Коммит
d5c001e64d
|
@ -293,6 +293,7 @@ mod bindings {
|
|||
"BORDER_STYLE_.*",
|
||||
"mozilla::SERVO_PREF_.*",
|
||||
"kNameSpaceID_.*",
|
||||
"kGenericFont_.*",
|
||||
];
|
||||
let whitelist = [
|
||||
"RawGecko.*",
|
||||
|
|
|
@ -1012,6 +1012,12 @@ extern "C" {
|
|||
pub fn Gecko_nsStyleFont_CopyLangFrom(aFont: *mut nsStyleFont,
|
||||
aSource: *const nsStyleFont);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_nsStyleFont_GetBaseSize(font: *const nsStyleFont,
|
||||
pres_context:
|
||||
RawGeckoPresContextBorrowed)
|
||||
-> nscoord;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_GetMediaFeatures() -> *const nsMediaFeature;
|
||||
}
|
||||
|
|
|
@ -19097,6 +19097,14 @@ pub mod root {
|
|||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct gfxFontStyle([u8; 0]);
|
||||
pub const kGenericFont_NONE: u8 = 0;
|
||||
pub const kGenericFont_moz_variable: u8 = 0;
|
||||
pub const kGenericFont_moz_fixed: u8 = 1;
|
||||
pub const kGenericFont_serif: u8 = 2;
|
||||
pub const kGenericFont_sans_serif: u8 = 4;
|
||||
pub const kGenericFont_monospace: u8 = 8;
|
||||
pub const kGenericFont_cursive: u8 = 16;
|
||||
pub const kGenericFont_fantasy: u8 = 32;
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct nsFont {
|
||||
|
|
|
@ -18546,6 +18546,14 @@ pub mod root {
|
|||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct gfxFontStyle([u8; 0]);
|
||||
pub const kGenericFont_NONE: u8 = 0;
|
||||
pub const kGenericFont_moz_variable: u8 = 0;
|
||||
pub const kGenericFont_moz_fixed: u8 = 1;
|
||||
pub const kGenericFont_serif: u8 = 2;
|
||||
pub const kGenericFont_sans_serif: u8 = 4;
|
||||
pub const kGenericFont_monospace: u8 = 8;
|
||||
pub const kGenericFont_cursive: u8 = 16;
|
||||
pub const kGenericFont_fantasy: u8 = 32;
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct nsFont {
|
||||
|
|
|
@ -80,6 +80,7 @@ pub struct ComputedValues {
|
|||
shareable: bool,
|
||||
pub writing_mode: WritingMode,
|
||||
pub root_font_size: Au,
|
||||
pub font_size_keyword: Option<longhands::font_size::KeywordSize>,
|
||||
}
|
||||
|
||||
impl ComputedValues {
|
||||
|
@ -89,6 +90,7 @@ impl ComputedValues {
|
|||
shareable: parent.shareable,
|
||||
writing_mode: parent.writing_mode,
|
||||
root_font_size: parent.root_font_size,
|
||||
font_size_keyword: parent.font_size_keyword,
|
||||
% for style_struct in data.style_structs:
|
||||
% if style_struct.inherited:
|
||||
${style_struct.ident}: parent.${style_struct.ident}.clone(),
|
||||
|
@ -103,6 +105,7 @@ impl ComputedValues {
|
|||
shareable: bool,
|
||||
writing_mode: WritingMode,
|
||||
root_font_size: Au,
|
||||
font_size_keyword: Option<longhands::font_size::KeywordSize>,
|
||||
% for style_struct in data.style_structs:
|
||||
${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
|
||||
% endfor
|
||||
|
@ -112,6 +115,7 @@ impl ComputedValues {
|
|||
shareable: shareable,
|
||||
writing_mode: writing_mode,
|
||||
root_font_size: root_font_size,
|
||||
font_size_keyword: font_size_keyword,
|
||||
% for style_struct in data.style_structs:
|
||||
${style_struct.ident}: ${style_struct.ident},
|
||||
% endfor
|
||||
|
@ -124,6 +128,7 @@ impl ComputedValues {
|
|||
shareable: true,
|
||||
writing_mode: WritingMode::empty(), // FIXME(bz): This seems dubious
|
||||
root_font_size: longhands::font_size::get_initial_value(), // FIXME(bz): Also seems dubious?
|
||||
font_size_keyword: Some(Default::default()),
|
||||
% for style_struct in data.style_structs:
|
||||
${style_struct.ident}: style_structs::${style_struct.name}::default(pres_context),
|
||||
% endfor
|
||||
|
@ -194,6 +199,11 @@ impl ComputedValues {
|
|||
pub struct ${style_struct.gecko_struct_name} {
|
||||
gecko: ${style_struct.gecko_ffi_name},
|
||||
}
|
||||
impl ${style_struct.gecko_struct_name} {
|
||||
pub fn gecko(&self) -> &${style_struct.gecko_ffi_name} {
|
||||
&self.gecko
|
||||
}
|
||||
}
|
||||
</%def>
|
||||
|
||||
<%def name="impl_simple_setter(ident, gecko_ffi_name)">
|
||||
|
@ -1191,14 +1201,31 @@ fn static_assert() {
|
|||
unsafe { Gecko_FontFamilyList_AppendNamed(list, name.0.as_ptr()); }
|
||||
}
|
||||
FontFamily::Generic(ref name) => {
|
||||
let family_type =
|
||||
if name == &atom!("serif") { FontFamilyType::eFamily_serif }
|
||||
else if name == &atom!("sans-serif") { FontFamilyType::eFamily_sans_serif }
|
||||
else if name == &atom!("cursive") { FontFamilyType::eFamily_cursive }
|
||||
else if name == &atom!("fantasy") { FontFamilyType::eFamily_fantasy }
|
||||
else if name == &atom!("monospace") { FontFamilyType::eFamily_monospace }
|
||||
else if name == &atom!("-moz-fixed") { FontFamilyType::eFamily_moz_fixed }
|
||||
else { panic!("Unknown generic font family") };
|
||||
let (family_type, generic) =
|
||||
if name == &atom!("serif") {
|
||||
(FontFamilyType::eFamily_serif,
|
||||
structs::kGenericFont_serif)
|
||||
} else if name == &atom!("sans-serif") {
|
||||
(FontFamilyType::eFamily_sans_serif,
|
||||
structs::kGenericFont_sans_serif)
|
||||
} else if name == &atom!("cursive") {
|
||||
(FontFamilyType::eFamily_cursive,
|
||||
structs::kGenericFont_cursive)
|
||||
} else if name == &atom!("fantasy") {
|
||||
(FontFamilyType::eFamily_fantasy,
|
||||
structs::kGenericFont_fantasy)
|
||||
} else if name == &atom!("monospace") {
|
||||
(FontFamilyType::eFamily_monospace,
|
||||
structs::kGenericFont_monospace)
|
||||
} else if name == &atom!("-moz-fixed") {
|
||||
(FontFamilyType::eFamily_moz_fixed,
|
||||
structs::kGenericFont_moz_fixed)
|
||||
} else {
|
||||
panic!("Unknown generic font family")
|
||||
};
|
||||
if v.0.len() == 1 {
|
||||
self.gecko.mGenericID = generic;
|
||||
}
|
||||
unsafe { Gecko_FontFamilyList_AppendGeneric(list, family_type); }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -266,6 +266,13 @@
|
|||
match *value {
|
||||
DeclaredValue::Value(ref specified_value) => {
|
||||
let computed = specified_value.to_computed_value(context);
|
||||
% if property.ident == "font_size":
|
||||
if let longhands::font_size::SpecifiedValue::Keyword(kw) = **specified_value {
|
||||
context.mutate_style().font_size_keyword = Some(kw);
|
||||
} else {
|
||||
context.mutate_style().font_size_keyword = None;
|
||||
}
|
||||
% endif
|
||||
% if property.has_uncacheable_values:
|
||||
context.mutate_style().mutate_${data.current_style_struct.name_lower}()
|
||||
.set_${property.ident}(computed, cacheable ${maybe_wm});
|
||||
|
@ -280,12 +287,22 @@
|
|||
CSSWideKeyword::Unset |
|
||||
% endif
|
||||
CSSWideKeyword::Initial => {
|
||||
// We assume that it's faster to use copy_*_from rather than
|
||||
// set_*(get_initial_value());
|
||||
let initial_struct = default_style
|
||||
.get_${data.current_style_struct.name_lower}();
|
||||
context.mutate_style().mutate_${data.current_style_struct.name_lower}()
|
||||
.copy_${property.ident}_from(initial_struct ${maybe_wm});
|
||||
% if property.ident == "font_size":
|
||||
// font-size's default ("medium") does not always
|
||||
// compute to the same value and depends on the font
|
||||
let computed = longhands::font_size::get_initial_specified_value()
|
||||
.to_computed_value(context);
|
||||
context.mutate_style().mutate_${data.current_style_struct.name_lower}()
|
||||
.set_font_size(computed);
|
||||
context.mutate_style().font_size_keyword = Some(Default::default());
|
||||
% else:
|
||||
// We assume that it's faster to use copy_*_from rather than
|
||||
// set_*(get_initial_value());
|
||||
let initial_struct = default_style
|
||||
.get_${data.current_style_struct.name_lower}();
|
||||
context.mutate_style().mutate_${data.current_style_struct.name_lower}()
|
||||
.copy_${property.ident}_from(initial_struct ${maybe_wm});
|
||||
% endif
|
||||
},
|
||||
% if data.current_style_struct.inherited:
|
||||
CSSWideKeyword::Unset |
|
||||
|
@ -300,6 +317,10 @@
|
|||
inherited_style.get_${data.current_style_struct.name_lower}();
|
||||
context.mutate_style().mutate_${data.current_style_struct.name_lower}()
|
||||
.copy_${property.ident}_from(inherited_struct ${maybe_wm});
|
||||
% if property.ident == "font_size":
|
||||
context.mutate_style().font_size_keyword =
|
||||
context.inherited_style.font_size_keyword;
|
||||
% endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -465,6 +465,12 @@ ${helpers.single_keyword("font-variant-caps",
|
|||
}
|
||||
}
|
||||
|
||||
impl Default for KeywordSize {
|
||||
fn default() -> Self {
|
||||
Medium
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for KeywordSize {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
dest.write_str(match *self {
|
||||
|
@ -482,29 +488,79 @@ ${helpers.single_keyword("font-variant-caps",
|
|||
}
|
||||
}
|
||||
|
||||
impl ToComputedValue for KeywordSize {
|
||||
type ComputedValue = Au;
|
||||
#[inline]
|
||||
fn to_computed_value(&self, _: &Context) -> computed_value::T {
|
||||
// https://drafts.csswg.org/css-fonts-3/#font-size-prop
|
||||
use values::FONT_MEDIUM_PX;
|
||||
match *self {
|
||||
XXSmall => Au::from_px(FONT_MEDIUM_PX) * 3 / 5,
|
||||
XSmall => Au::from_px(FONT_MEDIUM_PX) * 3 / 4,
|
||||
Small => Au::from_px(FONT_MEDIUM_PX) * 8 / 9,
|
||||
Medium => Au::from_px(FONT_MEDIUM_PX),
|
||||
Large => Au::from_px(FONT_MEDIUM_PX) * 6 / 5,
|
||||
XLarge => Au::from_px(FONT_MEDIUM_PX) * 3 / 2,
|
||||
XXLarge => Au::from_px(FONT_MEDIUM_PX) * 2,
|
||||
XXXLarge => Au::from_px(FONT_MEDIUM_PX) * 3,
|
||||
% if product == "servo":
|
||||
impl ToComputedValue for KeywordSize {
|
||||
type ComputedValue = Au;
|
||||
#[inline]
|
||||
fn to_computed_value(&self, _: &Context) -> computed_value::T {
|
||||
// https://drafts.csswg.org/css-fonts-3/#font-size-prop
|
||||
use values::FONT_MEDIUM_PX;
|
||||
match *self {
|
||||
XXSmall => Au::from_px(FONT_MEDIUM_PX) * 3 / 5,
|
||||
XSmall => Au::from_px(FONT_MEDIUM_PX) * 3 / 4,
|
||||
Small => Au::from_px(FONT_MEDIUM_PX) * 8 / 9,
|
||||
Medium => Au::from_px(FONT_MEDIUM_PX),
|
||||
Large => Au::from_px(FONT_MEDIUM_PX) * 6 / 5,
|
||||
XLarge => Au::from_px(FONT_MEDIUM_PX) * 3 / 2,
|
||||
XXLarge => Au::from_px(FONT_MEDIUM_PX) * 2,
|
||||
XXXLarge => Au::from_px(FONT_MEDIUM_PX) * 3,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_computed_value(_: &computed_value::T) -> Self {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
% else:
|
||||
impl ToComputedValue for KeywordSize {
|
||||
type ComputedValue = Au;
|
||||
#[inline]
|
||||
fn to_computed_value(&self, cx: &Context) -> computed_value::T {
|
||||
use gecko_bindings::bindings::Gecko_nsStyleFont_GetBaseSize;
|
||||
use values::specified::length::au_to_int_px;
|
||||
// Data from nsRuleNode.cpp in Gecko
|
||||
// Mapping from base size and HTML size to pixels
|
||||
// The first index is (base_size - 9), the second is the
|
||||
// HTML size. "0" is CSS keyword xx-small, not HTML size 0,
|
||||
// since HTML size 0 is the same as 1.
|
||||
//
|
||||
// xxs xs s m l xl xxl -
|
||||
// - 0/1 2 3 4 5 6 7
|
||||
static FONT_SIZE_MAPPING: [[i32; 8]; 8] = [
|
||||
[9, 9, 9, 9, 11, 14, 18, 27],
|
||||
[9, 9, 9, 10, 12, 15, 20, 30],
|
||||
[9, 9, 10, 11, 13, 17, 22, 33],
|
||||
[9, 9, 10, 12, 14, 18, 24, 36],
|
||||
[9, 10, 12, 13, 16, 20, 26, 39],
|
||||
[9, 10, 12, 14, 17, 21, 28, 42],
|
||||
[9, 10, 13, 15, 18, 23, 30, 45],
|
||||
[9, 10, 13, 16, 18, 24, 32, 48]
|
||||
];
|
||||
|
||||
#[inline]
|
||||
fn from_computed_value(_: &computed_value::T) -> Self {
|
||||
unreachable!()
|
||||
static FONT_SIZE_FACTORS: [i32; 8] = [60, 75, 89, 100, 120, 150, 200, 300];
|
||||
|
||||
// XXXManishearth handle quirks mode
|
||||
|
||||
let base_size = unsafe {
|
||||
Gecko_nsStyleFont_GetBaseSize(cx.style().get_font().gecko(),
|
||||
&*cx.device.pres_context)
|
||||
};
|
||||
let base_size_px = au_to_int_px(base_size as f32);
|
||||
let html_size = *self as usize;
|
||||
if base_size_px >= 9 && base_size_px <= 16 {
|
||||
Au::from_px(FONT_SIZE_MAPPING[(base_size_px - 9) as usize][html_size])
|
||||
} else {
|
||||
Au(FONT_SIZE_FACTORS[html_size] * base_size / 100)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_computed_value(_: &computed_value::T) -> Self {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
% endif
|
||||
|
||||
impl SpecifiedValue {
|
||||
/// https://html.spec.whatwg.org/multipage/#rules-for-parsing-a-legacy-font-size
|
||||
|
|
|
@ -1502,6 +1502,8 @@ pub struct ComputedValues {
|
|||
pub writing_mode: WritingMode,
|
||||
/// The root element's computed font size.
|
||||
pub root_font_size: Au,
|
||||
/// The keyword behind the current font-size property, if any
|
||||
pub font_size_keyword: Option<longhands::font_size::KeywordSize>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "servo")]
|
||||
|
@ -1511,6 +1513,7 @@ impl ComputedValues {
|
|||
shareable: bool,
|
||||
writing_mode: WritingMode,
|
||||
root_font_size: Au,
|
||||
font_size_keyword: Option<longhands::font_size::KeywordSize>,
|
||||
% for style_struct in data.active_style_structs():
|
||||
${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
|
||||
% endfor
|
||||
|
@ -1520,6 +1523,7 @@ impl ComputedValues {
|
|||
shareable: shareable,
|
||||
writing_mode: writing_mode,
|
||||
root_font_size: root_font_size,
|
||||
font_size_keyword: font_size_keyword,
|
||||
% for style_struct in data.active_style_structs():
|
||||
${style_struct.ident}: ${style_struct.ident},
|
||||
% endfor
|
||||
|
@ -1843,6 +1847,7 @@ mod lazy_static_module {
|
|||
shareable: true,
|
||||
writing_mode: WritingMode::empty(),
|
||||
root_font_size: longhands::font_size::get_initial_value(),
|
||||
font_size_keyword: Some(Default::default()),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1985,6 +1990,7 @@ pub fn apply_declarations<'a, F, I>(device: &Device,
|
|||
flags.contains(SHAREABLE),
|
||||
WritingMode::empty(),
|
||||
inherited_style.root_font_size,
|
||||
inherited_style.font_size_keyword,
|
||||
% for style_struct in data.active_style_structs():
|
||||
% if style_struct.inherited:
|
||||
inherited_style.clone_${style_struct.name_lower}(),
|
||||
|
@ -1998,6 +2004,7 @@ pub fn apply_declarations<'a, F, I>(device: &Device,
|
|||
flags.contains(SHAREABLE),
|
||||
WritingMode::empty(),
|
||||
inherited_style.root_font_size,
|
||||
inherited_style.font_size_keyword,
|
||||
% for style_struct in data.active_style_structs():
|
||||
inherited_style.clone_${style_struct.name_lower}(),
|
||||
% endfor
|
||||
|
@ -2030,6 +2037,13 @@ pub fn apply_declarations<'a, F, I>(device: &Device,
|
|||
// To improve i-cache behavior, we outline the individual functions and use
|
||||
// virtual dispatch instead.
|
||||
% for category_to_cascade_now in ["early", "other"]:
|
||||
% if category_to_cascade_now == "early":
|
||||
// Pull these out so that we can
|
||||
// compute them in a specific order without
|
||||
// introducing more iterations
|
||||
let mut font_size = None;
|
||||
let mut font_family = None;
|
||||
% endif
|
||||
for declaration in iter_declarations() {
|
||||
let longhand_id = match declaration.id() {
|
||||
PropertyDeclarationId::Longhand(id) => id,
|
||||
|
@ -2076,6 +2090,17 @@ pub fn apply_declarations<'a, F, I>(device: &Device,
|
|||
}
|
||||
seen.insert(physical_longhand_id);
|
||||
|
||||
% if category_to_cascade_now == "early":
|
||||
if LonghandId::FontSize == longhand_id {
|
||||
font_size = Some(declaration);
|
||||
continue;
|
||||
}
|
||||
if LonghandId::FontFamily == longhand_id {
|
||||
font_family = Some(declaration);
|
||||
continue;
|
||||
}
|
||||
% endif
|
||||
|
||||
let discriminant = longhand_id as usize;
|
||||
(CASCADE_PROPERTY[discriminant])(declaration,
|
||||
inherited_style,
|
||||
|
@ -2088,6 +2113,51 @@ pub fn apply_declarations<'a, F, I>(device: &Device,
|
|||
% if category_to_cascade_now == "early":
|
||||
let writing_mode = get_writing_mode(context.style.get_inheritedbox());
|
||||
context.style.writing_mode = writing_mode;
|
||||
// It is important that font_size is computed before
|
||||
// the late properties (for em units), but after font-family
|
||||
// (for the base-font-size dependence for default and keyword font-sizes)
|
||||
// Additionally, when we support system fonts they will have to be
|
||||
// computed early, and *before* font_family, so I'm including
|
||||
// font_family here preemptively instead of keeping it within
|
||||
// the early properties.
|
||||
//
|
||||
// To avoid an extra iteration, we just pull out the property
|
||||
// during the early iteration and cascade them in order
|
||||
// after it.
|
||||
if let Some(declaration) = font_family {
|
||||
let discriminant = LonghandId::FontFamily as usize;
|
||||
(CASCADE_PROPERTY[discriminant])(declaration,
|
||||
inherited_style,
|
||||
default_style,
|
||||
&mut context,
|
||||
&mut cacheable,
|
||||
&mut cascade_info,
|
||||
error_reporter);
|
||||
}
|
||||
if let Some(declaration) = font_size {
|
||||
let discriminant = LonghandId::FontSize as usize;
|
||||
(CASCADE_PROPERTY[discriminant])(declaration,
|
||||
inherited_style,
|
||||
default_style,
|
||||
&mut context,
|
||||
&mut cacheable,
|
||||
&mut cascade_info,
|
||||
error_reporter);
|
||||
} else if let Some(kw) = inherited_style.font_size_keyword {
|
||||
// Font size keywords will inherit as keywords and be recomputed
|
||||
// each time.
|
||||
let discriminant = LonghandId::FontSize as usize;
|
||||
let size = PropertyDeclaration::FontSize(
|
||||
longhands::font_size::SpecifiedValue::Keyword(kw)
|
||||
);
|
||||
(CASCADE_PROPERTY[discriminant])(&size,
|
||||
inherited_style,
|
||||
default_style,
|
||||
&mut context,
|
||||
&mut cacheable,
|
||||
&mut cascade_info,
|
||||
error_reporter);
|
||||
}
|
||||
% endif
|
||||
% endfor
|
||||
|
||||
|
|
|
@ -33,6 +33,14 @@ const AU_PER_Q: CSSFloat = AU_PER_MM / 4.;
|
|||
const AU_PER_PT: CSSFloat = AU_PER_IN / 72.;
|
||||
const AU_PER_PC: CSSFloat = AU_PER_PT * 12.;
|
||||
|
||||
/// Same as Gecko's AppUnitsToIntCSSPixels
|
||||
///
|
||||
/// Converts app units to integer pixel values,
|
||||
/// rounding during the conversion
|
||||
pub fn au_to_int_px(au: f32) -> i32 {
|
||||
(au / AU_PER_PX).round() as i32
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
/// A font relative length.
|
||||
|
|
Загрузка…
Ссылка в новой задаче