LCOV - code coverage report
Current view: top level - layout/style - CSSVariableImageTable.h (source / functions) Hit Total Coverage
Test: output.info Lines: 26 50 52.0 %
Date: 2017-07-14 16:53:18 Functions: 4 5 80.0 %
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             : /* A global table that tracks images referenced by CSS variables. */
       7             : 
       8             : #ifndef mozilla_CSSVariableImageTable_h
       9             : #define mozilla_CSSVariableImageTable_h
      10             : 
      11             : #include "nsClassHashtable.h"
      12             : #include "nsCSSPropertyID.h"
      13             : #include "nsCSSValue.h"
      14             : #include "nsStyleContext.h"
      15             : #include "nsTArray.h"
      16             : 
      17             : /**
      18             :  * CSSVariableImageTable maintains a global mapping
      19             :  *   (nsStyleContext, nsCSSPropertyID) -> nsTArray<ImageValue>
      20             :  * which allows us to track the relationship between CSS property values
      21             :  * involving variables and any images they may reference.
      22             :  *
      23             :  * When properties like background-image contain a normal url(), the
      24             :  * Declaration's data block will hold a reference to the ImageValue.  When a
      25             :  * token stream is used, the Declaration only holds on to an
      26             :  * nsCSSValueTokenStream object, and the ImageValue would only exist for the
      27             :  * duration of nsRuleNode::WalkRuleTree, in the AutoCSSValueArray.  So instead
      28             :  * when we re-parse a token stream and get an ImageValue, we record it in the
      29             :  * CSSVariableImageTable to keep the ImageValue alive. Such ImageValues are
      30             :  * eventually freed the next time the token stream is re-parsed, or when the
      31             :  * associated style context is destroyed.
      32             :  *
      33             :  * To add ImageValues to the CSSVariableImageTable, callers should pass a lambda
      34             :  * to CSSVariableImageTable::ReplaceAll() that calls
      35             :  * CSSVariableImageTable::Add() for each ImageValue that needs to be added to
      36             :  * the table. When callers are sure that the ImageValues for a given
      37             :  * nsStyleContext won't be needed anymore, they can call
      38             :  * CSSVariableImageTable::RemoveAll() to release them.
      39             :  */
      40             : 
      41             : namespace mozilla {
      42             : namespace CSSVariableImageTable {
      43             : 
      44             : namespace detail {
      45             : 
      46             : typedef nsTArray<RefPtr<css::ImageValue>> ImageValueArray;
      47             : typedef nsClassHashtable<nsGenericHashKey<nsCSSPropertyID>, ImageValueArray>
      48             :         PerPropertyImageHashtable;
      49             : typedef nsClassHashtable<nsPtrHashKey<nsStyleContext>, PerPropertyImageHashtable>
      50             :         CSSVariableImageHashtable;
      51             : 
      52        2501 : inline CSSVariableImageHashtable& GetTable()
      53             : {
      54        2501 :   static CSSVariableImageHashtable imageTable;
      55        2501 :   return imageTable;
      56             : }
      57             : 
      58             : #ifdef DEBUG
      59        2649 : inline bool& IsReplacing()
      60             : {
      61             :   static bool isReplacing = false;
      62        2649 :   return isReplacing;
      63             : }
      64             : #endif
      65             : 
      66             : } // namespace detail
      67             : 
      68             : /**
      69             :  * ReplaceAll() allows callers to replace the ImageValues associated with a
      70             :  * (nsStyleContext, nsCSSPropertyID) pair. The memory used by the previous list of
      71             :  * ImageValues is automatically released.
      72             :  *
      73             :  * @param aContext The style context the ImageValues are associated with.
      74             :  * @param aProp    The CSS property the ImageValues are associated with.
      75             :  * @param aFunc    A lambda that calls CSSVariableImageTable::Add() to add new
      76             :  *                 ImageValues which will replace the old ones.
      77             :  */
      78             : template <typename Lambda>
      79         883 : inline void ReplaceAll(nsStyleContext* aContext,
      80             :                        nsCSSPropertyID aProp,
      81             :                        Lambda aFunc)
      82             : {
      83         883 :   MOZ_ASSERT(aContext);
      84             : 
      85         883 :   auto& imageTable = detail::GetTable();
      86             : 
      87             :   // Clear the existing image array, if any, for this property.
      88             :   {
      89         883 :     auto* perPropertyImageTable = imageTable.Get(aContext);
      90             :     auto* imageList = perPropertyImageTable ? perPropertyImageTable->Get(aProp)
      91         883 :                                             : nullptr;
      92         883 :     if (imageList) {
      93           0 :       imageList->ClearAndRetainStorage();
      94             :     }
      95             :   }
      96             : 
      97             : #ifdef DEBUG
      98         883 :   MOZ_ASSERT(!detail::IsReplacing());
      99         883 :   detail::IsReplacing() = true;
     100             : #endif
     101             : 
     102         883 :   aFunc();
     103             : 
     104             : #ifdef DEBUG
     105         883 :   detail::IsReplacing() = false;
     106             : #endif
     107             : 
     108             :   // Clean up.
     109         883 :   auto* perPropertyImageTable = imageTable.Get(aContext);
     110             :   auto* imageList = perPropertyImageTable ? perPropertyImageTable->Get(aProp)
     111         883 :                                           : nullptr;
     112         883 :   if (imageList) {
     113           0 :     if (imageList->IsEmpty()) {
     114             :       // We used to have an image array for this property, but now we don't.
     115             :       // Remove the entry in the per-property image table for this property.
     116             :       // That may then allow us to remove the entire per-property image table.
     117           0 :       perPropertyImageTable->Remove(aProp);
     118           0 :       if (perPropertyImageTable->Count() == 0) {
     119           0 :         imageTable.Remove(aContext);
     120             :       }
     121             :     } else {
     122             :       // We still have a non-empty image array for this property. Compact the
     123             :       // storage it's using if possible.
     124           0 :       imageList->Compact();
     125             :     }
     126             :   }
     127         883 : }
     128             : 
     129             : /**
     130             :  * Adds a new ImageValue @aValue to the CSSVariableImageTable, which will be
     131             :  * associated with @aContext and @aProp.
     132             :  *
     133             :  * It's illegal to call this function outside of a lambda passed to
     134             :  * CSSVariableImageTable::ReplaceAll().
     135             :  */
     136             : inline void
     137           0 : Add(nsStyleContext* aContext, nsCSSPropertyID aProp, css::ImageValue* aValue)
     138             : {
     139           0 :   MOZ_ASSERT(aValue);
     140           0 :   MOZ_ASSERT(aContext);
     141           0 :   MOZ_ASSERT(detail::IsReplacing());
     142             : 
     143           0 :   auto& imageTable = detail::GetTable();
     144             : 
     145             :   // Ensure there's a per-property image table for this style context.
     146           0 :   auto* perPropertyImageTable = imageTable.Get(aContext);
     147           0 :   if (!perPropertyImageTable) {
     148           0 :     perPropertyImageTable = new detail::PerPropertyImageHashtable();
     149           0 :     imageTable.Put(aContext, perPropertyImageTable);
     150             :   }
     151             : 
     152             :   // Ensure there's an image array for this property.
     153           0 :   auto* imageList = perPropertyImageTable->Get(aProp);
     154           0 :   if (!imageList) {
     155           0 :     imageList = new detail::ImageValueArray();
     156           0 :     perPropertyImageTable->Put(aProp, imageList);
     157             :   }
     158             : 
     159             :   // Append the provided ImageValue to the list.
     160           0 :   imageList->AppendElement(aValue);
     161           0 : }
     162             : 
     163             : /**
     164             :  * Removes all ImageValues stored in the CSSVariableImageTable for the provided
     165             :  * @aContext.
     166             :  */
     167             : inline void
     168        1618 : RemoveAll(nsStyleContext* aContext)
     169             : {
     170             :   // Move all ImageValue references into removedImageList so that we can
     171             :   // release them outside of any hashtable methods.  (If we just call
     172             :   // Remove(aContext) on the table then we can end up calling back
     173             :   // re-entrantly into hashtable methods, as other style contexts
     174             :   // are released.)
     175        3236 :   detail::ImageValueArray removedImages;
     176        1618 :   auto& imageTable = detail::GetTable();
     177        1618 :   auto* perPropertyImageTable = imageTable.Get(aContext);
     178        1618 :   if (perPropertyImageTable) {
     179           0 :     for (auto it = perPropertyImageTable->Iter(); !it.Done(); it.Next()) {
     180           0 :       auto* imageList = it.UserData();
     181           0 :       removedImages.AppendElements(Move(*imageList));
     182             :     }
     183             :   }
     184        1618 :   imageTable.Remove(aContext);
     185        1618 : }
     186             : 
     187             : } // namespace CSSVariableImageTable
     188             : } // namespace mozilla
     189             : 
     190             : #endif // mozilla_CSSVariableImageTable_h

Generated by: LCOV version 1.13