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