Home | History | Annotate | Download | only in css
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include <algorithm>
      8 
      9 #include "xfa/src/foxitlib.h"
     10 #include "fde_csscache.h"
     11 _FDE_CSSCACHEITEM::_FDE_CSSCACHEITEM(IFDE_CSSStyleSheet* p)
     12     : pStylesheet(p), dwActivity(0) {
     13   FXSYS_assert(pStylesheet);
     14   pStylesheet->AddRef();
     15 }
     16 _FDE_CSSCACHEITEM::~_FDE_CSSCACHEITEM() {
     17   pStylesheet->Release();
     18 }
     19 IFDE_CSSStyleSheetCache* IFDE_CSSStyleSheetCache::Create() {
     20   return new CFDE_CSSStyleSheetCache;
     21 }
     22 
     23 CFDE_CSSStyleSheetCache::CFDE_CSSStyleSheetCache()
     24     : m_pFixedStore(NULL), m_iMaxItems(5) {}
     25 
     26 CFDE_CSSStyleSheetCache::~CFDE_CSSStyleSheetCache() {
     27   for (const auto& pair : m_Stylesheets) {
     28     FDE_DeleteWith(FDE_CSSCACHEITEM, m_pFixedStore, pair.second);
     29   }
     30   m_Stylesheets.clear();
     31   if (m_pFixedStore) {
     32     m_pFixedStore->Release();
     33   }
     34 }
     35 void CFDE_CSSStyleSheetCache::AddStyleSheet(const CFX_ByteStringC& szKey,
     36                                             IFDE_CSSStyleSheet* pStyleSheet) {
     37   FXSYS_assert(pStyleSheet != NULL);
     38   if (m_pFixedStore == NULL) {
     39     m_pFixedStore =
     40         FX_CreateAllocator(FX_ALLOCTYPE_Fixed, std::max(10, m_iMaxItems),
     41                            sizeof(FDE_CSSCACHEITEM));
     42     FXSYS_assert(m_pFixedStore != NULL);
     43   }
     44   auto it = m_Stylesheets.find(szKey);
     45   if (it != m_Stylesheets.end()) {
     46     FDE_LPCSSCACHEITEM pItem = it->second;
     47     if (pItem->pStylesheet != pStyleSheet) {
     48       pItem->pStylesheet->Release();
     49       pItem->pStylesheet = pStyleSheet;
     50       pItem->pStylesheet->AddRef();
     51       pItem->dwActivity = 0;
     52     }
     53   } else {
     54     while (static_cast<int32_t>(m_Stylesheets.size()) >= m_iMaxItems) {
     55       RemoveLowestActivityItem();
     56     }
     57     m_Stylesheets[szKey] =
     58         FDE_NewWith(m_pFixedStore) FDE_CSSCACHEITEM(pStyleSheet);
     59   }
     60 }
     61 IFDE_CSSStyleSheet* CFDE_CSSStyleSheetCache::GetStyleSheet(
     62     const CFX_ByteStringC& szKey) const {
     63   auto it = m_Stylesheets.find(szKey);
     64   if (it == m_Stylesheets.end()) {
     65     return nullptr;
     66   }
     67   FDE_LPCSSCACHEITEM pItem = it->second;
     68   pItem->dwActivity++;
     69   pItem->pStylesheet->AddRef();
     70   return pItem->pStylesheet;
     71 }
     72 void CFDE_CSSStyleSheetCache::RemoveStyleSheet(const CFX_ByteStringC& szKey) {
     73   auto it = m_Stylesheets.find(szKey);
     74   if (it == m_Stylesheets.end()) {
     75     return;
     76   }
     77   FDE_DeleteWith(FDE_CSSCACHEITEM, m_pFixedStore, it->second);
     78   m_Stylesheets.erase(it);
     79 }
     80 void CFDE_CSSStyleSheetCache::RemoveLowestActivityItem() {
     81   auto found = m_Stylesheets.end();
     82   for (auto it = m_Stylesheets.begin(); it != m_Stylesheets.end(); ++it) {
     83     switch (it->first.GetID()) {
     84       case FXBSTR_ID('#', 'U', 'S', 'E'):
     85       case FXBSTR_ID('#', 'A', 'G', 'E'):
     86         continue;
     87     }
     88     if (found == m_Stylesheets.end() ||
     89         it->second->dwActivity > found->second->dwActivity) {
     90       found = it;
     91     }
     92   }
     93   if (found != m_Stylesheets.end()) {
     94     FDE_DeleteWith(FDE_CSSCACHEITEM, m_pFixedStore, found->second);
     95     m_Stylesheets.erase(found);
     96   }
     97 }
     98 _FDE_CSSTAGCACHE::_FDE_CSSTAGCACHE(_FDE_CSSTAGCACHE* parent,
     99                                    IFDE_CSSTagProvider* tag)
    100     : pTag(tag),
    101       pParent(parent),
    102       dwIDHash(0),
    103       dwTagHash(0),
    104       iClassIndex(0),
    105       dwClassHashs(1) {
    106   FXSYS_assert(pTag != NULL);
    107   CFX_WideStringC wsValue, wsName = pTag->GetTagName();
    108   dwTagHash =
    109       FX_HashCode_String_GetW(wsName.GetPtr(), wsName.GetLength(), TRUE);
    110   FX_POSITION pos = pTag->GetFirstAttribute();
    111   while (pos != NULL) {
    112     pTag->GetNextAttribute(pos, wsName, wsValue);
    113     FX_DWORD dwNameHash =
    114         FX_HashCode_String_GetW(wsName.GetPtr(), wsName.GetLength(), TRUE);
    115     static const FX_DWORD s_dwIDHash = FX_HashCode_String_GetW(L"id", 2, TRUE);
    116     static const FX_DWORD s_dwClassHash =
    117         FX_HashCode_String_GetW(L"class", 5, TRUE);
    118     if (dwNameHash == s_dwClassHash) {
    119       FX_DWORD dwHash =
    120           FX_HashCode_String_GetW(wsValue.GetPtr(), wsValue.GetLength());
    121       dwClassHashs.Add(dwHash);
    122     } else if (dwNameHash == s_dwIDHash) {
    123       dwIDHash = FX_HashCode_String_GetW(wsValue.GetPtr(), wsValue.GetLength());
    124     }
    125   }
    126 }
    127 _FDE_CSSTAGCACHE::_FDE_CSSTAGCACHE(const _FDE_CSSTAGCACHE& it)
    128     : pTag(it.pTag),
    129       pParent(it.pParent),
    130       dwIDHash(it.dwIDHash),
    131       dwTagHash(it.dwTagHash),
    132       iClassIndex(0),
    133       dwClassHashs(1) {
    134   if (it.dwClassHashs.GetSize() > 0) {
    135     dwClassHashs.Copy(it.dwClassHashs);
    136   }
    137 }
    138 void CFDE_CSSAccelerator::OnEnterTag(IFDE_CSSTagProvider* pTag) {
    139   FDE_CSSTAGCACHE* pTop = GetTopElement();
    140   FDE_CSSTAGCACHE item(pTop, pTag);
    141   m_Stack.Push(item);
    142 }
    143 void CFDE_CSSAccelerator::OnLeaveTag(IFDE_CSSTagProvider* pTag) {
    144   FDE_CSSTAGCACHE* pItem = m_Stack.GetTopElement();
    145   FXSYS_assert(pItem && pItem->GetTag() == pTag);
    146   m_Stack.Pop();
    147 }
    148