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 18CFDE_CSSStyleSheet::CFDE_CSSStyleSheet() {} 19 20CFDE_CSSStyleSheet::~CFDE_CSSStyleSheet() { 21 Reset(); 22} 23 24void CFDE_CSSStyleSheet::Reset() { 25 m_RuleArray.clear(); 26 m_StringCache.clear(); 27} 28 29int32_t CFDE_CSSStyleSheet::CountRules() const { 30 return pdfium::CollectionSize<int32_t>(m_RuleArray); 31} 32 33CFDE_CSSStyleRule* CFDE_CSSStyleSheet::GetRule(int32_t index) const { 34 return m_RuleArray[index].get(); 35} 36 37bool 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 60FDE_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 127void 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