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