LCOV - code coverage report
Current view: top level - layout/style - nsStyleContext.h (source / functions) Hit Total Coverage
Test: output.info Lines: 64 81 79.0 %
Date: 2017-07-14 16:53:18 Functions: 28 30 93.3 %
Legend: Lines: hit not hit

          Line data    Source 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/. */
       5             : 
       6             : /* the interface (to internal code) for retrieving computed style data */
       7             : 
       8             : #ifndef _nsStyleContext_h_
       9             : #define _nsStyleContext_h_
      10             : 
      11             : #include "mozilla/Assertions.h"
      12             : #include "mozilla/RestyleLogging.h"
      13             : #include "mozilla/ServoStyleSet.h"
      14             : #include "mozilla/ServoUtils.h"
      15             : #include "mozilla/StyleComplexColor.h"
      16             : #include "nsCSSAnonBoxes.h"
      17             : #include "nsStyleSet.h"
      18             : 
      19             : class nsIAtom;
      20             : class nsPresContext;
      21             : 
      22             : namespace mozilla {
      23             : enum class CSSPseudoElementType : uint8_t;
      24             : class GeckoStyleContext;
      25             : class ServoStyleContext;
      26             : } // namespace mozilla
      27             : 
      28             : extern "C" {
      29             : #define STYLE_STRUCT(name_, checkdata_cb_)     \
      30             :   struct nsStyle##name_;                       \
      31             :   const nsStyle##name_* Servo_GetStyle##name_( \
      32             :     ServoComputedValuesBorrowedOrNull computed_values);
      33             : #include "nsStyleStructList.h"
      34             : #undef STYLE_STRUCT
      35             : }
      36             : 
      37             : /**
      38             :  * An nsStyleContext represents the computed style data for an element.
      39             :  * The computed style data are stored in a set of structs (see
      40             :  * nsStyleStruct.h) that are cached either on the style context or in
      41             :  * the rule tree (see nsRuleNode.h for a description of this caching and
      42             :  * how the cached structs are shared).
      43             :  *
      44             :  * Since the data in |nsIStyleRule|s and |nsRuleNode|s are immutable
      45             :  * (with a few exceptions, like system color changes), the data in an
      46             :  * nsStyleContext are also immutable (with the additional exception of
      47             :  * GetUniqueStyleData).  When style data change,
      48             :  * ElementRestyler::Restyle creates a new style context.
      49             :  *
      50             :  * Style contexts are reference counted.  References are generally held
      51             :  * by:
      52             :  *  1. the |nsIFrame|s that are using the style context and
      53             :  *  2. any *child* style contexts (this might be the reverse of
      54             :  *     expectation, but it makes sense in this case)
      55             :  */
      56             : 
      57             : class nsStyleContext
      58             : {
      59             : public:
      60             : #ifdef MOZ_STYLO
      61             :   bool IsGecko() const { return !IsServo(); }
      62             :   bool IsServo() const { return (mBits & NS_STYLE_CONTEXT_IS_GECKO) == 0; }
      63             : #else
      64     1187646 :   bool IsGecko() const { return true; }
      65       77891 :   bool IsServo() const { return false; }
      66             : #endif
      67             :   MOZ_DECL_STYLO_CONVERT_METHODS(mozilla::GeckoStyleContext, mozilla::ServoStyleContext);
      68             : 
      69             :   void Destroy();
      70             : 
      71             :   // These two methods are for use by ArenaRefPtr.
      72           8 :   static mozilla::ArenaObjectID ArenaObjectID()
      73             :   {
      74           8 :     return mozilla::eArenaObjectID_GeckoStyleContext;
      75             :   }
      76             :   nsIPresShell* Arena();
      77             : 
      78             : #ifdef DEBUG
      79             :   /**
      80             :    * Initializes a cached pref, which is only used in DEBUG code.
      81             :    */
      82             :   static void Initialize();
      83             : #endif
      84             : 
      85       14604 :   nsrefcnt AddRef() {
      86       14604 :     if (mRefCnt == UINT32_MAX) {
      87           0 :       NS_WARNING("refcount overflow, leaking object");
      88           0 :       return mRefCnt;
      89             :     }
      90       14604 :     ++mRefCnt;
      91       14604 :     NS_LOG_ADDREF(this, mRefCnt, "nsStyleContext", sizeof(nsStyleContext));
      92       14604 :     return mRefCnt;
      93             :   }
      94             : 
      95       13323 :   nsrefcnt Release() {
      96       13323 :     if (mRefCnt == UINT32_MAX) {
      97           0 :       NS_WARNING("refcount overflow, leaking object");
      98           0 :       return mRefCnt;
      99             :     }
     100       13323 :     --mRefCnt;
     101       13323 :     NS_LOG_RELEASE(this, mRefCnt, "nsStyleContext");
     102       13323 :     if (mRefCnt == 0) {
     103        1618 :       Destroy();
     104        1618 :       return 0;
     105             :     }
     106       11705 :     return mRefCnt;
     107             :   }
     108             : 
     109             : #ifdef DEBUG
     110        1411 :   void FrameAddRef() {
     111        1411 :     ++mFrameRefCnt;
     112        1411 :   }
     113             : 
     114         871 :   void FrameRelease() {
     115         871 :     --mFrameRefCnt;
     116         871 :   }
     117             : 
     118             :   uint32_t FrameRefCnt() const {
     119             :     return mFrameRefCnt;
     120             :   }
     121             : #endif
     122             : 
     123         412 :   bool HasSingleReference() const {
     124         412 :     NS_ASSERTION(mRefCnt != 0,
     125             :                  "do not call HasSingleReference on a newly created "
     126             :                  "nsStyleContext with no references yet");
     127         412 :     return mRefCnt == 1;
     128             :   }
     129             : 
     130             :   inline nsPresContext* PresContext() const;
     131             : 
     132             :   inline mozilla::GeckoStyleContext* GetParent() const;
     133             : 
     134         476 :   nsStyleContext* GetParentAllowServo() const {
     135         476 :     return mParent;
     136             :   }
     137             : 
     138       36057 :   nsIAtom* GetPseudo() const { return mPseudoTag; }
     139       30418 :   mozilla::CSSPseudoElementType GetPseudoType() const {
     140             :     return static_cast<mozilla::CSSPseudoElementType>(
     141       30418 :              mBits >> NS_STYLE_CONTEXT_TYPE_SHIFT);
     142             :   }
     143             : 
     144         389 :   bool IsAnonBox() const {
     145             :     return
     146         435 :       GetPseudoType() == mozilla::CSSPseudoElementType::InheritingAnonBox ||
     147         435 :       GetPseudoType() == mozilla::CSSPseudoElementType::NonInheritingAnonBox;
     148             :   }
     149        2140 :   bool IsPseudoElement() const { return mPseudoTag && !IsAnonBox(); }
     150             : 
     151             : 
     152             :   // Does this style context or any of its ancestors have text
     153             :   // decoration lines?
     154             :   // Differs from nsStyleTextReset::HasTextDecorationLines, which tests
     155             :   // only the data for a single context.
     156        2448 :   bool HasTextDecorationLines() const
     157        2448 :     { return !!(mBits & NS_STYLE_HAS_TEXT_DECORATION_LINES); }
     158             : 
     159             :   // Whether any line break inside should be suppressed? If this returns
     160             :   // true, the line should not be broken inside, which means inlines act
     161             :   // as if nowrap is set, <br> is suppressed, and blocks are inlinized.
     162             :   // This bit is propogated to all children of line partitipants. It is
     163             :   // currently used by ruby to make its content frames unbreakable.
     164             :   // NOTE: for nsTextFrame, use nsTextFrame::ShouldSuppressLineBreak()
     165             :   // instead of this method.
     166        2164 :   bool ShouldSuppressLineBreak() const
     167        2164 :     { return !!(mBits & NS_STYLE_SUPPRESS_LINEBREAK); }
     168             : 
     169             :   // Does this style context or any of its ancestors have display:none set?
     170        5136 :   bool IsInDisplayNoneSubtree() const
     171        5136 :     { return !!(mBits & NS_STYLE_IN_DISPLAY_NONE_SUBTREE); }
     172             : 
     173             :   // Is this horizontal-in-vertical (tate-chu-yoko) text? This flag is
     174             :   // only set on style contexts whose pseudo is nsCSSAnonBoxes::mozText.
     175         697 :   bool IsTextCombined() const
     176         697 :     { return !!(mBits & NS_STYLE_IS_TEXT_COMBINED); }
     177             : 
     178             :   // Does this style context represent the style for a pseudo-element or
     179             :   // inherit data from such a style context?  Whether this returns true
     180             :   // is equivalent to whether it or any of its ancestors returns
     181             :   // non-null for IsPseudoElement().
     182        4419 :   bool HasPseudoElementData() const
     183        4419 :     { return !!(mBits & NS_STYLE_HAS_PSEUDO_ELEMENT_DATA); }
     184             : 
     185          37 :   bool HasChildThatUsesResetStyle() const
     186          37 :     { return mBits & NS_STYLE_HAS_CHILD_THAT_USES_RESET_STYLE; }
     187             : 
     188             :   // Is the only link whose visitedness is allowed to influence the
     189             :   // style of the node this style context is for (which is that element
     190             :   // or its nearest ancestor that is a link) visited?
     191        4676 :   bool RelevantLinkVisited() const
     192        4676 :     { return !!(mBits & NS_STYLE_RELEVANT_LINK_VISITED); }
     193             : 
     194             :   // Is this a style context for a link?
     195             :   inline bool IsLinkContext() const;
     196             : 
     197             :   // Is this style context the GetStyleIfVisited() for some other style
     198             :   // context?
     199       11197 :   bool IsStyleIfVisited() const
     200       11197 :     { return !!(mBits & NS_STYLE_IS_STYLE_IF_VISITED); }
     201             : 
     202             :   // Tells this style context that it should return true from
     203             :   // IsStyleIfVisited.
     204           0 :   void SetIsStyleIfVisited()
     205           0 :     { mBits |= NS_STYLE_IS_STYLE_IF_VISITED; }
     206             : 
     207             :   // Return the style context whose style data should be used for the R,
     208             :   // G, and B components of color, background-color, and border-*-color
     209             :   // if RelevantLinkIsVisited().
     210             :   //
     211             :   // GetPseudo() and GetPseudoType() on this style context return the
     212             :   // same as on |this|, and its depth in the tree (number of GetParent()
     213             :   // calls until null is returned) is the same as |this|, since its
     214             :   // parent is either |this|'s parent or |this|'s parent's
     215             :   // style-if-visited.
     216             :   //
     217             :   // Structs on this context should never be examined without also
     218             :   // examining the corresponding struct on |this|.  Doing so will likely
     219             :   // both (1) lead to a privacy leak and (2) lead to dynamic change bugs
     220             :   // related to the Peek code in nsStyleContext::CalcStyleDifference.
     221       12946 :   nsStyleContext* GetStyleIfVisited() const
     222       12946 :     { return mStyleIfVisited; }
     223             : 
     224             :   // To be called only from nsStyleSet / ServoStyleSet.
     225           0 :   void SetStyleIfVisited(already_AddRefed<nsStyleContext> aStyleIfVisited)
     226             :   {
     227           0 :     MOZ_ASSERT(!IsStyleIfVisited(), "this context is not visited data");
     228           0 :     NS_ASSERTION(!mStyleIfVisited, "should only be set once");
     229             : 
     230           0 :     mStyleIfVisited = aStyleIfVisited;
     231             : 
     232           0 :     MOZ_ASSERT(mStyleIfVisited->IsStyleIfVisited(),
     233             :                "other context is visited data");
     234           0 :     MOZ_ASSERT(!mStyleIfVisited->GetStyleIfVisited(),
     235             :                "other context does not have visited data");
     236           0 :     NS_ASSERTION(GetStyleIfVisited()->GetPseudo() == GetPseudo(),
     237             :                  "pseudo tag mismatch");
     238           0 :     if (GetParentAllowServo() && GetParentAllowServo()->GetStyleIfVisited()) {
     239           0 :       NS_ASSERTION(GetStyleIfVisited()->GetParentAllowServo() ==
     240             :                      GetParentAllowServo()->GetStyleIfVisited() ||
     241             :                    GetStyleIfVisited()->GetParentAllowServo() ==
     242             :                      GetParentAllowServo(),
     243             :                    "parent mismatch");
     244             :     } else {
     245           0 :       NS_ASSERTION(GetStyleIfVisited()->GetParentAllowServo() ==
     246             :                      GetParentAllowServo(),
     247             :                    "parent mismatch");
     248             :     }
     249           0 :   }
     250             : 
     251             :   // Does any descendant of this style context have any style values
     252             :   // that were computed based on this style context's ancestors?
     253        1112 :   bool HasChildThatUsesGrandancestorStyle() const
     254        1112 :     { return !!(mBits & NS_STYLE_CHILD_USES_GRANDANCESTOR_STYLE); }
     255             : 
     256             :   // Is this style context shared with a sibling or cousin?
     257             :   // (See nsStyleSet::GetContext.)
     258        2632 :   bool IsShared() const
     259        2632 :     { return !!(mBits & NS_STYLE_IS_SHARED); }
     260             : 
     261             :   /**
     262             :    * Returns whether this style context has cached style data for a
     263             :    * given style struct and it does NOT own that struct.  This can
     264             :    * happen because it was inherited from the parent style context, or
     265             :    * because it was stored conditionally on the rule node.
     266             :    */
     267         903 :   bool HasCachedDependentStyleData(nsStyleStructID aSID) {
     268         903 :     return mBits & nsCachedStyleData::GetBitForSID(aSID);
     269             :   }
     270             : 
     271             :   inline nsRuleNode* RuleNode();
     272             :   inline ServoComputedValues* ComputedValues();
     273             : 
     274        4906 :   void AddStyleBit(const uint64_t& aBit) { mBits |= aBit; }
     275             : 
     276             :   /**
     277             :    * Define typesafe getter functions for each style struct by
     278             :    * preprocessing the list of style structs.  These functions are the
     279             :    * preferred way to get style data.  The macro creates functions like:
     280             :    *   const nsStyleBorder* StyleBorder();
     281             :    *   const nsStyleColor* StyleColor();
     282             :    */
     283             :   #define STYLE_STRUCT(name_, checkdata_cb_) \
     284             :     inline const nsStyle##name_ * Style##name_() MOZ_NONNULL_RETURN;
     285             :   #include "nsStyleStructList.h"
     286             :   #undef STYLE_STRUCT
     287             : 
     288             :   /**
     289             :    * Equivalent to StyleFoo(), except that we skip the cache write during the
     290             :    * servo traversal. This can cause incorrect behavior if used improperly,
     291             :    * since we won't record that layout potentially depends on the values in
     292             :    * this style struct. Use with care.
     293             :    */
     294             : 
     295             :   #define STYLE_STRUCT(name_, checkdata_cb_) \
     296             :     inline const nsStyle##name_ * ThreadsafeStyle##name_();
     297             :   #include "nsStyleStructList.h"
     298             :   #undef STYLE_STRUCT
     299             : 
     300             : 
     301             :   /**
     302             :    * PeekStyle* is like Style* but doesn't trigger style
     303             :    * computation if the data is not cached on either the style context
     304             :    * or the rule node.
     305             :    *
     306             :    * Perhaps this shouldn't be a public nsStyleContext API.
     307             :    */
     308             :   #define STYLE_STRUCT(name_, checkdata_cb_)  \
     309             :     inline const nsStyle##name_ * PeekStyle##name_();
     310             :   #include "nsStyleStructList.h"
     311             :   #undef STYLE_STRUCT
     312             : 
     313             :   /**
     314             :    * Compute the style changes needed during restyling when this style
     315             :    * context is being replaced by aNewContext.  (This is nonsymmetric since
     316             :    * we optimize by skipping comparison for styles that have never been
     317             :    * requested.)
     318             :    *
     319             :    * This method returns a change hint (see nsChangeHint.h).  All change
     320             :    * hints apply to the frame and its later continuations or ib-split
     321             :    * siblings.  Most (all of those except the "NotHandledForDescendants"
     322             :    * hints) also apply to all descendants.
     323             :    *
     324             :    * aEqualStructs must not be null.  Into it will be stored a bitfield
     325             :    * representing which structs were compared to be non-equal.
     326             :    */
     327             :   nsChangeHint CalcStyleDifference(nsStyleContext* aNewContext,
     328             :                                    uint32_t* aEqualStructs,
     329             :                                    uint32_t* aSamePointerStructs);
     330             : 
     331             :   /**
     332             :    * Like the above, but allows comparing ServoComputedValues instead of needing
     333             :    * a full-fledged style context.
     334             :    */
     335             :   nsChangeHint CalcStyleDifference(const ServoComputedValues* aNewComputedValues,
     336             :                                    uint32_t* aEqualStructs,
     337             :                                    uint32_t* aSamePointerStructs);
     338             : 
     339             : private:
     340             :   template<class StyleContextLike>
     341             :   nsChangeHint CalcStyleDifferenceInternal(StyleContextLike* aNewContext,
     342             :                                            uint32_t* aEqualStructs,
     343             :                                            uint32_t* aSamePointerStructs);
     344             : 
     345             : public:
     346             :   /**
     347             :    * Get a color that depends on link-visitedness using this and
     348             :    * this->GetStyleIfVisited().
     349             :    *
     350             :    * @param aField A pointer to a member variable in a style struct.
     351             :    *               The member variable and its style struct must have
     352             :    *               been listed in nsCSSVisitedDependentPropList.h.
     353             :    */
     354             :   template<typename T, typename S>
     355             :   nscolor GetVisitedDependentColor(T S::* aField);
     356             : 
     357             :   /**
     358             :    * aColors should be a two element array of nscolor in which the first
     359             :    * color is the unvisited color and the second is the visited color.
     360             :    *
     361             :    * Combine the R, G, and B components of whichever of aColors should
     362             :    * be used based on aLinkIsVisited with the A component of aColors[0].
     363             :    */
     364             :   static nscolor CombineVisitedColors(nscolor *aColors,
     365             :                                       bool aLinkIsVisited);
     366             : 
     367             :   /**
     368             :    * Start the background image loads for this style context.
     369             :    */
     370             :   inline void StartBackgroundImageLoads();
     371             : 
     372             :   /**
     373             :    * Moves this style context to a new parent.
     374             :    *
     375             :    * This function violates style context tree immutability, and
     376             :    * is a very low-level function and should only be used after verifying
     377             :    * many conditions that make it safe to call.
     378             :    */
     379             :   void MoveTo(nsStyleContext* aNewParent);
     380             : 
     381             : #ifdef DEBUG
     382             :   void List(FILE* out, int32_t aIndent, bool aListDescendants = true);
     383             :   static const char* StructName(nsStyleStructID aSID);
     384             :   static bool LookupStruct(const nsACString& aName, nsStyleStructID& aResult);
     385             : #endif
     386             : 
     387             : protected:
     388             :   // protected destructor to discourage deletion outside of Release()
     389        1618 :   ~nsStyleContext() {}
     390             :   // Where the actual destructor lives
     391             :   // We use this instead of a real destructor because we need
     392             :   // this to be called *before* the subclass fields are destroyed
     393             :   // by the subclass destructor
     394             :   void Destructor();
     395             :   // Delegated Helper constructor.
     396             :   nsStyleContext(nsStyleContext* aParent,
     397             :                  nsIAtom* aPseudoTag,
     398             :                  mozilla::CSSPseudoElementType aPseudoType);
     399             : 
     400             :   // Helper post-contruct hook.
     401             :   void FinishConstruction();
     402             : 
     403             :   // Only does stuff in Gecko mode
     404             :   void AddChild(nsStyleContext* aChild);
     405             :   void RemoveChild(nsStyleContext* aChild);
     406             : 
     407             :   void SetStyleBits();
     408             : 
     409             :   const void* StyleStructFromServoComputedValues(nsStyleStructID aSID) {
     410             :     switch (aSID) {
     411             : #define STYLE_STRUCT(name_, checkdata_cb_)                                    \
     412             :       case eStyleStruct_##name_:                                              \
     413             :         return Servo_GetStyle##name_(ComputedValues());
     414             : #include "nsStyleStructList.h"
     415             : #undef STYLE_STRUCT
     416             :       default:
     417             :         MOZ_ASSERT_UNREACHABLE("unexpected nsStyleStructID value");
     418             :         return nullptr;
     419             :     }
     420             :   }
     421             : 
     422             :   // Helper functions for GetStyle* and PeekStyle*
     423             :   #define STYLE_STRUCT_INHERITED(name_, checkdata_cb_)                  \
     424             :     template<bool aComputeData>                                         \
     425             :     const nsStyle##name_ * DoGetStyle##name_();
     426             :   #define STYLE_STRUCT_RESET(name_, checkdata_cb_)                      \
     427             :     template<bool aComputeData>                                         \
     428             :     const nsStyle##name_ * DoGetStyle##name_();
     429             : 
     430             :   #include "nsStyleStructList.h"
     431             :   #undef STYLE_STRUCT_RESET
     432             :   #undef STYLE_STRUCT_INHERITED
     433             : 
     434             :   RefPtr<nsStyleContext> mParent;
     435             : 
     436             :   // Style to be used instead for the R, G, and B components of color,
     437             :   // background-color, and border-*-color if the nearest ancestor link
     438             :   // element is visited (see RelevantLinkVisited()).
     439             :   RefPtr<nsStyleContext> mStyleIfVisited;
     440             : 
     441             :   // If this style context is for a pseudo-element or anonymous box,
     442             :   // the relevant atom.
     443             :   nsCOMPtr<nsIAtom> mPseudoTag;
     444             : 
     445             :   // mBits stores a number of things:
     446             :   //  - It records (using the style struct bits) which structs are
     447             :   //    inherited from the parent context or owned by the rule node (i.e.,
     448             :   //    not owned by the style context).
     449             :   //  - It also stores the additional bits listed at the top of
     450             :   //    nsStyleStruct.h.
     451             :   uint64_t                mBits;
     452             : 
     453             :   uint32_t                mRefCnt;
     454             : 
     455             : #ifdef DEBUG
     456             :   uint32_t                mFrameRefCnt; // number of frames that use this
     457             :                                         // as their style context
     458             : 
     459          67 :   static bool DependencyAllowed(nsStyleStructID aOuterSID,
     460             :                                 nsStyleStructID aInnerSID)
     461             :   {
     462         134 :     return !!(sDependencyTable[aOuterSID] &
     463         134 :               nsCachedStyleData::GetBitForSID(aInnerSID));
     464             :   }
     465             : 
     466             :   static const uint32_t sDependencyTable[];
     467             : #endif
     468             : };
     469             : 
     470             : already_AddRefed<nsStyleContext>
     471             : NS_NewStyleContext(nsStyleContext* aParentContext,
     472             :                    nsIAtom* aPseudoTag,
     473             :                    mozilla::CSSPseudoElementType aPseudoType,
     474             :                    nsRuleNode* aRuleNode,
     475             :                    bool aSkipParentDisplayBasedStyleFixup);
     476             : 
     477             : #endif

Generated by: LCOV version 1.13