xref: /aosp_15_r20/external/pdfium/core/fxcrt/css/cfx_cssstylesheet.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1 // Copyright 2014 The PDFium Authors
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_cssdata.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 
16 CFX_CSSStyleSheet::CFX_CSSStyleSheet() = default;
17 
18 CFX_CSSStyleSheet::~CFX_CSSStyleSheet() = default;
19 
CountRules() const20 size_t CFX_CSSStyleSheet::CountRules() const {
21   return m_RuleArray.size();
22 }
23 
GetRule(size_t index) const24 CFX_CSSStyleRule* CFX_CSSStyleSheet::GetRule(size_t index) const {
25   return m_RuleArray[index].get();
26 }
27 
LoadBuffer(WideStringView buffer)28 bool CFX_CSSStyleSheet::LoadBuffer(WideStringView buffer) {
29   m_RuleArray.clear();
30   auto pSyntax = std::make_unique<CFX_CSSSyntaxParser>(buffer);
31   while (true) {
32     CFX_CSSSyntaxParser::Status eStatus = pSyntax->DoSyntaxParse();
33     if (eStatus == CFX_CSSSyntaxParser::Status::kStyleRule)
34       eStatus = LoadStyleRule(pSyntax.get());
35     if (eStatus == CFX_CSSSyntaxParser::Status::kEOS)
36       return true;
37     if (eStatus == CFX_CSSSyntaxParser::Status::kError)
38       return false;
39   }
40 }
41 
LoadStyleRule(CFX_CSSSyntaxParser * pSyntax)42 CFX_CSSSyntaxParser::Status CFX_CSSStyleSheet::LoadStyleRule(
43     CFX_CSSSyntaxParser* pSyntax) {
44   std::vector<std::unique_ptr<CFX_CSSSelector>> selectors;
45   CFX_CSSStyleRule* pStyleRule = nullptr;
46   int32_t iValueLen = 0;
47   const CFX_CSSData::Property* property = nullptr;
48   WideString wsName;
49   while (true) {
50     switch (pSyntax->DoSyntaxParse()) {
51       case CFX_CSSSyntaxParser::Status::kSelector: {
52         WideStringView strValue = pSyntax->GetCurrentString();
53         auto pSelector = CFX_CSSSelector::FromString(strValue);
54         if (pSelector)
55           selectors.push_back(std::move(pSelector));
56         break;
57       }
58       case CFX_CSSSyntaxParser::Status::kPropertyName: {
59         WideStringView strValue = pSyntax->GetCurrentString();
60         property = CFX_CSSData::GetPropertyByName(strValue);
61         if (!property)
62           wsName = WideString(strValue);
63         break;
64       }
65       case CFX_CSSSyntaxParser::Status::kPropertyValue: {
66         if (property || iValueLen > 0) {
67           WideStringView strValue = pSyntax->GetCurrentString();
68           auto* decl = pStyleRule->GetDeclaration();
69           if (!strValue.IsEmpty()) {
70             if (property) {
71               decl->AddProperty(property, strValue);
72             } else {
73               decl->AddProperty(wsName, WideString(strValue));
74             }
75           }
76         }
77         break;
78       }
79       case CFX_CSSSyntaxParser::Status::kDeclOpen: {
80         if (!pStyleRule && !selectors.empty()) {
81           auto rule = std::make_unique<CFX_CSSStyleRule>();
82           pStyleRule = rule.get();
83           pStyleRule->SetSelector(&selectors);
84           m_RuleArray.push_back(std::move(rule));
85         } else {
86           SkipRuleSet(pSyntax);
87           return CFX_CSSSyntaxParser::Status::kNone;
88         }
89         break;
90       }
91       case CFX_CSSSyntaxParser::Status::kDeclClose: {
92         if (pStyleRule && pStyleRule->GetDeclaration()->empty()) {
93           m_RuleArray.pop_back();
94           pStyleRule = nullptr;
95         }
96         return CFX_CSSSyntaxParser::Status::kNone;
97       }
98       case CFX_CSSSyntaxParser::Status::kEOS:
99         return CFX_CSSSyntaxParser::Status::kEOS;
100       case CFX_CSSSyntaxParser::Status::kError:
101       default:
102         return CFX_CSSSyntaxParser::Status::kError;
103     }
104   }
105 }
106 
SkipRuleSet(CFX_CSSSyntaxParser * pSyntax)107 void CFX_CSSStyleSheet::SkipRuleSet(CFX_CSSSyntaxParser* pSyntax) {
108   while (true) {
109     switch (pSyntax->DoSyntaxParse()) {
110       case CFX_CSSSyntaxParser::Status::kSelector:
111       case CFX_CSSSyntaxParser::Status::kDeclOpen:
112       case CFX_CSSSyntaxParser::Status::kPropertyName:
113       case CFX_CSSSyntaxParser::Status::kPropertyValue:
114         break;
115       case CFX_CSSSyntaxParser::Status::kDeclClose:
116       case CFX_CSSSyntaxParser::Status::kEOS:
117       case CFX_CSSSyntaxParser::Status::kError:
118       default:
119         return;
120     }
121   }
122 }
123