diff options
-rw-r--r-- | components/layout/flow.rs | 2 | ||||
-rw-r--r-- | components/style/gecko/conversions.rs | 22 | ||||
-rw-r--r-- | components/style/properties/longhand/inherited_text.mako.rs | 165 | ||||
-rw-r--r-- | components/style/values/computed/mod.rs | 2 | ||||
-rw-r--r-- | components/style/values/computed/text.rs | 2 | ||||
-rw-r--r-- | components/style/values/specified/mod.rs | 3 | ||||
-rw-r--r-- | components/style/values/specified/text.rs | 171 |
7 files changed, 203 insertions, 164 deletions
diff --git a/components/layout/flow.rs b/components/layout/flow.rs index e4841bd2e0f..c706516933b 100644 --- a/components/layout/flow.rs +++ b/components/layout/flow.rs @@ -654,7 +654,7 @@ impl FlowFlags { #[inline] pub fn set_text_align(&mut self, value: TextAlign) { *self = (*self & !FlowFlags::TEXT_ALIGN) | - FlowFlags::from_bits(value.to_u32() << TEXT_ALIGN_SHIFT).unwrap(); + FlowFlags::from_bits((value as u32) << TEXT_ALIGN_SHIFT).unwrap(); } #[inline] diff --git a/components/style/gecko/conversions.rs b/components/style/gecko/conversions.rs index 6d082549dfc..2d0dc1adcef 100644 --- a/components/style/gecko/conversions.rs +++ b/components/style/gecko/conversions.rs @@ -18,7 +18,7 @@ use gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordData, CoordData use std::f32::consts::PI; use stylesheets::{Origin, RulesMutateError}; use values::computed::{Angle, CalcLengthOrPercentage, ComputedUrl, Gradient, Image}; -use values::computed::{Integer, LengthOrPercentage, LengthOrPercentageOrAuto, Percentage}; +use values::computed::{Integer, LengthOrPercentage, LengthOrPercentageOrAuto, Percentage, TextAlign}; use values::generics::box_::VerticalAlign; use values::generics::grid::{TrackListValue, TrackSize}; use values::generics::image::{CompatMode, Image as GenericImage, GradientItem}; @@ -995,6 +995,26 @@ impl<L> VerticalAlign<L> { } } +impl TextAlign { + /// Obtain a specified value from a Gecko keyword value + /// + /// Intended for use with presentation attributes, not style structs + pub fn from_gecko_keyword(kw: u32) -> Self { + match kw { + structs::NS_STYLE_TEXT_ALIGN_LEFT => TextAlign::Left, + structs::NS_STYLE_TEXT_ALIGN_RIGHT => TextAlign::Right, + structs::NS_STYLE_TEXT_ALIGN_CENTER => TextAlign::Center, + structs::NS_STYLE_TEXT_ALIGN_JUSTIFY => TextAlign::Justify, + structs::NS_STYLE_TEXT_ALIGN_MOZ_LEFT => TextAlign::MozLeft, + structs::NS_STYLE_TEXT_ALIGN_MOZ_RIGHT => TextAlign::MozRight, + structs::NS_STYLE_TEXT_ALIGN_MOZ_CENTER => TextAlign::MozCenter, + structs::NS_STYLE_TEXT_ALIGN_CHAR => TextAlign::Char, + structs::NS_STYLE_TEXT_ALIGN_END => TextAlign::End, + x => panic!("Found unexpected value in style struct for text-align property: {:?}", x), + } + } +} + /// Convert to String from given chars pointer. pub unsafe fn string_from_chars_pointer(p: *const u16) -> String { use std::slice; diff --git a/components/style/properties/longhand/inherited_text.mako.rs b/components/style/properties/longhand/inherited_text.mako.rs index ff8381e8794..830886a9569 100644 --- a/components/style/properties/longhand/inherited_text.mako.rs +++ b/components/style/properties/longhand/inherited_text.mako.rs @@ -111,165 +111,12 @@ ${helpers.single_keyword("text-align-last", // TODO make this a shorthand and implement text-align-last/text-align-all // // FIXME(emilio): This can't really be that complicated. -<%helpers:longhand name="text-align" animation_value_type="discrete" - flags="APPLIES_TO_PLACEHOLDER" - spec="https://drafts.csswg.org/css-text/#propdef-text-align"> - pub use self::computed_value::TextAlign; - - pub mod computed_value { - pub use self::TextAlign as T; - - macro_rules! define_text_align { - ( $( $name: ident ( $string: expr ) => $discriminant: expr, )+ ) => { - define_css_keyword_enum! { TextAlign: - $( - $string => $name, - )+ - } - - impl TextAlign { - pub fn to_u32(self) -> u32 { - match self { - $( - T::$name => $discriminant, - )+ - } - } - pub fn from_u32(discriminant: u32) -> Option<T> { - match discriminant { - $( - $discriminant => Some(T::$name), - )+ - _ => None - } - } - } - } - } - // FIXME(emilio): Why reinventing the world? - define_text_align! { - Start("start") => 0, - End("end") => 1, - Left("left") => 2, - Right("right") => 3, - Center("center") => 4, - Justify("justify") => 5, - % if product == "servo": - ServoCenter("-servo-center") => 6, - ServoLeft("-servo-left") => 7, - ServoRight("-servo-right") => 8, - % else: - MozCenter("-moz-center") => 6, - MozLeft("-moz-left") => 7, - MozRight("-moz-right") => 8, - Char("char") => 10, - % endif - } - - ${helpers.gecko_keyword_conversion(Keyword('text-align', - """left right center justify -moz-left -moz-right - -moz-center char end""", - gecko_strip_moz_prefix=False), type="T")} - } - - #[inline] pub fn get_initial_value() -> TextAlign { - TextAlign::Start - } - - - % if product == "gecko": - use std::fmt; - use style_traits::ToCss; - - #[cfg_attr(feature = "gecko", derive(MallocSizeOf))] - #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] - pub enum SpecifiedValue { - Keyword(TextAlign), - MatchParent, - MozCenterOrInherit, - } - pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) - -> Result<SpecifiedValue, ParseError<'i>> { - // MozCenterOrInherit cannot be parsed, only set directly on th elements - if let Ok(key) = input.try(TextAlign::parse) { - Ok(SpecifiedValue::Keyword(key)) - } else { - input.expect_ident_matching("match-parent")?; - Ok(SpecifiedValue::MatchParent) - } - } - impl ToCss for SpecifiedValue { - fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - match *self { - SpecifiedValue::Keyword(key) => key.to_css(dest), - SpecifiedValue::MatchParent => dest.write_str("match-parent"), - SpecifiedValue::MozCenterOrInherit => Ok(()), - } - } - } - - impl SpecifiedValue { - pub fn from_gecko_keyword(kw: u32) -> Self { - use gecko_bindings::structs::NS_STYLE_TEXT_ALIGN_MATCH_PARENT; - if kw == NS_STYLE_TEXT_ALIGN_MATCH_PARENT { - SpecifiedValue::MatchParent - } else { - SpecifiedValue::Keyword(computed_value::T::from_gecko_keyword(kw)) - } - } - } - impl ToComputedValue for SpecifiedValue { - type ComputedValue = TextAlign; - - #[inline] - fn to_computed_value(&self, context: &Context) -> TextAlign { - match *self { - SpecifiedValue::Keyword(key) => key, - SpecifiedValue::MatchParent => { - // on the root <html> element we should still respect the dir - // but the parent dir of that element is LTR even if it's <html dir=rtl> - // and will only be RTL if certain prefs have been set. - // In that case, the default behavior here will set it to left, - // but we want to set it to right -- instead set it to the default (`start`), - // which will do the right thing in this case (but not the general case) - if context.is_root_element { - return get_initial_value(); - } - let parent = context.builder.get_parent_inheritedtext().clone_text_align(); - let ltr = context.builder.inherited_writing_mode().is_bidi_ltr(); - match (parent, ltr) { - (TextAlign::Start, true) => TextAlign::Left, - (TextAlign::Start, false) => TextAlign::Right, - (TextAlign::End, true) => TextAlign::Right, - (TextAlign::End, false) => TextAlign::Left, - _ => parent - } - } - SpecifiedValue::MozCenterOrInherit => { - let parent = context.builder.get_parent_inheritedtext().clone_text_align(); - if parent == TextAlign::Start { - TextAlign::Center - } else { - parent - } - } - } - } - - #[inline] - fn from_computed_value(computed: &computed_value::T) -> Self { - SpecifiedValue::Keyword(*computed) - } - } - % else: - pub use self::computed_value::T as SpecifiedValue; - add_impls_for_keyword_enum!(SpecifiedValue); - pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) - -> Result<SpecifiedValue, ParseError<'i>> { - computed_value::T::parse(input) - } - % endif -</%helpers:longhand> +${helpers.predefined_type("text-align", + "TextAlign", + "computed::TextAlign::start()", + animation_value_type="discrete", + flags="APPLIES_TO_PLACEHOLDER", + spec="https://drafts.csswg.org/css-text/#propdef-text-align")} ${helpers.predefined_type("letter-spacing", "LetterSpacing", diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index b446aa6caa7..0be28319206 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -60,7 +60,7 @@ pub use self::percentage::Percentage; pub use self::position::{Position, GridAutoFlow, GridTemplateAreas}; pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind, SVGStrokeDashArray, SVGWidth}; pub use self::table::XSpan; -pub use self::text::{InitialLetter, LetterSpacing, LineHeight, TextOverflow, WordSpacing}; +pub use self::text::{InitialLetter, LetterSpacing, LineHeight, TextAlign, TextOverflow, WordSpacing}; pub use self::time::Time; pub use self::transform::{TimingFunction, Transform, TransformOperation, TransformOrigin}; pub use self::ui::MozForceBrokenImageIcon; diff --git a/components/style/values/computed/text.rs b/components/style/values/computed/text.rs index b488f1eacc5..bb849b813f9 100644 --- a/components/style/values/computed/text.rs +++ b/components/style/values/computed/text.rs @@ -15,6 +15,8 @@ use values::generics::text::LineHeight as GenericLineHeight; use values::generics::text::Spacing; use values::specified::text::{TextOverflowSide, TextDecorationLine}; +pub use values::specified::TextAlignKeyword as TextAlign; + /// A computed value for the `initial-letter` property. pub type InitialLetter = GenericInitialLetter<CSSFloat, CSSInteger>; diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index 93fd4643015..25b5bcf3ca5 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -56,7 +56,8 @@ pub use self::percentage::Percentage; pub use self::position::{Position, PositionComponent, GridAutoFlow, GridTemplateAreas}; pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind, SVGStrokeDashArray, SVGWidth}; pub use self::table::XSpan; -pub use self::text::{InitialLetter, LetterSpacing, LineHeight, TextDecorationLine, TextOverflow, WordSpacing}; +pub use self::text::{InitialLetter, LetterSpacing, LineHeight, TextDecorationLine}; +pub use self::text::{TextAlign, TextAlignKeyword, TextOverflow, WordSpacing}; pub use self::time::Time; pub use self::transform::{TimingFunction, Transform, TransformOrigin}; pub use self::ui::MozForceBrokenImageIcon; diff --git a/components/style/values/specified/text.rs b/components/style/values/specified/text.rs index e9d19a772ea..caca98ab3f2 100644 --- a/components/style/values/specified/text.rs +++ b/components/style/values/specified/text.rs @@ -10,7 +10,8 @@ use parser::{Parse, ParserContext}; use properties::{longhands, PropertyDeclaration}; use selectors::parser::SelectorParseErrorKind; #[allow(unused_imports)] use std::ascii::AsciiExt; -use style_traits::{ParseError, StyleParseErrorKind}; +use std::fmt; +use style_traits::{ParseError, StyleParseErrorKind, ToCss}; use values::computed::{Context, ToComputedValue}; use values::computed::text::LineHeight as ComputedLineHeight; use values::computed::text::TextOverflow as ComputedTextOverflow; @@ -349,3 +350,171 @@ impl Parse for TextDecorationLine { } } } + +macro_rules! define_text_align_keyword { + ($($name: ident => $discriminant: expr,)+) => { + /// Specified value of text-align keyword value. + #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)] + #[allow(missing_docs)] + pub enum TextAlignKeyword { + $( + $name = $discriminant, + )+ + } + + impl TextAlignKeyword { + /// Construct a TextAlignKeyword from u32. + pub fn from_u32(discriminant: u32) -> Option<TextAlignKeyword> { + match discriminant { + $( + $discriminant => Some(TextAlignKeyword::$name), + )+ + _ => None + } + } + } + } +} + +// FIXME(emilio): Why reinventing the world? +#[cfg(feature = "gecko")] +define_text_align_keyword! { + Start => 0, + End => 1, + Left => 2, + Right => 3, + Center => 4, + Justify => 5, + MozCenter => 6, + MozLeft => 7, + MozRight => 8, + Char => 10, +} + +#[cfg(feature = "servo")] +define_text_align_keyword! { + Start => 0, + End => 1, + Left => 2, + Right => 3, + Center => 4, + Justify => 5, + ServoCenter => 6, + ServoLeft => 7, + ServoRight => 8, +} + +impl TextAlignKeyword { + /// Return the initial value of TextAlignKeyword. + #[inline] + pub fn start() -> TextAlignKeyword { + TextAlignKeyword::Start + } +} + +/// Specified value of text-align property. +#[cfg_attr(feature = "gecko", derive(MallocSizeOf))] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +pub enum TextAlign { + /// Keyword value of text-align property. + Keyword(TextAlignKeyword), + /// `match-parent` value of text-align property. It has a different handling + /// unlike other keywords. + #[cfg(feature = "gecko")] + MatchParent, + /// `MozCenterOrInherit` value of text-align property. It cannot be parsed, + /// only set directly on the elements and it has a different handling + /// unlike other values. + #[cfg(feature = "gecko")] + MozCenterOrInherit, + +} + +impl Parse for TextAlign { + fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> { + // MozCenterOrInherit cannot be parsed, only set directly on the elements + if let Ok(key) = input.try(TextAlignKeyword::parse) { + return Ok(TextAlign::Keyword(key)); + } + #[cfg(feature = "gecko")] + { + input.expect_ident_matching("match-parent")?; + return Ok(TextAlign::MatchParent); + } + #[cfg(feature = "servo")] + { + return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); + } + } +} + +impl ToCss for TextAlign { + fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + match *self { + TextAlign::Keyword(key) => key.to_css(dest), + #[cfg(feature = "gecko")] + TextAlign::MatchParent => dest.write_str("match-parent"), + #[cfg(feature = "gecko")] + TextAlign::MozCenterOrInherit => Ok(()), + } + } +} + +impl TextAlign { + /// Convert an enumerated value coming from Gecko to a `TextAlign`. + #[cfg(feature = "gecko")] + pub fn from_gecko_keyword(kw: u32) -> Self { + use gecko_bindings::structs::NS_STYLE_TEXT_ALIGN_MATCH_PARENT; + if kw == NS_STYLE_TEXT_ALIGN_MATCH_PARENT { + TextAlign::MatchParent + } else { + TextAlign::Keyword(TextAlignKeyword::from_gecko_keyword(kw)) + } + } +} + +impl ToComputedValue for TextAlign { + type ComputedValue = TextAlignKeyword; + + #[inline] + fn to_computed_value(&self, _context: &Context) -> Self::ComputedValue { + match *self { + TextAlign::Keyword(key) => key, + #[cfg(feature = "gecko")] + TextAlign::MatchParent => { + // on the root <html> element we should still respect the dir + // but the parent dir of that element is LTR even if it's <html dir=rtl> + // and will only be RTL if certain prefs have been set. + // In that case, the default behavior here will set it to left, + // but we want to set it to right -- instead set it to the default (`start`), + // which will do the right thing in this case (but not the general case) + if _context.is_root_element { + return TextAlignKeyword::start(); + } + let parent = _context.builder.get_parent_inheritedtext().clone_text_align(); + let ltr = _context.builder.inherited_writing_mode().is_bidi_ltr(); + match (parent, ltr) { + (TextAlignKeyword::Start, true) => TextAlignKeyword::Left, + (TextAlignKeyword::Start, false) => TextAlignKeyword::Right, + (TextAlignKeyword::End, true) => TextAlignKeyword::Right, + (TextAlignKeyword::End, false) => TextAlignKeyword::Left, + _ => parent + } + }, + #[cfg(feature = "gecko")] + TextAlign::MozCenterOrInherit => { + let parent = _context.builder.get_parent_inheritedtext().clone_text_align(); + if parent == TextAlignKeyword::Start { + TextAlignKeyword::Center + } else { + parent + } + } + } + } + + #[inline] + fn from_computed_value(computed: &Self::ComputedValue) -> Self { + TextAlign::Keyword(*computed) + } +} |