Bug 1358688 - Part 5: stylo: Disable text-zoom for <svg:text>; r?emilio
MozReview-Commit-ID: C1j2exsPigE
--- a/servo/components/style/gecko/media_queries.rs
+++ b/servo/components/style/gecko/media_queries.rs
@@ -186,16 +186,20 @@ impl Device {
pub fn default_background_color(&self) -> RGBA {
convert_nscolor_to_rgba(self.pres_context().mBackgroundColor)
}
/// Applies text zoom to a font-size or line-height value (see nsStyleFont::ZoomText).
pub fn zoom_text(&self, size: Au) -> Au {
size.scale_by(self.pres_context().mEffectiveTextZoom)
}
+ /// Un-apply text zoom (see nsStyleFont::UnzoomText).
+ pub fn unzoom_text(&self, size: Au) -> Au {
+ size.scale_by(1. / self.pres_context().mEffectiveTextZoom)
+ }
}
/// A expression for gecko contains a reference to the media feature, the value
/// the media query contained, and the range to evaluate.
#[derive(Debug, Clone)]
pub struct Expression {
feature: &'static nsMediaFeature,
value: Option<MediaExpressionValue>,
--- a/servo/components/style/gecko/wrapper.rs
+++ b/servo/components/style/gecko/wrapper.rs
@@ -1404,16 +1404,17 @@ impl<'le> PresentationalHintsSynthesizer
fn synthesize_presentational_hints_for_legacy_attributes<V>(&self,
visited_handling: VisitedHandlingMode,
hints: &mut V)
where V: Push<ApplicableDeclarationBlock>,
{
use properties::longhands::_x_lang::SpecifiedValue as SpecifiedLang;
use properties::longhands::color::SpecifiedValue as SpecifiedColor;
use properties::longhands::text_align::SpecifiedValue as SpecifiedTextAlign;
+ use properties::longhands::_x_text_zoom::SpecifiedValue as SpecifiedZoom;
use values::specified::color::Color;
lazy_static! {
static ref TH_RULE: ApplicableDeclarationBlock = {
let global_style_data = &*GLOBAL_STYLE_DATA;
let pdb = PropertyDeclarationBlock::with_one(
PropertyDeclaration::TextAlign(SpecifiedTextAlign::MozCenterOrInherit),
Importance::Normal
);
@@ -1433,28 +1434,42 @@ impl<'le> PresentationalHintsSynthesizer
let global_style_data = &*GLOBAL_STYLE_DATA;
let pdb = PropertyDeclarationBlock::with_one(
PropertyDeclaration::XLang(SpecifiedLang(atom!("x-math"))),
Importance::Normal
);
let arc = Arc::new(global_style_data.shared_lock.wrap(pdb));
ApplicableDeclarationBlock::from_declarations(arc, ServoCascadeLevel::PresHints)
};
+ static ref SVG_TEXT_DISABLE_ZOOM_RULE: ApplicableDeclarationBlock = {
+ let global_style_data = &*GLOBAL_STYLE_DATA;
+ let pdb = PropertyDeclarationBlock::with_one(
+ PropertyDeclaration::XTextZoom(SpecifiedZoom(false)),
+ Importance::Normal
+ );
+ let arc = Arc::new(global_style_data.shared_lock.wrap(pdb));
+ ApplicableDeclarationBlock::from_declarations(arc, ServoCascadeLevel::PresHints)
+ };
};
let ns = self.get_namespace();
// <th> elements get a default MozCenterOrInherit which may get overridden
if ns == &*Namespace(atom!("http://www.w3.org/1999/xhtml")) {
if self.get_local_name().as_ptr() == atom!("th").as_ptr() {
hints.push(TH_RULE.clone());
} else if self.get_local_name().as_ptr() == atom!("table").as_ptr() &&
self.as_node().owner_doc().mCompatMode == structs::nsCompatibility::eCompatibility_NavQuirks {
hints.push(TABLE_COLOR_RULE.clone());
}
}
+ if ns == &*Namespace(atom!("http://www.w3.org/2000/svg")) {
+ if self.get_local_name().as_ptr() == atom!("text").as_ptr() {
+ hints.push(SVG_TEXT_DISABLE_ZOOM_RULE.clone());
+ }
+ }
let declarations = unsafe { Gecko_GetHTMLPresentationAttrDeclarationBlock(self.0) };
let declarations: Option<&RawOffsetArc<Locked<PropertyDeclarationBlock>>> =
declarations.and_then(|s| s.as_arc_opt());
if let Some(decl) = declarations {
hints.push(
ApplicableDeclarationBlock::from_declarations(decl.clone_arc(), ServoCascadeLevel::PresHints)
);
}
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -2052,17 +2052,17 @@ fn static_assert() {
</%self:impl_trait>
<%
skip_font_longhands = """font-family font-size font-size-adjust font-weight
font-synthesis -x-lang font-variant-alternates
font-variant-east-asian font-variant-ligatures
font-variant-numeric font-language-override
font-feature-settings font-variation-settings
- -moz-min-font-size-ratio"""
+ -moz-min-font-size-ratio -x-text-zoom"""
%>
<%self:impl_trait style_struct_name="Font"
skip_longhands="${skip_font_longhands}"
skip_additionals="*">
pub fn set_font_feature_settings(&mut self, v: longhands::font_feature_settings::computed_value::T) {
use values::generics::FontSettings;
@@ -2226,16 +2226,22 @@ fn static_assert() {
quoted: true
}),
x => panic!("Found unexpected font FontFamilyType: {:?}", x),
}
}).collect()
)
}
+ pub fn unzoom_fonts(&mut self, device: &Device) {
+ self.gecko.mSize = device.unzoom_text(Au(self.gecko.mSize)).0;
+ self.gecko.mScriptUnconstrainedSize = device.unzoom_text(Au(self.gecko.mScriptUnconstrainedSize)).0;
+ self.gecko.mFont.size = device.unzoom_text(Au(self.gecko.mFont.size)).0;
+ }
+
pub fn set_font_size(&mut self, v: longhands::font_size::computed_value::T) {
self.gecko.mSize = v.0;
self.gecko.mScriptUnconstrainedSize = v.0;
}
/// 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,
@@ -2461,16 +2467,26 @@ fn static_assert() {
#[allow(non_snake_case)]
pub fn copy__x_lang_from(&mut self, other: &Self) {
unsafe {
Gecko_nsStyleFont_CopyLangFrom(&mut self.gecko, &other.gecko);
}
}
#[allow(non_snake_case)]
+ pub fn set__x_text_zoom(&mut self, v: longhands::_x_text_zoom::computed_value::T) {
+ self.gecko.mAllowZoom = v.0;
+ }
+
+ #[allow(non_snake_case)]
+ pub fn copy__x_text_zoom_from(&mut self, other: &Self) {
+ self.gecko.mAllowZoom = other.gecko.mAllowZoom;
+ }
+
+ #[allow(non_snake_case)]
pub fn reset__x_lang(&mut self, other: &Self) {
self.copy__x_lang_from(other)
}
<% 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) {
use gecko_bindings::bindings::{Gecko_ClearAlternateValues, Gecko_AppendAlternateValues};
--- a/servo/components/style/properties/longhand/font.mako.rs
+++ b/servo/components/style/properties/longhand/font.mako.rs
@@ -2378,16 +2378,51 @@ https://drafts.csswg.org/css-fonts-4/#lo
pub fn parse<'i, 't>(_context: &ParserContext, _input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
debug_assert!(false, "Should be set directly by presentation attributes only.");
Err(StyleParseError::UnspecifiedError.into())
}
</%helpers:longhand>
+<%helpers:longhand name="-x-text-zoom" products="gecko" animation_value_type="none" internal="True"
+ spec="Internal (not web-exposed)">
+ use values::computed::ComputedValueAsSpecified;
+ pub use self::computed_value::T as SpecifiedValue;
+
+ impl ComputedValueAsSpecified for SpecifiedValue {}
+ no_viewport_percentage!(SpecifiedValue);
+
+ pub mod computed_value {
+ use std::fmt;
+ use style_traits::ToCss;
+
+ impl ToCss for T {
+ fn to_css<W>(&self, _: &mut W) -> fmt::Result where W: fmt::Write {
+ Ok(())
+ }
+ }
+
+ #[derive(Clone, Debug, PartialEq)]
+ #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+ /// text-zoom. Enable if true, disable if false
+ pub struct T(pub bool);
+ }
+
+ #[inline]
+ pub fn get_initial_value() -> computed_value::T {
+ computed_value::T(true)
+ }
+
+ pub fn parse<'i, 't>(_context: &ParserContext, _input: &mut Parser<'i, 't>)
+ -> Result<SpecifiedValue, ParseError<'i>> {
+ debug_assert!(false, "Should be set directly by presentation attributes only.");
+ Err(StyleParseError::UnspecifiedError.into())
+ }
+</%helpers:longhand>
% if product == "gecko":
pub mod system_font {
//! We deal with system fonts here
//!
//! System fonts can only be set as a group via the font shorthand.
//! They resolve at compute time (not parse time -- this lets the
//! browser respond to changes to the OS font settings).
--- a/servo/components/style/properties/properties.mako.rs
+++ b/servo/components/style/properties/properties.mako.rs
@@ -603,16 +603,17 @@ impl LonghandId {
/// correct.
fn is_early_property(&self) -> bool {
matches!(*self,
% if product == 'gecko':
LonghandId::TextOrientation |
LonghandId::AnimationName |
LonghandId::TransitionProperty |
LonghandId::XLang |
+ LonghandId::XTextZoom |
LonghandId::MozScriptLevel |
LonghandId::MozMinFontSizeRatio |
% endif
LonghandId::FontSize |
LonghandId::FontFamily |
LonghandId::Color |
LonghandId::TextDecorationLine |
LonghandId::WritingMode |
@@ -3202,16 +3203,33 @@ where
}
% if category_to_cascade_now == "early":
let writing_mode = get_writing_mode(context.builder.get_inheritedbox());
context.builder.writing_mode = writing_mode;
let mut _skip_font_family = false;
% if product == "gecko":
+
+ // <svg:text> is not affected by text zoom, and it uses a preshint to
+ // disable it. We fix up the struct when this happens by unzooming
+ // its contained font values, which will have been zoomed in the parent
+ if seen.contains(LonghandId::XTextZoom) {
+ let zoom = context.builder.get_font().gecko().mAllowZoom;
+ let parent_zoom = context.style().get_parent_font().gecko().mAllowZoom;
+ if zoom != parent_zoom {
+ debug_assert!(!zoom,
+ "We only ever disable text zoom (in svg:text), never enable it");
+ // can't borrow both device and font, use the take/put machinery
+ let mut font = context.builder.take_font();
+ font.unzoom_fonts(context.device());
+ context.builder.put_font(font);
+ }
+ }
+
// Whenever a single generic value is specified, gecko will do a bunch of
// recalculation walking up the rule tree, including handling the font-size stuff.
// It basically repopulates the font struct with the default font for a given
// generic and language. We handle the font-size stuff separately, so this boils
// down to just copying over the font-family lists (no other aspect of the default
// font can be configured).
if seen.contains(LonghandId::XLang) || font_family.is_some() {