• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "core/fxcrt/css/cfx_cssstylesheet.h"
8 
9 #include <utility>
10 
11 #include "core/fxcrt/css/cfx_cssdatatable.h"
12 #include "core/fxcrt/css/cfx_cssdeclaration.h"
13 #include "core/fxcrt/css/cfx_cssstylerule.h"
14 #include "core/fxcrt/fx_codepage.h"
15 #include "third_party/base/ptr_util.h"
16 #include "third_party/base/stl_util.h"
17 
CFX_CSSStyleSheet()18 CFX_CSSStyleSheet::CFX_CSSStyleSheet() {}
19 
~CFX_CSSStyleSheet()20 CFX_CSSStyleSheet::~CFX_CSSStyleSheet() {
21   Reset();
22 }
23 
Reset()24 void CFX_CSSStyleSheet::Reset() {
25   m_RuleArray.clear();
26   m_StringCache.clear();
27 }
28 
CountRules() const29 int32_t CFX_CSSStyleSheet::CountRules() const {
30   return pdfium::CollectionSize<int32_t>(m_RuleArray);
31 }
32 
GetRule(int32_t index) const33 CFX_CSSStyleRule* CFX_CSSStyleSheet::GetRule(int32_t index) const {
34   return m_RuleArray[index].get();
35 }
36 
LoadBuffer(const wchar_t * pBuffer,int32_t iBufSize)37 bool CFX_CSSStyleSheet::LoadBuffer(const wchar_t* pBuffer, int32_t iBufSize) {
38   ASSERT(pBuffer);
39   ASSERT(iBufSize > 0);
40 
41   auto pSyntax = pdfium::MakeUnique<CFX_CSSSyntaxParser>(pBuffer, iBufSize);
42   Reset();
43   CFX_CSSSyntaxStatus eStatus;
44   do {
45     switch (eStatus = pSyntax->DoSyntaxParse()) {
46       case CFX_CSSSyntaxStatus::StyleRule:
47         eStatus = LoadStyleRule(pSyntax.get(), &m_RuleArray);
48         break;
49       default:
50         break;
51     }
52   } while (eStatus >= CFX_CSSSyntaxStatus::None);
53 
54   m_StringCache.clear();
55   return eStatus != CFX_CSSSyntaxStatus::Error;
56 }
57 
LoadStyleRule(CFX_CSSSyntaxParser * pSyntax,std::vector<std::unique_ptr<CFX_CSSStyleRule>> * ruleArray)58 CFX_CSSSyntaxStatus CFX_CSSStyleSheet::LoadStyleRule(
59     CFX_CSSSyntaxParser* pSyntax,
60     std::vector<std::unique_ptr<CFX_CSSStyleRule>>* ruleArray) {
61   std::vector<std::unique_ptr<CFX_CSSSelector>> selectors;
62 
63   CFX_CSSStyleRule* pStyleRule = nullptr;
64   int32_t iValueLen = 0;
65   const CFX_CSSPropertyTable* propertyTable = nullptr;
66   WideString wsName;
67   while (1) {
68     switch (pSyntax->DoSyntaxParse()) {
69       case CFX_CSSSyntaxStatus::Selector: {
70         WideStringView strValue = pSyntax->GetCurrentString();
71         auto pSelector = CFX_CSSSelector::FromString(strValue);
72         if (pSelector)
73           selectors.push_back(std::move(pSelector));
74         break;
75       }
76       case CFX_CSSSyntaxStatus::PropertyName: {
77         WideStringView strValue = pSyntax->GetCurrentString();
78         propertyTable = CFX_GetCSSPropertyByName(strValue);
79         if (!propertyTable)
80           wsName = WideString(strValue);
81         break;
82       }
83       case CFX_CSSSyntaxStatus::PropertyValue: {
84         if (propertyTable || iValueLen > 0) {
85           WideStringView strValue = pSyntax->GetCurrentString();
86           auto* decl = pStyleRule->GetDeclaration();
87           if (!strValue.IsEmpty()) {
88             if (propertyTable) {
89               decl->AddProperty(propertyTable, strValue);
90             } else {
91               decl->AddProperty(wsName, WideString(strValue));
92             }
93           }
94         }
95         break;
96       }
97       case CFX_CSSSyntaxStatus::DeclOpen: {
98         if (!pStyleRule && !selectors.empty()) {
99           auto rule = pdfium::MakeUnique<CFX_CSSStyleRule>();
100           pStyleRule = rule.get();
101           pStyleRule->SetSelector(&selectors);
102           ruleArray->push_back(std::move(rule));
103         } else {
104           SkipRuleSet(pSyntax);
105           return CFX_CSSSyntaxStatus::None;
106         }
107         break;
108       }
109       case CFX_CSSSyntaxStatus::DeclClose: {
110         if (pStyleRule && pStyleRule->GetDeclaration()->empty()) {
111           ruleArray->pop_back();
112           pStyleRule = nullptr;
113         }
114         return CFX_CSSSyntaxStatus::None;
115       }
116       case CFX_CSSSyntaxStatus::EOS:
117         return CFX_CSSSyntaxStatus::EOS;
118       case CFX_CSSSyntaxStatus::Error:
119       default:
120         return CFX_CSSSyntaxStatus::Error;
121     }
122   }
123 }
124 
SkipRuleSet(CFX_CSSSyntaxParser * pSyntax)125 void CFX_CSSStyleSheet::SkipRuleSet(CFX_CSSSyntaxParser* pSyntax) {
126   while (1) {
127     switch (pSyntax->DoSyntaxParse()) {
128       case CFX_CSSSyntaxStatus::Selector:
129       case CFX_CSSSyntaxStatus::DeclOpen:
130       case CFX_CSSSyntaxStatus::PropertyName:
131       case CFX_CSSSyntaxStatus::PropertyValue:
132         break;
133       case CFX_CSSSyntaxStatus::DeclClose:
134       case CFX_CSSSyntaxStatus::EOS:
135       case CFX_CSSSyntaxStatus::Error:
136       default:
137         return;
138     }
139   }
140 }
141