layout/style/Declaration.h

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 /*
     7  * representation of a declaration block (or style attribute) in a CSS
     8  * stylesheet
     9  */
    11 #ifndef mozilla_css_Declaration_h
    12 #define mozilla_css_Declaration_h
    14 // This header is in EXPORTS because it's used in several places in content/,
    15 // but it's not really a public interface.
    16 #ifndef MOZILLA_INTERNAL_API
    17 #error "This file should only be included within libxul"
    18 #endif
    20 #include "mozilla/Attributes.h"
    21 #include "mozilla/MemoryReporting.h"
    22 #include "CSSVariableDeclarations.h"
    23 #include "nsCSSDataBlock.h"
    24 #include "nsCSSProperty.h"
    25 #include "nsCSSProps.h"
    26 #include "nsStringFwd.h"
    27 #include "nsTArray.h"
    28 #include <stdio.h>
    30 namespace mozilla {
    31 namespace css {
    33 // Declaration objects have unusual lifetime rules.  Every declaration
    34 // begins life in an invalid state which ends when InitializeEmpty or
    35 // CompressFrom is called upon it.  After that, it can be attached to
    36 // exactly one style rule, and will be destroyed when that style rule
    37 // is destroyed.  A declaration becomes immutable when its style rule's
    38 // |RuleMatched| method is called; after that, it must be copied before
    39 // it can be modified, which is taken care of by |EnsureMutable|.
    41 class Declaration {
    42 public:
    43   /**
    44    * Construct an |Declaration| that is in an invalid state (null
    45    * |mData|) and cannot be used until its |CompressFrom| method or
    46    * |InitializeEmpty| method is called.
    47    */
    48   Declaration();
    50   Declaration(const Declaration& aCopy);
    52   ~Declaration();
    54   /**
    55    * |ValueAppended| must be called to maintain this declaration's
    56    * |mOrder| whenever a property is parsed into an expanded data block
    57    * for this declaration.  aProperty must not be a shorthand.
    58    */
    59   void ValueAppended(nsCSSProperty aProperty);
    61   void RemoveProperty(nsCSSProperty aProperty);
    63   bool HasProperty(nsCSSProperty aProperty) const;
    65   void GetValue(nsCSSProperty aProperty, nsAString& aValue) const;
    66   void GetAuthoredValue(nsCSSProperty aProperty, nsAString& aValue) const;
    68   bool HasImportantData() const {
    69     return mImportantData || mImportantVariables;
    70   }
    71   bool GetValueIsImportant(nsCSSProperty aProperty) const;
    72   bool GetValueIsImportant(const nsAString& aProperty) const;
    74   /**
    75    * Adds a custom property declaration to this object.
    76    *
    77    * @param aName The variable name (i.e., without the "--" prefix).
    78    * @param aType The type of value the variable has.
    79    * @param aValue The value of the variable, if aType is
    80    *   CSSVariableDeclarations::eTokenStream.
    81    * @param aIsImportant Whether the declaration is !important.
    82    * @param aOverrideImportant When aIsImportant is false, whether an
    83    *   existing !important declaration will be overridden.
    84    */
    85   void AddVariableDeclaration(const nsAString& aName,
    86                               CSSVariableDeclarations::Type aType,
    87                               const nsString& aValue,
    88                               bool aIsImportant,
    89                               bool aOverrideImportant);
    91   /**
    92    * Removes a custom property declaration from this object.
    93    *
    94    * @param aName The variable name (i.e., without the "--" prefix).
    95    */
    96   void RemoveVariableDeclaration(const nsAString& aName);
    98   /**
    99    * Returns whether a custom property declaration for a variable with
   100    * a given name exists on this object.
   101    *
   102    * @param aName The variable name (i.e., without the "--" prefix).
   103    */
   104   bool HasVariableDeclaration(const nsAString& aName) const;
   106   /**
   107    * Gets the string value for a custom property declaration of a variable
   108    * with a given name.
   109    *
   110    * @param aName The variable name (i.e., without the "--" prefix).
   111    * @param aValue Out parameter into which the variable's value will be
   112    *   stored.  If the value is 'initial' or 'inherit', that exact string
   113    *   will be stored in aValue.
   114    */
   115   void GetVariableDeclaration(const nsAString& aName, nsAString& aValue) const;
   117   /**
   118    * Returns whether the custom property declaration for a variable with
   119    * the given name was !important.
   120    */
   121   bool GetVariableValueIsImportant(const nsAString& aName) const;
   123   uint32_t Count() const {
   124     return mOrder.Length();
   125   }
   127   // Returns whether we actually had a property at aIndex
   128   bool GetNthProperty(uint32_t aIndex, nsAString& aReturn) const;
   130   void ToString(nsAString& aString) const;
   132   nsCSSCompressedDataBlock* GetNormalBlock() const { return mData; }
   133   nsCSSCompressedDataBlock* GetImportantBlock() const { return mImportantData; }
   135   /**
   136    * Initialize this declaration as holding no data.  Cannot fail.
   137    */
   138   void InitializeEmpty();
   140   /**
   141    * Transfer all of the state from |aExpandedData| into this declaration.
   142    * After calling, |aExpandedData| should be in its initial state.
   143    * Callers must make sure mOrder is updated as necessary.
   144    */
   145   void CompressFrom(nsCSSExpandedDataBlock *aExpandedData) {
   146     NS_ABORT_IF_FALSE(!mData, "oops");
   147     NS_ABORT_IF_FALSE(!mImportantData, "oops");
   148     aExpandedData->Compress(getter_Transfers(mData),
   149                             getter_Transfers(mImportantData));
   150     aExpandedData->AssertInitialState();
   151   }
   153   /**
   154    * Transfer all of the state from this declaration into
   155    * |aExpandedData| and put this declaration temporarily into an
   156    * invalid state (ended by |CompressFrom| or |InitializeEmpty|) that
   157    * should last only during parsing.  During this time only
   158    * |ValueAppended| should be called.
   159    */
   160   void ExpandTo(nsCSSExpandedDataBlock *aExpandedData) {
   161     AssertMutable();
   162     aExpandedData->AssertInitialState();
   164     NS_ABORT_IF_FALSE(mData, "oops");
   165     aExpandedData->Expand(mData.forget(), mImportantData.forget());
   166   }
   168   /**
   169    * Do what |nsIStyleRule::MapRuleInfoInto| needs to do for a style
   170    * rule using this declaration for storage.
   171    */
   172   void MapNormalRuleInfoInto(nsRuleData *aRuleData) const {
   173     NS_ABORT_IF_FALSE(mData, "called while expanded");
   174     mData->MapRuleInfoInto(aRuleData);
   175     if (mVariables) {
   176       mVariables->MapRuleInfoInto(aRuleData);
   177     }
   178   }
   179   void MapImportantRuleInfoInto(nsRuleData *aRuleData) const {
   180     NS_ABORT_IF_FALSE(mData, "called while expanded");
   181     NS_ABORT_IF_FALSE(mImportantData || mImportantVariables,
   182                       "must have important data or variables");
   183     if (mImportantData) {
   184       mImportantData->MapRuleInfoInto(aRuleData);
   185     }
   186     if (mImportantVariables) {
   187       mImportantVariables->MapRuleInfoInto(aRuleData);
   188     }
   189   }
   191   /**
   192    * Attempt to replace the value for |aProperty| stored in this
   193    * declaration with the matching value from |aFromBlock|.
   194    * This method may only be called on a mutable declaration.
   195    * It will fail (returning false) if |aProperty| is shorthand,
   196    * is not already in this declaration, or does not have the indicated
   197    * importance level.  If it returns true, it erases the value in
   198    * |aFromBlock|.  |aChanged| is set to true if the declaration
   199    * changed as a result of the call, and to false otherwise.
   200    */
   201   bool TryReplaceValue(nsCSSProperty aProperty, bool aIsImportant,
   202                          nsCSSExpandedDataBlock& aFromBlock,
   203                          bool* aChanged)
   204   {
   205     AssertMutable();
   206     NS_ABORT_IF_FALSE(mData, "called while expanded");
   208     if (nsCSSProps::IsShorthand(aProperty)) {
   209       *aChanged = false;
   210       return false;
   211     }
   212     nsCSSCompressedDataBlock *block = aIsImportant ? mImportantData : mData;
   213     // mImportantData might be null
   214     if (!block) {
   215       *aChanged = false;
   216       return false;
   217     }
   219 #ifdef DEBUG
   220     {
   221       nsCSSCompressedDataBlock *other = aIsImportant ? mData : mImportantData;
   222       NS_ABORT_IF_FALSE(!other || !other->ValueFor(aProperty) ||
   223                         !block->ValueFor(aProperty),
   224                         "Property both important and not?");
   225     }
   226 #endif
   227     return block->TryReplaceValue(aProperty, aFromBlock, aChanged);
   228   }
   230   bool HasNonImportantValueFor(nsCSSProperty aProperty) const {
   231     NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(aProperty), "must be longhand");
   232     return !!mData->ValueFor(aProperty);
   233   }
   235   /**
   236    * Return whether |this| may be modified.
   237    */
   238   bool IsMutable() const {
   239     return !mImmutable;
   240   }
   242   /**
   243    * Copy |this|, if necessary to ensure that it can be modified.
   244    */
   245   Declaration* EnsureMutable();
   247   /**
   248    * Crash if |this| cannot be modified.
   249    */
   250   void AssertMutable() const {
   251     NS_ABORT_IF_FALSE(IsMutable(), "someone forgot to call EnsureMutable");
   252   }
   254   /**
   255    * Mark this declaration as unmodifiable.  It's 'const' so it can
   256    * be called from ToString.
   257    */
   258   void SetImmutable() const { mImmutable = true; }
   260   /**
   261    * Clear the data, in preparation for its replacement with entirely
   262    * new data by a call to |CompressFrom|.
   263    */
   264   void ClearData() {
   265     AssertMutable();
   266     mData = nullptr;
   267     mImportantData = nullptr;
   268     mVariables = nullptr;
   269     mImportantVariables = nullptr;
   270     mOrder.Clear();
   271     mVariableOrder.Clear();
   272   }
   274 #ifdef DEBUG
   275   void List(FILE* out = stdout, int32_t aIndent = 0) const;
   276 #endif
   278 private:
   279   Declaration& operator=(const Declaration& aCopy) MOZ_DELETE;
   280   bool operator==(const Declaration& aCopy) const MOZ_DELETE;
   282   void GetValue(nsCSSProperty aProperty, nsAString& aValue,
   283                 nsCSSValue::Serialization aValueSerialization) const;
   285   static void AppendImportanceToString(bool aIsImportant, nsAString& aString);
   286   // return whether there was a value in |aValue| (i.e., it had a non-null unit)
   287   bool AppendValueToString(nsCSSProperty aProperty, nsAString& aResult) const;
   288   bool AppendValueToString(nsCSSProperty aProperty, nsAString& aResult,
   289                            nsCSSValue::Serialization aValueSerialization) const;
   290   // Helper for ToString with strange semantics regarding aValue.
   291   void AppendPropertyAndValueToString(nsCSSProperty aProperty,
   292                                       nsAutoString& aValue,
   293                                       nsAString& aResult) const;
   294   // helper for ToString that serializes a custom property declaration for
   295   // a variable with the specified name
   296   void AppendVariableAndValueToString(const nsAString& aName,
   297                                       nsAString& aResult) const;
   299 public:
   300   /**
   301    * Returns the property at the given index in the ordered list of
   302    * declarations.  For custom properties, eCSSPropertyExtra_variable
   303    * is returned.
   304    */
   305   nsCSSProperty GetPropertyAt(uint32_t aIndex) const {
   306     uint32_t value = mOrder[aIndex];
   307     if (value >= eCSSProperty_COUNT) {
   308       return eCSSPropertyExtra_variable;
   309     }
   310     return nsCSSProperty(value);
   311   }
   313   /**
   314    * Gets the name of the custom property at the given index in the ordered
   315    * list of declarations.
   316    */
   317   void GetCustomPropertyNameAt(uint32_t aIndex, nsAString& aResult) const {
   318     MOZ_ASSERT(mOrder[aIndex] >= eCSSProperty_COUNT);
   319     uint32_t variableIndex = mOrder[aIndex] - eCSSProperty_COUNT;
   320     aResult.Truncate();
   321     aResult.AppendLiteral("--");
   322     aResult.Append(mVariableOrder[variableIndex]);
   323   }
   325   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
   327 private:
   328   // The order of properties in this declaration.  Longhand properties are
   329   // represented by their nsCSSProperty value, and each custom property (--*)
   330   // is represented by a value that begins at eCSSProperty_COUNT.
   331   //
   332   // Subtracting eCSSProperty_COUNT from those values that represent custom
   333   // properties results in an index into mVariableOrder, which identifies the
   334   // specific variable the custom property declaration is for.
   335   nsAutoTArray<uint32_t, 8> mOrder;
   337   // variable names of custom properties found in mOrder
   338   nsTArray<nsString> mVariableOrder;
   340   // never null, except while expanded, or before the first call to
   341   // InitializeEmpty or CompressFrom.
   342   nsAutoPtr<nsCSSCompressedDataBlock> mData;
   344   // may be null
   345   nsAutoPtr<nsCSSCompressedDataBlock> mImportantData;
   347   // may be null
   348   nsAutoPtr<CSSVariableDeclarations> mVariables;
   350   // may be null
   351   nsAutoPtr<CSSVariableDeclarations> mImportantVariables;
   353   // set by style rules when |RuleMatched| is called;
   354   // also by ToString (hence the 'mutable').
   355   mutable bool mImmutable;
   356 };
   358 } // namespace css
   359 } // namespace mozilla
   361 #endif /* mozilla_css_Declaration_h */

mercurial