blob: b888311bf4d6531b49da53e2f894a59ffb9c2d64 [file] [log] [blame] [edit]
// Copyright 2014 The PDFium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
#include "core/fxcrt/css/cfx_cssstylesheet.h"
#include <utility>
#include "core/fxcrt/css/cfx_cssdata.h"
#include "core/fxcrt/css/cfx_cssdeclaration.h"
#include "core/fxcrt/css/cfx_cssstylerule.h"
#include "core/fxcrt/fx_codepage.h"
CFX_CSSStyleSheet::CFX_CSSStyleSheet() = default;
CFX_CSSStyleSheet::~CFX_CSSStyleSheet() = default;
size_t CFX_CSSStyleSheet::CountRules() const {
return m_RuleArray.size();
}
CFX_CSSStyleRule* CFX_CSSStyleSheet::GetRule(size_t index) const {
return m_RuleArray[index].get();
}
bool CFX_CSSStyleSheet::LoadBuffer(WideStringView buffer) {
m_RuleArray.clear();
auto pSyntax = std::make_unique<CFX_CSSSyntaxParser>(buffer);
while (true) {
CFX_CSSSyntaxParser::Status eStatus = pSyntax->DoSyntaxParse();
if (eStatus == CFX_CSSSyntaxParser::Status::kStyleRule)
eStatus = LoadStyleRule(pSyntax.get());
if (eStatus == CFX_CSSSyntaxParser::Status::kEOS)
return true;
if (eStatus == CFX_CSSSyntaxParser::Status::kError)
return false;
}
}
CFX_CSSSyntaxParser::Status CFX_CSSStyleSheet::LoadStyleRule(
CFX_CSSSyntaxParser* pSyntax) {
std::vector<std::unique_ptr<CFX_CSSSelector>> selectors;
CFX_CSSStyleRule* pStyleRule = nullptr;
int32_t iValueLen = 0;
const CFX_CSSData::Property* property = nullptr;
WideString wsName;
while (true) {
switch (pSyntax->DoSyntaxParse()) {
case CFX_CSSSyntaxParser::Status::kSelector: {
WideStringView strValue = pSyntax->GetCurrentString();
auto pSelector = CFX_CSSSelector::FromString(strValue);
if (pSelector)
selectors.push_back(std::move(pSelector));
break;
}
case CFX_CSSSyntaxParser::Status::kPropertyName: {
WideStringView strValue = pSyntax->GetCurrentString();
property = CFX_CSSData::GetPropertyByName(strValue);
if (!property)
wsName = WideString(strValue);
break;
}
case CFX_CSSSyntaxParser::Status::kPropertyValue: {
if (property || iValueLen > 0) {
WideStringView strValue = pSyntax->GetCurrentString();
auto* decl = pStyleRule->GetDeclaration();
if (!strValue.IsEmpty()) {
if (property) {
decl->AddProperty(property, strValue);
} else {
decl->AddProperty(wsName, WideString(strValue));
}
}
}
break;
}
case CFX_CSSSyntaxParser::Status::kDeclOpen: {
if (!pStyleRule && !selectors.empty()) {
auto rule = std::make_unique<CFX_CSSStyleRule>();
pStyleRule = rule.get();
pStyleRule->SetSelector(&selectors);
m_RuleArray.push_back(std::move(rule));
} else {
SkipRuleSet(pSyntax);
return CFX_CSSSyntaxParser::Status::kNone;
}
break;
}
case CFX_CSSSyntaxParser::Status::kDeclClose: {
if (pStyleRule && pStyleRule->GetDeclaration()->empty()) {
m_RuleArray.pop_back();
pStyleRule = nullptr;
}
return CFX_CSSSyntaxParser::Status::kNone;
}
case CFX_CSSSyntaxParser::Status::kEOS:
return CFX_CSSSyntaxParser::Status::kEOS;
case CFX_CSSSyntaxParser::Status::kError:
default:
return CFX_CSSSyntaxParser::Status::kError;
}
}
}
void CFX_CSSStyleSheet::SkipRuleSet(CFX_CSSSyntaxParser* pSyntax) {
while (true) {
switch (pSyntax->DoSyntaxParse()) {
case CFX_CSSSyntaxParser::Status::kSelector:
case CFX_CSSSyntaxParser::Status::kDeclOpen:
case CFX_CSSSyntaxParser::Status::kPropertyName:
case CFX_CSSSyntaxParser::Status::kPropertyValue:
break;
case CFX_CSSSyntaxParser::Status::kDeclClose:
case CFX_CSSSyntaxParser::Status::kEOS:
case CFX_CSSSyntaxParser::Status::kError:
default:
return;
}
}
}