aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/layout/flow.rs2
-rw-r--r--components/style/gecko/conversions.rs22
-rw-r--r--components/style/properties/longhand/inherited_text.mako.rs165
-rw-r--r--components/style/values/computed/mod.rs2
-rw-r--r--components/style/values/computed/text.rs2
-rw-r--r--components/style/values/specified/mod.rs3
-rw-r--r--components/style/values/specified/text.rs171
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)
+ }
+}