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