| // Copyright 2014 PDFium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
| |
| #include <algorithm> |
| |
| #include "xfa/src/foxitlib.h" |
| #include "fde_csscache.h" |
| _FDE_CSSCACHEITEM::_FDE_CSSCACHEITEM(IFDE_CSSStyleSheet* p) |
| : pStylesheet(p), dwActivity(0) { |
| FXSYS_assert(pStylesheet); |
| pStylesheet->AddRef(); |
| } |
| _FDE_CSSCACHEITEM::~_FDE_CSSCACHEITEM() { |
| pStylesheet->Release(); |
| } |
| IFDE_CSSStyleSheetCache* IFDE_CSSStyleSheetCache::Create() { |
| return new CFDE_CSSStyleSheetCache; |
| } |
| |
| CFDE_CSSStyleSheetCache::CFDE_CSSStyleSheetCache() |
| : m_pFixedStore(NULL), m_iMaxItems(5) {} |
| |
| CFDE_CSSStyleSheetCache::~CFDE_CSSStyleSheetCache() { |
| for (const auto& pair : m_Stylesheets) { |
| FDE_DeleteWith(FDE_CSSCACHEITEM, m_pFixedStore, pair.second); |
| } |
| m_Stylesheets.clear(); |
| if (m_pFixedStore) { |
| m_pFixedStore->Release(); |
| } |
| } |
| void CFDE_CSSStyleSheetCache::AddStyleSheet(const CFX_ByteStringC& szKey, |
| IFDE_CSSStyleSheet* pStyleSheet) { |
| FXSYS_assert(pStyleSheet != NULL); |
| if (m_pFixedStore == NULL) { |
| m_pFixedStore = |
| FX_CreateAllocator(FX_ALLOCTYPE_Fixed, std::max(10, m_iMaxItems), |
| sizeof(FDE_CSSCACHEITEM)); |
| FXSYS_assert(m_pFixedStore != NULL); |
| } |
| auto it = m_Stylesheets.find(szKey); |
| if (it != m_Stylesheets.end()) { |
| FDE_LPCSSCACHEITEM pItem = it->second; |
| if (pItem->pStylesheet != pStyleSheet) { |
| pItem->pStylesheet->Release(); |
| pItem->pStylesheet = pStyleSheet; |
| pItem->pStylesheet->AddRef(); |
| pItem->dwActivity = 0; |
| } |
| } else { |
| while (static_cast<int32_t>(m_Stylesheets.size()) >= m_iMaxItems) { |
| RemoveLowestActivityItem(); |
| } |
| m_Stylesheets[szKey] = |
| FDE_NewWith(m_pFixedStore) FDE_CSSCACHEITEM(pStyleSheet); |
| } |
| } |
| IFDE_CSSStyleSheet* CFDE_CSSStyleSheetCache::GetStyleSheet( |
| const CFX_ByteStringC& szKey) const { |
| auto it = m_Stylesheets.find(szKey); |
| if (it == m_Stylesheets.end()) { |
| return nullptr; |
| } |
| FDE_LPCSSCACHEITEM pItem = it->second; |
| pItem->dwActivity++; |
| pItem->pStylesheet->AddRef(); |
| return pItem->pStylesheet; |
| } |
| void CFDE_CSSStyleSheetCache::RemoveStyleSheet(const CFX_ByteStringC& szKey) { |
| auto it = m_Stylesheets.find(szKey); |
| if (it == m_Stylesheets.end()) { |
| return; |
| } |
| FDE_DeleteWith(FDE_CSSCACHEITEM, m_pFixedStore, it->second); |
| m_Stylesheets.erase(it); |
| } |
| void CFDE_CSSStyleSheetCache::RemoveLowestActivityItem() { |
| auto found = m_Stylesheets.end(); |
| for (auto it = m_Stylesheets.begin(); it != m_Stylesheets.end(); ++it) { |
| switch (it->first.GetID()) { |
| case FXBSTR_ID('#', 'U', 'S', 'E'): |
| case FXBSTR_ID('#', 'A', 'G', 'E'): |
| continue; |
| } |
| if (found == m_Stylesheets.end() || |
| it->second->dwActivity > found->second->dwActivity) { |
| found = it; |
| } |
| } |
| if (found != m_Stylesheets.end()) { |
| FDE_DeleteWith(FDE_CSSCACHEITEM, m_pFixedStore, found->second); |
| m_Stylesheets.erase(found); |
| } |
| } |
| _FDE_CSSTAGCACHE::_FDE_CSSTAGCACHE(_FDE_CSSTAGCACHE* parent, |
| IFDE_CSSTagProvider* tag) |
| : pTag(tag), |
| pParent(parent), |
| dwIDHash(0), |
| dwTagHash(0), |
| iClassIndex(0), |
| dwClassHashs(1) { |
| FXSYS_assert(pTag != NULL); |
| CFX_WideStringC wsValue, wsName = pTag->GetTagName(); |
| dwTagHash = |
| FX_HashCode_String_GetW(wsName.GetPtr(), wsName.GetLength(), TRUE); |
| FX_POSITION pos = pTag->GetFirstAttribute(); |
| while (pos != NULL) { |
| pTag->GetNextAttribute(pos, wsName, wsValue); |
| FX_DWORD dwNameHash = |
| FX_HashCode_String_GetW(wsName.GetPtr(), wsName.GetLength(), TRUE); |
| static const FX_DWORD s_dwIDHash = FX_HashCode_String_GetW(L"id", 2, TRUE); |
| static const FX_DWORD s_dwClassHash = |
| FX_HashCode_String_GetW(L"class", 5, TRUE); |
| if (dwNameHash == s_dwClassHash) { |
| FX_DWORD dwHash = |
| FX_HashCode_String_GetW(wsValue.GetPtr(), wsValue.GetLength()); |
| dwClassHashs.Add(dwHash); |
| } else if (dwNameHash == s_dwIDHash) { |
| dwIDHash = FX_HashCode_String_GetW(wsValue.GetPtr(), wsValue.GetLength()); |
| } |
| } |
| } |
| _FDE_CSSTAGCACHE::_FDE_CSSTAGCACHE(const _FDE_CSSTAGCACHE& it) |
| : pTag(it.pTag), |
| pParent(it.pParent), |
| dwIDHash(it.dwIDHash), |
| dwTagHash(it.dwTagHash), |
| iClassIndex(0), |
| dwClassHashs(1) { |
| if (it.dwClassHashs.GetSize() > 0) { |
| dwClassHashs.Copy(it.dwClassHashs); |
| } |
| } |
| void CFDE_CSSAccelerator::OnEnterTag(IFDE_CSSTagProvider* pTag) { |
| FDE_CSSTAGCACHE* pTop = GetTopElement(); |
| FDE_CSSTAGCACHE item(pTop, pTag); |
| m_Stack.Push(item); |
| } |
| void CFDE_CSSAccelerator::OnLeaveTag(IFDE_CSSTagProvider* pTag) { |
| FDE_CSSTAGCACHE* pItem = m_Stack.GetTopElement(); |
| FXSYS_assert(pItem && pItem->GetTag() == pTag); |
| m_Stack.Pop(); |
| } |