LCOV - code coverage report
Current view: top level - layout/style - CounterStyleManager.h (source / functions) Hit Total Coverage
Test: output.info Lines: 35 98 35.7 %
Date: 2017-07-14 16:53:18 Functions: 15 42 35.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : #ifndef mozilla_CounterStyleManager_h_
       7             : #define mozilla_CounterStyleManager_h_
       8             : 
       9             : #include "nsIAtom.h"
      10             : #include "nsStringFwd.h"
      11             : #include "nsDataHashtable.h"
      12             : #include "nsHashKeys.h"
      13             : 
      14             : #include "nsStyleConsts.h"
      15             : 
      16             : #include "mozilla/Attributes.h"
      17             : 
      18             : #include "nsCSSValue.h"
      19             : 
      20             : class nsPresContext;
      21             : 
      22             : namespace mozilla {
      23             : 
      24             : class WritingMode;
      25             : 
      26             : typedef int32_t CounterValue;
      27             : 
      28             : class CounterStyleManager;
      29             : class AnonymousCounterStyle;
      30             : 
      31             : struct NegativeType;
      32             : struct PadType;
      33             : 
      34             : class CounterStyle
      35             : {
      36             : protected:
      37           0 :   explicit constexpr CounterStyle(int32_t aStyle)
      38           0 :     : mStyle(aStyle)
      39             :   {
      40           0 :   }
      41             : 
      42             : private:
      43             :   CounterStyle(const CounterStyle& aOther) = delete;
      44             :   void operator=(const CounterStyle& other) = delete;
      45             : 
      46             : public:
      47           0 :   int32_t GetStyle() const { return mStyle; }
      48           0 :   bool IsNone() const { return mStyle == NS_STYLE_LIST_STYLE_NONE; }
      49           0 :   bool IsCustomStyle() const { return mStyle == NS_STYLE_LIST_STYLE_CUSTOM; }
      50             :   // A style is dependent if it depends on the counter style manager.
      51             :   // Custom styles are certainly dependent. In addition, some builtin
      52             :   // styles are dependent for fallback.
      53             :   bool IsDependentStyle() const;
      54             : 
      55             :   virtual void GetStyleName(nsAString& aResult) = 0;
      56             :   virtual void GetPrefix(nsAString& aResult) = 0;
      57             :   virtual void GetSuffix(nsAString& aResult) = 0;
      58             :   void GetCounterText(CounterValue aOrdinal,
      59             :                       WritingMode aWritingMode,
      60             :                       nsAString& aResult,
      61             :                       bool& aIsRTL);
      62             :   virtual void GetSpokenCounterText(CounterValue aOrdinal,
      63             :                                     WritingMode aWritingMode,
      64             :                                     nsAString& aResult,
      65             :                                     bool& aIsBullet);
      66             : 
      67             :   // XXX This method could be removed once ::-moz-list-bullet and
      68             :   //     ::-moz-list-number are completely merged into ::marker.
      69             :   virtual bool IsBullet() = 0;
      70             : 
      71             :   virtual void GetNegative(NegativeType& aResult) = 0;
      72             :   /**
      73             :    * This method returns whether an ordinal is in the range of this
      74             :    * counter style. Note that, it is possible that an ordinal in range
      75             :    * is rejected by the generating algorithm.
      76             :    */
      77             :   virtual bool IsOrdinalInRange(CounterValue aOrdinal) = 0;
      78             :   /**
      79             :    * This method returns whether an ordinal is in the default range of
      80             :    * this counter style. This is the effective range when no 'range'
      81             :    * descriptor is specified.
      82             :    */
      83             :   virtual bool IsOrdinalInAutoRange(CounterValue aOrdinal) = 0;
      84             :   virtual void GetPad(PadType& aResult) = 0;
      85             :   virtual CounterStyle* GetFallback() = 0;
      86             :   virtual uint8_t GetSpeakAs() = 0;
      87             :   virtual bool UseNegativeSign() = 0;
      88             : 
      89             :   virtual void CallFallbackStyle(CounterValue aOrdinal,
      90             :                                  WritingMode aWritingMode,
      91             :                                  nsAString& aResult,
      92             :                                  bool& aIsRTL);
      93             :   virtual bool GetInitialCounterText(CounterValue aOrdinal,
      94             :                                      WritingMode aWritingMode,
      95             :                                      nsAString& aResult,
      96             :                                      bool& aIsRTL) = 0;
      97             : 
      98           3 :   virtual AnonymousCounterStyle* AsAnonymous() { return nullptr; }
      99             : 
     100             : protected:
     101             :   int32_t mStyle;
     102             : };
     103             : 
     104             : class AnonymousCounterStyle final : public CounterStyle
     105             : {
     106             : public:
     107             :   explicit AnonymousCounterStyle(const nsAString& aContent);
     108             :   AnonymousCounterStyle(uint8_t aSystem, nsTArray<nsString> aSymbols);
     109             :   explicit AnonymousCounterStyle(const nsCSSValue::Array* aValue);
     110             : 
     111             :   virtual void GetStyleName(nsAString& aResult) override;
     112             :   virtual void GetPrefix(nsAString& aResult) override;
     113             :   virtual void GetSuffix(nsAString& aResult) override;
     114             :   virtual bool IsBullet() override;
     115             : 
     116             :   virtual void GetNegative(NegativeType& aResult) override;
     117             :   virtual bool IsOrdinalInRange(CounterValue aOrdinal) override;
     118             :   virtual bool IsOrdinalInAutoRange(CounterValue aOrdinal) override;
     119             :   virtual void GetPad(PadType& aResult) override;
     120             :   virtual CounterStyle* GetFallback() override;
     121             :   virtual uint8_t GetSpeakAs() override;
     122             :   virtual bool UseNegativeSign() override;
     123             : 
     124             :   virtual bool GetInitialCounterText(CounterValue aOrdinal,
     125             :                                      WritingMode aWritingMode,
     126             :                                      nsAString& aResult,
     127             :                                      bool& aIsRTL) override;
     128             : 
     129           0 :   virtual AnonymousCounterStyle* AsAnonymous() override { return this; }
     130             : 
     131           0 :   bool IsSingleString() const { return mSingleString; }
     132           0 :   uint8_t GetSystem() const { return mSystem; }
     133           0 :   const nsTArray<nsString>& GetSymbols() const { return mSymbols; }
     134             : 
     135           0 :   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AnonymousCounterStyle)
     136             : 
     137             : private:
     138           0 :   ~AnonymousCounterStyle() {}
     139             : 
     140             :   bool mSingleString;
     141             :   uint8_t mSystem;
     142             :   nsTArray<nsString> mSymbols;
     143             : };
     144             : 
     145             : // A smart pointer to CounterStyle. It either owns a reference to an
     146             : // anonymous counter style, or weakly refers to a named counter style
     147             : // managed by counter style manager.
     148             : class CounterStylePtr
     149             : {
     150             : public:
     151           3 :   CounterStylePtr() : mRaw(0) {}
     152         130 :   CounterStylePtr(const CounterStylePtr& aOther)
     153         130 :     : mRaw(aOther.mRaw)
     154             :   {
     155         130 :     switch (GetType()) {
     156             :       case eCounterStyle:
     157         130 :         break;
     158             :       case eAnonymousCounterStyle:
     159           0 :         AsAnonymous()->AddRef();
     160           0 :         break;
     161             :       case eUnresolvedAtom:
     162           0 :         AsAtom()->AddRef();
     163           0 :         break;
     164             :       case eMask:
     165           0 :         MOZ_ASSERT_UNREACHABLE("Unknown type");
     166             :         break;
     167             :     }
     168         130 :   }
     169             :   CounterStylePtr(CounterStylePtr&& aOther)
     170             :     : mRaw(aOther.mRaw)
     171             :   {
     172             :     aOther.mRaw = 0;
     173             :   }
     174         105 :   ~CounterStylePtr() { Reset(); }
     175             : 
     176           0 :   CounterStylePtr& operator=(const CounterStylePtr& aOther)
     177             :   {
     178           0 :     if (this != &aOther) {
     179           0 :       Reset();
     180           0 :       new (this) CounterStylePtr(aOther);
     181             :     }
     182           0 :     return *this;
     183             :   }
     184             :   CounterStylePtr& operator=(CounterStylePtr&& aOther)
     185             :   {
     186             :     if (this != &aOther) {
     187             :       Reset();
     188             :       mRaw = aOther.mRaw;
     189             :       aOther.mRaw = 0;
     190             :     }
     191             :     return *this;
     192             :   }
     193             :   CounterStylePtr& operator=(decltype(nullptr))
     194             :   {
     195             :     Reset();
     196             :     return *this;
     197             :   }
     198           0 :   CounterStylePtr& operator=(already_AddRefed<nsIAtom> aAtom)
     199             :   {
     200           0 :     Reset();
     201           0 :     if (nsIAtom* raw = aAtom.take()) {
     202           0 :       AssertPointerAligned(raw);
     203           0 :       mRaw = reinterpret_cast<uintptr_t>(raw) | eUnresolvedAtom;
     204             :     }
     205           0 :     return *this;
     206             :   }
     207           0 :   CounterStylePtr& operator=(AnonymousCounterStyle* aCounterStyle)
     208             :   {
     209           0 :     Reset();
     210           0 :     if (aCounterStyle) {
     211           0 :       CounterStyle* raw = do_AddRef(aCounterStyle).take();
     212           0 :       AssertPointerAligned(raw);
     213           0 :       mRaw = reinterpret_cast<uintptr_t>(raw) | eAnonymousCounterStyle;
     214             :     }
     215           0 :     return *this;
     216             :   }
     217           3 :   CounterStylePtr& operator=(CounterStyle* aCounterStyle)
     218             :   {
     219           3 :     Reset();
     220           3 :     if (aCounterStyle) {
     221           3 :       MOZ_ASSERT(!aCounterStyle->AsAnonymous());
     222           3 :       AssertPointerAligned(aCounterStyle);
     223           3 :       mRaw = reinterpret_cast<uintptr_t>(aCounterStyle) | eCounterStyle;
     224             :     }
     225           3 :     return *this;
     226             :   }
     227             : 
     228           0 :   operator CounterStyle*() const & { return Get(); }
     229             :   operator CounterStyle*() const && = delete;
     230           0 :   CounterStyle* operator->() const { return Get(); }
     231             :   explicit operator bool() const { return !!mRaw; }
     232             :   bool operator!() const { return !mRaw; }
     233           0 :   bool operator==(const CounterStylePtr& aOther) const
     234           0 :     { return mRaw == aOther.mRaw; }
     235          93 :   bool operator!=(const CounterStylePtr& aOther) const
     236          93 :     { return mRaw != aOther.mRaw; }
     237             : 
     238           0 :   bool IsResolved() const { return !IsUnresolved(); }
     239             :   inline void Resolve(CounterStyleManager* aManager);
     240             : 
     241             : private:
     242           0 :   CounterStyle* Get() const
     243             :   {
     244           0 :     MOZ_ASSERT(IsResolved());
     245           0 :     return reinterpret_cast<CounterStyle*>(mRaw & ~eMask);
     246             :   }
     247             :   template<typename T>
     248           3 :   void AssertPointerAligned(T* aPointer)
     249             :   {
     250             :     // This can be checked at compile time via
     251             :     // > static_assert(alignof(CounterStyle) >= 4);
     252             :     // > static_assert(alignof(nsIAtom) >= 4);
     253             :     // but MSVC2015 doesn't support using alignof on an abstract class.
     254             :     // Once we move to MSVC2017, we can replace this runtime check with
     255             :     // the compile time check above.
     256           3 :     MOZ_ASSERT(!(reinterpret_cast<uintptr_t>(aPointer) & eMask));
     257           3 :   }
     258             : 
     259             :   enum Type : uintptr_t {
     260             :     eCounterStyle = 0,
     261             :     eAnonymousCounterStyle = 1,
     262             :     eUnresolvedAtom = 2,
     263             :     eMask = 3,
     264             :   };
     265             : 
     266         238 :   Type GetType() const { return static_cast<Type>(mRaw & eMask); }
     267           0 :   bool IsUnresolved() const { return GetType() == eUnresolvedAtom; }
     268           0 :   bool IsAnonymous() const { return GetType() == eAnonymousCounterStyle; }
     269           0 :   nsIAtom* AsAtom()
     270             :   {
     271           0 :     MOZ_ASSERT(IsUnresolved());
     272           0 :     return reinterpret_cast<nsIAtom*>(mRaw & ~eMask);
     273             :   }
     274           0 :   AnonymousCounterStyle* AsAnonymous()
     275             :   {
     276           0 :     MOZ_ASSERT(IsAnonymous());
     277             :     return static_cast<AnonymousCounterStyle*>(
     278           0 :       reinterpret_cast<CounterStyle*>(mRaw & ~eMask));
     279             :   }
     280             : 
     281         108 :   void Reset()
     282             :   {
     283         108 :     switch (GetType()) {
     284             :       case eCounterStyle:
     285         108 :         break;
     286             :       case eAnonymousCounterStyle:
     287           0 :         AsAnonymous()->Release();
     288           0 :         break;
     289             :       case eUnresolvedAtom:
     290           0 :         AsAtom()->Release();
     291           0 :         break;
     292             :       case eMask:
     293           0 :         MOZ_ASSERT_UNREACHABLE("Unknown type");
     294             :         break;
     295             :     }
     296         108 :     mRaw = 0;
     297         108 :   }
     298             : 
     299             :   // mRaw contains the pointer, and its last two bits are used for type
     300             :   // of the pointer.
     301             :   // If the type is eUnresolvedAtom, the pointer owns a reference to an
     302             :   // nsIAtom, and it needs to be resolved to a counter style before use.
     303             :   // If the type is eAnonymousCounterStyle, it owns a reference to an
     304             :   // anonymous counter style.
     305             :   // Otherwise it is a weak pointer referring a named counter style
     306             :   // managed by CounterStyleManager.
     307             :   uintptr_t mRaw;
     308             : };
     309             : 
     310             : class CounterStyleManager final
     311             : {
     312             : private:
     313             :   ~CounterStyleManager();
     314             : public:
     315             :   explicit CounterStyleManager(nsPresContext* aPresContext);
     316             : 
     317             :   static void InitializeBuiltinCounterStyles();
     318             : 
     319             :   void Disconnect();
     320             : 
     321         247 :   bool IsInitial() const
     322             :   {
     323             :     // only 'none', 'decimal', and 'disc'
     324         247 :     return mStyles.Count() == 3;
     325             :   }
     326             : 
     327             :   // Returns the counter style object for the given name from the style
     328             :   // table if it is already built, and nullptr otherwise.
     329           0 :   CounterStyle* GetCounterStyle(nsIAtom* aName) const {
     330           0 :     return mStyles.Get(aName);
     331             :   }
     332             :   // Same as GetCounterStyle but try to build the counter style object
     333             :   // rather than returning nullptr if that hasn't been built.
     334             :   CounterStyle* BuildCounterStyle(nsIAtom* aName);
     335             : 
     336             :   static CounterStyle* GetBuiltinStyle(int32_t aStyle);
     337          28 :   static CounterStyle* GetNoneStyle()
     338             :   {
     339          28 :     return GetBuiltinStyle(NS_STYLE_LIST_STYLE_NONE);
     340             :   }
     341          28 :   static CounterStyle* GetDecimalStyle()
     342             :   {
     343          28 :     return GetBuiltinStyle(NS_STYLE_LIST_STYLE_DECIMAL);
     344             :   }
     345          31 :   static CounterStyle* GetDiscStyle()
     346             :   {
     347          31 :     return GetBuiltinStyle(NS_STYLE_LIST_STYLE_DISC);
     348             :   }
     349             : 
     350             :   // This method will scan all existing counter styles generated by this
     351             :   // manager, and remove or mark data dirty accordingly. It returns true
     352             :   // if any counter style is changed, false elsewise. This method should
     353             :   // be called when any counter style may be affected.
     354             :   bool NotifyRuleChanged();
     355             :   // NotifyRuleChanged will evict no longer needed counter styles into
     356             :   // mRetiredStyles, and this function destroys all objects listed there.
     357             :   // It should be called only after no one may ever use those objects.
     358             :   void CleanRetiredStyles();
     359             : 
     360           0 :   nsPresContext* PresContext() const { return mPresContext; }
     361             : 
     362          36 :   NS_INLINE_DECL_REFCOUNTING(CounterStyleManager)
     363             : 
     364             : private:
     365             :   void DestroyCounterStyle(CounterStyle* aCounterStyle);
     366             : 
     367             :   nsPresContext* mPresContext;
     368             :   nsDataHashtable<nsRefPtrHashKey<nsIAtom>, CounterStyle*> mStyles;
     369             :   nsTArray<CounterStyle*> mRetiredStyles;
     370             : };
     371             : 
     372             : void
     373           0 : CounterStylePtr::Resolve(CounterStyleManager* aManager)
     374             : {
     375           0 :   if (IsUnresolved()) {
     376           0 :     *this = aManager->BuildCounterStyle(AsAtom());
     377             :   }
     378           0 : }
     379             : 
     380             : } // namespace mozilla
     381             : 
     382             : #endif /* !defined(mozilla_CounterStyleManager_h_) */

Generated by: LCOV version 1.13