Bug 1309752: Introduce PropertyDeclaration::to_physical. r?heycam draft
authorEmilio Cobos Álvarez <emilio@crisal.io>
Fri, 06 Jul 2018 05:15:34 +0200
changeset 815642 a8fcee647805fc363885125bb9e8e5be54c911e9
parent 815641 19efac2b69ea32f475d77f76d0d4a1362fa1a75f
child 815643 f289db27f31ace8a0211611d7bf012e870a815d9
push id115591
push userbmo:emilio@crisal.io
push dateMon, 09 Jul 2018 16:15:39 +0000
reviewersheycam
bugs1309752
milestone63.0a1
Bug 1309752: Introduce PropertyDeclaration::to_physical. r?heycam MozReview-Commit-ID: FAL04K5G948
servo/components/style/properties/data.py
servo/components/style/properties/properties.mako.rs
--- a/servo/components/style/properties/data.py
+++ b/servo/components/style/properties/data.py
@@ -229,16 +229,31 @@ class Longhand(object):
 
         # See compute_damage for the various values this can take
         self.servo_restyle_damage = servo_restyle_damage
 
     @staticmethod
     def type():
         return "longhand"
 
+    # For a given logical property return all the physical
+    # property names corresponding to it.
+    def all_physical_mapped_properties(self):
+        assert self.logical
+        logical_side = None
+        for s in LOGICAL_SIDES + LOGICAL_SIZES:
+            if s in self.name:
+                assert not logical_side
+                logical_side = s
+        assert logical_side
+        physical = PHYSICAL_SIDES if logical_side in LOGICAL_SIDES else PHYSICAL_SIZES
+        return [self.name.replace(logical_side, physical_side).replace("inset-", "") \
+            for physical_side in physical]
+
+
     def experimental(self, product):
         if product == "gecko":
             return bool(self.gecko_pref)
         return bool(self.servo_pref)
 
     # FIXME(emilio): Shorthand and Longhand should really share a base class.
     def explicitly_enabled_in_ua_sheets(self):
         return self.enabled_in in ["ua", "chrome"]
--- a/servo/components/style/properties/properties.mako.rs
+++ b/servo/components/style/properties/properties.mako.rs
@@ -1492,17 +1492,17 @@ impl UnparsedValue {
                 keyword,
             })
         })
     }
 }
 
 /// An identifier for a given property declaration, which can be either a
 /// longhand or a custom property.
-#[derive(Clone, Copy, PartialEq)]
+#[derive(Clone, Copy, Debug, PartialEq)]
 #[cfg_attr(feature = "servo", derive(MallocSizeOf))]
 pub enum PropertyDeclarationId<'a> {
     /// A longhand.
     Longhand(LonghandId),
     /// A custom property declaration.
     Custom(&'a ::custom_properties::Name),
 }
 
@@ -1898,28 +1898,90 @@ impl PropertyDeclaration {
             PropertyDeclaration::CSSWideKeyword(ref declaration) => {
                 return PropertyDeclarationId::Longhand(declaration.id);
             }
             PropertyDeclaration::WithVariables(ref declaration) => {
                 return PropertyDeclarationId::Longhand(declaration.id);
             }
             _ => {}
         }
-        // This is just fine because PropertyDeclarationId and LonghandId
+        // This is just fine because PropertyDeclaration and LonghandId
         // have corresponding discriminants.
         let id = unsafe { *(self as *const _ as *const LonghandId) };
         debug_assert_eq!(id, match *self {
             % for property in data.longhands:
             PropertyDeclaration::${property.camel_case}(..) => LonghandId::${property.camel_case},
             % endfor
             _ => id,
         });
         PropertyDeclarationId::Longhand(id)
     }
 
+    /// Given a declaration, convert it into a declaration for a corresponding
+    /// physical property.
+    #[inline]
+    pub fn to_physical(&self, wm: WritingMode) -> Self {
+        match *self {
+            PropertyDeclaration::WithVariables(VariableDeclaration {
+                id,
+                ref value,
+            }) => {
+                return PropertyDeclaration::WithVariables(VariableDeclaration {
+                    id: id.to_physical(wm),
+                    value: value.clone(),
+                })
+            }
+            PropertyDeclaration::CSSWideKeyword(WideKeywordDeclaration {
+                id,
+                keyword,
+            }) => {
+                return PropertyDeclaration::CSSWideKeyword(WideKeywordDeclaration {
+                    id: id.to_physical(wm),
+                    keyword,
+                })
+            }
+            PropertyDeclaration::Custom(..) => return self.clone(),
+            % for prop in data.longhands:
+            PropertyDeclaration::${prop.camel_case}(..) => {},
+            % endfor
+        }
+
+        let mut ret = self.clone();
+
+        % for prop in data.longhands:
+        % if prop.logical:
+        % for physical_property in prop.all_physical_mapped_properties():
+        % if data.longhands_by_name[physical_property].specified_type() != prop.specified_type():
+            <% raise "Logical property %s should share specified value with physical property %s" % (prop.name, physical_property) %>
+        % endif
+        % endfor
+        % endif
+        % endfor
+
+        unsafe {
+            let longhand_id = *(&mut ret as *mut _ as *mut LonghandId);
+
+            debug_assert_eq!(
+                PropertyDeclarationId::Longhand(longhand_id),
+                ret.id()
+            );
+
+            // This is just fine because PropertyDeclaration and LonghandId
+            // have corresponding discriminants.
+            *(&mut ret as *mut _ as *mut LonghandId) = longhand_id.to_physical(wm);
+
+            debug_assert_eq!(
+                PropertyDeclarationId::Longhand(longhand_id.to_physical(wm)),
+                ret.id()
+            );
+        }
+
+        ret
+    }
+
     fn with_variables_from_shorthand(&self, shorthand: ShorthandId) -> Option< &str> {
         match *self {
             PropertyDeclaration::WithVariables(ref declaration) => {
                 let s = declaration.value.from_shorthand?;
                 if s != shorthand {
                     return None;
                 }
                 Some(&*declaration.value.css)