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