Dan Sinclair | 1770c02 | 2016-03-14 14:14:16 -0400 | [diff] [blame] | 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 | |
Dan Sinclair | 95bec80 | 2017-01-19 10:27:58 -0500 | [diff] [blame] | 7 | #include "xfa/fde/css/cfde_cssstylesheet.h" |
Dan Sinclair | 1770c02 | 2016-03-14 14:14:16 -0400 | [diff] [blame] | 8 | |
Dan Sinclair | 95bec80 | 2017-01-19 10:27:58 -0500 | [diff] [blame] | 9 | #include <utility> |
tsepez | f74ad99 | 2016-05-11 10:26:05 -0700 | [diff] [blame] | 10 | |
Dan Sinclair | 3b71d26 | 2017-04-19 08:58:54 -0400 | [diff] [blame] | 11 | #include "core/fxcrt/fx_codepage.h" |
tsepez | 7cda31a | 2016-12-07 12:10:20 -0800 | [diff] [blame] | 12 | #include "third_party/base/ptr_util.h" |
Dan Sinclair | 3285c56 | 2017-01-17 16:35:16 -0500 | [diff] [blame] | 13 | #include "third_party/base/stl_util.h" |
Dan Sinclair | 95bec80 | 2017-01-19 10:27:58 -0500 | [diff] [blame] | 14 | #include "xfa/fde/css/cfde_cssdeclaration.h" |
Dan Sinclair | 95bec80 | 2017-01-19 10:27:58 -0500 | [diff] [blame] | 15 | #include "xfa/fde/css/cfde_cssstylerule.h" |
Dan Sinclair | 1770c02 | 2016-03-14 14:14:16 -0400 | [diff] [blame] | 16 | #include "xfa/fde/css/fde_cssdatatable.h" |
Dan Sinclair | 1770c02 | 2016-03-14 14:14:16 -0400 | [diff] [blame] | 17 | |
Dan Sinclair | b76f49b | 2017-01-23 13:55:39 -0500 | [diff] [blame] | 18 | CFDE_CSSStyleSheet::CFDE_CSSStyleSheet() {} |
weili | eec3a36 | 2016-06-18 06:25:37 -0700 | [diff] [blame] | 19 | |
Dan Sinclair | 1770c02 | 2016-03-14 14:14:16 -0400 | [diff] [blame] | 20 | CFDE_CSSStyleSheet::~CFDE_CSSStyleSheet() { |
| 21 | Reset(); |
| 22 | } |
weili | eec3a36 | 2016-06-18 06:25:37 -0700 | [diff] [blame] | 23 | |
Dan Sinclair | 1770c02 | 2016-03-14 14:14:16 -0400 | [diff] [blame] | 24 | void CFDE_CSSStyleSheet::Reset() { |
Dan Sinclair | 3285c56 | 2017-01-17 16:35:16 -0500 | [diff] [blame] | 25 | m_RuleArray.clear(); |
tsepez | 788ac38 | 2016-05-19 21:06:16 -0700 | [diff] [blame] | 26 | m_StringCache.clear(); |
Dan Sinclair | 1770c02 | 2016-03-14 14:14:16 -0400 | [diff] [blame] | 27 | } |
weili | eec3a36 | 2016-06-18 06:25:37 -0700 | [diff] [blame] | 28 | |
Dan Sinclair | 1770c02 | 2016-03-14 14:14:16 -0400 | [diff] [blame] | 29 | int32_t CFDE_CSSStyleSheet::CountRules() const { |
Dan Sinclair | 3285c56 | 2017-01-17 16:35:16 -0500 | [diff] [blame] | 30 | return pdfium::CollectionSize<int32_t>(m_RuleArray); |
Dan Sinclair | 1770c02 | 2016-03-14 14:14:16 -0400 | [diff] [blame] | 31 | } |
weili | eec3a36 | 2016-06-18 06:25:37 -0700 | [diff] [blame] | 32 | |
Dan Sinclair | b76f49b | 2017-01-23 13:55:39 -0500 | [diff] [blame] | 33 | CFDE_CSSStyleRule* CFDE_CSSStyleSheet::GetRule(int32_t index) const { |
Dan Sinclair | 3285c56 | 2017-01-17 16:35:16 -0500 | [diff] [blame] | 34 | return m_RuleArray[index].get(); |
Dan Sinclair | 1770c02 | 2016-03-14 14:14:16 -0400 | [diff] [blame] | 35 | } |
tsepez | f74ad99 | 2016-05-11 10:26:05 -0700 | [diff] [blame] | 36 | |
Dan Sinclair | 812e96c | 2017-03-13 16:43:37 -0400 | [diff] [blame] | 37 | bool CFDE_CSSStyleSheet::LoadBuffer(const wchar_t* pBuffer, int32_t iBufSize) { |
Lei Zhang | f3024c3 | 2017-06-26 15:28:15 -0700 | [diff] [blame^] | 38 | ASSERT(pBuffer); |
| 39 | ASSERT(iBufSize > 0); |
Dan Sinclair | cfb856c | 2017-01-16 16:03:44 -0500 | [diff] [blame] | 40 | |
Lei Zhang | f3024c3 | 2017-06-26 15:28:15 -0700 | [diff] [blame^] | 41 | auto pSyntax = pdfium::MakeUnique<CFDE_CSSSyntaxParser>(pBuffer, iBufSize); |
Dan Sinclair | 1770c02 | 2016-03-14 14:14:16 -0400 | [diff] [blame] | 42 | Reset(); |
Dan Sinclair | 96f482c | 2017-01-11 16:31:27 -0500 | [diff] [blame] | 43 | FDE_CSSSyntaxStatus eStatus; |
Dan Sinclair | 1770c02 | 2016-03-14 14:14:16 -0400 | [diff] [blame] | 44 | do { |
| 45 | switch (eStatus = pSyntax->DoSyntaxParse()) { |
Dan Sinclair | 96f482c | 2017-01-11 16:31:27 -0500 | [diff] [blame] | 46 | case FDE_CSSSyntaxStatus::StyleRule: |
Dan Sinclair | 6414b27 | 2017-01-23 13:54:53 -0500 | [diff] [blame] | 47 | eStatus = LoadStyleRule(pSyntax.get(), &m_RuleArray); |
Dan Sinclair | 1770c02 | 2016-03-14 14:14:16 -0400 | [diff] [blame] | 48 | break; |
| 49 | default: |
| 50 | break; |
| 51 | } |
Dan Sinclair | 96f482c | 2017-01-11 16:31:27 -0500 | [diff] [blame] | 52 | } while (eStatus >= FDE_CSSSyntaxStatus::None); |
Dan Sinclair | a715f52 | 2017-01-17 16:03:48 -0500 | [diff] [blame] | 53 | |
tsepez | 788ac38 | 2016-05-19 21:06:16 -0700 | [diff] [blame] | 54 | m_StringCache.clear(); |
Dan Sinclair | 96f482c | 2017-01-11 16:31:27 -0500 | [diff] [blame] | 55 | return eStatus != FDE_CSSSyntaxStatus::Error; |
Dan Sinclair | 1770c02 | 2016-03-14 14:14:16 -0400 | [diff] [blame] | 56 | } |
weili | eec3a36 | 2016-06-18 06:25:37 -0700 | [diff] [blame] | 57 | |
Dan Sinclair | 96f482c | 2017-01-11 16:31:27 -0500 | [diff] [blame] | 58 | FDE_CSSSyntaxStatus CFDE_CSSStyleSheet::LoadStyleRule( |
dsinclair | e6ebf7a | 2016-04-28 06:34:24 -0700 | [diff] [blame] | 59 | CFDE_CSSSyntaxParser* pSyntax, |
Dan Sinclair | 6414b27 | 2017-01-23 13:54:53 -0500 | [diff] [blame] | 60 | std::vector<std::unique_ptr<CFDE_CSSStyleRule>>* ruleArray) { |
Dan Sinclair | a715f52 | 2017-01-17 16:03:48 -0500 | [diff] [blame] | 61 | std::vector<std::unique_ptr<CFDE_CSSSelector>> selectors; |
Dan Sinclair | 3285c56 | 2017-01-17 16:35:16 -0500 | [diff] [blame] | 62 | |
thestig | cfb77cc | 2016-06-10 12:21:53 -0700 | [diff] [blame] | 63 | CFDE_CSSStyleRule* pStyleRule = nullptr; |
Dan Sinclair | 1770c02 | 2016-03-14 14:14:16 -0400 | [diff] [blame] | 64 | int32_t iValueLen = 0; |
Dan Sinclair | 21e954b | 2017-02-08 10:05:05 -0500 | [diff] [blame] | 65 | const FDE_CSSPropertyTable* propertyTable = nullptr; |
Dan Sinclair | 1770c02 | 2016-03-14 14:14:16 -0400 | [diff] [blame] | 66 | CFX_WideString wsName; |
Dan Sinclair | 6414b27 | 2017-01-23 13:54:53 -0500 | [diff] [blame] | 67 | while (1) { |
Dan Sinclair | 1770c02 | 2016-03-14 14:14:16 -0400 | [diff] [blame] | 68 | switch (pSyntax->DoSyntaxParse()) { |
Dan Sinclair | 96f482c | 2017-01-11 16:31:27 -0500 | [diff] [blame] | 69 | case FDE_CSSSyntaxStatus::Selector: { |
Dan Sinclair | 21e954b | 2017-02-08 10:05:05 -0500 | [diff] [blame] | 70 | CFX_WideStringC strValue = pSyntax->GetCurrentString(); |
| 71 | auto pSelector = CFDE_CSSSelector::FromString(strValue); |
thestig | cfb77cc | 2016-06-10 12:21:53 -0700 | [diff] [blame] | 72 | if (pSelector) |
Dan Sinclair | a715f52 | 2017-01-17 16:03:48 -0500 | [diff] [blame] | 73 | selectors.push_back(std::move(pSelector)); |
| 74 | break; |
| 75 | } |
Dan Sinclair | 21e954b | 2017-02-08 10:05:05 -0500 | [diff] [blame] | 76 | case FDE_CSSSyntaxStatus::PropertyName: { |
| 77 | CFX_WideStringC strValue = pSyntax->GetCurrentString(); |
| 78 | propertyTable = FDE_GetCSSPropertyByName(strValue); |
| 79 | if (!propertyTable) |
| 80 | wsName = CFX_WideString(strValue); |
Dan Sinclair | 1770c02 | 2016-03-14 14:14:16 -0400 | [diff] [blame] | 81 | break; |
Dan Sinclair | 21e954b | 2017-02-08 10:05:05 -0500 | [diff] [blame] | 82 | } |
| 83 | case FDE_CSSSyntaxStatus::PropertyValue: { |
| 84 | if (propertyTable || iValueLen > 0) { |
| 85 | CFX_WideStringC strValue = pSyntax->GetCurrentString(); |
Lei Zhang | 375c276 | 2017-03-10 14:37:14 -0800 | [diff] [blame] | 86 | auto* decl = pStyleRule->GetDeclaration(); |
Dan Sinclair | 21e954b | 2017-02-08 10:05:05 -0500 | [diff] [blame] | 87 | if (!strValue.IsEmpty()) { |
| 88 | if (propertyTable) { |
| 89 | decl->AddProperty(propertyTable, strValue); |
| 90 | } else { |
| 91 | decl->AddProperty(wsName, CFX_WideString(strValue)); |
| 92 | } |
Dan Sinclair | 1770c02 | 2016-03-14 14:14:16 -0400 | [diff] [blame] | 93 | } |
| 94 | } |
| 95 | break; |
Dan Sinclair | 21e954b | 2017-02-08 10:05:05 -0500 | [diff] [blame] | 96 | } |
| 97 | case FDE_CSSSyntaxStatus::DeclOpen: { |
Dan Sinclair | a715f52 | 2017-01-17 16:03:48 -0500 | [diff] [blame] | 98 | if (!pStyleRule && !selectors.empty()) { |
Dan Sinclair | 3285c56 | 2017-01-17 16:35:16 -0500 | [diff] [blame] | 99 | auto rule = pdfium::MakeUnique<CFDE_CSSStyleRule>(); |
| 100 | pStyleRule = rule.get(); |
Dan Sinclair | a715f52 | 2017-01-17 16:03:48 -0500 | [diff] [blame] | 101 | pStyleRule->SetSelector(&selectors); |
Dan Sinclair | 3285c56 | 2017-01-17 16:35:16 -0500 | [diff] [blame] | 102 | ruleArray->push_back(std::move(rule)); |
Dan Sinclair | 1770c02 | 2016-03-14 14:14:16 -0400 | [diff] [blame] | 103 | } else { |
| 104 | SkipRuleSet(pSyntax); |
Dan Sinclair | 96f482c | 2017-01-11 16:31:27 -0500 | [diff] [blame] | 105 | return FDE_CSSSyntaxStatus::None; |
Dan Sinclair | 1770c02 | 2016-03-14 14:14:16 -0400 | [diff] [blame] | 106 | } |
| 107 | break; |
Dan Sinclair | 21e954b | 2017-02-08 10:05:05 -0500 | [diff] [blame] | 108 | } |
| 109 | case FDE_CSSSyntaxStatus::DeclClose: { |
Dan Sinclair | 09065ae | 2017-01-18 08:56:52 -0500 | [diff] [blame] | 110 | if (pStyleRule && pStyleRule->GetDeclaration()->empty()) { |
Dan Sinclair | 3285c56 | 2017-01-17 16:35:16 -0500 | [diff] [blame] | 111 | ruleArray->pop_back(); |
| 112 | pStyleRule = nullptr; |
Dan Sinclair | 1770c02 | 2016-03-14 14:14:16 -0400 | [diff] [blame] | 113 | } |
Dan Sinclair | 96f482c | 2017-01-11 16:31:27 -0500 | [diff] [blame] | 114 | return FDE_CSSSyntaxStatus::None; |
Dan Sinclair | 21e954b | 2017-02-08 10:05:05 -0500 | [diff] [blame] | 115 | } |
Dan Sinclair | 96f482c | 2017-01-11 16:31:27 -0500 | [diff] [blame] | 116 | case FDE_CSSSyntaxStatus::EOS: |
| 117 | return FDE_CSSSyntaxStatus::EOS; |
| 118 | case FDE_CSSSyntaxStatus::Error: |
| 119 | default: |
| 120 | return FDE_CSSSyntaxStatus::Error; |
Dan Sinclair | 1770c02 | 2016-03-14 14:14:16 -0400 | [diff] [blame] | 121 | } |
| 122 | } |
| 123 | } |
weili | eec3a36 | 2016-06-18 06:25:37 -0700 | [diff] [blame] | 124 | |
Dan Sinclair | 6414b27 | 2017-01-23 13:54:53 -0500 | [diff] [blame] | 125 | void CFDE_CSSStyleSheet::SkipRuleSet(CFDE_CSSSyntaxParser* pSyntax) { |
| 126 | while (1) { |
Dan Sinclair | 1770c02 | 2016-03-14 14:14:16 -0400 | [diff] [blame] | 127 | switch (pSyntax->DoSyntaxParse()) { |
Dan Sinclair | 96f482c | 2017-01-11 16:31:27 -0500 | [diff] [blame] | 128 | case FDE_CSSSyntaxStatus::Selector: |
| 129 | case FDE_CSSSyntaxStatus::DeclOpen: |
| 130 | case FDE_CSSSyntaxStatus::PropertyName: |
| 131 | case FDE_CSSSyntaxStatus::PropertyValue: |
Dan Sinclair | 1770c02 | 2016-03-14 14:14:16 -0400 | [diff] [blame] | 132 | break; |
Dan Sinclair | 96f482c | 2017-01-11 16:31:27 -0500 | [diff] [blame] | 133 | case FDE_CSSSyntaxStatus::DeclClose: |
Dan Sinclair | 96f482c | 2017-01-11 16:31:27 -0500 | [diff] [blame] | 134 | case FDE_CSSSyntaxStatus::EOS: |
Dan Sinclair | 96f482c | 2017-01-11 16:31:27 -0500 | [diff] [blame] | 135 | case FDE_CSSSyntaxStatus::Error: |
| 136 | default: |
Dan Sinclair | 6414b27 | 2017-01-23 13:54:53 -0500 | [diff] [blame] | 137 | return; |
Dan Sinclair | 1770c02 | 2016-03-14 14:14:16 -0400 | [diff] [blame] | 138 | } |
| 139 | } |
Dan Sinclair | 1770c02 | 2016-03-14 14:14:16 -0400 | [diff] [blame] | 140 | } |