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() const20size_t CFX_CSSStyleSheet::CountRules() const { 21 return m_RuleArray.size(); 22 } 23 GetRule(size_t index) const24CFX_CSSStyleRule* CFX_CSSStyleSheet::GetRule(size_t index) const { 25 return m_RuleArray[index].get(); 26 } 27 LoadBuffer(WideStringView buffer)28bool 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)42CFX_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)107void 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