mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Auto merge of #16539 - Manishearth:stylo-scriptminsize, r=heycam
stylo: Properly support -moz-script-size-multiplier, -moz-script-level, and -moz-script-min-size r=heycam https://bugzilla.mozilla.org/show_bug.cgi?id=1355427 (copying over the relevant commit message so that it doesn't get lost in the vcssync) scriptlevel is a property that affects how font-size is inherited. If scriptlevel is +1, for example, it will inherit as the script size multiplier times the parent font. This does not affect cases where the font-size is explicitly set. However, this transformation is not allowed to reduce the size below scriptminsize. If this inheritance will reduce it to below scriptminsize, it will be set to scriptminsize or the parent size, whichever is smaller (the parent size could be smaller than the min size because it was explicitly specified). Now, within a node that has inherited a font-size which was crossing scriptminsize once the scriptlevel was applied, a negative scriptlevel may be used to increase the size again. This should work, however if we have already been capped by the scriptminsize multiple times, this can lead to a jump in the size. For example, if we have text of the form: huge large medium small tiny reallytiny tiny small medium huge which is represented by progressive nesting and scriptlevel values of +1 till the center after which the scriptlevel is -1, the "tiny"s should be the same size, as should be the "small"s and "medium"s, etc. However, if scriptminsize kicked it at around "medium", then medium/tiny/reallytiny will all be the same size (the min size). A -1 scriptlevel change after this will increase the min size by the multiplier, making the second tiny larger than medium. Instead, we wish for the second "tiny" to still be capped by the script level, and when we reach the second "large", it should be the same size as the original one. We do this by cascading two separate font sizes. The font size (mSize) is the actual displayed font size. The unconstrained font size (mScriptUnconstrainedSize) is the font size in the situation where scriptminsize never applied. We calculate the proposed inherited font size based on scriptlevel and the parent unconstrained size, instead of using the parent font size. This is stored in the node's unconstrained size and will also be stored in the font size provided that it is above the min size. All of this only applies when inheriting. When the font size is manually set, scriptminsize does not apply, and both the real and unconstrained size are set to the explicit value. However, if the font size is manually set to an em or percent unit, the unconstrained size will be set to the value of that unit computed against the parent unconstrained size, whereas the font size will be set computing against the parent font size. <!-- 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/16539) <!-- Reviewable:end -->
This commit is contained in:
commit
7919e591a4
6 changed files with 332 additions and 87 deletions
|
@ -1352,11 +1352,170 @@ fn static_assert() {
|
|||
pub fn set_font_size(&mut self, v: longhands::font_size::computed_value::T) {
|
||||
self.gecko.mFont.size = v.0;
|
||||
self.gecko.mSize = v.0;
|
||||
self.gecko.mScriptUnconstrainedSize = v.0;
|
||||
}
|
||||
pub fn copy_font_size_from(&mut self, other: &Self) {
|
||||
self.gecko.mFont.size = other.gecko.mFont.size;
|
||||
self.gecko.mSize = other.gecko.mSize;
|
||||
|
||||
/// Set font size, taking into account scriptminsize and scriptlevel
|
||||
/// Returns Some(size) if we have to recompute the script unconstrained size
|
||||
pub fn apply_font_size(&mut self, v: longhands::font_size::computed_value::T,
|
||||
parent: &Self) -> Option<Au> {
|
||||
let (adjusted_size, adjusted_unconstrained_size)
|
||||
= self.calculate_script_level_size(parent);
|
||||
// In this case, we have been unaffected by scriptminsize, ignore it
|
||||
if parent.gecko.mSize == parent.gecko.mScriptUnconstrainedSize &&
|
||||
adjusted_size == adjusted_unconstrained_size {
|
||||
self.set_font_size(v);
|
||||
None
|
||||
} else {
|
||||
self.gecko.mFont.size = v.0;
|
||||
self.gecko.mSize = v.0;
|
||||
Some(Au(parent.gecko.mScriptUnconstrainedSize))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn apply_unconstrained_font_size(&mut self, v: Au) {
|
||||
self.gecko.mScriptUnconstrainedSize = v.0;
|
||||
}
|
||||
|
||||
/// Calculates the constrained and unconstrained font sizes to be inherited
|
||||
/// from the parent.
|
||||
///
|
||||
/// See ComputeScriptLevelSize in Gecko's nsRuleNode.cpp
|
||||
///
|
||||
/// scriptlevel is a property that affects how font-size is inherited. If scriptlevel is
|
||||
/// +1, for example, it will inherit as the script size multiplier times
|
||||
/// the parent font. This does not affect cases where the font-size is
|
||||
/// explicitly set.
|
||||
///
|
||||
/// However, this transformation is not allowed to reduce the size below
|
||||
/// scriptminsize. If this inheritance will reduce it to below
|
||||
/// scriptminsize, it will be set to scriptminsize or the parent size,
|
||||
/// whichever is smaller (the parent size could be smaller than the min size
|
||||
/// because it was explicitly specified).
|
||||
///
|
||||
/// Now, within a node that has inherited a font-size which was
|
||||
/// crossing scriptminsize once the scriptlevel was applied, a negative
|
||||
/// scriptlevel may be used to increase the size again.
|
||||
///
|
||||
/// This should work, however if we have already been capped by the
|
||||
/// scriptminsize multiple times, this can lead to a jump in the size.
|
||||
///
|
||||
/// For example, if we have text of the form:
|
||||
///
|
||||
/// huge large medium small tiny reallytiny tiny small medium huge
|
||||
///
|
||||
/// which is represented by progressive nesting and scriptlevel values of
|
||||
/// +1 till the center after which the scriptlevel is -1, the "tiny"s should
|
||||
/// be the same size, as should be the "small"s and "medium"s, etc.
|
||||
///
|
||||
/// However, if scriptminsize kicked it at around "medium", then
|
||||
/// medium/tiny/reallytiny will all be the same size (the min size).
|
||||
/// A -1 scriptlevel change after this will increase the min size by the
|
||||
/// multiplier, making the second tiny larger than medium.
|
||||
///
|
||||
/// Instead, we wish for the second "tiny" to still be capped by the script
|
||||
/// level, and when we reach the second "large", it should be the same size
|
||||
/// as the original one.
|
||||
///
|
||||
/// We do this by cascading two separate font sizes. The font size (mSize)
|
||||
/// is the actual displayed font size. The unconstrained font size
|
||||
/// (mScriptUnconstrainedSize) is the font size in the situation where
|
||||
/// scriptminsize never applied.
|
||||
///
|
||||
/// We calculate the proposed inherited font size based on scriptlevel and
|
||||
/// the parent unconstrained size, instead of using the parent font size.
|
||||
/// This is stored in the node's unconstrained size and will also be stored
|
||||
/// in the font size provided that it is above the min size.
|
||||
///
|
||||
/// All of this only applies when inheriting. When the font size is
|
||||
/// manually set, scriptminsize does not apply, and both the real and
|
||||
/// unconstrained size are set to the explicit value. However, if the font
|
||||
/// size is manually set to an em or percent unit, the unconstrained size
|
||||
/// will be set to the value of that unit computed against the parent
|
||||
/// unconstrained size, whereas the font size will be set computing against
|
||||
/// the parent font size.
|
||||
pub fn calculate_script_level_size(&self, parent: &Self) -> (Au, Au) {
|
||||
use std::cmp;
|
||||
|
||||
let delta = self.gecko.mScriptLevel - parent.gecko.mScriptLevel;
|
||||
|
||||
let parent_size = Au(parent.gecko.mSize);
|
||||
let parent_unconstrained_size = Au(parent.gecko.mScriptUnconstrainedSize);
|
||||
|
||||
if delta == 0 {
|
||||
return (parent_size, parent_unconstrained_size)
|
||||
}
|
||||
|
||||
/// XXXManishearth this should also handle text zoom
|
||||
let min = Au(parent.gecko.mScriptMinSize);
|
||||
|
||||
let scale = (parent.gecko.mScriptSizeMultiplier as f32).powi(delta as i32);
|
||||
|
||||
let new_size = parent_size.scale_by(scale);
|
||||
let new_unconstrained_size = parent_unconstrained_size.scale_by(scale);
|
||||
|
||||
if scale < 1. {
|
||||
// The parent size can be smaller than scriptminsize,
|
||||
// e.g. if it was specified explicitly. Don't scale
|
||||
// in this case, but we don't want to set it to scriptminsize
|
||||
// either since that will make it larger.
|
||||
if parent_size < min {
|
||||
(parent_size, new_unconstrained_size)
|
||||
} else {
|
||||
(cmp::max(min, new_size), new_unconstrained_size)
|
||||
}
|
||||
} else {
|
||||
// If the new unconstrained size is larger than the min size,
|
||||
// this means we have escaped the grasp of scriptminsize
|
||||
// and can revert to using the unconstrained size.
|
||||
// However, if the new size is even larger (perhaps due to usage
|
||||
// of em units), use that instead.
|
||||
(cmp::min(new_size, cmp::max(new_unconstrained_size, min)),
|
||||
new_unconstrained_size)
|
||||
}
|
||||
}
|
||||
|
||||
/// This function will also handle scriptminsize and scriptlevel
|
||||
/// so should not be called when you just want the font sizes to be copied.
|
||||
/// Hence the different name.
|
||||
pub fn inherit_font_size_from(&mut self, parent: &Self,
|
||||
kw_inherited_size: Option<Au>) {
|
||||
let (adjusted_size, adjusted_unconstrained_size)
|
||||
= self.calculate_script_level_size(parent);
|
||||
if adjusted_size.0 != parent.gecko.mSize ||
|
||||
adjusted_unconstrained_size.0 != parent.gecko.mScriptUnconstrainedSize {
|
||||
// This is incorrect. When there is both a keyword size being inherited
|
||||
// and a scriptlevel change, we must handle the keyword size the same
|
||||
// way we handle em units. This complicates things because we now have
|
||||
// to keep track of the adjusted and unadjusted ratios in the kw font size.
|
||||
// This only affects the use case of a generic font being used in MathML.
|
||||
//
|
||||
// If we were to fix this I would prefer doing it by removing the
|
||||
// ruletree walk on the Gecko side in nsRuleNode::SetGenericFont
|
||||
// and instead using extra bookkeeping in the mSize and mScriptUnconstrainedSize
|
||||
// values, and reusing those instead of font_size_keyword.
|
||||
|
||||
|
||||
// In the case that MathML has given us an adjusted size, apply it.
|
||||
// Keep track of the unconstrained adjusted size.
|
||||
self.gecko.mFont.size = adjusted_size.0;
|
||||
self.gecko.mSize = adjusted_size.0;
|
||||
self.gecko.mScriptUnconstrainedSize = adjusted_unconstrained_size.0;
|
||||
} else if let Some(size) = kw_inherited_size {
|
||||
// Parent element was a keyword-derived size.
|
||||
self.gecko.mFont.size = size.0;
|
||||
self.gecko.mSize = size.0;
|
||||
// MathML constraints didn't apply here, so we can ignore this.
|
||||
self.gecko.mScriptUnconstrainedSize = size.0;
|
||||
} else {
|
||||
// MathML isn't affecting us, and our parent element does not
|
||||
// have a keyword-derived size. Set things normally.
|
||||
self.gecko.mFont.size = parent.gecko.mFont.size;
|
||||
self.gecko.mSize = parent.gecko.mSize;
|
||||
self.gecko.mScriptUnconstrainedSize = parent.gecko.mScriptUnconstrainedSize;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clone_font_size(&self) -> longhands::font_size::computed_value::T {
|
||||
Au(self.gecko.mSize)
|
||||
}
|
||||
|
|
|
@ -267,31 +267,18 @@
|
|||
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, fraction)
|
||||
= **specified_value {
|
||||
context.mutate_style().font_size_keyword = Some((kw, fraction));
|
||||
} else if let Some(ratio) = specified_value.as_font_ratio() {
|
||||
// In case a font-size-relative value was applied to a keyword
|
||||
// value, we must preserve this fact in case the generic font family
|
||||
// changes. relative values (em and %) applied to keywords must be
|
||||
// recomputed from the base size for the keyword and the relative size.
|
||||
//
|
||||
// See bug 1355707
|
||||
if let Some((kw, fraction)) = context.inherited_style().font_size_keyword {
|
||||
context.mutate_style().font_size_keyword = Some((kw, fraction * ratio));
|
||||
} else {
|
||||
context.mutate_style().font_size_keyword = None;
|
||||
}
|
||||
} 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});
|
||||
longhands::font_size::cascade_specified_font_size(context,
|
||||
specified_value,
|
||||
computed,
|
||||
inherited_style.get_font());
|
||||
% else:
|
||||
context.mutate_style().mutate_${data.current_style_struct.name_lower}()
|
||||
.set_${property.ident}(computed ${maybe_wm});
|
||||
% if property.has_uncacheable_values:
|
||||
context.mutate_style().mutate_${data.current_style_struct.name_lower}()
|
||||
.set_${property.ident}(computed, cacheable ${maybe_wm});
|
||||
% else:
|
||||
context.mutate_style().mutate_${data.current_style_struct.name_lower}()
|
||||
.set_${property.ident}(computed ${maybe_wm});
|
||||
% endif
|
||||
% endif
|
||||
}
|
||||
DeclaredValue::WithVariables(_) => unreachable!(),
|
||||
|
@ -301,13 +288,7 @@
|
|||
% endif
|
||||
CSSWideKeyword::Initial => {
|
||||
% 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(), 1.));
|
||||
longhands::font_size::cascade_initial_font_size(context);
|
||||
% else:
|
||||
// We assume that it's faster to use copy_*_from rather than
|
||||
// set_*(get_initial_value());
|
||||
|
@ -328,11 +309,12 @@
|
|||
*cacheable = false;
|
||||
let inherited_struct =
|
||||
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;
|
||||
longhands::font_size::cascade_inherit_font_size(context, inherited_struct);
|
||||
% else:
|
||||
context.mutate_style().mutate_${data.current_style_struct.name_lower}()
|
||||
.copy_${property.ident}_from(inherited_struct ${maybe_wm});
|
||||
% endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -413,11 +413,13 @@ ${helpers.single_keyword("font-variant-caps",
|
|||
<%helpers:longhand name="font-size" need_clone="True" animation_type="normal"
|
||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-size">
|
||||
use app_units::Au;
|
||||
use properties::style_structs::Font;
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use values::{FONT_MEDIUM_PX, HasViewportPercentage};
|
||||
use values::specified::{FontRelativeLength, LengthOrPercentage, Length};
|
||||
use values::specified::{NoCalcLength, Percentage};
|
||||
use values::specified::length::FontBaseSize;
|
||||
|
||||
impl ToCss for SpecifiedValue {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
|
@ -627,6 +629,43 @@ ${helpers.single_keyword("font-variant-caps",
|
|||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Compute it against a given base font size
|
||||
pub fn to_computed_value_against(&self, context: &Context, base_size: FontBaseSize) -> Au {
|
||||
use values::specified::length::FontRelativeLength;
|
||||
match *self {
|
||||
SpecifiedValue::Length(LengthOrPercentage::Length(
|
||||
NoCalcLength::FontRelative(value))) => {
|
||||
value.to_computed_value(context, base_size)
|
||||
}
|
||||
SpecifiedValue::Length(LengthOrPercentage::Length(
|
||||
NoCalcLength::ServoCharacterWidth(value))) => {
|
||||
value.to_computed_value(base_size.resolve(context))
|
||||
}
|
||||
SpecifiedValue::Length(LengthOrPercentage::Length(ref l)) => {
|
||||
l.to_computed_value(context)
|
||||
}
|
||||
SpecifiedValue::Length(LengthOrPercentage::Percentage(Percentage(value))) => {
|
||||
base_size.resolve(context).scale_by(value)
|
||||
}
|
||||
SpecifiedValue::Length(LengthOrPercentage::Calc(ref calc)) => {
|
||||
let calc = calc.to_computed_value(context);
|
||||
calc.length() + base_size.resolve(context)
|
||||
.scale_by(calc.percentage())
|
||||
}
|
||||
SpecifiedValue::Keyword(ref key, fraction) => {
|
||||
key.to_computed_value(context).scale_by(fraction)
|
||||
}
|
||||
SpecifiedValue::Smaller => {
|
||||
FontRelativeLength::Em(0.85)
|
||||
.to_computed_value(context, base_size)
|
||||
}
|
||||
SpecifiedValue::Larger => {
|
||||
FontRelativeLength::Em(1.2)
|
||||
.to_computed_value(context, base_size)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -640,44 +679,13 @@ ${helpers.single_keyword("font-variant-caps",
|
|||
SpecifiedValue::Keyword(Medium, 1.)
|
||||
}
|
||||
|
||||
|
||||
impl ToComputedValue for SpecifiedValue {
|
||||
type ComputedValue = computed_value::T;
|
||||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
||||
use values::specified::length::FontRelativeLength;
|
||||
match *self {
|
||||
SpecifiedValue::Length(LengthOrPercentage::Length(
|
||||
NoCalcLength::FontRelative(value))) => {
|
||||
value.to_computed_value(context, /* use inherited */ true)
|
||||
}
|
||||
SpecifiedValue::Length(LengthOrPercentage::Length(
|
||||
NoCalcLength::ServoCharacterWidth(value))) => {
|
||||
value.to_computed_value(context.inherited_style().get_font().clone_font_size())
|
||||
}
|
||||
SpecifiedValue::Length(LengthOrPercentage::Length(ref l)) => {
|
||||
l.to_computed_value(context)
|
||||
}
|
||||
SpecifiedValue::Length(LengthOrPercentage::Percentage(Percentage(value))) => {
|
||||
context.inherited_style().get_font().clone_font_size().scale_by(value)
|
||||
}
|
||||
SpecifiedValue::Length(LengthOrPercentage::Calc(ref calc)) => {
|
||||
let calc = calc.to_computed_value(context);
|
||||
calc.length() + context.inherited_style().get_font().clone_font_size()
|
||||
.scale_by(calc.percentage())
|
||||
}
|
||||
SpecifiedValue::Keyword(ref key, fraction) => {
|
||||
key.to_computed_value(context).scale_by(fraction)
|
||||
}
|
||||
SpecifiedValue::Smaller => {
|
||||
FontRelativeLength::Em(0.85).to_computed_value(context,
|
||||
/* use_inherited */ true)
|
||||
}
|
||||
SpecifiedValue::Larger => {
|
||||
FontRelativeLength::Em(1.2).to_computed_value(context,
|
||||
/* use_inherited */ true)
|
||||
}
|
||||
}
|
||||
self.to_computed_value_against(context, FontBaseSize::InheritedStyle)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -703,6 +711,66 @@ ${helpers.single_keyword("font-variant-caps",
|
|||
_ => Err(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cascade_specified_font_size(context: &mut Context,
|
||||
specified_value: &SpecifiedValue,
|
||||
computed: Au,
|
||||
parent: &Font) {
|
||||
if let SpecifiedValue::Keyword(kw, fraction)
|
||||
= *specified_value {
|
||||
context.mutate_style().font_size_keyword = Some((kw, fraction));
|
||||
} else if let Some(ratio) = specified_value.as_font_ratio() {
|
||||
// In case a font-size-relative value was applied to a keyword
|
||||
// value, we must preserve this fact in case the generic font family
|
||||
// changes. relative values (em and %) applied to keywords must be
|
||||
// recomputed from the base size for the keyword and the relative size.
|
||||
//
|
||||
// See bug 1355707
|
||||
if let Some((kw, fraction)) = context.inherited_style().font_size_keyword {
|
||||
context.mutate_style().font_size_keyword = Some((kw, fraction * ratio));
|
||||
} else {
|
||||
context.mutate_style().font_size_keyword = None;
|
||||
}
|
||||
} else {
|
||||
context.mutate_style().font_size_keyword = None;
|
||||
}
|
||||
|
||||
let parent_unconstrained = context.mutate_style()
|
||||
.mutate_font()
|
||||
.apply_font_size(computed,
|
||||
parent);
|
||||
|
||||
if let Some(parent) = parent_unconstrained {
|
||||
let new_unconstrained = specified_value
|
||||
.to_computed_value_against(context, FontBaseSize::Custom(parent));
|
||||
context.mutate_style()
|
||||
.mutate_font()
|
||||
.apply_unconstrained_font_size(new_unconstrained);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cascade_inherit_font_size(context: &mut Context, parent: &Font) {
|
||||
// If inheriting, we must recompute font-size in case of language changes
|
||||
// using the font_size_keyword. We also need to do this to handle
|
||||
// mathml scriptlevel changes
|
||||
let kw_inherited_size = context.style().font_size_keyword.map(|(kw, ratio)| {
|
||||
SpecifiedValue::Keyword(kw, ratio).to_computed_value(context)
|
||||
});
|
||||
context.mutate_style().mutate_font()
|
||||
.inherit_font_size_from(parent, kw_inherited_size);
|
||||
context.mutate_style().font_size_keyword =
|
||||
context.inherited_style.font_size_keyword;
|
||||
}
|
||||
|
||||
pub fn cascade_initial_font_size(context: &mut Context) {
|
||||
// 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(), 1.));
|
||||
}
|
||||
</%helpers:longhand>
|
||||
|
||||
<%helpers:longhand products="gecko" name="font-size-adjust" animation_type="normal"
|
||||
|
|
|
@ -1429,6 +1429,7 @@ pub use gecko_properties::style_structs;
|
|||
/// The module where all the style structs are defined.
|
||||
#[cfg(feature = "servo")]
|
||||
pub mod style_structs {
|
||||
use app_units::Au;
|
||||
use fnv::FnvHasher;
|
||||
use super::longhands;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
@ -1526,6 +1527,23 @@ pub mod style_structs {
|
|||
self.font_family.hash(&mut hasher);
|
||||
self.hash = hasher.finish()
|
||||
}
|
||||
|
||||
/// (Servo does not handle MathML, so this just calls copy_font_size_from)
|
||||
pub fn inherit_font_size_from(&mut self, parent: &Self,
|
||||
_: Option<Au>) {
|
||||
self.copy_font_size_from(parent);
|
||||
}
|
||||
/// (Servo does not handle MathML, so this just calls set_font_size)
|
||||
pub fn apply_font_size(&mut self,
|
||||
v: longhands::font_size::computed_value::T,
|
||||
_: &Self) -> Option<Au> {
|
||||
self.set_font_size(v);
|
||||
None
|
||||
}
|
||||
/// (Servo does not handle MathML, so this does nothing)
|
||||
pub fn apply_unconstrained_font_size(&mut self, _: Au) {
|
||||
}
|
||||
|
||||
% elif style_struct.name == "Outline":
|
||||
/// Whether the outline-width property is non-zero.
|
||||
#[inline]
|
||||
|
@ -2229,6 +2247,7 @@ pub fn apply_declarations<'a, F, I>(device: &Device,
|
|||
| LonghandId::AnimationName
|
||||
| LonghandId::TransitionProperty
|
||||
| LonghandId::XLang
|
||||
| LonghandId::MozScriptLevel
|
||||
% endif
|
||||
);
|
||||
if
|
||||
|
@ -2300,12 +2319,12 @@ pub fn apply_declarations<'a, F, I>(device: &Device,
|
|||
&mut cacheable,
|
||||
&mut cascade_info,
|
||||
error_reporter);
|
||||
} else if let Some((kw, fraction)) = inherited_style.font_size_keyword {
|
||||
// Font size keywords will inherit as keywords and be recomputed
|
||||
// each time.
|
||||
} else {
|
||||
// Font size must be explicitly inherited to handle keyword
|
||||
// sizes and scriptlevel
|
||||
let discriminant = LonghandId::FontSize as usize;
|
||||
let size = PropertyDeclaration::FontSize(
|
||||
longhands::font_size::SpecifiedValue::Keyword(kw, fraction)
|
||||
let size = PropertyDeclaration::CSSWideKeyword(
|
||||
LonghandId::FontSize, CSSWideKeyword::Inherit
|
||||
);
|
||||
(CASCADE_PROPERTY[discriminant])(&size,
|
||||
inherited_style,
|
||||
|
|
|
@ -10,7 +10,7 @@ use std::fmt;
|
|||
use style_traits::ToCss;
|
||||
use super::{Number, ToComputedValue, Context};
|
||||
use values::{Auto, CSSFloat, Either, ExtremumLength, None_, Normal, specified};
|
||||
use values::specified::length::{AbsoluteLength, FontRelativeLength, ViewportPercentageLength};
|
||||
use values::specified::length::{AbsoluteLength, FontBaseSize, FontRelativeLength, ViewportPercentageLength};
|
||||
|
||||
pub use super::image::{EndingShape as GradientShape, Gradient, GradientKind, Image};
|
||||
pub use super::image::{LengthOrKeyword, LengthOrPercentageOrKeyword};
|
||||
|
@ -25,7 +25,7 @@ impl ToComputedValue for specified::NoCalcLength {
|
|||
specified::NoCalcLength::Absolute(length) =>
|
||||
length.to_computed_value(context),
|
||||
specified::NoCalcLength::FontRelative(length) =>
|
||||
length.to_computed_value(context, /* use inherited */ false),
|
||||
length.to_computed_value(context, FontBaseSize::CurrentStyle),
|
||||
specified::NoCalcLength::ViewportPercentage(length) =>
|
||||
length.to_computed_value(context.viewport_size()),
|
||||
specified::NoCalcLength::ServoCharacterWidth(length) =>
|
||||
|
@ -159,7 +159,7 @@ impl ToComputedValue for specified::CalcLengthOrPercentage {
|
|||
self.ex.map(FontRelativeLength::Ex),
|
||||
self.rem.map(FontRelativeLength::Rem)] {
|
||||
if let Some(val) = *val {
|
||||
length += val.to_computed_value(context, /* use inherited */ false);
|
||||
length += val.to_computed_value(context, FontBaseSize::CurrentStyle);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -76,10 +76,31 @@ impl ToCss for FontRelativeLength {
|
|||
}
|
||||
}
|
||||
|
||||
/// A source to resolve font-relative units against
|
||||
pub enum FontBaseSize {
|
||||
/// Use the font-size of the current element
|
||||
CurrentStyle,
|
||||
/// Use the inherited font-size
|
||||
InheritedStyle,
|
||||
/// Use a custom base size
|
||||
Custom(Au),
|
||||
}
|
||||
|
||||
impl FontBaseSize {
|
||||
/// Calculate the actual size for a given context
|
||||
pub fn resolve(&self, context: &Context) -> Au {
|
||||
match *self {
|
||||
FontBaseSize::Custom(size) => size,
|
||||
FontBaseSize::CurrentStyle => context.style().get_font().clone_font_size(),
|
||||
FontBaseSize::InheritedStyle => context.inherited_style().get_font().clone_font_size(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FontRelativeLength {
|
||||
/// Computes the font-relative length. We use the use_inherited flag to
|
||||
/// special-case the computation of font-size.
|
||||
pub fn to_computed_value(&self, context: &Context, use_inherited: bool) -> Au {
|
||||
/// Computes the font-relative length. We use the base_size
|
||||
/// flag to pass a different size for computing font-size and unconstrained font-size
|
||||
pub fn to_computed_value(&self, context: &Context, base_size: FontBaseSize) -> Au {
|
||||
fn query_font_metrics(context: &Context, reference_font_size: Au) -> FontMetricsQueryResult {
|
||||
context.font_metrics_provider.query(context.style().get_font(),
|
||||
reference_font_size,
|
||||
|
@ -88,11 +109,7 @@ impl FontRelativeLength {
|
|||
context.device)
|
||||
}
|
||||
|
||||
let reference_font_size = if use_inherited {
|
||||
context.inherited_style().get_font().clone_font_size()
|
||||
} else {
|
||||
context.style().get_font().clone_font_size()
|
||||
};
|
||||
let reference_font_size = base_size.resolve(context);
|
||||
|
||||
let root_font_size = context.style().root_font_size;
|
||||
match *self {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue