aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2016-12-10 13:57:14 -0800
committerGitHub <noreply@github.com>2016-12-10 13:57:14 -0800
commit37c4051d21f5baacdf843510c8b111202ac2e876 (patch)
treec1f52fa5a3e4e8326dc912bd88803d1efa145d7d
parent872ec89a9c546eb05246b5047aabfc032d140eff (diff)
parentfaddb0c3bbd5300b0c0b611033283fe950d5f8d8 (diff)
downloadservo-37c4051d21f5baacdf843510c8b111202ac2e876.tar.gz
servo-37c4051d21f5baacdf843510c8b111202ac2e876.zip
Auto merge of #14498 - dpyro:image-orientation, r=canaltinova
Added image-orientation property <!-- Please describe your changes on the following line: --> Implemented as per the MDN documentation—I could not find a current CSS draft. I am not sure if this is the complete correct metadata for the longhand helper: ``` <%helpers:longhand name="image-orientation” experimental=“True” animatable=“False”> ``` Also I am not sure how to test this and would appreciate help in creating a testing strategy. --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix #13877. <!-- Either: --> - [X] There are tests for these changes <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- 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/14498) <!-- Reviewable:end -->
-rw-r--r--components/style/properties/longhand/inherited_box.mako.rs133
-rw-r--r--tests/unit/style/parsing/inherited_box.rs31
-rw-r--r--tests/unit/style/parsing/mod.rs1
3 files changed, 165 insertions, 0 deletions
diff --git a/components/style/properties/longhand/inherited_box.mako.rs b/components/style/properties/longhand/inherited_box.mako.rs
index 15b65ee418d..7eca5ab0ee5 100644
--- a/components/style/properties/longhand/inherited_box.mako.rs
+++ b/components/style/properties/longhand/inherited_box.mako.rs
@@ -50,6 +50,139 @@ ${helpers.single_keyword("image-rendering",
custom_consts=image_rendering_custom_consts,
animatable=False)}
+// Image Orientation
+// https://drafts.csswg.org/css-images/#the-image-orientation
+<%helpers:longhand name="image-orientation"
+ products="None"
+ animatable="False">
+ use std::fmt;
+ use style_traits::ToCss;
+ use values::specified::Angle;
+
+ use values::NoViewportPercentage;
+ impl NoViewportPercentage for SpecifiedValue {}
+
+ use std::f32::consts::PI;
+ use values::CSSFloat;
+ const TWO_PI: CSSFloat = 2.0*PI;
+
+ #[derive(Clone, PartialEq, Copy, Debug)]
+ #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+ pub struct SpecifiedValue {
+ pub angle: Option<Angle>,
+ pub flipped: bool
+ }
+
+ impl ToCss for SpecifiedValue {
+ fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+ if let Some(angle) = self.angle {
+ try!(angle.to_css(dest));
+ if self.flipped {
+ dest.write_str(" flipped")
+ } else {
+ Ok(())
+ }
+ } else {
+ if self.flipped {
+ dest.write_str("flipped")
+ } else {
+ dest.write_str("from-image")
+ }
+ }
+ }
+ }
+
+ pub mod computed_value {
+ use values::specified::Angle;
+
+ #[derive(Clone, PartialEq, Copy, Debug)]
+ #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+ pub enum T {
+ FromImage,
+ AngleWithFlipped(Angle, bool),
+ }
+ }
+
+ const INITIAL_ANGLE: Angle = Angle(0.0);
+
+ #[inline]
+ pub fn get_initial_value() -> computed_value::T {
+ computed_value::T::AngleWithFlipped(INITIAL_ANGLE, false)
+ }
+
+ // According to CSS Content Module Level 3:
+ // The computed value of the property is calculated by rounding the specified angle
+ // to the nearest quarter-turn, rounding away from 0, then moduloing the value by 1 turn.
+ #[inline]
+ fn normalize_angle(angle: &Angle) -> Angle {
+ let radians = angle.radians();
+ let rounded_quarter_turns = (4.0 * radians / TWO_PI).round();
+ let normalized_quarter_turns = (rounded_quarter_turns % 4.0 + 4.0) % 4.0;
+ let normalized_radians = normalized_quarter_turns/4.0 * TWO_PI;
+ Angle::from_radians(normalized_radians)
+ }
+
+ impl ToComputedValue for SpecifiedValue {
+ type ComputedValue = computed_value::T;
+
+ #[inline]
+ fn to_computed_value(&self, _: &Context) -> computed_value::T {
+ if let Some(ref angle) = self.angle {
+ let normalized_angle = normalize_angle(angle);
+ computed_value::T::AngleWithFlipped(normalized_angle, self.flipped)
+ } else {
+ if self.flipped {
+ computed_value::T::AngleWithFlipped(INITIAL_ANGLE, true)
+ } else {
+ computed_value::T::FromImage
+ }
+ }
+ }
+
+ #[inline]
+ fn from_computed_value(computed: &computed_value::T) -> Self {
+ match *computed {
+ computed_value::T::FromImage => SpecifiedValue { angle: None, flipped: false },
+ computed_value::T::AngleWithFlipped(angle, flipped) =>
+ SpecifiedValue { angle: Some(angle), flipped: flipped },
+ }
+ }
+ }
+
+ impl ToCss for computed_value::T {
+ fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+ match *self {
+ computed_value::T::FromImage => dest.write_str("from-image"),
+ computed_value::T::AngleWithFlipped(angle, flipped) => {
+ try!(angle.to_css(dest));
+ if flipped {
+ try!(dest.write_str(" flipped"));
+ }
+ Ok(())
+ },
+ }
+ }
+ }
+
+ pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
+ if input.try(|input| input.expect_ident_matching("from-image")).is_ok() {
+ // Handle from-image
+ Ok(SpecifiedValue { angle: None, flipped: false })
+ } else {
+ // Handle <angle> | <angle>? flip
+ let angle = input.try(|input| Angle::parse(context, input)).ok();
+ let flipped = input.try(|input| input.expect_ident_matching("flip")).is_ok();
+ let explicit_angle = if angle.is_none() && !flipped {
+ Some(INITIAL_ANGLE)
+ } else {
+ angle
+ };
+
+ Ok(SpecifiedValue { angle: explicit_angle, flipped: flipped })
+ }
+ }
+</%helpers:longhand>
+
// Used in the bottom-up flow construction traversal to avoid constructing flows for
// descendants of nodes with `display: none`.
<%helpers:longhand name="-servo-under-display-none"
diff --git a/tests/unit/style/parsing/inherited_box.rs b/tests/unit/style/parsing/inherited_box.rs
new file mode 100644
index 00000000000..0fc78ed6131
--- /dev/null
+++ b/tests/unit/style/parsing/inherited_box.rs
@@ -0,0 +1,31 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use cssparser::Parser;
+use media_queries::CSSErrorReporterTest;
+use style::parser::ParserContext;
+use style::stylesheets::Origin;
+
+#[test]
+fn image_orientation_longhand_should_parse_properly() {
+ use std::f32::consts::PI;
+ use style::properties::longhands::image_orientation;
+ use style::properties::longhands::image_orientation::SpecifiedValue;
+ use style::values::specified::Angle;
+
+ let from_image = parse_longhand!(image_orientation, "from-image");
+ assert_eq!(from_image, SpecifiedValue { angle: None, flipped: false });
+
+ let flip = parse_longhand!(image_orientation, "flip");
+ assert_eq!(flip, SpecifiedValue { angle: None, flipped: true });
+
+ let zero = parse_longhand!(image_orientation, "0deg");
+ assert_eq!(zero, SpecifiedValue { angle: Some(Angle::from_radians(0.0)), flipped: false });
+
+ let negative_rad = parse_longhand!(image_orientation, "-1rad");
+ assert_eq!(negative_rad, SpecifiedValue { angle: Some(Angle::from_radians(-1.0)), flipped: false });
+
+ let flip_with_180 = parse_longhand!(image_orientation, "180deg flip");
+ assert_eq!(flip_with_180, SpecifiedValue { angle: Some(Angle::from_radians(PI)), flipped: true });
+}
diff --git a/tests/unit/style/parsing/mod.rs b/tests/unit/style/parsing/mod.rs
index 369e0b66bf0..05bd3e8d912 100644
--- a/tests/unit/style/parsing/mod.rs
+++ b/tests/unit/style/parsing/mod.rs
@@ -52,6 +52,7 @@ mod basic_shape;
mod border;
mod font;
mod image;
+mod inherited_box;
mod inherited_text;
mod mask;
mod position;