summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/fxcrt/css/cfx_css.h242
-rw-r--r--core/fxcrt/css/cfx_csscolorvalue.cpp12
-rw-r--r--core/fxcrt/css/cfx_csscolorvalue.h23
-rw-r--r--core/fxcrt/css/cfx_csscomputedstyle.cpp195
-rw-r--r--core/fxcrt/css/cfx_csscomputedstyle.h111
-rw-r--r--core/fxcrt/css/cfx_csscustomproperty.cpp14
-rw-r--r--core/fxcrt/css/cfx_csscustomproperty.h27
-rw-r--r--core/fxcrt/css/cfx_cssdatatable.cpp285
-rw-r--r--core/fxcrt/css/cfx_cssdatatable.h56
-rw-r--r--core/fxcrt/css/cfx_cssdeclaration.cpp634
-rw-r--r--core/fxcrt/css/cfx_cssdeclaration.h93
-rw-r--r--core/fxcrt/css/cfx_cssdeclaration_unittest.cpp62
-rw-r--r--core/fxcrt/css/cfx_cssenumvalue.cpp12
-rw-r--r--core/fxcrt/css/cfx_cssenumvalue.h23
-rw-r--r--core/fxcrt/css/cfx_cssexttextbuf.cpp17
-rw-r--r--core/fxcrt/css/cfx_cssexttextbuf.h34
-rw-r--r--core/fxcrt/css/cfx_cssnumbervalue.cpp39
-rw-r--r--core/fxcrt/css/cfx_cssnumbervalue.h41
-rw-r--r--core/fxcrt/css/cfx_csspropertyholder.cpp11
-rw-r--r--core/fxcrt/css/cfx_csspropertyholder.h24
-rw-r--r--core/fxcrt/css/cfx_cssrulecollection.cpp56
-rw-r--r--core/fxcrt/css/cfx_cssrulecollection.h49
-rw-r--r--core/fxcrt/css/cfx_cssselector.cpp87
-rw-r--r--core/fxcrt/css/cfx_cssselector.h43
-rw-r--r--core/fxcrt/css/cfx_cssstringvalue.cpp12
-rw-r--r--core/fxcrt/css/cfx_cssstringvalue.h23
-rw-r--r--core/fxcrt/css/cfx_cssstylerule.cpp30
-rw-r--r--core/fxcrt/css/cfx_cssstylerule.h32
-rw-r--r--core/fxcrt/css/cfx_cssstyleselector.cpp598
-rw-r--r--core/fxcrt/css/cfx_cssstyleselector.h85
-rw-r--r--core/fxcrt/css/cfx_cssstylesheet.cpp140
-rw-r--r--core/fxcrt/css/cfx_cssstylesheet.h40
-rw-r--r--core/fxcrt/css/cfx_cssstylesheet_unittest.cpp239
-rw-r--r--core/fxcrt/css/cfx_csssyntaxparser.cpp228
-rw-r--r--core/fxcrt/css/cfx_csssyntaxparser.h75
-rw-r--r--core/fxcrt/css/cfx_csstextbuf.cpp49
-rw-r--r--core/fxcrt/css/cfx_csstextbuf.h35
-rw-r--r--core/fxcrt/css/cfx_cssvalue.cpp9
-rw-r--r--core/fxcrt/css/cfx_cssvalue.h23
-rw-r--r--core/fxcrt/css/cfx_cssvaluelist.cpp25
-rw-r--r--core/fxcrt/css/cfx_cssvaluelist.h26
-rw-r--r--core/fxcrt/css/cfx_cssvaluelistparser.cpp87
-rw-r--r--core/fxcrt/css/cfx_cssvaluelistparser.h30
-rw-r--r--core/fxcrt/css/cfx_cssvaluelistparser_unittest.cpp141
44 files changed, 4117 insertions, 0 deletions
diff --git a/core/fxcrt/css/cfx_css.h b/core/fxcrt/css/cfx_css.h
new file mode 100644
index 0000000000..7b1d7d3f99
--- /dev/null
+++ b/core/fxcrt/css/cfx_css.h
@@ -0,0 +1,242 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// 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
+
+#ifndef CORE_FXCRT_CSS_CFX_CSS_H_
+#define CORE_FXCRT_CSS_CFX_CSS_H_
+
+#include "core/fxcrt/cfx_seekablestreamproxy.h"
+#include "core/fxge/fx_dib.h"
+
+enum CFX_CSSVALUETYPE {
+ CFX_CSSVALUETYPE_Primitive = 1 << 0,
+ CFX_CSSVALUETYPE_List = 1 << 1,
+ CFX_CSSVALUETYPE_Shorthand = 1 << 2,
+ // Note the values below this comment must be > 0x0F so we can mask the above.
+ CFX_CSSVALUETYPE_MaybeNumber = 1 << 4,
+ CFX_CSSVALUETYPE_MaybeEnum = 1 << 5,
+ CFX_CSSVALUETYPE_MaybeString = 1 << 7,
+ CFX_CSSVALUETYPE_MaybeColor = 1 << 8
+};
+
+enum class CFX_CSSPrimitiveType : uint8_t {
+ Unknown = 0,
+ Number,
+ String,
+ RGB,
+ Enum,
+ Function,
+ List,
+};
+
+enum class CFX_CSSPropertyValue : uint8_t {
+ Bolder = 0,
+ None,
+ Dot,
+ Sub,
+ Top,
+ Right,
+ Normal,
+ Auto,
+ Text,
+ XSmall,
+ Thin,
+ Small,
+ Bottom,
+ Underline,
+ Double,
+ Lighter,
+ Oblique,
+ Super,
+ Center,
+ XxLarge,
+ Smaller,
+ Baseline,
+ Thick,
+ Justify,
+ Middle,
+ Medium,
+ ListItem,
+ XxSmall,
+ Bold,
+ SmallCaps,
+ Inline,
+ Overline,
+ TextBottom,
+ Larger,
+ InlineTable,
+ InlineBlock,
+ Blink,
+ Block,
+ Italic,
+ LineThrough,
+ XLarge,
+ Large,
+ Left,
+ TextTop,
+ LAST_MARKER
+};
+
+enum class CFX_CSSProperty : uint8_t {
+ BorderLeft = 0,
+ Top,
+ Margin,
+ TextIndent,
+ Right,
+ PaddingLeft,
+ MarginLeft,
+ Border,
+ BorderTop,
+ Bottom,
+ PaddingRight,
+ BorderBottom,
+ FontFamily,
+ FontWeight,
+ Color,
+ LetterSpacing,
+ TextAlign,
+ BorderRightWidth,
+ VerticalAlign,
+ PaddingTop,
+ FontVariant,
+ BorderWidth,
+ BorderBottomWidth,
+ BorderRight,
+ FontSize,
+ BorderSpacing,
+ FontStyle,
+ Font,
+ LineHeight,
+ MarginRight,
+ BorderLeftWidth,
+ Display,
+ PaddingBottom,
+ BorderTopWidth,
+ WordSpacing,
+ Left,
+ TextDecoration,
+ Padding,
+ MarginBottom,
+ MarginTop,
+ LAST_MARKER
+};
+
+enum class CFX_CSSSelectorType : uint8_t { Element = 0, Descendant };
+
+enum class CFX_CSSLengthUnit : uint8_t {
+ Auto,
+ None,
+ Normal,
+ Point,
+ Percent,
+};
+
+enum class CFX_CSSDisplay : uint8_t {
+ None,
+ ListItem,
+ Block,
+ Inline,
+ InlineBlock,
+ InlineTable,
+};
+
+enum class CFX_CSSFontStyle : uint8_t {
+ Normal,
+ Italic,
+};
+
+enum class CFX_CSSTextAlign : uint8_t {
+ Left,
+ Right,
+ Center,
+ Justify,
+ JustifyAll,
+};
+
+enum class CFX_CSSVerticalAlign : uint8_t {
+ Baseline,
+ Sub,
+ Super,
+ Top,
+ TextTop,
+ Middle,
+ Bottom,
+ TextBottom,
+ Number,
+};
+
+enum class CFX_CSSFontVariant : uint8_t {
+ Normal,
+ SmallCaps,
+};
+
+enum CFX_CSSTEXTDECORATION {
+ CFX_CSSTEXTDECORATION_None = 0,
+ CFX_CSSTEXTDECORATION_Underline = 1 << 0,
+ CFX_CSSTEXTDECORATION_Overline = 1 << 1,
+ CFX_CSSTEXTDECORATION_LineThrough = 1 << 2,
+ CFX_CSSTEXTDECORATION_Blink = 1 << 3,
+ CFX_CSSTEXTDECORATION_Double = 1 << 4,
+};
+
+class CFX_CSSLength {
+ public:
+ CFX_CSSLength() {}
+
+ explicit CFX_CSSLength(CFX_CSSLengthUnit eUnit) : m_unit(eUnit) {}
+
+ CFX_CSSLength(CFX_CSSLengthUnit eUnit, float fValue)
+ : m_unit(eUnit), m_fValue(fValue) {}
+
+ CFX_CSSLength& Set(CFX_CSSLengthUnit eUnit) {
+ m_unit = eUnit;
+ return *this;
+ }
+
+ CFX_CSSLength& Set(CFX_CSSLengthUnit eUnit, float fValue) {
+ m_unit = eUnit;
+ m_fValue = fValue;
+ return *this;
+ }
+
+ CFX_CSSLengthUnit GetUnit() const { return m_unit; }
+
+ float GetValue() const { return m_fValue; }
+ bool NonZero() const { return static_cast<int>(m_fValue) != 0; }
+
+ private:
+ CFX_CSSLengthUnit m_unit;
+ float m_fValue;
+};
+
+class CFX_CSSRect {
+ public:
+ CFX_CSSRect() {}
+
+ CFX_CSSRect(CFX_CSSLengthUnit eUnit, float val)
+ : left(eUnit, val),
+ top(eUnit, val),
+ right(eUnit, val),
+ bottom(eUnit, val) {}
+
+ CFX_CSSRect& Set(CFX_CSSLengthUnit eUnit) {
+ left.Set(eUnit);
+ top.Set(eUnit);
+ right.Set(eUnit);
+ bottom.Set(eUnit);
+ return *this;
+ }
+ CFX_CSSRect& Set(CFX_CSSLengthUnit eUnit, float fValue) {
+ left.Set(eUnit, fValue);
+ top.Set(eUnit, fValue);
+ right.Set(eUnit, fValue);
+ bottom.Set(eUnit, fValue);
+ return *this;
+ }
+
+ CFX_CSSLength left, top, right, bottom;
+};
+
+#endif // CORE_FXCRT_CSS_CFX_CSS_H_
diff --git a/core/fxcrt/css/cfx_csscolorvalue.cpp b/core/fxcrt/css/cfx_csscolorvalue.cpp
new file mode 100644
index 0000000000..8c5473b329
--- /dev/null
+++ b/core/fxcrt/css/cfx_csscolorvalue.cpp
@@ -0,0 +1,12 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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_csscolorvalue.h"
+
+CFX_CSSColorValue::CFX_CSSColorValue(FX_ARGB value)
+ : CFX_CSSValue(CFX_CSSPrimitiveType::RGB), value_(value) {}
+
+CFX_CSSColorValue::~CFX_CSSColorValue() {}
diff --git a/core/fxcrt/css/cfx_csscolorvalue.h b/core/fxcrt/css/cfx_csscolorvalue.h
new file mode 100644
index 0000000000..f59c0c5d3d
--- /dev/null
+++ b/core/fxcrt/css/cfx_csscolorvalue.h
@@ -0,0 +1,23 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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
+
+#ifndef CORE_FXCRT_CSS_CFX_CSSCOLORVALUE_H_
+#define CORE_FXCRT_CSS_CFX_CSSCOLORVALUE_H_
+
+#include "core/fxcrt/css/cfx_cssvalue.h"
+
+class CFX_CSSColorValue : public CFX_CSSValue {
+ public:
+ explicit CFX_CSSColorValue(FX_ARGB color);
+ ~CFX_CSSColorValue() override;
+
+ FX_ARGB Value() const { return value_; }
+
+ private:
+ FX_ARGB value_;
+};
+
+#endif // CORE_FXCRT_CSS_CFX_CSSCOLORVALUE_H_
diff --git a/core/fxcrt/css/cfx_csscomputedstyle.cpp b/core/fxcrt/css/cfx_csscomputedstyle.cpp
new file mode 100644
index 0000000000..953c107ec3
--- /dev/null
+++ b/core/fxcrt/css/cfx_csscomputedstyle.cpp
@@ -0,0 +1,195 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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_csscomputedstyle.h"
+
+#include "core/fxcrt/css/cfx_cssstringvalue.h"
+#include "core/fxcrt/css/cfx_cssvaluelist.h"
+#include "third_party/base/stl_util.h"
+
+CFX_CSSComputedStyle::CFX_CSSComputedStyle() {}
+
+CFX_CSSComputedStyle::~CFX_CSSComputedStyle() {}
+
+bool CFX_CSSComputedStyle::GetCustomStyle(const CFX_WideString& wsName,
+ CFX_WideString& wsValue) const {
+ for (auto iter = m_CustomProperties.rbegin();
+ iter != m_CustomProperties.rend(); iter++) {
+ if (wsName == iter->name()) {
+ wsValue = iter->value();
+ return true;
+ }
+ }
+ return false;
+}
+
+int32_t CFX_CSSComputedStyle::CountFontFamilies() const {
+ return m_InheritedData.m_pFontFamily
+ ? m_InheritedData.m_pFontFamily->CountValues()
+ : 0;
+}
+
+const CFX_WideString CFX_CSSComputedStyle::GetFontFamily(int32_t index) const {
+ return m_InheritedData.m_pFontFamily->GetValue(index)
+ .As<CFX_CSSStringValue>()
+ ->Value();
+}
+
+uint16_t CFX_CSSComputedStyle::GetFontWeight() const {
+ return m_InheritedData.m_wFontWeight;
+}
+
+CFX_CSSFontVariant CFX_CSSComputedStyle::GetFontVariant() const {
+ return m_InheritedData.m_eFontVariant;
+}
+
+CFX_CSSFontStyle CFX_CSSComputedStyle::GetFontStyle() const {
+ return m_InheritedData.m_eFontStyle;
+}
+
+float CFX_CSSComputedStyle::GetFontSize() const {
+ return m_InheritedData.m_fFontSize;
+}
+
+FX_ARGB CFX_CSSComputedStyle::GetColor() const {
+ return m_InheritedData.m_dwFontColor;
+}
+
+void CFX_CSSComputedStyle::SetFontWeight(uint16_t wFontWeight) {
+ m_InheritedData.m_wFontWeight = wFontWeight;
+}
+
+void CFX_CSSComputedStyle::SetFontVariant(CFX_CSSFontVariant eFontVariant) {
+ m_InheritedData.m_eFontVariant = eFontVariant;
+}
+
+void CFX_CSSComputedStyle::SetFontStyle(CFX_CSSFontStyle eFontStyle) {
+ m_InheritedData.m_eFontStyle = eFontStyle;
+}
+
+void CFX_CSSComputedStyle::SetFontSize(float fFontSize) {
+ m_InheritedData.m_fFontSize = fFontSize;
+}
+
+void CFX_CSSComputedStyle::SetColor(FX_ARGB dwFontColor) {
+ m_InheritedData.m_dwFontColor = dwFontColor;
+}
+
+const CFX_CSSRect* CFX_CSSComputedStyle::GetBorderWidth() const {
+ return m_NonInheritedData.m_bHasBorder ? &(m_NonInheritedData.m_BorderWidth)
+ : nullptr;
+}
+
+const CFX_CSSRect* CFX_CSSComputedStyle::GetMarginWidth() const {
+ return m_NonInheritedData.m_bHasMargin ? &(m_NonInheritedData.m_MarginWidth)
+ : nullptr;
+}
+
+const CFX_CSSRect* CFX_CSSComputedStyle::GetPaddingWidth() const {
+ return m_NonInheritedData.m_bHasPadding ? &(m_NonInheritedData.m_PaddingWidth)
+ : nullptr;
+}
+
+void CFX_CSSComputedStyle::SetMarginWidth(const CFX_CSSRect& rect) {
+ m_NonInheritedData.m_MarginWidth = rect;
+ m_NonInheritedData.m_bHasMargin = true;
+}
+
+void CFX_CSSComputedStyle::SetPaddingWidth(const CFX_CSSRect& rect) {
+ m_NonInheritedData.m_PaddingWidth = rect;
+ m_NonInheritedData.m_bHasPadding = true;
+}
+
+CFX_CSSDisplay CFX_CSSComputedStyle::GetDisplay() const {
+ return m_NonInheritedData.m_eDisplay;
+}
+
+float CFX_CSSComputedStyle::GetLineHeight() const {
+ return m_InheritedData.m_fLineHeight;
+}
+
+const CFX_CSSLength& CFX_CSSComputedStyle::GetTextIndent() const {
+ return m_InheritedData.m_TextIndent;
+}
+
+CFX_CSSTextAlign CFX_CSSComputedStyle::GetTextAlign() const {
+ return m_InheritedData.m_eTextAlign;
+}
+
+CFX_CSSVerticalAlign CFX_CSSComputedStyle::GetVerticalAlign() const {
+ return m_NonInheritedData.m_eVerticalAlign;
+}
+
+float CFX_CSSComputedStyle::GetNumberVerticalAlign() const {
+ return m_NonInheritedData.m_fVerticalAlign;
+}
+
+uint32_t CFX_CSSComputedStyle::GetTextDecoration() const {
+ return m_NonInheritedData.m_dwTextDecoration;
+}
+
+const CFX_CSSLength& CFX_CSSComputedStyle::GetLetterSpacing() const {
+ return m_InheritedData.m_LetterSpacing;
+}
+
+void CFX_CSSComputedStyle::SetLineHeight(float fLineHeight) {
+ m_InheritedData.m_fLineHeight = fLineHeight;
+}
+
+void CFX_CSSComputedStyle::SetTextIndent(const CFX_CSSLength& textIndent) {
+ m_InheritedData.m_TextIndent = textIndent;
+}
+
+void CFX_CSSComputedStyle::SetTextAlign(CFX_CSSTextAlign eTextAlign) {
+ m_InheritedData.m_eTextAlign = eTextAlign;
+}
+
+void CFX_CSSComputedStyle::SetNumberVerticalAlign(float fAlign) {
+ m_NonInheritedData.m_eVerticalAlign = CFX_CSSVerticalAlign::Number,
+ m_NonInheritedData.m_fVerticalAlign = fAlign;
+}
+
+void CFX_CSSComputedStyle::SetTextDecoration(uint32_t dwTextDecoration) {
+ m_NonInheritedData.m_dwTextDecoration = dwTextDecoration;
+}
+
+void CFX_CSSComputedStyle::SetLetterSpacing(
+ const CFX_CSSLength& letterSpacing) {
+ m_InheritedData.m_LetterSpacing = letterSpacing;
+}
+
+void CFX_CSSComputedStyle::AddCustomStyle(const CFX_CSSCustomProperty& prop) {
+ // Force the property to be copied so we aren't dependent on the lifetime
+ // of whatever currently owns it.
+ m_CustomProperties.push_back(prop);
+}
+
+CFX_CSSComputedStyle::InheritedData::InheritedData()
+ : m_LetterSpacing(CFX_CSSLengthUnit::Normal),
+ m_WordSpacing(CFX_CSSLengthUnit::Normal),
+ m_TextIndent(CFX_CSSLengthUnit::Point, 0),
+ m_pFontFamily(nullptr),
+ m_fFontSize(12.0f),
+ m_fLineHeight(14.0f),
+ m_dwFontColor(0xFF000000),
+ m_wFontWeight(400),
+ m_eFontVariant(CFX_CSSFontVariant::Normal),
+ m_eFontStyle(CFX_CSSFontStyle::Normal),
+ m_eTextAlign(CFX_CSSTextAlign::Left) {}
+
+CFX_CSSComputedStyle::InheritedData::~InheritedData() {}
+
+CFX_CSSComputedStyle::NonInheritedData::NonInheritedData()
+ : m_MarginWidth(CFX_CSSLengthUnit::Point, 0),
+ m_BorderWidth(CFX_CSSLengthUnit::Point, 0),
+ m_PaddingWidth(CFX_CSSLengthUnit::Point, 0),
+ m_fVerticalAlign(0.0f),
+ m_eDisplay(CFX_CSSDisplay::Inline),
+ m_eVerticalAlign(CFX_CSSVerticalAlign::Baseline),
+ m_dwTextDecoration(0),
+ m_bHasMargin(false),
+ m_bHasBorder(false),
+ m_bHasPadding(false) {}
diff --git a/core/fxcrt/css/cfx_csscomputedstyle.h b/core/fxcrt/css/cfx_csscomputedstyle.h
new file mode 100644
index 0000000000..bd7cd8268b
--- /dev/null
+++ b/core/fxcrt/css/cfx_csscomputedstyle.h
@@ -0,0 +1,111 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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
+
+#ifndef CORE_FXCRT_CSS_CFX_CSSCOMPUTEDSTYLE_H_
+#define CORE_FXCRT_CSS_CFX_CSSCOMPUTEDSTYLE_H_
+
+#include <vector>
+
+#include "core/fxcrt/css/cfx_css.h"
+#include "core/fxcrt/css/cfx_csscustomproperty.h"
+#include "core/fxcrt/fx_basic.h"
+#include "core/fxcrt/fx_string.h"
+
+class CFX_CSSValueList;
+
+class CFX_CSSComputedStyle : public CFX_Retainable {
+ public:
+ class InheritedData {
+ public:
+ InheritedData();
+ ~InheritedData();
+
+ CFX_CSSLength m_LetterSpacing;
+ CFX_CSSLength m_WordSpacing;
+ CFX_CSSLength m_TextIndent;
+ CFX_RetainPtr<CFX_CSSValueList> m_pFontFamily;
+ float m_fFontSize;
+ float m_fLineHeight;
+ FX_ARGB m_dwFontColor;
+ uint16_t m_wFontWeight;
+ CFX_CSSFontVariant m_eFontVariant;
+ CFX_CSSFontStyle m_eFontStyle;
+ CFX_CSSTextAlign m_eTextAlign;
+ };
+
+ class NonInheritedData {
+ public:
+ NonInheritedData();
+
+ CFX_CSSRect m_MarginWidth;
+ CFX_CSSRect m_BorderWidth;
+ CFX_CSSRect m_PaddingWidth;
+ CFX_CSSLength m_Top;
+ CFX_CSSLength m_Bottom;
+ CFX_CSSLength m_Left;
+ CFX_CSSLength m_Right;
+ float m_fVerticalAlign;
+ CFX_CSSDisplay m_eDisplay;
+ CFX_CSSVerticalAlign m_eVerticalAlign;
+ uint8_t m_dwTextDecoration;
+ bool m_bHasMargin;
+ bool m_bHasBorder;
+ bool m_bHasPadding;
+ };
+
+ int32_t CountFontFamilies() const;
+ const CFX_WideString GetFontFamily(int32_t index) const;
+ uint16_t GetFontWeight() const;
+ CFX_CSSFontVariant GetFontVariant() const;
+ CFX_CSSFontStyle GetFontStyle() const;
+ float GetFontSize() const;
+ FX_ARGB GetColor() const;
+ void SetFontWeight(uint16_t wFontWeight);
+ void SetFontVariant(CFX_CSSFontVariant eFontVariant);
+ void SetFontStyle(CFX_CSSFontStyle eFontStyle);
+ void SetFontSize(float fFontSize);
+ void SetColor(FX_ARGB dwFontColor);
+
+ const CFX_CSSRect* GetBorderWidth() const;
+ const CFX_CSSRect* GetMarginWidth() const;
+ const CFX_CSSRect* GetPaddingWidth() const;
+ void SetMarginWidth(const CFX_CSSRect& rect);
+ void SetPaddingWidth(const CFX_CSSRect& rect);
+
+ CFX_CSSDisplay GetDisplay() const;
+
+ float GetLineHeight() const;
+ const CFX_CSSLength& GetTextIndent() const;
+ CFX_CSSTextAlign GetTextAlign() const;
+ CFX_CSSVerticalAlign GetVerticalAlign() const;
+ float GetNumberVerticalAlign() const;
+ uint32_t GetTextDecoration() const;
+ const CFX_CSSLength& GetLetterSpacing() const;
+ void SetLineHeight(float fLineHeight);
+ void SetTextIndent(const CFX_CSSLength& textIndent);
+ void SetTextAlign(CFX_CSSTextAlign eTextAlign);
+ void SetNumberVerticalAlign(float fAlign);
+ void SetTextDecoration(uint32_t dwTextDecoration);
+ void SetLetterSpacing(const CFX_CSSLength& letterSpacing);
+ void AddCustomStyle(const CFX_CSSCustomProperty& prop);
+
+ bool GetCustomStyle(const CFX_WideString& wsName,
+ CFX_WideString& wsValue) const;
+
+ InheritedData m_InheritedData;
+ NonInheritedData m_NonInheritedData;
+
+ private:
+ template <typename T, typename... Args>
+ friend CFX_RetainPtr<T> pdfium::MakeRetain(Args&&... args);
+
+ CFX_CSSComputedStyle();
+ ~CFX_CSSComputedStyle() override;
+
+ std::vector<CFX_CSSCustomProperty> m_CustomProperties;
+};
+
+#endif // CORE_FXCRT_CSS_CFX_CSSCOMPUTEDSTYLE_H_
diff --git a/core/fxcrt/css/cfx_csscustomproperty.cpp b/core/fxcrt/css/cfx_csscustomproperty.cpp
new file mode 100644
index 0000000000..8bfb9d961e
--- /dev/null
+++ b/core/fxcrt/css/cfx_csscustomproperty.cpp
@@ -0,0 +1,14 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/fxcrt/css/cfx_csscustomproperty.h"
+
+CFX_CSSCustomProperty::CFX_CSSCustomProperty(const CFX_WideString& name,
+ const CFX_WideString& value)
+ : name_(name), value_(value) {}
+
+CFX_CSSCustomProperty::CFX_CSSCustomProperty(const CFX_CSSCustomProperty& prop)
+ : name_(prop.name_), value_(prop.value_) {}
+
+CFX_CSSCustomProperty::~CFX_CSSCustomProperty() {}
diff --git a/core/fxcrt/css/cfx_csscustomproperty.h b/core/fxcrt/css/cfx_csscustomproperty.h
new file mode 100644
index 0000000000..e062c3e953
--- /dev/null
+++ b/core/fxcrt/css/cfx_csscustomproperty.h
@@ -0,0 +1,27 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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
+
+#ifndef CORE_FXCRT_CSS_CFX_CSSCUSTOMPROPERTY_H_
+#define CORE_FXCRT_CSS_CFX_CSSCUSTOMPROPERTY_H_
+
+#include "core/fxcrt/fx_string.h"
+
+class CFX_CSSCustomProperty {
+ public:
+ CFX_CSSCustomProperty(const CFX_WideString& name,
+ const CFX_WideString& value);
+ CFX_CSSCustomProperty(const CFX_CSSCustomProperty& prop);
+ ~CFX_CSSCustomProperty();
+
+ CFX_WideString name() const { return name_; }
+ CFX_WideString value() const { return value_; }
+
+ private:
+ CFX_WideString name_;
+ CFX_WideString value_;
+};
+
+#endif // CORE_FXCRT_CSS_CFX_CSSCUSTOMPROPERTY_H_
diff --git a/core/fxcrt/css/cfx_cssdatatable.cpp b/core/fxcrt/css/cfx_cssdatatable.cpp
new file mode 100644
index 0000000000..ef555b395f
--- /dev/null
+++ b/core/fxcrt/css/cfx_cssdatatable.cpp
@@ -0,0 +1,285 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// 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_cssdatatable.h"
+
+#include <utility>
+
+#include "core/fxcrt/css/cfx_cssstyleselector.h"
+#include "core/fxcrt/css/cfx_cssvaluelistparser.h"
+#include "core/fxcrt/fx_codepage.h"
+#include "core/fxcrt/fx_extension.h"
+
+static const CFX_CSSPropertyTable g_CFX_CSSProperties[] = {
+ {CFX_CSSProperty::BorderLeft, L"border-left", 0x04080036,
+ CFX_CSSVALUETYPE_Shorthand},
+ {CFX_CSSProperty::Top, L"top", 0x0BEDAF33,
+ CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum |
+ CFX_CSSVALUETYPE_MaybeNumber},
+ {CFX_CSSProperty::Margin, L"margin", 0x0CB016BE,
+ CFX_CSSVALUETYPE_List | CFX_CSSVALUETYPE_MaybeEnum |
+ CFX_CSSVALUETYPE_MaybeNumber},
+ {CFX_CSSProperty::TextIndent, L"text-indent", 0x169ADB74,
+ CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeNumber},
+ {CFX_CSSProperty::Right, L"right", 0x193ADE3E,
+ CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum |
+ CFX_CSSVALUETYPE_MaybeNumber},
+ {CFX_CSSProperty::PaddingLeft, L"padding-left", 0x228CF02F,
+ CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeNumber},
+ {CFX_CSSProperty::MarginLeft, L"margin-left", 0x297C5656,
+ CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeNumber |
+ CFX_CSSVALUETYPE_MaybeEnum},
+ {CFX_CSSProperty::Border, L"border", 0x2A23349E,
+ CFX_CSSVALUETYPE_Shorthand},
+ {CFX_CSSProperty::BorderTop, L"border-top", 0x2B866ADE,
+ CFX_CSSVALUETYPE_Shorthand},
+ {CFX_CSSProperty::Bottom, L"bottom", 0x399F02B5,
+ CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum |
+ CFX_CSSVALUETYPE_MaybeNumber},
+ {CFX_CSSProperty::PaddingRight, L"padding-right", 0x3F616AC2,
+ CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeNumber},
+ {CFX_CSSProperty::BorderBottom, L"border-bottom", 0x452CE780,
+ CFX_CSSVALUETYPE_Shorthand},
+ {CFX_CSSProperty::FontFamily, L"font-family", 0x574686E6,
+ CFX_CSSVALUETYPE_List | CFX_CSSVALUETYPE_MaybeString},
+ {CFX_CSSProperty::FontWeight, L"font-weight", 0x6692F60C,
+ CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum |
+ CFX_CSSVALUETYPE_MaybeNumber},
+ {CFX_CSSProperty::Color, L"color", 0x6E67921F,
+ CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum |
+ CFX_CSSVALUETYPE_MaybeColor},
+ {CFX_CSSProperty::LetterSpacing, L"letter-spacing", 0x70536102,
+ CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum |
+ CFX_CSSVALUETYPE_MaybeNumber},
+ {CFX_CSSProperty::TextAlign, L"text-align", 0x7553F1BD,
+ CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum},
+ {CFX_CSSProperty::BorderRightWidth, L"border-right-width", 0x8F5A6036,
+ CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum |
+ CFX_CSSVALUETYPE_MaybeNumber},
+ {CFX_CSSProperty::VerticalAlign, L"vertical-align", 0x934A87D2,
+ CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum |
+ CFX_CSSVALUETYPE_MaybeNumber},
+ {CFX_CSSProperty::PaddingTop, L"padding-top", 0x959D22B7,
+ CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeNumber},
+ {CFX_CSSProperty::FontVariant, L"font-variant", 0x9C785779,
+ CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum},
+ {CFX_CSSProperty::BorderWidth, L"border-width", 0xA8DE4FEB,
+ CFX_CSSVALUETYPE_List | CFX_CSSVALUETYPE_MaybeEnum |
+ CFX_CSSVALUETYPE_MaybeNumber},
+ {CFX_CSSProperty::BorderBottomWidth, L"border-bottom-width", 0xAE41204D,
+ CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum |
+ CFX_CSSVALUETYPE_MaybeNumber},
+ {CFX_CSSProperty::BorderRight, L"border-right", 0xB78E9EA9,
+ CFX_CSSVALUETYPE_Shorthand},
+ {CFX_CSSProperty::FontSize, L"font-size", 0xB93956DF,
+ CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum |
+ CFX_CSSVALUETYPE_MaybeNumber},
+ {CFX_CSSProperty::BorderSpacing, L"border-spacing", 0xC72030F0,
+ CFX_CSSVALUETYPE_List | CFX_CSSVALUETYPE_MaybeNumber},
+ {CFX_CSSProperty::FontStyle, L"font-style", 0xCB1950F5,
+ CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum},
+ {CFX_CSSProperty::Font, L"font", 0xCD308B77, CFX_CSSVALUETYPE_Shorthand},
+ {CFX_CSSProperty::LineHeight, L"line-height", 0xCFCACE2E,
+ CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum |
+ CFX_CSSVALUETYPE_MaybeNumber},
+ {CFX_CSSProperty::MarginRight, L"margin-right", 0xD13C58C9,
+ CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeNumber |
+ CFX_CSSVALUETYPE_MaybeEnum},
+ {CFX_CSSProperty::BorderLeftWidth, L"border-left-width", 0xD1E93D83,
+ CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum |
+ CFX_CSSVALUETYPE_MaybeNumber},
+ {CFX_CSSProperty::Display, L"display", 0xD4224C36,
+ CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum},
+ {CFX_CSSProperty::PaddingBottom, L"padding-bottom", 0xE555B3B9,
+ CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeNumber},
+ {CFX_CSSProperty::BorderTopWidth, L"border-top-width", 0xED2CB62B,
+ CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum |
+ CFX_CSSVALUETYPE_MaybeNumber},
+ {CFX_CSSProperty::WordSpacing, L"word-spacing", 0xEDA63BAE,
+ CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum |
+ CFX_CSSVALUETYPE_MaybeNumber},
+ {CFX_CSSProperty::Left, L"left", 0xF5AD782B,
+ CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeEnum |
+ CFX_CSSVALUETYPE_MaybeNumber},
+ {CFX_CSSProperty::TextDecoration, L"text-decoration", 0xF7C634BA,
+ CFX_CSSVALUETYPE_List | CFX_CSSVALUETYPE_MaybeEnum},
+ {CFX_CSSProperty::Padding, L"padding", 0xF8C373F7,
+ CFX_CSSVALUETYPE_List | CFX_CSSVALUETYPE_MaybeNumber},
+ {CFX_CSSProperty::MarginBottom, L"margin-bottom", 0xF93485A0,
+ CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeNumber |
+ CFX_CSSVALUETYPE_MaybeEnum},
+ {CFX_CSSProperty::MarginTop, L"margin-top", 0xFE51DCFE,
+ CFX_CSSVALUETYPE_Primitive | CFX_CSSVALUETYPE_MaybeNumber |
+ CFX_CSSVALUETYPE_MaybeEnum},
+};
+const int32_t g_iCSSPropertyCount =
+ sizeof(g_CFX_CSSProperties) / sizeof(CFX_CSSPropertyTable);
+static_assert(g_iCSSPropertyCount ==
+ static_cast<int32_t>(CFX_CSSProperty::LAST_MARKER),
+ "Property table differs in size from property enum");
+
+static const CFX_CSSPropertyValueTable g_CFX_CSSPropertyValues[] = {
+ {CFX_CSSPropertyValue::Bolder, L"bolder", 0x009F1058},
+ {CFX_CSSPropertyValue::None, L"none", 0x048B6670},
+ {CFX_CSSPropertyValue::Dot, L"dot", 0x0A48CB27},
+ {CFX_CSSPropertyValue::Sub, L"sub", 0x0BD37FAA},
+ {CFX_CSSPropertyValue::Top, L"top", 0x0BEDAF33},
+ {CFX_CSSPropertyValue::Right, L"right", 0x193ADE3E},
+ {CFX_CSSPropertyValue::Normal, L"normal", 0x247CF3E9},
+ {CFX_CSSPropertyValue::Auto, L"auto", 0x2B35B6D9},
+ {CFX_CSSPropertyValue::Text, L"text", 0x2D08AF85},
+ {CFX_CSSPropertyValue::XSmall, L"x-small", 0x2D2FCAFE},
+ {CFX_CSSPropertyValue::Thin, L"thin", 0x2D574D53},
+ {CFX_CSSPropertyValue::Small, L"small", 0x316A3739},
+ {CFX_CSSPropertyValue::Bottom, L"bottom", 0x399F02B5},
+ {CFX_CSSPropertyValue::Underline, L"underline", 0x3A0273A6},
+ {CFX_CSSPropertyValue::Double, L"double", 0x3D98515B},
+ {CFX_CSSPropertyValue::Lighter, L"lighter", 0x45BEB7AF},
+ {CFX_CSSPropertyValue::Oblique, L"oblique", 0x53EBDDB1},
+ {CFX_CSSPropertyValue::Super, L"super", 0x6A4F842F},
+ {CFX_CSSPropertyValue::Center, L"center", 0x6C51AFC1},
+ {CFX_CSSPropertyValue::XxLarge, L"xx-large", 0x70BB1508},
+ {CFX_CSSPropertyValue::Smaller, L"smaller", 0x849769F0},
+ {CFX_CSSPropertyValue::Baseline, L"baseline", 0x87436BA3},
+ {CFX_CSSPropertyValue::Thick, L"thick", 0x8CC35EB3},
+ {CFX_CSSPropertyValue::Justify, L"justify", 0x8D269CAE},
+ {CFX_CSSPropertyValue::Middle, L"middle", 0x947FA00F},
+ {CFX_CSSPropertyValue::Medium, L"medium", 0xA084A381},
+ {CFX_CSSPropertyValue::ListItem, L"list-item", 0xA32382B8},
+ {CFX_CSSPropertyValue::XxSmall, L"xx-small", 0xADE1FC76},
+ {CFX_CSSPropertyValue::Bold, L"bold", 0xB18313A1},
+ {CFX_CSSPropertyValue::SmallCaps, L"small-caps", 0xB299428D},
+ {CFX_CSSPropertyValue::Inline, L"inline", 0xC02D649F},
+ {CFX_CSSPropertyValue::Overline, L"overline", 0xC0EC9FA4},
+ {CFX_CSSPropertyValue::TextBottom, L"text-bottom", 0xC7D08D87},
+ {CFX_CSSPropertyValue::Larger, L"larger", 0xCD3C409D},
+ {CFX_CSSPropertyValue::InlineTable, L"inline-table", 0xD131F494},
+ {CFX_CSSPropertyValue::InlineBlock, L"inline-block", 0xD26A8BD7},
+ {CFX_CSSPropertyValue::Blink, L"blink", 0xDC36E390},
+ {CFX_CSSPropertyValue::Block, L"block", 0xDCD480AB},
+ {CFX_CSSPropertyValue::Italic, L"italic", 0xE31D5396},
+ {CFX_CSSPropertyValue::LineThrough, L"line-through", 0xE4C5A276},
+ {CFX_CSSPropertyValue::XLarge, L"x-large", 0xF008E390},
+ {CFX_CSSPropertyValue::Large, L"large", 0xF4434FCB},
+ {CFX_CSSPropertyValue::Left, L"left", 0xF5AD782B},
+ {CFX_CSSPropertyValue::TextTop, L"text-top", 0xFCB58D45},
+};
+const int32_t g_iCSSPropertyValueCount =
+ sizeof(g_CFX_CSSPropertyValues) / sizeof(CFX_CSSPropertyValueTable);
+static_assert(g_iCSSPropertyValueCount ==
+ static_cast<int32_t>(CFX_CSSPropertyValue::LAST_MARKER),
+ "Property value table differs in size from property value enum");
+
+static const CFX_CSSLengthUnitTable g_CFX_CSSLengthUnits[] = {
+ {0x0672, CFX_CSSNumberType::EMS},
+ {0x067D, CFX_CSSNumberType::EXS},
+ {0x1AF7, CFX_CSSNumberType::Inches},
+ {0x2F7A, CFX_CSSNumberType::MilliMeters},
+ {0x3ED3, CFX_CSSNumberType::Picas},
+ {0x3EE4, CFX_CSSNumberType::Points},
+ {0x3EE8, CFX_CSSNumberType::Pixels},
+ {0xFC30, CFX_CSSNumberType::CentiMeters},
+};
+
+static const CFX_CSSCOLORTABLE g_CFX_CSSColors[] = {
+ {0x031B47FE, 0xff000080}, {0x0BB8DF5B, 0xffff0000},
+ {0x0D82A78C, 0xff800000}, {0x2ACC82E8, 0xff00ffff},
+ {0x2D083986, 0xff008080}, {0x4A6A6195, 0xffc0c0c0},
+ {0x546A8EF3, 0xff808080}, {0x65C9169C, 0xffffa500},
+ {0x8422BB61, 0xffffffff}, {0x9271A558, 0xff800080},
+ {0xA65A3EE3, 0xffff00ff}, {0xB1345708, 0xff0000ff},
+ {0xB6D2CF1F, 0xff808000}, {0xD19B5E1C, 0xffffff00},
+ {0xDB64391D, 0xff000000}, {0xF616D507, 0xff00ff00},
+ {0xF6EFFF31, 0xff008000},
+};
+
+const CFX_CSSPropertyTable* CFX_GetCSSPropertyByName(
+ const CFX_WideStringC& wsName) {
+ ASSERT(!wsName.IsEmpty());
+ uint32_t dwHash = FX_HashCode_GetW(wsName, true);
+ int32_t iEnd = g_iCSSPropertyCount;
+ int32_t iMid, iStart = 0;
+ uint32_t dwMid;
+ do {
+ iMid = (iStart + iEnd) / 2;
+ dwMid = g_CFX_CSSProperties[iMid].dwHash;
+ if (dwHash == dwMid) {
+ return g_CFX_CSSProperties + iMid;
+ } else if (dwHash > dwMid) {
+ iStart = iMid + 1;
+ } else {
+ iEnd = iMid - 1;
+ }
+ } while (iStart <= iEnd);
+ return nullptr;
+}
+
+const CFX_CSSPropertyTable* CFX_GetCSSPropertyByEnum(CFX_CSSProperty eName) {
+ return g_CFX_CSSProperties + static_cast<int>(eName);
+}
+
+const CFX_CSSPropertyValueTable* CFX_GetCSSPropertyValueByName(
+ const CFX_WideStringC& wsName) {
+ ASSERT(!wsName.IsEmpty());
+ uint32_t dwHash = FX_HashCode_GetW(wsName, true);
+ int32_t iEnd = g_iCSSPropertyValueCount;
+ int32_t iMid, iStart = 0;
+ uint32_t dwMid;
+ do {
+ iMid = (iStart + iEnd) / 2;
+ dwMid = g_CFX_CSSPropertyValues[iMid].dwHash;
+ if (dwHash == dwMid) {
+ return g_CFX_CSSPropertyValues + iMid;
+ } else if (dwHash > dwMid) {
+ iStart = iMid + 1;
+ } else {
+ iEnd = iMid - 1;
+ }
+ } while (iStart <= iEnd);
+ return nullptr;
+}
+
+const CFX_CSSLengthUnitTable* CFX_GetCSSLengthUnitByName(
+ const CFX_WideStringC& wsName) {
+ ASSERT(!wsName.IsEmpty());
+ uint16_t wHash = FX_HashCode_GetW(wsName, true);
+ int32_t iEnd =
+ sizeof(g_CFX_CSSLengthUnits) / sizeof(CFX_CSSLengthUnitTable) - 1;
+ int32_t iMid, iStart = 0;
+ uint16_t wMid;
+ do {
+ iMid = (iStart + iEnd) / 2;
+ wMid = g_CFX_CSSLengthUnits[iMid].wHash;
+ if (wHash == wMid) {
+ return g_CFX_CSSLengthUnits + iMid;
+ } else if (wHash > wMid) {
+ iStart = iMid + 1;
+ } else {
+ iEnd = iMid - 1;
+ }
+ } while (iStart <= iEnd);
+ return nullptr;
+}
+
+const CFX_CSSCOLORTABLE* CFX_GetCSSColorByName(const CFX_WideStringC& wsName) {
+ ASSERT(!wsName.IsEmpty());
+ uint32_t dwHash = FX_HashCode_GetW(wsName, true);
+ int32_t iEnd = sizeof(g_CFX_CSSColors) / sizeof(CFX_CSSCOLORTABLE) - 1;
+ int32_t iMid, iStart = 0;
+ uint32_t dwMid;
+ do {
+ iMid = (iStart + iEnd) / 2;
+ dwMid = g_CFX_CSSColors[iMid].dwHash;
+ if (dwHash == dwMid) {
+ return g_CFX_CSSColors + iMid;
+ } else if (dwHash > dwMid) {
+ iStart = iMid + 1;
+ } else {
+ iEnd = iMid - 1;
+ }
+ } while (iStart <= iEnd);
+ return nullptr;
+}
diff --git a/core/fxcrt/css/cfx_cssdatatable.h b/core/fxcrt/css/cfx_cssdatatable.h
new file mode 100644
index 0000000000..b6188f93bb
--- /dev/null
+++ b/core/fxcrt/css/cfx_cssdatatable.h
@@ -0,0 +1,56 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// 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
+
+#ifndef CORE_FXCRT_CSS_CFX_CSSDATATABLE_H_
+#define CORE_FXCRT_CSS_CFX_CSSDATATABLE_H_
+
+#include <memory>
+#include <vector>
+
+#include "core/fxcrt/css/cfx_css.h"
+#include "core/fxcrt/css/cfx_cssnumbervalue.h"
+#include "core/fxcrt/css/cfx_cssvalue.h"
+#include "core/fxcrt/fx_system.h"
+
+#define CFX_IsOnlyValue(type, enum) \
+ (((type) & ~(enum)) == CFX_CSSVALUETYPE_Primitive)
+
+struct CFX_CSSPropertyTable {
+ CFX_CSSProperty eName;
+ const wchar_t* pszName;
+ uint32_t dwHash;
+ uint32_t dwType;
+};
+
+struct CFX_CSSPropertyValueTable {
+ CFX_CSSPropertyValue eName;
+ const wchar_t* pszName;
+ uint32_t dwHash;
+};
+
+struct CFX_CSSLengthUnitTable {
+ uint16_t wHash;
+ CFX_CSSNumberType wValue;
+};
+
+struct CFX_CSSCOLORTABLE {
+ uint32_t dwHash;
+ FX_ARGB dwValue;
+};
+
+const CFX_CSSPropertyTable* CFX_GetCSSPropertyByName(
+ const CFX_WideStringC& wsName);
+const CFX_CSSPropertyTable* CFX_GetCSSPropertyByEnum(CFX_CSSProperty eName);
+
+const CFX_CSSPropertyValueTable* CFX_GetCSSPropertyValueByName(
+ const CFX_WideStringC& wsName);
+
+const CFX_CSSLengthUnitTable* CFX_GetCSSLengthUnitByName(
+ const CFX_WideStringC& wsName);
+
+const CFX_CSSCOLORTABLE* CFX_GetCSSColorByName(const CFX_WideStringC& wsName);
+
+#endif // CORE_FXCRT_CSS_CFX_CSSDATATABLE_H_
diff --git a/core/fxcrt/css/cfx_cssdeclaration.cpp b/core/fxcrt/css/cfx_cssdeclaration.cpp
new file mode 100644
index 0000000000..b65429edb7
--- /dev/null
+++ b/core/fxcrt/css/cfx_cssdeclaration.cpp
@@ -0,0 +1,634 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// 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_cssdeclaration.h"
+
+#include "core/fxcrt/css/cfx_csscolorvalue.h"
+#include "core/fxcrt/css/cfx_csscustomproperty.h"
+#include "core/fxcrt/css/cfx_cssenumvalue.h"
+#include "core/fxcrt/css/cfx_cssnumbervalue.h"
+#include "core/fxcrt/css/cfx_csspropertyholder.h"
+#include "core/fxcrt/css/cfx_cssstringvalue.h"
+#include "core/fxcrt/css/cfx_cssvaluelist.h"
+#include "core/fxcrt/css/cfx_cssvaluelistparser.h"
+#include "core/fxcrt/fx_extension.h"
+#include "third_party/base/logging.h"
+#include "third_party/base/ptr_util.h"
+
+namespace {
+
+uint8_t Hex2Dec(uint8_t hexHigh, uint8_t hexLow) {
+ return (FXSYS_HexCharToInt(hexHigh) << 4) + FXSYS_HexCharToInt(hexLow);
+}
+
+bool ParseCSSNumber(const wchar_t* pszValue,
+ int32_t iValueLen,
+ float& fValue,
+ CFX_CSSNumberType& eUnit) {
+ ASSERT(pszValue && iValueLen > 0);
+ int32_t iUsedLen = 0;
+ fValue = FXSYS_wcstof(pszValue, iValueLen, &iUsedLen);
+ if (iUsedLen <= 0)
+ return false;
+
+ iValueLen -= iUsedLen;
+ pszValue += iUsedLen;
+ eUnit = CFX_CSSNumberType::Number;
+ if (iValueLen >= 1 && *pszValue == '%') {
+ eUnit = CFX_CSSNumberType::Percent;
+ } else if (iValueLen == 2) {
+ const CFX_CSSLengthUnitTable* pUnit =
+ CFX_GetCSSLengthUnitByName(CFX_WideStringC(pszValue, 2));
+ if (pUnit)
+ eUnit = pUnit->wValue;
+ }
+ return true;
+}
+
+} // namespace
+
+// static
+bool CFX_CSSDeclaration::ParseCSSString(const wchar_t* pszValue,
+ int32_t iValueLen,
+ int32_t* iOffset,
+ int32_t* iLength) {
+ ASSERT(pszValue && iValueLen > 0);
+ *iOffset = 0;
+ *iLength = iValueLen;
+ if (iValueLen >= 2) {
+ wchar_t first = pszValue[0], last = pszValue[iValueLen - 1];
+ if ((first == '\"' && last == '\"') || (first == '\'' && last == '\'')) {
+ *iOffset = 1;
+ *iLength -= 2;
+ }
+ }
+ return iValueLen > 0;
+}
+
+// static.
+bool CFX_CSSDeclaration::ParseCSSColor(const wchar_t* pszValue,
+ int32_t iValueLen,
+ FX_ARGB* dwColor) {
+ ASSERT(pszValue && iValueLen > 0);
+ ASSERT(dwColor);
+
+ if (*pszValue == '#') {
+ switch (iValueLen) {
+ case 4: {
+ uint8_t red = Hex2Dec((uint8_t)pszValue[1], (uint8_t)pszValue[1]);
+ uint8_t green = Hex2Dec((uint8_t)pszValue[2], (uint8_t)pszValue[2]);
+ uint8_t blue = Hex2Dec((uint8_t)pszValue[3], (uint8_t)pszValue[3]);
+ *dwColor = ArgbEncode(255, red, green, blue);
+ return true;
+ }
+ case 7: {
+ uint8_t red = Hex2Dec((uint8_t)pszValue[1], (uint8_t)pszValue[2]);
+ uint8_t green = Hex2Dec((uint8_t)pszValue[3], (uint8_t)pszValue[4]);
+ uint8_t blue = Hex2Dec((uint8_t)pszValue[5], (uint8_t)pszValue[6]);
+ *dwColor = ArgbEncode(255, red, green, blue);
+ return true;
+ }
+ default:
+ return false;
+ }
+ }
+
+ if (iValueLen >= 10) {
+ if (pszValue[iValueLen - 1] != ')' || FXSYS_wcsnicmp(L"rgb(", pszValue, 4))
+ return false;
+
+ uint8_t rgb[3] = {0};
+ float fValue;
+ CFX_CSSPrimitiveType eType;
+ CFX_CSSValueListParser list(pszValue + 4, iValueLen - 5, ',');
+ for (int32_t i = 0; i < 3; ++i) {
+ if (!list.NextValue(eType, pszValue, iValueLen))
+ return false;
+ if (eType != CFX_CSSPrimitiveType::Number)
+ return false;
+ CFX_CSSNumberType eNumType;
+ if (!ParseCSSNumber(pszValue, iValueLen, fValue, eNumType))
+ return false;
+
+ rgb[i] = eNumType == CFX_CSSNumberType::Percent
+ ? FXSYS_round(fValue * 2.55f)
+ : FXSYS_round(fValue);
+ }
+ *dwColor = ArgbEncode(255, rgb[0], rgb[1], rgb[2]);
+ return true;
+ }
+
+ const CFX_CSSCOLORTABLE* pColor =
+ CFX_GetCSSColorByName(CFX_WideStringC(pszValue, iValueLen));
+ if (!pColor)
+ return false;
+
+ *dwColor = pColor->dwValue;
+ return true;
+}
+
+CFX_CSSDeclaration::CFX_CSSDeclaration() {}
+
+CFX_CSSDeclaration::~CFX_CSSDeclaration() {}
+
+CFX_RetainPtr<CFX_CSSValue> CFX_CSSDeclaration::GetProperty(
+ CFX_CSSProperty eProperty,
+ bool* bImportant) const {
+ for (const auto& p : properties_) {
+ if (p->eProperty == eProperty) {
+ *bImportant = p->bImportant;
+ return p->pValue;
+ }
+ }
+ return nullptr;
+}
+
+void CFX_CSSDeclaration::AddPropertyHolder(CFX_CSSProperty eProperty,
+ CFX_RetainPtr<CFX_CSSValue> pValue,
+ bool bImportant) {
+ auto pHolder = pdfium::MakeUnique<CFX_CSSPropertyHolder>();
+ pHolder->bImportant = bImportant;
+ pHolder->eProperty = eProperty;
+ pHolder->pValue = pValue;
+ properties_.push_back(std::move(pHolder));
+}
+
+void CFX_CSSDeclaration::AddProperty(const CFX_CSSPropertyTable* pTable,
+ const CFX_WideStringC& value) {
+ ASSERT(!value.IsEmpty());
+
+ const wchar_t* pszValue = value.unterminated_c_str();
+ int32_t iValueLen = value.GetLength();
+ bool bImportant = false;
+ if (iValueLen >= 10 && pszValue[iValueLen - 10] == '!' &&
+ FXSYS_wcsnicmp(L"important", pszValue + iValueLen - 9, 9) == 0) {
+ if ((iValueLen -= 10) == 0)
+ return;
+
+ bImportant = true;
+ }
+ const uint32_t dwType = pTable->dwType;
+ switch (dwType & 0x0F) {
+ case CFX_CSSVALUETYPE_Primitive: {
+ static const uint32_t g_ValueGuessOrder[] = {
+ CFX_CSSVALUETYPE_MaybeNumber, CFX_CSSVALUETYPE_MaybeEnum,
+ CFX_CSSVALUETYPE_MaybeColor, CFX_CSSVALUETYPE_MaybeString,
+ };
+ static const int32_t g_ValueGuessCount =
+ sizeof(g_ValueGuessOrder) / sizeof(uint32_t);
+ for (int32_t i = 0; i < g_ValueGuessCount; ++i) {
+ const uint32_t dwMatch = dwType & g_ValueGuessOrder[i];
+ if (dwMatch == 0) {
+ continue;
+ }
+ CFX_RetainPtr<CFX_CSSValue> pCSSValue;
+ switch (dwMatch) {
+ case CFX_CSSVALUETYPE_MaybeNumber:
+ pCSSValue = ParseNumber(pszValue, iValueLen);
+ break;
+ case CFX_CSSVALUETYPE_MaybeEnum:
+ pCSSValue = ParseEnum(pszValue, iValueLen);
+ break;
+ case CFX_CSSVALUETYPE_MaybeColor:
+ pCSSValue = ParseColor(pszValue, iValueLen);
+ break;
+ case CFX_CSSVALUETYPE_MaybeString:
+ pCSSValue = ParseString(pszValue, iValueLen);
+ break;
+ default:
+ break;
+ }
+ if (pCSSValue) {
+ AddPropertyHolder(pTable->eName, pCSSValue, bImportant);
+ return;
+ }
+ if (CFX_IsOnlyValue(dwType, g_ValueGuessOrder[i]))
+ return;
+ }
+ break;
+ }
+ case CFX_CSSVALUETYPE_Shorthand: {
+ CFX_RetainPtr<CFX_CSSValue> pWidth;
+ switch (pTable->eName) {
+ case CFX_CSSProperty::Font:
+ ParseFontProperty(pszValue, iValueLen, bImportant);
+ return;
+ case CFX_CSSProperty::Border:
+ if (ParseBorderProperty(pszValue, iValueLen, pWidth)) {
+ AddPropertyHolder(CFX_CSSProperty::BorderLeftWidth, pWidth,
+ bImportant);
+ AddPropertyHolder(CFX_CSSProperty::BorderTopWidth, pWidth,
+ bImportant);
+ AddPropertyHolder(CFX_CSSProperty::BorderRightWidth, pWidth,
+ bImportant);
+ AddPropertyHolder(CFX_CSSProperty::BorderBottomWidth, pWidth,
+ bImportant);
+ return;
+ }
+ break;
+ case CFX_CSSProperty::BorderLeft:
+ if (ParseBorderProperty(pszValue, iValueLen, pWidth)) {
+ AddPropertyHolder(CFX_CSSProperty::BorderLeftWidth, pWidth,
+ bImportant);
+ return;
+ }
+ break;
+ case CFX_CSSProperty::BorderTop:
+ if (ParseBorderProperty(pszValue, iValueLen, pWidth)) {
+ AddPropertyHolder(CFX_CSSProperty::BorderTopWidth, pWidth,
+ bImportant);
+ return;
+ }
+ break;
+ case CFX_CSSProperty::BorderRight:
+ if (ParseBorderProperty(pszValue, iValueLen, pWidth)) {
+ AddPropertyHolder(CFX_CSSProperty::BorderRightWidth, pWidth,
+ bImportant);
+ return;
+ }
+ break;
+ case CFX_CSSProperty::BorderBottom:
+ if (ParseBorderProperty(pszValue, iValueLen, pWidth)) {
+ AddPropertyHolder(CFX_CSSProperty::BorderBottomWidth, pWidth,
+ bImportant);
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+ } break;
+ case CFX_CSSVALUETYPE_List:
+ ParseValueListProperty(pTable, pszValue, iValueLen, bImportant);
+ return;
+ default:
+ NOTREACHED();
+ break;
+ }
+}
+
+void CFX_CSSDeclaration::AddProperty(const CFX_WideString& prop,
+ const CFX_WideString& value) {
+ custom_properties_.push_back(
+ pdfium::MakeUnique<CFX_CSSCustomProperty>(prop, value));
+}
+
+CFX_RetainPtr<CFX_CSSValue> CFX_CSSDeclaration::ParseNumber(
+ const wchar_t* pszValue,
+ int32_t iValueLen) {
+ float fValue;
+ CFX_CSSNumberType eUnit;
+ if (!ParseCSSNumber(pszValue, iValueLen, fValue, eUnit))
+ return nullptr;
+ return pdfium::MakeRetain<CFX_CSSNumberValue>(eUnit, fValue);
+}
+
+CFX_RetainPtr<CFX_CSSValue> CFX_CSSDeclaration::ParseEnum(
+ const wchar_t* pszValue,
+ int32_t iValueLen) {
+ const CFX_CSSPropertyValueTable* pValue =
+ CFX_GetCSSPropertyValueByName(CFX_WideStringC(pszValue, iValueLen));
+ return pValue ? pdfium::MakeRetain<CFX_CSSEnumValue>(pValue->eName) : nullptr;
+}
+
+CFX_RetainPtr<CFX_CSSValue> CFX_CSSDeclaration::ParseColor(
+ const wchar_t* pszValue,
+ int32_t iValueLen) {
+ FX_ARGB dwColor;
+ if (!ParseCSSColor(pszValue, iValueLen, &dwColor))
+ return nullptr;
+ return pdfium::MakeRetain<CFX_CSSColorValue>(dwColor);
+}
+
+CFX_RetainPtr<CFX_CSSValue> CFX_CSSDeclaration::ParseString(
+ const wchar_t* pszValue,
+ int32_t iValueLen) {
+ int32_t iOffset;
+ if (!ParseCSSString(pszValue, iValueLen, &iOffset, &iValueLen))
+ return nullptr;
+
+ if (iValueLen <= 0)
+ return nullptr;
+
+ return pdfium::MakeRetain<CFX_CSSStringValue>(
+ CFX_WideString(pszValue + iOffset, iValueLen));
+}
+
+void CFX_CSSDeclaration::ParseValueListProperty(
+ const CFX_CSSPropertyTable* pTable,
+ const wchar_t* pszValue,
+ int32_t iValueLen,
+ bool bImportant) {
+ wchar_t separator =
+ (pTable->eName == CFX_CSSProperty::FontFamily) ? ',' : ' ';
+ CFX_CSSValueListParser parser(pszValue, iValueLen, separator);
+
+ const uint32_t dwType = pTable->dwType;
+ CFX_CSSPrimitiveType eType;
+ std::vector<CFX_RetainPtr<CFX_CSSValue>> list;
+ while (parser.NextValue(eType, pszValue, iValueLen)) {
+ switch (eType) {
+ case CFX_CSSPrimitiveType::Number:
+ if (dwType & CFX_CSSVALUETYPE_MaybeNumber) {
+ float fValue;
+ CFX_CSSNumberType eNumType;
+ if (ParseCSSNumber(pszValue, iValueLen, fValue, eNumType))
+ list.push_back(
+ pdfium::MakeRetain<CFX_CSSNumberValue>(eNumType, fValue));
+ }
+ break;
+ case CFX_CSSPrimitiveType::String:
+ if (dwType & CFX_CSSVALUETYPE_MaybeColor) {
+ FX_ARGB dwColor;
+ if (ParseCSSColor(pszValue, iValueLen, &dwColor)) {
+ list.push_back(pdfium::MakeRetain<CFX_CSSColorValue>(dwColor));
+ continue;
+ }
+ }
+ if (dwType & CFX_CSSVALUETYPE_MaybeEnum) {
+ const CFX_CSSPropertyValueTable* pValue =
+ CFX_GetCSSPropertyValueByName(
+ CFX_WideStringC(pszValue, iValueLen));
+ if (pValue) {
+ list.push_back(pdfium::MakeRetain<CFX_CSSEnumValue>(pValue->eName));
+ continue;
+ }
+ }
+ if (dwType & CFX_CSSVALUETYPE_MaybeString) {
+ list.push_back(pdfium::MakeRetain<CFX_CSSStringValue>(
+ CFX_WideString(pszValue, iValueLen)));
+ }
+ break;
+ case CFX_CSSPrimitiveType::RGB:
+ if (dwType & CFX_CSSVALUETYPE_MaybeColor) {
+ FX_ARGB dwColor;
+ if (ParseCSSColor(pszValue, iValueLen, &dwColor)) {
+ list.push_back(pdfium::MakeRetain<CFX_CSSColorValue>(dwColor));
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ if (list.empty())
+ return;
+
+ switch (pTable->eName) {
+ case CFX_CSSProperty::BorderWidth:
+ Add4ValuesProperty(list, bImportant, CFX_CSSProperty::BorderLeftWidth,
+ CFX_CSSProperty::BorderTopWidth,
+ CFX_CSSProperty::BorderRightWidth,
+ CFX_CSSProperty::BorderBottomWidth);
+ return;
+ case CFX_CSSProperty::Margin:
+ Add4ValuesProperty(list, bImportant, CFX_CSSProperty::MarginLeft,
+ CFX_CSSProperty::MarginTop,
+ CFX_CSSProperty::MarginRight,
+ CFX_CSSProperty::MarginBottom);
+ return;
+ case CFX_CSSProperty::Padding:
+ Add4ValuesProperty(list, bImportant, CFX_CSSProperty::PaddingLeft,
+ CFX_CSSProperty::PaddingTop,
+ CFX_CSSProperty::PaddingRight,
+ CFX_CSSProperty::PaddingBottom);
+ return;
+ default: {
+ auto pList = pdfium::MakeRetain<CFX_CSSValueList>(list);
+ AddPropertyHolder(pTable->eName, pList, bImportant);
+ return;
+ }
+ }
+}
+
+void CFX_CSSDeclaration::Add4ValuesProperty(
+ const std::vector<CFX_RetainPtr<CFX_CSSValue>>& list,
+ bool bImportant,
+ CFX_CSSProperty eLeft,
+ CFX_CSSProperty eTop,
+ CFX_CSSProperty eRight,
+ CFX_CSSProperty eBottom) {
+ switch (list.size()) {
+ case 1:
+ AddPropertyHolder(eLeft, list[0], bImportant);
+ AddPropertyHolder(eTop, list[0], bImportant);
+ AddPropertyHolder(eRight, list[0], bImportant);
+ AddPropertyHolder(eBottom, list[0], bImportant);
+ return;
+ case 2:
+ AddPropertyHolder(eLeft, list[1], bImportant);
+ AddPropertyHolder(eTop, list[0], bImportant);
+ AddPropertyHolder(eRight, list[1], bImportant);
+ AddPropertyHolder(eBottom, list[0], bImportant);
+ return;
+ case 3:
+ AddPropertyHolder(eLeft, list[1], bImportant);
+ AddPropertyHolder(eTop, list[0], bImportant);
+ AddPropertyHolder(eRight, list[1], bImportant);
+ AddPropertyHolder(eBottom, list[2], bImportant);
+ return;
+ case 4:
+ AddPropertyHolder(eLeft, list[3], bImportant);
+ AddPropertyHolder(eTop, list[0], bImportant);
+ AddPropertyHolder(eRight, list[1], bImportant);
+ AddPropertyHolder(eBottom, list[2], bImportant);
+ return;
+ default:
+ break;
+ }
+}
+
+bool CFX_CSSDeclaration::ParseBorderProperty(
+ const wchar_t* pszValue,
+ int32_t iValueLen,
+ CFX_RetainPtr<CFX_CSSValue>& pWidth) const {
+ pWidth.Reset(nullptr);
+
+ CFX_CSSValueListParser parser(pszValue, iValueLen, ' ');
+ CFX_CSSPrimitiveType eType;
+ while (parser.NextValue(eType, pszValue, iValueLen)) {
+ switch (eType) {
+ case CFX_CSSPrimitiveType::Number: {
+ if (pWidth)
+ continue;
+
+ float fValue;
+ CFX_CSSNumberType eNumType;
+ if (ParseCSSNumber(pszValue, iValueLen, fValue, eNumType))
+ pWidth = pdfium::MakeRetain<CFX_CSSNumberValue>(eNumType, fValue);
+ break;
+ }
+ case CFX_CSSPrimitiveType::String: {
+ const CFX_CSSCOLORTABLE* pColorItem =
+ CFX_GetCSSColorByName(CFX_WideStringC(pszValue, iValueLen));
+ if (pColorItem)
+ continue;
+
+ const CFX_CSSPropertyValueTable* pValue =
+ CFX_GetCSSPropertyValueByName(CFX_WideStringC(pszValue, iValueLen));
+ if (!pValue)
+ continue;
+
+ switch (pValue->eName) {
+ case CFX_CSSPropertyValue::Thin:
+ case CFX_CSSPropertyValue::Thick:
+ case CFX_CSSPropertyValue::Medium:
+ if (!pWidth)
+ pWidth = pdfium::MakeRetain<CFX_CSSEnumValue>(pValue->eName);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ if (!pWidth)
+ pWidth =
+ pdfium::MakeRetain<CFX_CSSNumberValue>(CFX_CSSNumberType::Number, 0.0f);
+
+ return true;
+}
+
+void CFX_CSSDeclaration::ParseFontProperty(const wchar_t* pszValue,
+ int32_t iValueLen,
+ bool bImportant) {
+ CFX_CSSValueListParser parser(pszValue, iValueLen, '/');
+ CFX_RetainPtr<CFX_CSSValue> pStyle;
+ CFX_RetainPtr<CFX_CSSValue> pVariant;
+ CFX_RetainPtr<CFX_CSSValue> pWeight;
+ CFX_RetainPtr<CFX_CSSValue> pFontSize;
+ CFX_RetainPtr<CFX_CSSValue> pLineHeight;
+ std::vector<CFX_RetainPtr<CFX_CSSValue>> familyList;
+ CFX_CSSPrimitiveType eType;
+ while (parser.NextValue(eType, pszValue, iValueLen)) {
+ switch (eType) {
+ case CFX_CSSPrimitiveType::String: {
+ const CFX_CSSPropertyValueTable* pValue =
+ CFX_GetCSSPropertyValueByName(CFX_WideStringC(pszValue, iValueLen));
+ if (pValue) {
+ switch (pValue->eName) {
+ case CFX_CSSPropertyValue::XxSmall:
+ case CFX_CSSPropertyValue::XSmall:
+ case CFX_CSSPropertyValue::Small:
+ case CFX_CSSPropertyValue::Medium:
+ case CFX_CSSPropertyValue::Large:
+ case CFX_CSSPropertyValue::XLarge:
+ case CFX_CSSPropertyValue::XxLarge:
+ case CFX_CSSPropertyValue::Smaller:
+ case CFX_CSSPropertyValue::Larger:
+ if (!pFontSize)
+ pFontSize = pdfium::MakeRetain<CFX_CSSEnumValue>(pValue->eName);
+ continue;
+ case CFX_CSSPropertyValue::Bold:
+ case CFX_CSSPropertyValue::Bolder:
+ case CFX_CSSPropertyValue::Lighter:
+ if (!pWeight)
+ pWeight = pdfium::MakeRetain<CFX_CSSEnumValue>(pValue->eName);
+ continue;
+ case CFX_CSSPropertyValue::Italic:
+ case CFX_CSSPropertyValue::Oblique:
+ if (!pStyle)
+ pStyle = pdfium::MakeRetain<CFX_CSSEnumValue>(pValue->eName);
+ continue;
+ case CFX_CSSPropertyValue::SmallCaps:
+ if (!pVariant)
+ pVariant = pdfium::MakeRetain<CFX_CSSEnumValue>(pValue->eName);
+ continue;
+ case CFX_CSSPropertyValue::Normal:
+ if (!pStyle)
+ pStyle = pdfium::MakeRetain<CFX_CSSEnumValue>(pValue->eName);
+ else if (!pVariant)
+ pVariant = pdfium::MakeRetain<CFX_CSSEnumValue>(pValue->eName);
+ else if (!pWeight)
+ pWeight = pdfium::MakeRetain<CFX_CSSEnumValue>(pValue->eName);
+ else if (!pFontSize)
+ pFontSize = pdfium::MakeRetain<CFX_CSSEnumValue>(pValue->eName);
+ else if (!pLineHeight)
+ pLineHeight =
+ pdfium::MakeRetain<CFX_CSSEnumValue>(pValue->eName);
+ continue;
+ default:
+ break;
+ }
+ }
+ if (pFontSize) {
+ familyList.push_back(pdfium::MakeRetain<CFX_CSSStringValue>(
+ CFX_WideString(pszValue, iValueLen)));
+ }
+ parser.m_Separator = ',';
+ break;
+ }
+ case CFX_CSSPrimitiveType::Number: {
+ float fValue;
+ CFX_CSSNumberType eNumType;
+ if (!ParseCSSNumber(pszValue, iValueLen, fValue, eNumType))
+ break;
+ if (eType == CFX_CSSPrimitiveType::Number) {
+ switch ((int32_t)fValue) {
+ case 100:
+ case 200:
+ case 300:
+ case 400:
+ case 500:
+ case 600:
+ case 700:
+ case 800:
+ case 900:
+ if (!pWeight)
+ pWeight = pdfium::MakeRetain<CFX_CSSNumberValue>(
+ CFX_CSSNumberType::Number, fValue);
+ continue;
+ }
+ }
+ if (!pFontSize)
+ pFontSize = pdfium::MakeRetain<CFX_CSSNumberValue>(eNumType, fValue);
+ else if (!pLineHeight)
+ pLineHeight =
+ pdfium::MakeRetain<CFX_CSSNumberValue>(eNumType, fValue);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ if (!pStyle) {
+ pStyle = pdfium::MakeRetain<CFX_CSSEnumValue>(CFX_CSSPropertyValue::Normal);
+ }
+ if (!pVariant) {
+ pVariant =
+ pdfium::MakeRetain<CFX_CSSEnumValue>(CFX_CSSPropertyValue::Normal);
+ }
+ if (!pWeight) {
+ pWeight =
+ pdfium::MakeRetain<CFX_CSSEnumValue>(CFX_CSSPropertyValue::Normal);
+ }
+ if (!pFontSize) {
+ pFontSize =
+ pdfium::MakeRetain<CFX_CSSEnumValue>(CFX_CSSPropertyValue::Medium);
+ }
+ if (!pLineHeight) {
+ pLineHeight =
+ pdfium::MakeRetain<CFX_CSSEnumValue>(CFX_CSSPropertyValue::Normal);
+ }
+
+ AddPropertyHolder(CFX_CSSProperty::FontStyle, pStyle, bImportant);
+ AddPropertyHolder(CFX_CSSProperty::FontVariant, pVariant, bImportant);
+ AddPropertyHolder(CFX_CSSProperty::FontWeight, pWeight, bImportant);
+ AddPropertyHolder(CFX_CSSProperty::FontSize, pFontSize, bImportant);
+ AddPropertyHolder(CFX_CSSProperty::LineHeight, pLineHeight, bImportant);
+ if (!familyList.empty()) {
+ auto pList = pdfium::MakeRetain<CFX_CSSValueList>(familyList);
+ AddPropertyHolder(CFX_CSSProperty::FontFamily, pList, bImportant);
+ }
+}
+
+size_t CFX_CSSDeclaration::PropertyCountForTesting() const {
+ return properties_.size();
+}
diff --git a/core/fxcrt/css/cfx_cssdeclaration.h b/core/fxcrt/css/cfx_cssdeclaration.h
new file mode 100644
index 0000000000..7b39daef7e
--- /dev/null
+++ b/core/fxcrt/css/cfx_cssdeclaration.h
@@ -0,0 +1,93 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// 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
+
+#ifndef CORE_FXCRT_CSS_CFX_CSSDECLARATION_H_
+#define CORE_FXCRT_CSS_CFX_CSSDECLARATION_H_
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "core/fxcrt/css/cfx_cssdatatable.h"
+
+class CFX_CSSPropertyHolder;
+class CFX_CSSCustomProperty;
+
+class CFX_CSSDeclaration {
+ public:
+ using const_prop_iterator =
+ std::vector<std::unique_ptr<CFX_CSSPropertyHolder>>::const_iterator;
+ using const_custom_iterator =
+ std::vector<std::unique_ptr<CFX_CSSCustomProperty>>::const_iterator;
+
+ static bool ParseCSSString(const wchar_t* pszValue,
+ int32_t iValueLen,
+ int32_t* iOffset,
+ int32_t* iLength);
+ static bool ParseCSSColor(const wchar_t* pszValue,
+ int32_t iValueLen,
+ FX_ARGB* dwColor);
+
+ CFX_CSSDeclaration();
+ ~CFX_CSSDeclaration();
+
+ CFX_RetainPtr<CFX_CSSValue> GetProperty(CFX_CSSProperty eProperty,
+ bool* bImportant) const;
+
+ const_prop_iterator begin() const { return properties_.begin(); }
+ const_prop_iterator end() const { return properties_.end(); }
+
+ const_custom_iterator custom_begin() const {
+ return custom_properties_.begin();
+ }
+ const_custom_iterator custom_end() const { return custom_properties_.end(); }
+
+ bool empty() const { return properties_.empty(); }
+
+ void AddProperty(const CFX_CSSPropertyTable* pTable,
+ const CFX_WideStringC& value);
+ void AddProperty(const CFX_WideString& prop, const CFX_WideString& value);
+
+ size_t PropertyCountForTesting() const;
+
+ FX_ARGB ParseColorForTest(const wchar_t* pszValue,
+ int32_t iValueLen,
+ FX_ARGB* dwColor) const;
+
+ private:
+ void ParseFontProperty(const wchar_t* pszValue,
+ int32_t iValueLen,
+ bool bImportant);
+ bool ParseBorderProperty(const wchar_t* pszValue,
+ int32_t iValueLen,
+ CFX_RetainPtr<CFX_CSSValue>& pWidth) const;
+ void ParseValueListProperty(const CFX_CSSPropertyTable* pTable,
+ const wchar_t* pszValue,
+ int32_t iValueLen,
+ bool bImportant);
+ void Add4ValuesProperty(const std::vector<CFX_RetainPtr<CFX_CSSValue>>& list,
+ bool bImportant,
+ CFX_CSSProperty eLeft,
+ CFX_CSSProperty eTop,
+ CFX_CSSProperty eRight,
+ CFX_CSSProperty eBottom);
+ CFX_RetainPtr<CFX_CSSValue> ParseNumber(const wchar_t* pszValue,
+ int32_t iValueLen);
+ CFX_RetainPtr<CFX_CSSValue> ParseEnum(const wchar_t* pszValue,
+ int32_t iValueLen);
+ CFX_RetainPtr<CFX_CSSValue> ParseColor(const wchar_t* pszValue,
+ int32_t iValueLen);
+ CFX_RetainPtr<CFX_CSSValue> ParseString(const wchar_t* pszValue,
+ int32_t iValueLen);
+ void AddPropertyHolder(CFX_CSSProperty eProperty,
+ CFX_RetainPtr<CFX_CSSValue> pValue,
+ bool bImportant);
+
+ std::vector<std::unique_ptr<CFX_CSSPropertyHolder>> properties_;
+ std::vector<std::unique_ptr<CFX_CSSCustomProperty>> custom_properties_;
+};
+
+#endif // CORE_FXCRT_CSS_CFX_CSSDECLARATION_H_
diff --git a/core/fxcrt/css/cfx_cssdeclaration_unittest.cpp b/core/fxcrt/css/cfx_cssdeclaration_unittest.cpp
new file mode 100644
index 0000000000..535e67da97
--- /dev/null
+++ b/core/fxcrt/css/cfx_cssdeclaration_unittest.cpp
@@ -0,0 +1,62 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/fxcrt/css/cfx_cssdeclaration.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/test_support.h"
+
+TEST(CFX_CSSDeclarationTest, HexEncodingParsing) {
+ FX_ARGB color;
+
+ // Length value invalid.
+ EXPECT_FALSE(CFX_CSSDeclaration::ParseCSSColor(L"#000", 3, &color));
+ EXPECT_FALSE(CFX_CSSDeclaration::ParseCSSColor(L"#000000", 5, &color));
+ EXPECT_FALSE(CFX_CSSDeclaration::ParseCSSColor(L"#000000", 8, &color));
+
+ // Invalid characters
+ EXPECT_TRUE(CFX_CSSDeclaration::ParseCSSColor(L"#zxytlm", 7, &color));
+ EXPECT_EQ(0, FXARGB_R(color));
+ EXPECT_EQ(0, FXARGB_G(color));
+ EXPECT_EQ(0, FXARGB_B(color));
+
+ EXPECT_TRUE(CFX_CSSDeclaration::ParseCSSColor(L"#000", 4, &color));
+ EXPECT_EQ(0, FXARGB_R(color));
+ EXPECT_EQ(0, FXARGB_G(color));
+ EXPECT_EQ(0, FXARGB_B(color));
+
+ EXPECT_TRUE(CFX_CSSDeclaration::ParseCSSColor(L"#FFF", 4, &color));
+ EXPECT_EQ(255, FXARGB_R(color));
+ EXPECT_EQ(255, FXARGB_G(color));
+ EXPECT_EQ(255, FXARGB_B(color));
+
+ EXPECT_TRUE(CFX_CSSDeclaration::ParseCSSColor(L"#F0F0F0", 7, &color));
+ EXPECT_EQ(240, FXARGB_R(color));
+ EXPECT_EQ(240, FXARGB_G(color));
+ EXPECT_EQ(240, FXARGB_B(color));
+
+ // Upper and lower case characters.
+ EXPECT_TRUE(CFX_CSSDeclaration::ParseCSSColor(L"#1b2F3c", 7, &color));
+ EXPECT_EQ(27, FXARGB_R(color));
+ EXPECT_EQ(47, FXARGB_G(color));
+ EXPECT_EQ(60, FXARGB_B(color));
+}
+
+TEST(CFX_CSSDeclarationTest, RGBEncodingParsing) {
+ FX_ARGB color;
+
+ // Invalid input for rgb() syntax.
+ EXPECT_FALSE(CFX_CSSDeclaration::ParseCSSColor(L"blahblahblah", 11, &color));
+
+ EXPECT_TRUE(CFX_CSSDeclaration::ParseCSSColor(L"rgb(0, 0, 0)", 12, &color));
+ EXPECT_EQ(0, FXARGB_R(color));
+ EXPECT_EQ(0, FXARGB_G(color));
+ EXPECT_EQ(0, FXARGB_B(color));
+
+ EXPECT_TRUE(
+ CFX_CSSDeclaration::ParseCSSColor(L"rgb(128,255,48)", 15, &color));
+ EXPECT_EQ(128, FXARGB_R(color));
+ EXPECT_EQ(255, FXARGB_G(color));
+ EXPECT_EQ(48, FXARGB_B(color));
+}
diff --git a/core/fxcrt/css/cfx_cssenumvalue.cpp b/core/fxcrt/css/cfx_cssenumvalue.cpp
new file mode 100644
index 0000000000..c9b39beb34
--- /dev/null
+++ b/core/fxcrt/css/cfx_cssenumvalue.cpp
@@ -0,0 +1,12 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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_cssenumvalue.h"
+
+CFX_CSSEnumValue::CFX_CSSEnumValue(CFX_CSSPropertyValue value)
+ : CFX_CSSValue(CFX_CSSPrimitiveType::Enum), value_(value) {}
+
+CFX_CSSEnumValue::~CFX_CSSEnumValue() {}
diff --git a/core/fxcrt/css/cfx_cssenumvalue.h b/core/fxcrt/css/cfx_cssenumvalue.h
new file mode 100644
index 0000000000..0d6b87e85d
--- /dev/null
+++ b/core/fxcrt/css/cfx_cssenumvalue.h
@@ -0,0 +1,23 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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
+
+#ifndef CORE_FXCRT_CSS_CFX_CSSENUMVALUE_H_
+#define CORE_FXCRT_CSS_CFX_CSSENUMVALUE_H_
+
+#include "core/fxcrt/css/cfx_cssvalue.h"
+
+class CFX_CSSEnumValue : public CFX_CSSValue {
+ public:
+ explicit CFX_CSSEnumValue(CFX_CSSPropertyValue value);
+ ~CFX_CSSEnumValue() override;
+
+ CFX_CSSPropertyValue Value() const { return value_; }
+
+ private:
+ CFX_CSSPropertyValue value_;
+};
+
+#endif // CORE_FXCRT_CSS_CFX_CSSENUMVALUE_H_
diff --git a/core/fxcrt/css/cfx_cssexttextbuf.cpp b/core/fxcrt/css/cfx_cssexttextbuf.cpp
new file mode 100644
index 0000000000..287dc2e954
--- /dev/null
+++ b/core/fxcrt/css/cfx_cssexttextbuf.cpp
@@ -0,0 +1,17 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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_cssexttextbuf.h"
+
+CFX_CSSExtTextBuf::CFX_CSSExtTextBuf()
+ : m_pExtBuffer(nullptr), m_iDatLen(0), m_iDatPos(0) {}
+
+CFX_CSSExtTextBuf::~CFX_CSSExtTextBuf() {}
+
+void CFX_CSSExtTextBuf::AttachBuffer(const wchar_t* pBuffer, int32_t iBufLen) {
+ m_pExtBuffer = pBuffer;
+ m_iDatLen = iBufLen;
+}
diff --git a/core/fxcrt/css/cfx_cssexttextbuf.h b/core/fxcrt/css/cfx_cssexttextbuf.h
new file mode 100644
index 0000000000..342b91e8aa
--- /dev/null
+++ b/core/fxcrt/css/cfx_cssexttextbuf.h
@@ -0,0 +1,34 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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
+
+#ifndef CORE_FXCRT_CSS_CFX_CSSEXTTEXTBUF_H_
+#define CORE_FXCRT_CSS_CFX_CSSEXTTEXTBUF_H_
+
+#include "core/fxcrt/fx_system.h"
+
+class CFX_CSSExtTextBuf {
+ public:
+ CFX_CSSExtTextBuf();
+ ~CFX_CSSExtTextBuf();
+
+ void AttachBuffer(const wchar_t* pBuffer, int32_t iBufLen);
+
+ bool IsEOF() const { return m_iDatPos >= m_iDatLen; }
+
+ wchar_t GetChar() const { return m_pExtBuffer[m_iDatPos]; }
+ wchar_t GetNextChar() const {
+ return (m_iDatPos + 1 >= m_iDatLen) ? 0 : m_pExtBuffer[m_iDatPos + 1];
+ }
+
+ void MoveNext() { m_iDatPos++; }
+
+ protected:
+ const wchar_t* m_pExtBuffer;
+ int32_t m_iDatLen;
+ int32_t m_iDatPos;
+};
+
+#endif // CORE_FXCRT_CSS_CFX_CSSEXTTEXTBUF_H_
diff --git a/core/fxcrt/css/cfx_cssnumbervalue.cpp b/core/fxcrt/css/cfx_cssnumbervalue.cpp
new file mode 100644
index 0000000000..d8f72479d4
--- /dev/null
+++ b/core/fxcrt/css/cfx_cssnumbervalue.cpp
@@ -0,0 +1,39 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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_cssnumbervalue.h"
+
+CFX_CSSNumberValue::CFX_CSSNumberValue(CFX_CSSNumberType type, float value)
+ : CFX_CSSValue(CFX_CSSPrimitiveType::Number), type_(type), value_(value) {
+ if (type_ == CFX_CSSNumberType::Number && fabs(value_) < 0.001f)
+ value_ = 0.0f;
+}
+
+CFX_CSSNumberValue::~CFX_CSSNumberValue() {}
+
+float CFX_CSSNumberValue::Apply(float percentBase) const {
+ switch (type_) {
+ case CFX_CSSNumberType::Pixels:
+ case CFX_CSSNumberType::Number:
+ return value_ * 72 / 96;
+ case CFX_CSSNumberType::EMS:
+ case CFX_CSSNumberType::EXS:
+ return value_ * percentBase;
+ case CFX_CSSNumberType::Percent:
+ return value_ * percentBase / 100.0f;
+ case CFX_CSSNumberType::CentiMeters:
+ return value_ * 28.3464f;
+ case CFX_CSSNumberType::MilliMeters:
+ return value_ * 2.8346f;
+ case CFX_CSSNumberType::Inches:
+ return value_ * 72.0f;
+ case CFX_CSSNumberType::Picas:
+ return value_ / 12.0f;
+ case CFX_CSSNumberType::Points:
+ return value_;
+ }
+ return value_;
+}
diff --git a/core/fxcrt/css/cfx_cssnumbervalue.h b/core/fxcrt/css/cfx_cssnumbervalue.h
new file mode 100644
index 0000000000..a49328d663
--- /dev/null
+++ b/core/fxcrt/css/cfx_cssnumbervalue.h
@@ -0,0 +1,41 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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
+
+#ifndef CORE_FXCRT_CSS_CFX_CSSNUMBERVALUE_H_
+#define CORE_FXCRT_CSS_CFX_CSSNUMBERVALUE_H_
+
+#include "core/fxcrt/css/cfx_cssvalue.h"
+#include "core/fxcrt/fx_system.h"
+
+enum class CFX_CSSNumberType {
+ Number,
+ Percent,
+ EMS,
+ EXS,
+ Pixels,
+ CentiMeters,
+ MilliMeters,
+ Inches,
+ Points,
+ Picas,
+};
+
+class CFX_CSSNumberValue : public CFX_CSSValue {
+ public:
+ CFX_CSSNumberValue(CFX_CSSNumberType type, float value);
+ ~CFX_CSSNumberValue() override;
+
+ float Value() const { return value_; }
+ CFX_CSSNumberType Kind() const { return type_; }
+
+ float Apply(float percentBase) const;
+
+ private:
+ CFX_CSSNumberType type_;
+ float value_;
+};
+
+#endif // CORE_FXCRT_CSS_CFX_CSSNUMBERVALUE_H_
diff --git a/core/fxcrt/css/cfx_csspropertyholder.cpp b/core/fxcrt/css/cfx_csspropertyholder.cpp
new file mode 100644
index 0000000000..11e0d4b752
--- /dev/null
+++ b/core/fxcrt/css/cfx_csspropertyholder.cpp
@@ -0,0 +1,11 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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_csspropertyholder.h"
+
+CFX_CSSPropertyHolder::CFX_CSSPropertyHolder() {}
+
+CFX_CSSPropertyHolder::~CFX_CSSPropertyHolder() {}
diff --git a/core/fxcrt/css/cfx_csspropertyholder.h b/core/fxcrt/css/cfx_csspropertyholder.h
new file mode 100644
index 0000000000..ab0e0ae1fb
--- /dev/null
+++ b/core/fxcrt/css/cfx_csspropertyholder.h
@@ -0,0 +1,24 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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
+
+#ifndef CORE_FXCRT_CSS_CFX_CSSPROPERTYHOLDER_H_
+#define CORE_FXCRT_CSS_CFX_CSSPROPERTYHOLDER_H_
+
+#include "core/fxcrt/cfx_retain_ptr.h"
+#include "core/fxcrt/css/cfx_css.h"
+#include "core/fxcrt/css/cfx_cssvalue.h"
+
+class CFX_CSSPropertyHolder {
+ public:
+ CFX_CSSPropertyHolder();
+ ~CFX_CSSPropertyHolder();
+
+ CFX_CSSProperty eProperty;
+ bool bImportant;
+ CFX_RetainPtr<CFX_CSSValue> pValue;
+};
+
+#endif // CORE_FXCRT_CSS_CFX_CSSPROPERTYHOLDER_H_
diff --git a/core/fxcrt/css/cfx_cssrulecollection.cpp b/core/fxcrt/css/cfx_cssrulecollection.cpp
new file mode 100644
index 0000000000..635ca91c72
--- /dev/null
+++ b/core/fxcrt/css/cfx_cssrulecollection.cpp
@@ -0,0 +1,56 @@
+// Copyright 2016 PDFium Authors. All rights reserved.
+// 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_cssrulecollection.h"
+
+#include <algorithm>
+#include <utility>
+
+#include "core/fxcrt/css/cfx_cssdeclaration.h"
+#include "core/fxcrt/css/cfx_cssselector.h"
+#include "core/fxcrt/css/cfx_cssstylerule.h"
+#include "core/fxcrt/css/cfx_cssstylesheet.h"
+#include "core/fxcrt/css/cfx_csssyntaxparser.h"
+#include "third_party/base/ptr_util.h"
+
+CFX_CSSRuleCollection::CFX_CSSRuleCollection() : m_iSelectors(0) {}
+
+CFX_CSSRuleCollection::~CFX_CSSRuleCollection() {
+ Clear();
+}
+
+void CFX_CSSRuleCollection::Clear() {
+ m_TagRules.clear();
+ m_iSelectors = 0;
+}
+
+const std::vector<std::unique_ptr<CFX_CSSRuleCollection::Data>>*
+CFX_CSSRuleCollection::GetTagRuleData(const CFX_WideString& tagname) const {
+ auto it = m_TagRules.find(FX_HashCode_GetW(tagname.c_str(), true));
+ return it != m_TagRules.end() ? &it->second : nullptr;
+}
+
+void CFX_CSSRuleCollection::AddRulesFrom(const CFX_CSSStyleSheet* sheet) {
+ int32_t iRules = sheet->CountRules();
+ for (int32_t j = 0; j < iRules; j++)
+ AddRulesFrom(sheet, sheet->GetRule(j));
+}
+
+void CFX_CSSRuleCollection::AddRulesFrom(const CFX_CSSStyleSheet* pStyleSheet,
+ CFX_CSSStyleRule* pStyleRule) {
+ CFX_CSSDeclaration* pDeclaration = pStyleRule->GetDeclaration();
+ int32_t iSelectors = pStyleRule->CountSelectorLists();
+ for (int32_t i = 0; i < iSelectors; ++i) {
+ CFX_CSSSelector* pSelector = pStyleRule->GetSelectorList(i);
+ m_TagRules[pSelector->GetNameHash()].push_back(
+ pdfium::MakeUnique<Data>(pSelector, pDeclaration));
+ m_iSelectors++;
+ }
+}
+
+CFX_CSSRuleCollection::Data::Data(CFX_CSSSelector* pSel,
+ CFX_CSSDeclaration* pDecl)
+ : pSelector(pSel), pDeclaration(pDecl) {}
diff --git a/core/fxcrt/css/cfx_cssrulecollection.h b/core/fxcrt/css/cfx_cssrulecollection.h
new file mode 100644
index 0000000000..6a509d49e7
--- /dev/null
+++ b/core/fxcrt/css/cfx_cssrulecollection.h
@@ -0,0 +1,49 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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
+
+#ifndef CORE_FXCRT_CSS_CFX_CSSRULECOLLECTION_H_
+#define CORE_FXCRT_CSS_CFX_CSSRULECOLLECTION_H_
+
+#include <map>
+#include <memory>
+#include <vector>
+
+#include "core/fxcrt/fx_basic.h"
+
+class CFX_CSSDeclaration;
+class CFX_CSSSelector;
+class CFX_CSSStyleRule;
+class CFX_CSSStyleSheet;
+
+class CFX_CSSRuleCollection {
+ public:
+ class Data {
+ public:
+ Data(CFX_CSSSelector* pSel, CFX_CSSDeclaration* pDecl);
+
+ CFX_CSSSelector* const pSelector;
+ CFX_CSSDeclaration* const pDeclaration;
+ };
+
+ CFX_CSSRuleCollection();
+ ~CFX_CSSRuleCollection();
+
+ void AddRulesFrom(const CFX_CSSStyleSheet* sheet);
+ void Clear();
+ int32_t CountSelectors() const { return m_iSelectors; }
+
+ const std::vector<std::unique_ptr<Data>>* GetTagRuleData(
+ const CFX_WideString& tagname) const;
+
+ private:
+ void AddRulesFrom(const CFX_CSSStyleSheet* pStyleSheet,
+ CFX_CSSStyleRule* pRule);
+
+ std::map<uint32_t, std::vector<std::unique_ptr<Data>>> m_TagRules;
+ int32_t m_iSelectors;
+};
+
+#endif // CORE_FXCRT_CSS_CFX_CSSRULECOLLECTION_H_
diff --git a/core/fxcrt/css/cfx_cssselector.cpp b/core/fxcrt/css/cfx_cssselector.cpp
new file mode 100644
index 0000000000..6ee81f5610
--- /dev/null
+++ b/core/fxcrt/css/cfx_cssselector.cpp
@@ -0,0 +1,87 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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_cssselector.h"
+
+#include <utility>
+
+#include "core/fxcrt/fx_extension.h"
+#include "third_party/base/ptr_util.h"
+
+namespace {
+
+int32_t GetCSSNameLen(const wchar_t* psz, const wchar_t* pEnd) {
+ const wchar_t* pStart = psz;
+ while (psz < pEnd) {
+ wchar_t wch = *psz;
+ if (!FXSYS_iswalnum(wch) && wch != '_' && wch != '-')
+ break;
+ ++psz;
+ }
+ return psz - pStart;
+}
+
+} // namespace
+
+CFX_CSSSelector::CFX_CSSSelector(CFX_CSSSelectorType eType,
+ const wchar_t* psz,
+ int32_t iLen,
+ bool bIgnoreCase)
+ : m_eType(eType),
+ m_dwHash(FX_HashCode_GetW(CFX_WideStringC(psz, iLen), bIgnoreCase)) {}
+
+CFX_CSSSelector::~CFX_CSSSelector() {}
+
+CFX_CSSSelectorType CFX_CSSSelector::GetType() const {
+ return m_eType;
+}
+
+uint32_t CFX_CSSSelector::GetNameHash() const {
+ return m_dwHash;
+}
+
+CFX_CSSSelector* CFX_CSSSelector::GetNextSelector() const {
+ return m_pNext.get();
+}
+
+// static.
+std::unique_ptr<CFX_CSSSelector> CFX_CSSSelector::FromString(
+ const CFX_WideStringC& str) {
+ ASSERT(!str.IsEmpty());
+
+ const wchar_t* psz = str.unterminated_c_str();
+ const wchar_t* pStart = psz;
+ const wchar_t* pEnd = psz + str.GetLength();
+ for (; psz < pEnd; ++psz) {
+ switch (*psz) {
+ case '>':
+ case '[':
+ case '+':
+ return nullptr;
+ }
+ }
+
+ std::unique_ptr<CFX_CSSSelector> pFirst = nullptr;
+ for (psz = pStart; psz < pEnd;) {
+ wchar_t wch = *psz;
+ if (FXSYS_iswalpha(wch) || wch == '*') {
+ int32_t iNameLen = wch == '*' ? 1 : GetCSSNameLen(psz, pEnd);
+ auto p = pdfium::MakeUnique<CFX_CSSSelector>(CFX_CSSSelectorType::Element,
+ psz, iNameLen, true);
+ if (pFirst) {
+ pFirst->SetType(CFX_CSSSelectorType::Descendant);
+ p->SetNext(std::move(pFirst));
+ }
+ pFirst = std::move(p);
+ psz += iNameLen;
+ } else if (wch == ' ') {
+ psz++;
+ } else {
+ return nullptr;
+ }
+ }
+ return pFirst;
+}
diff --git a/core/fxcrt/css/cfx_cssselector.h b/core/fxcrt/css/cfx_cssselector.h
new file mode 100644
index 0000000000..9fff42a850
--- /dev/null
+++ b/core/fxcrt/css/cfx_cssselector.h
@@ -0,0 +1,43 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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
+
+#ifndef CORE_FXCRT_CSS_CFX_CSSSELECTOR_H_
+#define CORE_FXCRT_CSS_CFX_CSSSELECTOR_H_
+
+#include <memory>
+#include <utility>
+
+#include "core/fxcrt/css/cfx_css.h"
+#include "core/fxcrt/fx_string.h"
+
+class CFX_CSSSelector {
+ public:
+ static std::unique_ptr<CFX_CSSSelector> FromString(
+ const CFX_WideStringC& str);
+
+ CFX_CSSSelector(CFX_CSSSelectorType eType,
+ const wchar_t* psz,
+ int32_t iLen,
+ bool bIgnoreCase);
+ ~CFX_CSSSelector();
+
+ CFX_CSSSelectorType GetType() const;
+ uint32_t GetNameHash() const;
+ CFX_CSSSelector* GetNextSelector() const;
+
+ void SetNext(std::unique_ptr<CFX_CSSSelector> pNext) {
+ m_pNext = std::move(pNext);
+ }
+
+ private:
+ void SetType(CFX_CSSSelectorType eType) { m_eType = eType; }
+
+ CFX_CSSSelectorType m_eType;
+ uint32_t m_dwHash;
+ std::unique_ptr<CFX_CSSSelector> m_pNext;
+};
+
+#endif // CORE_FXCRT_CSS_CFX_CSSSELECTOR_H_
diff --git a/core/fxcrt/css/cfx_cssstringvalue.cpp b/core/fxcrt/css/cfx_cssstringvalue.cpp
new file mode 100644
index 0000000000..b66c54505f
--- /dev/null
+++ b/core/fxcrt/css/cfx_cssstringvalue.cpp
@@ -0,0 +1,12 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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_cssstringvalue.h"
+
+CFX_CSSStringValue::CFX_CSSStringValue(const CFX_WideString& value)
+ : CFX_CSSValue(CFX_CSSPrimitiveType::String), value_(value) {}
+
+CFX_CSSStringValue::~CFX_CSSStringValue() {}
diff --git a/core/fxcrt/css/cfx_cssstringvalue.h b/core/fxcrt/css/cfx_cssstringvalue.h
new file mode 100644
index 0000000000..7680360973
--- /dev/null
+++ b/core/fxcrt/css/cfx_cssstringvalue.h
@@ -0,0 +1,23 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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
+
+#ifndef CORE_FXCRT_CSS_CFX_CSSSTRINGVALUE_H_
+#define CORE_FXCRT_CSS_CFX_CSSSTRINGVALUE_H_
+
+#include "core/fxcrt/css/cfx_cssvalue.h"
+
+class CFX_CSSStringValue : public CFX_CSSValue {
+ public:
+ explicit CFX_CSSStringValue(const CFX_WideString& value);
+ ~CFX_CSSStringValue() override;
+
+ const CFX_WideString Value() const { return value_; }
+
+ private:
+ const CFX_WideString value_;
+};
+
+#endif // CORE_FXCRT_CSS_CFX_CSSSTRINGVALUE_H_
diff --git a/core/fxcrt/css/cfx_cssstylerule.cpp b/core/fxcrt/css/cfx_cssstylerule.cpp
new file mode 100644
index 0000000000..504771ed46
--- /dev/null
+++ b/core/fxcrt/css/cfx_cssstylerule.cpp
@@ -0,0 +1,30 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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_cssstylerule.h"
+
+CFX_CSSStyleRule::CFX_CSSStyleRule() {}
+
+CFX_CSSStyleRule::~CFX_CSSStyleRule() {}
+
+size_t CFX_CSSStyleRule::CountSelectorLists() const {
+ return m_ppSelector.size();
+}
+
+CFX_CSSSelector* CFX_CSSStyleRule::GetSelectorList(int32_t index) const {
+ return m_ppSelector[index].get();
+}
+
+CFX_CSSDeclaration* CFX_CSSStyleRule::GetDeclaration() {
+ return &m_Declaration;
+}
+
+void CFX_CSSStyleRule::SetSelector(
+ std::vector<std::unique_ptr<CFX_CSSSelector>>* list) {
+ ASSERT(m_ppSelector.empty());
+
+ m_ppSelector.swap(*list);
+}
diff --git a/core/fxcrt/css/cfx_cssstylerule.h b/core/fxcrt/css/cfx_cssstylerule.h
new file mode 100644
index 0000000000..bba1fc53c8
--- /dev/null
+++ b/core/fxcrt/css/cfx_cssstylerule.h
@@ -0,0 +1,32 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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
+
+#ifndef CORE_FXCRT_CSS_CFX_CSSSTYLERULE_H_
+#define CORE_FXCRT_CSS_CFX_CSSSTYLERULE_H_
+
+#include <memory>
+#include <vector>
+
+#include "core/fxcrt/css/cfx_cssdeclaration.h"
+#include "core/fxcrt/css/cfx_cssselector.h"
+
+class CFX_CSSStyleRule {
+ public:
+ CFX_CSSStyleRule();
+ ~CFX_CSSStyleRule();
+
+ size_t CountSelectorLists() const;
+ CFX_CSSSelector* GetSelectorList(int32_t index) const;
+ CFX_CSSDeclaration* GetDeclaration();
+
+ void SetSelector(std::vector<std::unique_ptr<CFX_CSSSelector>>* list);
+
+ private:
+ CFX_CSSDeclaration m_Declaration;
+ std::vector<std::unique_ptr<CFX_CSSSelector>> m_ppSelector;
+};
+
+#endif // CORE_FXCRT_CSS_CFX_CSSSTYLERULE_H_
diff --git a/core/fxcrt/css/cfx_cssstyleselector.cpp b/core/fxcrt/css/cfx_cssstyleselector.cpp
new file mode 100644
index 0000000000..9a2bc8c498
--- /dev/null
+++ b/core/fxcrt/css/cfx_cssstyleselector.cpp
@@ -0,0 +1,598 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// 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_cssstyleselector.h"
+
+#include <algorithm>
+#include <utility>
+
+#include "core/fxcrt/css/cfx_csscolorvalue.h"
+#include "core/fxcrt/css/cfx_csscomputedstyle.h"
+#include "core/fxcrt/css/cfx_csscustomproperty.h"
+#include "core/fxcrt/css/cfx_cssdeclaration.h"
+#include "core/fxcrt/css/cfx_cssenumvalue.h"
+#include "core/fxcrt/css/cfx_csspropertyholder.h"
+#include "core/fxcrt/css/cfx_cssselector.h"
+#include "core/fxcrt/css/cfx_cssstylesheet.h"
+#include "core/fxcrt/css/cfx_csssyntaxparser.h"
+#include "core/fxcrt/css/cfx_cssvaluelist.h"
+#include "third_party/base/logging.h"
+#include "third_party/base/ptr_util.h"
+
+CFX_CSSStyleSelector::CFX_CSSStyleSelector() : m_fDefFontSize(12.0f) {}
+
+CFX_CSSStyleSelector::~CFX_CSSStyleSelector() {}
+
+void CFX_CSSStyleSelector::SetDefFontSize(float fFontSize) {
+ ASSERT(fFontSize > 0);
+ m_fDefFontSize = fFontSize;
+}
+
+CFX_RetainPtr<CFX_CSSComputedStyle> CFX_CSSStyleSelector::CreateComputedStyle(
+ CFX_CSSComputedStyle* pParentStyle) {
+ auto pStyle = pdfium::MakeRetain<CFX_CSSComputedStyle>();
+ if (pParentStyle)
+ pStyle->m_InheritedData = pParentStyle->m_InheritedData;
+ return pStyle;
+}
+
+void CFX_CSSStyleSelector::SetUAStyleSheet(
+ std::unique_ptr<CFX_CSSStyleSheet> pSheet) {
+ m_UAStyles = std::move(pSheet);
+}
+
+void CFX_CSSStyleSelector::UpdateStyleIndex() {
+ m_UARules.Clear();
+ m_UARules.AddRulesFrom(m_UAStyles.get());
+}
+
+std::vector<const CFX_CSSDeclaration*> CFX_CSSStyleSelector::MatchDeclarations(
+ const CFX_WideString& tagname) {
+ std::vector<const CFX_CSSDeclaration*> matchedDecls;
+ if (m_UARules.CountSelectors() == 0 || tagname.IsEmpty())
+ return matchedDecls;
+
+ auto* rules = m_UARules.GetTagRuleData(tagname);
+ if (!rules)
+ return matchedDecls;
+
+ for (const auto& d : *rules) {
+ if (MatchSelector(tagname, d->pSelector))
+ matchedDecls.push_back(d->pDeclaration);
+ }
+ return matchedDecls;
+}
+
+bool CFX_CSSStyleSelector::MatchSelector(const CFX_WideString& tagname,
+ CFX_CSSSelector* pSel) {
+ // TODO(dsinclair): The code only supports a single level of selector at this
+ // point. None of the code using selectors required the complexity so lets
+ // just say we don't support them to simplify the code for now.
+ if (!pSel || pSel->GetNextSelector() ||
+ pSel->GetType() == CFX_CSSSelectorType::Descendant) {
+ return false;
+ }
+ return pSel->GetNameHash() == FX_HashCode_GetW(tagname.c_str(), true);
+}
+
+void CFX_CSSStyleSelector::ComputeStyle(
+ const std::vector<const CFX_CSSDeclaration*>& declArray,
+ const CFX_WideString& styleString,
+ const CFX_WideString& alignString,
+ CFX_CSSComputedStyle* pDest) {
+ std::unique_ptr<CFX_CSSDeclaration> pDecl;
+ if (!styleString.IsEmpty() || !alignString.IsEmpty()) {
+ pDecl = pdfium::MakeUnique<CFX_CSSDeclaration>();
+
+ if (!styleString.IsEmpty())
+ AppendInlineStyle(pDecl.get(), styleString);
+ if (!alignString.IsEmpty()) {
+ pDecl->AddProperty(CFX_GetCSSPropertyByEnum(CFX_CSSProperty::TextAlign),
+ alignString.AsStringC());
+ }
+ }
+ ApplyDeclarations(declArray, pDecl.get(), pDest);
+}
+
+void CFX_CSSStyleSelector::ApplyDeclarations(
+ const std::vector<const CFX_CSSDeclaration*>& declArray,
+ const CFX_CSSDeclaration* extraDecl,
+ CFX_CSSComputedStyle* pComputedStyle) {
+ std::vector<const CFX_CSSPropertyHolder*> importants;
+ std::vector<const CFX_CSSPropertyHolder*> normals;
+ std::vector<const CFX_CSSCustomProperty*> customs;
+
+ for (auto* decl : declArray)
+ ExtractValues(decl, &importants, &normals, &customs);
+
+ if (extraDecl)
+ ExtractValues(extraDecl, &importants, &normals, &customs);
+
+ for (auto* prop : normals)
+ ApplyProperty(prop->eProperty, prop->pValue, pComputedStyle);
+
+ for (auto* prop : customs)
+ pComputedStyle->AddCustomStyle(*prop);
+
+ for (auto* prop : importants)
+ ApplyProperty(prop->eProperty, prop->pValue, pComputedStyle);
+}
+
+void CFX_CSSStyleSelector::ExtractValues(
+ const CFX_CSSDeclaration* decl,
+ std::vector<const CFX_CSSPropertyHolder*>* importants,
+ std::vector<const CFX_CSSPropertyHolder*>* normals,
+ std::vector<const CFX_CSSCustomProperty*>* custom) {
+ for (const auto& holder : *decl) {
+ if (holder->bImportant)
+ importants->push_back(holder.get());
+ else
+ normals->push_back(holder.get());
+ }
+ for (auto it = decl->custom_begin(); it != decl->custom_end(); it++)
+ custom->push_back(it->get());
+}
+
+void CFX_CSSStyleSelector::AppendInlineStyle(CFX_CSSDeclaration* pDecl,
+ const CFX_WideString& style) {
+ ASSERT(pDecl && !style.IsEmpty());
+
+ auto pSyntax = pdfium::MakeUnique<CFX_CSSSyntaxParser>(
+ style.c_str(), style.GetLength(), 32, true);
+ int32_t iLen2 = 0;
+ const CFX_CSSPropertyTable* table = nullptr;
+ CFX_WideString wsName;
+ while (1) {
+ CFX_CSSSyntaxStatus eStatus = pSyntax->DoSyntaxParse();
+ if (eStatus == CFX_CSSSyntaxStatus::PropertyName) {
+ CFX_WideStringC strValue = pSyntax->GetCurrentString();
+ table = CFX_GetCSSPropertyByName(strValue);
+ if (!table)
+ wsName = CFX_WideString(strValue);
+ } else if (eStatus == CFX_CSSSyntaxStatus::PropertyValue) {
+ if (table || iLen2 > 0) {
+ CFX_WideStringC strValue = pSyntax->GetCurrentString();
+ if (!strValue.IsEmpty()) {
+ if (table)
+ pDecl->AddProperty(table, strValue);
+ else if (iLen2 > 0)
+ pDecl->AddProperty(wsName, CFX_WideString(strValue));
+ }
+ }
+ } else {
+ break;
+ }
+ }
+}
+
+void CFX_CSSStyleSelector::ApplyProperty(
+ CFX_CSSProperty eProperty,
+ const CFX_RetainPtr<CFX_CSSValue>& pValue,
+ CFX_CSSComputedStyle* pComputedStyle) {
+ if (pValue->GetType() != CFX_CSSPrimitiveType::List) {
+ CFX_CSSPrimitiveType eType = pValue->GetType();
+ switch (eProperty) {
+ case CFX_CSSProperty::Display:
+ if (eType == CFX_CSSPrimitiveType::Enum) {
+ pComputedStyle->m_NonInheritedData.m_eDisplay =
+ ToDisplay(pValue.As<CFX_CSSEnumValue>()->Value());
+ }
+ break;
+ case CFX_CSSProperty::FontSize: {
+ float& fFontSize = pComputedStyle->m_InheritedData.m_fFontSize;
+ if (eType == CFX_CSSPrimitiveType::Number) {
+ fFontSize = pValue.As<CFX_CSSNumberValue>()->Apply(fFontSize);
+ } else if (eType == CFX_CSSPrimitiveType::Enum) {
+ fFontSize =
+ ToFontSize(pValue.As<CFX_CSSEnumValue>()->Value(), fFontSize);
+ }
+ } break;
+ case CFX_CSSProperty::LineHeight:
+ if (eType == CFX_CSSPrimitiveType::Number) {
+ CFX_RetainPtr<CFX_CSSNumberValue> v = pValue.As<CFX_CSSNumberValue>();
+ if (v->Kind() == CFX_CSSNumberType::Number) {
+ pComputedStyle->m_InheritedData.m_fLineHeight =
+ v->Value() * pComputedStyle->m_InheritedData.m_fFontSize;
+ } else {
+ pComputedStyle->m_InheritedData.m_fLineHeight =
+ v->Apply(pComputedStyle->m_InheritedData.m_fFontSize);
+ }
+ }
+ break;
+ case CFX_CSSProperty::TextAlign:
+ if (eType == CFX_CSSPrimitiveType::Enum) {
+ pComputedStyle->m_InheritedData.m_eTextAlign =
+ ToTextAlign(pValue.As<CFX_CSSEnumValue>()->Value());
+ }
+ break;
+ case CFX_CSSProperty::TextIndent:
+ SetLengthWithPercent(pComputedStyle->m_InheritedData.m_TextIndent,
+ eType, pValue,
+ pComputedStyle->m_InheritedData.m_fFontSize);
+ break;
+ case CFX_CSSProperty::FontWeight:
+ if (eType == CFX_CSSPrimitiveType::Enum) {
+ pComputedStyle->m_InheritedData.m_wFontWeight =
+ ToFontWeight(pValue.As<CFX_CSSEnumValue>()->Value());
+ } else if (eType == CFX_CSSPrimitiveType::Number) {
+ int32_t iValue =
+ (int32_t)pValue.As<CFX_CSSNumberValue>()->Value() / 100;
+ if (iValue >= 1 && iValue <= 9) {
+ pComputedStyle->m_InheritedData.m_wFontWeight = iValue * 100;
+ }
+ }
+ break;
+ case CFX_CSSProperty::FontStyle:
+ if (eType == CFX_CSSPrimitiveType::Enum) {
+ pComputedStyle->m_InheritedData.m_eFontStyle =
+ ToFontStyle(pValue.As<CFX_CSSEnumValue>()->Value());
+ }
+ break;
+ case CFX_CSSProperty::Color:
+ if (eType == CFX_CSSPrimitiveType::RGB) {
+ pComputedStyle->m_InheritedData.m_dwFontColor =
+ pValue.As<CFX_CSSColorValue>()->Value();
+ }
+ break;
+ case CFX_CSSProperty::MarginLeft:
+ if (SetLengthWithPercent(
+ pComputedStyle->m_NonInheritedData.m_MarginWidth.left, eType,
+ pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
+ pComputedStyle->m_NonInheritedData.m_bHasMargin = true;
+ }
+ break;
+ case CFX_CSSProperty::MarginTop:
+ if (SetLengthWithPercent(
+ pComputedStyle->m_NonInheritedData.m_MarginWidth.top, eType,
+ pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
+ pComputedStyle->m_NonInheritedData.m_bHasMargin = true;
+ }
+ break;
+ case CFX_CSSProperty::MarginRight:
+ if (SetLengthWithPercent(
+ pComputedStyle->m_NonInheritedData.m_MarginWidth.right, eType,
+ pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
+ pComputedStyle->m_NonInheritedData.m_bHasMargin = true;
+ }
+ break;
+ case CFX_CSSProperty::MarginBottom:
+ if (SetLengthWithPercent(
+ pComputedStyle->m_NonInheritedData.m_MarginWidth.bottom, eType,
+ pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
+ pComputedStyle->m_NonInheritedData.m_bHasMargin = true;
+ }
+ break;
+ case CFX_CSSProperty::PaddingLeft:
+ if (SetLengthWithPercent(
+ pComputedStyle->m_NonInheritedData.m_PaddingWidth.left, eType,
+ pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
+ pComputedStyle->m_NonInheritedData.m_bHasPadding = true;
+ }
+ break;
+ case CFX_CSSProperty::PaddingTop:
+ if (SetLengthWithPercent(
+ pComputedStyle->m_NonInheritedData.m_PaddingWidth.top, eType,
+ pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
+ pComputedStyle->m_NonInheritedData.m_bHasPadding = true;
+ }
+ break;
+ case CFX_CSSProperty::PaddingRight:
+ if (SetLengthWithPercent(
+ pComputedStyle->m_NonInheritedData.m_PaddingWidth.right, eType,
+ pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
+ pComputedStyle->m_NonInheritedData.m_bHasPadding = true;
+ }
+ break;
+ case CFX_CSSProperty::PaddingBottom:
+ if (SetLengthWithPercent(
+ pComputedStyle->m_NonInheritedData.m_PaddingWidth.bottom, eType,
+ pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
+ pComputedStyle->m_NonInheritedData.m_bHasPadding = true;
+ }
+ break;
+ case CFX_CSSProperty::BorderLeftWidth:
+ if (SetLengthWithPercent(
+ pComputedStyle->m_NonInheritedData.m_BorderWidth.left, eType,
+ pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
+ pComputedStyle->m_NonInheritedData.m_bHasBorder = true;
+ }
+ break;
+ case CFX_CSSProperty::BorderTopWidth:
+ if (SetLengthWithPercent(
+ pComputedStyle->m_NonInheritedData.m_BorderWidth.top, eType,
+ pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
+ pComputedStyle->m_NonInheritedData.m_bHasBorder = true;
+ }
+ break;
+ case CFX_CSSProperty::BorderRightWidth:
+ if (SetLengthWithPercent(
+ pComputedStyle->m_NonInheritedData.m_BorderWidth.right, eType,
+ pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
+ pComputedStyle->m_NonInheritedData.m_bHasBorder = true;
+ }
+ break;
+ case CFX_CSSProperty::BorderBottomWidth:
+ if (SetLengthWithPercent(
+ pComputedStyle->m_NonInheritedData.m_BorderWidth.bottom, eType,
+ pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
+ pComputedStyle->m_NonInheritedData.m_bHasBorder = true;
+ }
+ break;
+ case CFX_CSSProperty::VerticalAlign:
+ if (eType == CFX_CSSPrimitiveType::Enum) {
+ pComputedStyle->m_NonInheritedData.m_eVerticalAlign =
+ ToVerticalAlign(pValue.As<CFX_CSSEnumValue>()->Value());
+ } else if (eType == CFX_CSSPrimitiveType::Number) {
+ pComputedStyle->m_NonInheritedData.m_eVerticalAlign =
+ CFX_CSSVerticalAlign::Number;
+ pComputedStyle->m_NonInheritedData.m_fVerticalAlign =
+ pValue.As<CFX_CSSNumberValue>()->Apply(
+ pComputedStyle->m_InheritedData.m_fFontSize);
+ }
+ break;
+ case CFX_CSSProperty::FontVariant:
+ if (eType == CFX_CSSPrimitiveType::Enum) {
+ pComputedStyle->m_InheritedData.m_eFontVariant =
+ ToFontVariant(pValue.As<CFX_CSSEnumValue>()->Value());
+ }
+ break;
+ case CFX_CSSProperty::LetterSpacing:
+ if (eType == CFX_CSSPrimitiveType::Enum) {
+ pComputedStyle->m_InheritedData.m_LetterSpacing.Set(
+ CFX_CSSLengthUnit::Normal);
+ } else if (eType == CFX_CSSPrimitiveType::Number) {
+ if (pValue.As<CFX_CSSNumberValue>()->Kind() ==
+ CFX_CSSNumberType::Percent) {
+ break;
+ }
+
+ SetLengthWithPercent(pComputedStyle->m_InheritedData.m_LetterSpacing,
+ eType, pValue,
+ pComputedStyle->m_InheritedData.m_fFontSize);
+ }
+ break;
+ case CFX_CSSProperty::WordSpacing:
+ if (eType == CFX_CSSPrimitiveType::Enum) {
+ pComputedStyle->m_InheritedData.m_WordSpacing.Set(
+ CFX_CSSLengthUnit::Normal);
+ } else if (eType == CFX_CSSPrimitiveType::Number) {
+ if (pValue.As<CFX_CSSNumberValue>()->Kind() ==
+ CFX_CSSNumberType::Percent) {
+ break;
+ }
+ SetLengthWithPercent(pComputedStyle->m_InheritedData.m_WordSpacing,
+ eType, pValue,
+ pComputedStyle->m_InheritedData.m_fFontSize);
+ }
+ break;
+ case CFX_CSSProperty::Top:
+ SetLengthWithPercent(pComputedStyle->m_NonInheritedData.m_Top, eType,
+ pValue,
+ pComputedStyle->m_InheritedData.m_fFontSize);
+ break;
+ case CFX_CSSProperty::Bottom:
+ SetLengthWithPercent(pComputedStyle->m_NonInheritedData.m_Bottom, eType,
+ pValue,
+ pComputedStyle->m_InheritedData.m_fFontSize);
+ break;
+ case CFX_CSSProperty::Left:
+ SetLengthWithPercent(pComputedStyle->m_NonInheritedData.m_Left, eType,
+ pValue,
+ pComputedStyle->m_InheritedData.m_fFontSize);
+ break;
+ case CFX_CSSProperty::Right:
+ SetLengthWithPercent(pComputedStyle->m_NonInheritedData.m_Right, eType,
+ pValue,
+ pComputedStyle->m_InheritedData.m_fFontSize);
+ break;
+ default:
+ break;
+ }
+ } else if (pValue->GetType() == CFX_CSSPrimitiveType::List) {
+ CFX_RetainPtr<CFX_CSSValueList> pList = pValue.As<CFX_CSSValueList>();
+ int32_t iCount = pList->CountValues();
+ if (iCount > 0) {
+ switch (eProperty) {
+ case CFX_CSSProperty::FontFamily:
+ pComputedStyle->m_InheritedData.m_pFontFamily = pList;
+ break;
+ case CFX_CSSProperty::TextDecoration:
+ pComputedStyle->m_NonInheritedData.m_dwTextDecoration =
+ ToTextDecoration(pList);
+ break;
+ default:
+ break;
+ }
+ }
+ } else {
+ NOTREACHED();
+ }
+}
+
+CFX_CSSDisplay CFX_CSSStyleSelector::ToDisplay(CFX_CSSPropertyValue eValue) {
+ switch (eValue) {
+ case CFX_CSSPropertyValue::Block:
+ return CFX_CSSDisplay::Block;
+ case CFX_CSSPropertyValue::None:
+ return CFX_CSSDisplay::None;
+ case CFX_CSSPropertyValue::ListItem:
+ return CFX_CSSDisplay::ListItem;
+ case CFX_CSSPropertyValue::InlineTable:
+ return CFX_CSSDisplay::InlineTable;
+ case CFX_CSSPropertyValue::InlineBlock:
+ return CFX_CSSDisplay::InlineBlock;
+ case CFX_CSSPropertyValue::Inline:
+ default:
+ return CFX_CSSDisplay::Inline;
+ }
+}
+
+CFX_CSSTextAlign CFX_CSSStyleSelector::ToTextAlign(
+ CFX_CSSPropertyValue eValue) {
+ switch (eValue) {
+ case CFX_CSSPropertyValue::Center:
+ return CFX_CSSTextAlign::Center;
+ case CFX_CSSPropertyValue::Right:
+ return CFX_CSSTextAlign::Right;
+ case CFX_CSSPropertyValue::Justify:
+ return CFX_CSSTextAlign::Justify;
+ case CFX_CSSPropertyValue::Left:
+ default:
+ return CFX_CSSTextAlign::Left;
+ }
+}
+
+uint16_t CFX_CSSStyleSelector::ToFontWeight(CFX_CSSPropertyValue eValue) {
+ switch (eValue) {
+ case CFX_CSSPropertyValue::Bold:
+ return 700;
+ case CFX_CSSPropertyValue::Bolder:
+ return 900;
+ case CFX_CSSPropertyValue::Lighter:
+ return 200;
+ case CFX_CSSPropertyValue::Normal:
+ default:
+ return 400;
+ }
+}
+
+CFX_CSSFontStyle CFX_CSSStyleSelector::ToFontStyle(
+ CFX_CSSPropertyValue eValue) {
+ switch (eValue) {
+ case CFX_CSSPropertyValue::Italic:
+ case CFX_CSSPropertyValue::Oblique:
+ return CFX_CSSFontStyle::Italic;
+ default:
+ return CFX_CSSFontStyle::Normal;
+ }
+}
+
+bool CFX_CSSStyleSelector::SetLengthWithPercent(
+ CFX_CSSLength& width,
+ CFX_CSSPrimitiveType eType,
+ const CFX_RetainPtr<CFX_CSSValue>& pValue,
+ float fFontSize) {
+ if (eType == CFX_CSSPrimitiveType::Number) {
+ CFX_RetainPtr<CFX_CSSNumberValue> v = pValue.As<CFX_CSSNumberValue>();
+ if (v->Kind() == CFX_CSSNumberType::Percent) {
+ width.Set(CFX_CSSLengthUnit::Percent,
+ pValue.As<CFX_CSSNumberValue>()->Value() / 100.0f);
+ return width.NonZero();
+ }
+
+ float fValue = v->Apply(fFontSize);
+ width.Set(CFX_CSSLengthUnit::Point, fValue);
+ return width.NonZero();
+ } else if (eType == CFX_CSSPrimitiveType::Enum) {
+ switch (pValue.As<CFX_CSSEnumValue>()->Value()) {
+ case CFX_CSSPropertyValue::Auto:
+ width.Set(CFX_CSSLengthUnit::Auto);
+ return true;
+ case CFX_CSSPropertyValue::None:
+ width.Set(CFX_CSSLengthUnit::None);
+ return true;
+ case CFX_CSSPropertyValue::Thin:
+ width.Set(CFX_CSSLengthUnit::Point, 2);
+ return true;
+ case CFX_CSSPropertyValue::Medium:
+ width.Set(CFX_CSSLengthUnit::Point, 3);
+ return true;
+ case CFX_CSSPropertyValue::Thick:
+ width.Set(CFX_CSSLengthUnit::Point, 4);
+ return true;
+ default:
+ return false;
+ }
+ }
+ return false;
+}
+
+float CFX_CSSStyleSelector::ToFontSize(CFX_CSSPropertyValue eValue,
+ float fCurFontSize) {
+ switch (eValue) {
+ case CFX_CSSPropertyValue::XxSmall:
+ return m_fDefFontSize / 1.2f / 1.2f / 1.2f;
+ case CFX_CSSPropertyValue::XSmall:
+ return m_fDefFontSize / 1.2f / 1.2f;
+ case CFX_CSSPropertyValue::Small:
+ return m_fDefFontSize / 1.2f;
+ case CFX_CSSPropertyValue::Medium:
+ return m_fDefFontSize;
+ case CFX_CSSPropertyValue::Large:
+ return m_fDefFontSize * 1.2f;
+ case CFX_CSSPropertyValue::XLarge:
+ return m_fDefFontSize * 1.2f * 1.2f;
+ case CFX_CSSPropertyValue::XxLarge:
+ return m_fDefFontSize * 1.2f * 1.2f * 1.2f;
+ case CFX_CSSPropertyValue::Larger:
+ return fCurFontSize * 1.2f;
+ case CFX_CSSPropertyValue::Smaller:
+ return fCurFontSize / 1.2f;
+ default:
+ return fCurFontSize;
+ }
+}
+
+CFX_CSSVerticalAlign CFX_CSSStyleSelector::ToVerticalAlign(
+ CFX_CSSPropertyValue eValue) {
+ switch (eValue) {
+ case CFX_CSSPropertyValue::Middle:
+ return CFX_CSSVerticalAlign::Middle;
+ case CFX_CSSPropertyValue::Bottom:
+ return CFX_CSSVerticalAlign::Bottom;
+ case CFX_CSSPropertyValue::Super:
+ return CFX_CSSVerticalAlign::Super;
+ case CFX_CSSPropertyValue::Sub:
+ return CFX_CSSVerticalAlign::Sub;
+ case CFX_CSSPropertyValue::Top:
+ return CFX_CSSVerticalAlign::Top;
+ case CFX_CSSPropertyValue::TextTop:
+ return CFX_CSSVerticalAlign::TextTop;
+ case CFX_CSSPropertyValue::TextBottom:
+ return CFX_CSSVerticalAlign::TextBottom;
+ case CFX_CSSPropertyValue::Baseline:
+ default:
+ return CFX_CSSVerticalAlign::Baseline;
+ }
+}
+
+uint32_t CFX_CSSStyleSelector::ToTextDecoration(
+ const CFX_RetainPtr<CFX_CSSValueList>& pValue) {
+ uint32_t dwDecoration = 0;
+ for (int32_t i = pValue->CountValues() - 1; i >= 0; --i) {
+ const CFX_RetainPtr<CFX_CSSValue> pVal = pValue->GetValue(i);
+ if (pVal->GetType() != CFX_CSSPrimitiveType::Enum)
+ continue;
+
+ switch (pVal.As<CFX_CSSEnumValue>()->Value()) {
+ case CFX_CSSPropertyValue::Underline:
+ dwDecoration |= CFX_CSSTEXTDECORATION_Underline;
+ break;
+ case CFX_CSSPropertyValue::LineThrough:
+ dwDecoration |= CFX_CSSTEXTDECORATION_LineThrough;
+ break;
+ case CFX_CSSPropertyValue::Overline:
+ dwDecoration |= CFX_CSSTEXTDECORATION_Overline;
+ break;
+ case CFX_CSSPropertyValue::Blink:
+ dwDecoration |= CFX_CSSTEXTDECORATION_Blink;
+ break;
+ case CFX_CSSPropertyValue::Double:
+ dwDecoration |= CFX_CSSTEXTDECORATION_Double;
+ break;
+ default:
+ break;
+ }
+ }
+ return dwDecoration;
+}
+
+CFX_CSSFontVariant CFX_CSSStyleSelector::ToFontVariant(
+ CFX_CSSPropertyValue eValue) {
+ return eValue == CFX_CSSPropertyValue::SmallCaps
+ ? CFX_CSSFontVariant::SmallCaps
+ : CFX_CSSFontVariant::Normal;
+}
diff --git a/core/fxcrt/css/cfx_cssstyleselector.h b/core/fxcrt/css/cfx_cssstyleselector.h
new file mode 100644
index 0000000000..56d933b614
--- /dev/null
+++ b/core/fxcrt/css/cfx_cssstyleselector.h
@@ -0,0 +1,85 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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
+
+#ifndef CORE_FXCRT_CSS_CFX_CSSSTYLESELECTOR_H_
+#define CORE_FXCRT_CSS_CFX_CSSSTYLESELECTOR_H_
+
+#include <memory>
+#include <vector>
+
+#include "core/fxcrt/css/cfx_css.h"
+#include "core/fxcrt/css/cfx_cssrulecollection.h"
+#include "core/fxcrt/fx_basic.h"
+#include "core/fxcrt/fx_system.h"
+
+class CFX_CSSComputedStyle;
+class CFX_CSSCustomProperty;
+class CFX_CSSDeclaration;
+class CFX_CSSPropertyHolder;
+class CFX_CSSSelector;
+class CFX_CSSStyleSheet;
+class CFX_CSSValue;
+class CFX_CSSValueList;
+
+class CFX_CSSStyleSelector {
+ public:
+ CFX_CSSStyleSelector();
+ ~CFX_CSSStyleSelector();
+
+ void SetDefFontSize(float fFontSize);
+ void SetUAStyleSheet(std::unique_ptr<CFX_CSSStyleSheet> pSheet);
+ void UpdateStyleIndex();
+
+ CFX_RetainPtr<CFX_CSSComputedStyle> CreateComputedStyle(
+ CFX_CSSComputedStyle* pParentStyle);
+
+ // Note, the dest style has to be an out param because the CXFA_TextParser
+ // adds non-inherited data from the parent style. Attempting to copy
+ // internally will fail as you'll lose the non-inherited data.
+ void ComputeStyle(const std::vector<const CFX_CSSDeclaration*>& declArray,
+ const CFX_WideString& styleString,
+ const CFX_WideString& alignString,
+ CFX_CSSComputedStyle* pDestStyle);
+
+ std::vector<const CFX_CSSDeclaration*> MatchDeclarations(
+ const CFX_WideString& tagname);
+
+ private:
+ bool MatchSelector(const CFX_WideString& tagname, CFX_CSSSelector* pSel);
+
+ void AppendInlineStyle(CFX_CSSDeclaration* pDecl,
+ const CFX_WideString& style);
+ void ApplyDeclarations(
+ const std::vector<const CFX_CSSDeclaration*>& declArray,
+ const CFX_CSSDeclaration* extraDecl,
+ CFX_CSSComputedStyle* pDestStyle);
+ void ApplyProperty(CFX_CSSProperty eProperty,
+ const CFX_RetainPtr<CFX_CSSValue>& pValue,
+ CFX_CSSComputedStyle* pComputedStyle);
+ void ExtractValues(const CFX_CSSDeclaration* decl,
+ std::vector<const CFX_CSSPropertyHolder*>* importants,
+ std::vector<const CFX_CSSPropertyHolder*>* normals,
+ std::vector<const CFX_CSSCustomProperty*>* custom);
+
+ bool SetLengthWithPercent(CFX_CSSLength& width,
+ CFX_CSSPrimitiveType eType,
+ const CFX_RetainPtr<CFX_CSSValue>& pValue,
+ float fFontSize);
+ float ToFontSize(CFX_CSSPropertyValue eValue, float fCurFontSize);
+ CFX_CSSDisplay ToDisplay(CFX_CSSPropertyValue eValue);
+ CFX_CSSTextAlign ToTextAlign(CFX_CSSPropertyValue eValue);
+ uint16_t ToFontWeight(CFX_CSSPropertyValue eValue);
+ CFX_CSSFontStyle ToFontStyle(CFX_CSSPropertyValue eValue);
+ CFX_CSSVerticalAlign ToVerticalAlign(CFX_CSSPropertyValue eValue);
+ uint32_t ToTextDecoration(const CFX_RetainPtr<CFX_CSSValueList>& pList);
+ CFX_CSSFontVariant ToFontVariant(CFX_CSSPropertyValue eValue);
+
+ float m_fDefFontSize;
+ std::unique_ptr<CFX_CSSStyleSheet> m_UAStyles;
+ CFX_CSSRuleCollection m_UARules;
+};
+
+#endif // CORE_FXCRT_CSS_CFX_CSSSTYLESELECTOR_H_
diff --git a/core/fxcrt/css/cfx_cssstylesheet.cpp b/core/fxcrt/css/cfx_cssstylesheet.cpp
new file mode 100644
index 0000000000..9bd25c044f
--- /dev/null
+++ b/core/fxcrt/css/cfx_cssstylesheet.cpp
@@ -0,0 +1,140 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// 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_cssdatatable.h"
+#include "core/fxcrt/css/cfx_cssdeclaration.h"
+#include "core/fxcrt/css/cfx_cssstylerule.h"
+#include "core/fxcrt/fx_codepage.h"
+#include "third_party/base/ptr_util.h"
+#include "third_party/base/stl_util.h"
+
+CFX_CSSStyleSheet::CFX_CSSStyleSheet() {}
+
+CFX_CSSStyleSheet::~CFX_CSSStyleSheet() {
+ Reset();
+}
+
+void CFX_CSSStyleSheet::Reset() {
+ m_RuleArray.clear();
+ m_StringCache.clear();
+}
+
+int32_t CFX_CSSStyleSheet::CountRules() const {
+ return pdfium::CollectionSize<int32_t>(m_RuleArray);
+}
+
+CFX_CSSStyleRule* CFX_CSSStyleSheet::GetRule(int32_t index) const {
+ return m_RuleArray[index].get();
+}
+
+bool CFX_CSSStyleSheet::LoadBuffer(const wchar_t* pBuffer, int32_t iBufSize) {
+ ASSERT(pBuffer);
+ ASSERT(iBufSize > 0);
+
+ auto pSyntax = pdfium::MakeUnique<CFX_CSSSyntaxParser>(pBuffer, iBufSize);
+ Reset();
+ CFX_CSSSyntaxStatus eStatus;
+ do {
+ switch (eStatus = pSyntax->DoSyntaxParse()) {
+ case CFX_CSSSyntaxStatus::StyleRule:
+ eStatus = LoadStyleRule(pSyntax.get(), &m_RuleArray);
+ break;
+ default:
+ break;
+ }
+ } while (eStatus >= CFX_CSSSyntaxStatus::None);
+
+ m_StringCache.clear();
+ return eStatus != CFX_CSSSyntaxStatus::Error;
+}
+
+CFX_CSSSyntaxStatus CFX_CSSStyleSheet::LoadStyleRule(
+ CFX_CSSSyntaxParser* pSyntax,
+ std::vector<std::unique_ptr<CFX_CSSStyleRule>>* ruleArray) {
+ std::vector<std::unique_ptr<CFX_CSSSelector>> selectors;
+
+ CFX_CSSStyleRule* pStyleRule = nullptr;
+ int32_t iValueLen = 0;
+ const CFX_CSSPropertyTable* propertyTable = nullptr;
+ CFX_WideString wsName;
+ while (1) {
+ switch (pSyntax->DoSyntaxParse()) {
+ case CFX_CSSSyntaxStatus::Selector: {
+ CFX_WideStringC strValue = pSyntax->GetCurrentString();
+ auto pSelector = CFX_CSSSelector::FromString(strValue);
+ if (pSelector)
+ selectors.push_back(std::move(pSelector));
+ break;
+ }
+ case CFX_CSSSyntaxStatus::PropertyName: {
+ CFX_WideStringC strValue = pSyntax->GetCurrentString();
+ propertyTable = CFX_GetCSSPropertyByName(strValue);
+ if (!propertyTable)
+ wsName = CFX_WideString(strValue);
+ break;
+ }
+ case CFX_CSSSyntaxStatus::PropertyValue: {
+ if (propertyTable || iValueLen > 0) {
+ CFX_WideStringC strValue = pSyntax->GetCurrentString();
+ auto* decl = pStyleRule->GetDeclaration();
+ if (!strValue.IsEmpty()) {
+ if (propertyTable) {
+ decl->AddProperty(propertyTable, strValue);
+ } else {
+ decl->AddProperty(wsName, CFX_WideString(strValue));
+ }
+ }
+ }
+ break;
+ }
+ case CFX_CSSSyntaxStatus::DeclOpen: {
+ if (!pStyleRule && !selectors.empty()) {
+ auto rule = pdfium::MakeUnique<CFX_CSSStyleRule>();
+ pStyleRule = rule.get();
+ pStyleRule->SetSelector(&selectors);
+ ruleArray->push_back(std::move(rule));
+ } else {
+ SkipRuleSet(pSyntax);
+ return CFX_CSSSyntaxStatus::None;
+ }
+ break;
+ }
+ case CFX_CSSSyntaxStatus::DeclClose: {
+ if (pStyleRule && pStyleRule->GetDeclaration()->empty()) {
+ ruleArray->pop_back();
+ pStyleRule = nullptr;
+ }
+ return CFX_CSSSyntaxStatus::None;
+ }
+ case CFX_CSSSyntaxStatus::EOS:
+ return CFX_CSSSyntaxStatus::EOS;
+ case CFX_CSSSyntaxStatus::Error:
+ default:
+ return CFX_CSSSyntaxStatus::Error;
+ }
+ }
+}
+
+void CFX_CSSStyleSheet::SkipRuleSet(CFX_CSSSyntaxParser* pSyntax) {
+ while (1) {
+ switch (pSyntax->DoSyntaxParse()) {
+ case CFX_CSSSyntaxStatus::Selector:
+ case CFX_CSSSyntaxStatus::DeclOpen:
+ case CFX_CSSSyntaxStatus::PropertyName:
+ case CFX_CSSSyntaxStatus::PropertyValue:
+ break;
+ case CFX_CSSSyntaxStatus::DeclClose:
+ case CFX_CSSSyntaxStatus::EOS:
+ case CFX_CSSSyntaxStatus::Error:
+ default:
+ return;
+ }
+ }
+}
diff --git a/core/fxcrt/css/cfx_cssstylesheet.h b/core/fxcrt/css/cfx_cssstylesheet.h
new file mode 100644
index 0000000000..3f3a94a84b
--- /dev/null
+++ b/core/fxcrt/css/cfx_cssstylesheet.h
@@ -0,0 +1,40 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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
+
+#ifndef CORE_FXCRT_CSS_CFX_CSSSTYLESHEET_H_
+#define CORE_FXCRT_CSS_CFX_CSSSTYLESHEET_H_
+
+#include <map>
+#include <memory>
+#include <vector>
+
+#include "core/fxcrt/css/cfx_csssyntaxparser.h"
+#include "core/fxcrt/fx_string.h"
+
+class CFX_CSSStyleRule;
+
+class CFX_CSSStyleSheet {
+ public:
+ CFX_CSSStyleSheet();
+ ~CFX_CSSStyleSheet();
+
+ bool LoadBuffer(const wchar_t* pBuffer, int32_t iBufSize);
+
+ int32_t CountRules() const;
+ CFX_CSSStyleRule* GetRule(int32_t index) const;
+
+ private:
+ void Reset();
+ CFX_CSSSyntaxStatus LoadStyleRule(
+ CFX_CSSSyntaxParser* pSyntax,
+ std::vector<std::unique_ptr<CFX_CSSStyleRule>>* ruleArray);
+ void SkipRuleSet(CFX_CSSSyntaxParser* pSyntax);
+
+ std::vector<std::unique_ptr<CFX_CSSStyleRule>> m_RuleArray;
+ std::map<uint32_t, wchar_t*> m_StringCache;
+};
+
+#endif // CORE_FXCRT_CSS_CFX_CSSSTYLESHEET_H_
diff --git a/core/fxcrt/css/cfx_cssstylesheet_unittest.cpp b/core/fxcrt/css/cfx_cssstylesheet_unittest.cpp
new file mode 100644
index 0000000000..4194a70490
--- /dev/null
+++ b/core/fxcrt/css/cfx_cssstylesheet_unittest.cpp
@@ -0,0 +1,239 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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 <memory>
+#include <vector>
+
+#include "core/fxcrt/css/cfx_cssdeclaration.h"
+#include "core/fxcrt/css/cfx_cssenumvalue.h"
+#include "core/fxcrt/css/cfx_cssnumbervalue.h"
+#include "core/fxcrt/css/cfx_cssstylerule.h"
+#include "core/fxcrt/css/cfx_cssvaluelist.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/base/ptr_util.h"
+#include "third_party/base/stl_util.h"
+
+class CFX_CSSStyleSheetTest : public testing::Test {
+ public:
+ void SetUp() override {
+ sheet_ = pdfium::MakeUnique<CFX_CSSStyleSheet>();
+ decl_ = nullptr;
+ }
+
+ void TearDown() override { decl_ = nullptr; }
+
+ void LoadAndVerifyDecl(const wchar_t* buf,
+ const std::vector<CFX_WideString>& selectors,
+ size_t decl_count) {
+ ASSERT(sheet_);
+
+ EXPECT_TRUE(sheet_->LoadBuffer(buf, FXSYS_wcslen(buf)));
+ EXPECT_EQ(sheet_->CountRules(), 1);
+
+ CFX_CSSStyleRule* style = sheet_->GetRule(0);
+ EXPECT_EQ(selectors.size(), style->CountSelectorLists());
+
+ for (size_t i = 0; i < selectors.size(); i++) {
+ uint32_t hash = FX_HashCode_GetW(selectors[i].AsStringC(), true);
+ EXPECT_EQ(hash, style->GetSelectorList(i)->GetNameHash());
+ }
+
+ decl_ = style->GetDeclaration();
+ EXPECT_EQ(decl_->PropertyCountForTesting(), decl_count);
+ }
+
+ void VerifyFloat(CFX_CSSProperty prop, float val, CFX_CSSNumberType type) {
+ ASSERT(decl_);
+
+ bool important;
+ CFX_RetainPtr<CFX_CSSValue> v = decl_->GetProperty(prop, &important);
+ EXPECT_EQ(v->GetType(), CFX_CSSPrimitiveType::Number);
+ EXPECT_EQ(v.As<CFX_CSSNumberValue>()->Kind(), type);
+ EXPECT_EQ(v.As<CFX_CSSNumberValue>()->Value(), val);
+ }
+
+ void VerifyEnum(CFX_CSSProperty prop, CFX_CSSPropertyValue val) {
+ ASSERT(decl_);
+
+ bool important;
+ CFX_RetainPtr<CFX_CSSValue> v = decl_->GetProperty(prop, &important);
+ EXPECT_EQ(v->GetType(), CFX_CSSPrimitiveType::Enum);
+ EXPECT_EQ(v.As<CFX_CSSEnumValue>()->Value(), val);
+ }
+
+ void VerifyList(CFX_CSSProperty prop,
+ std::vector<CFX_CSSPropertyValue> values) {
+ ASSERT(decl_);
+
+ bool important;
+ CFX_RetainPtr<CFX_CSSValueList> list =
+ decl_->GetProperty(prop, &important).As<CFX_CSSValueList>();
+ EXPECT_EQ(list->CountValues(), pdfium::CollectionSize<int32_t>(values));
+
+ for (size_t i = 0; i < values.size(); i++) {
+ CFX_RetainPtr<CFX_CSSValue> val = list->GetValue(i);
+ EXPECT_EQ(val->GetType(), CFX_CSSPrimitiveType::Enum);
+ EXPECT_EQ(val.As<CFX_CSSEnumValue>()->Value(), values[i]);
+ }
+ }
+
+ std::unique_ptr<CFX_CSSStyleSheet> sheet_;
+ CFX_CSSDeclaration* decl_;
+};
+
+TEST_F(CFX_CSSStyleSheetTest, ParseMultipleSelectors) {
+ const wchar_t* buf =
+ L"a { border: 10px; }\nb { text-decoration: underline; }";
+ EXPECT_TRUE(sheet_->LoadBuffer(buf, FXSYS_wcslen(buf)));
+ EXPECT_EQ(2, sheet_->CountRules());
+
+ CFX_CSSStyleRule* style = sheet_->GetRule(0);
+ EXPECT_EQ(1UL, style->CountSelectorLists());
+
+ bool found_selector = false;
+ uint32_t hash = FX_HashCode_GetW(L"a", true);
+ for (size_t i = 0; i < style->CountSelectorLists(); i++) {
+ if (style->GetSelectorList(i)->GetNameHash() == hash) {
+ found_selector = true;
+ break;
+ }
+ }
+ EXPECT_TRUE(found_selector);
+
+ decl_ = style->GetDeclaration();
+ EXPECT_EQ(4UL, decl_->PropertyCountForTesting());
+
+ VerifyFloat(CFX_CSSProperty::BorderLeftWidth, 10.0,
+ CFX_CSSNumberType::Pixels);
+ VerifyFloat(CFX_CSSProperty::BorderRightWidth, 10.0,
+ CFX_CSSNumberType::Pixels);
+ VerifyFloat(CFX_CSSProperty::BorderTopWidth, 10.0, CFX_CSSNumberType::Pixels);
+ VerifyFloat(CFX_CSSProperty::BorderBottomWidth, 10.0,
+ CFX_CSSNumberType::Pixels);
+
+ style = sheet_->GetRule(1);
+ EXPECT_EQ(1UL, style->CountSelectorLists());
+
+ found_selector = false;
+ hash = FX_HashCode_GetW(L"b", true);
+ for (size_t i = 0; i < style->CountSelectorLists(); i++) {
+ if (style->GetSelectorList(i)->GetNameHash() == hash) {
+ found_selector = true;
+ break;
+ }
+ }
+ EXPECT_TRUE(found_selector);
+
+ decl_ = style->GetDeclaration();
+ EXPECT_EQ(1UL, decl_->PropertyCountForTesting());
+ VerifyList(CFX_CSSProperty::TextDecoration,
+ {CFX_CSSPropertyValue::Underline});
+}
+
+TEST_F(CFX_CSSStyleSheetTest, ParseChildSelectors) {
+ const wchar_t* buf = L"a b c { border: 10px; }";
+ EXPECT_TRUE(sheet_->LoadBuffer(buf, FXSYS_wcslen(buf)));
+ EXPECT_EQ(1, sheet_->CountRules());
+
+ CFX_CSSStyleRule* style = sheet_->GetRule(0);
+ EXPECT_EQ(1UL, style->CountSelectorLists());
+
+ auto* sel = style->GetSelectorList(0);
+ EXPECT_TRUE(sel != nullptr);
+ EXPECT_EQ(FX_HashCode_GetW(L"c", true), sel->GetNameHash());
+
+ sel = sel->GetNextSelector();
+ EXPECT_TRUE(sel != nullptr);
+ EXPECT_EQ(FX_HashCode_GetW(L"b", true), sel->GetNameHash());
+
+ sel = sel->GetNextSelector();
+ EXPECT_TRUE(sel != nullptr);
+ EXPECT_EQ(FX_HashCode_GetW(L"a", true), sel->GetNameHash());
+
+ sel = sel->GetNextSelector();
+ EXPECT_TRUE(sel == nullptr);
+
+ decl_ = style->GetDeclaration();
+ EXPECT_EQ(4UL, decl_->PropertyCountForTesting());
+
+ VerifyFloat(CFX_CSSProperty::BorderLeftWidth, 10.0,
+ CFX_CSSNumberType::Pixels);
+ VerifyFloat(CFX_CSSProperty::BorderRightWidth, 10.0,
+ CFX_CSSNumberType::Pixels);
+ VerifyFloat(CFX_CSSProperty::BorderTopWidth, 10.0, CFX_CSSNumberType::Pixels);
+ VerifyFloat(CFX_CSSProperty::BorderBottomWidth, 10.0,
+ CFX_CSSNumberType::Pixels);
+}
+
+TEST_F(CFX_CSSStyleSheetTest, ParseUnhandledSelectors) {
+ const wchar_t* buf = L"a > b { padding: 0; }";
+ EXPECT_TRUE(sheet_->LoadBuffer(buf, FXSYS_wcslen(buf)));
+ EXPECT_EQ(0, sheet_->CountRules());
+
+ buf = L"a[first] { padding: 0; }";
+ EXPECT_TRUE(sheet_->LoadBuffer(buf, FXSYS_wcslen(buf)));
+ EXPECT_EQ(0, sheet_->CountRules());
+
+ buf = L"a+b { padding: 0; }";
+ EXPECT_TRUE(sheet_->LoadBuffer(buf, FXSYS_wcslen(buf)));
+ EXPECT_EQ(0, sheet_->CountRules());
+
+ buf = L"a ^ b { padding: 0; }";
+ EXPECT_TRUE(sheet_->LoadBuffer(buf, FXSYS_wcslen(buf)));
+ EXPECT_EQ(0, sheet_->CountRules());
+}
+
+TEST_F(CFX_CSSStyleSheetTest, ParseMultipleSelectorsCombined) {
+ LoadAndVerifyDecl(L"a, b, c { border: 5px; }", {L"a", L"b", L"c"}, 4);
+}
+
+TEST_F(CFX_CSSStyleSheetTest, ParseBorder) {
+ LoadAndVerifyDecl(L"a { border: 5px; }", {L"a"}, 4);
+ VerifyFloat(CFX_CSSProperty::BorderLeftWidth, 5.0, CFX_CSSNumberType::Pixels);
+ VerifyFloat(CFX_CSSProperty::BorderRightWidth, 5.0,
+ CFX_CSSNumberType::Pixels);
+ VerifyFloat(CFX_CSSProperty::BorderTopWidth, 5.0, CFX_CSSNumberType::Pixels);
+ VerifyFloat(CFX_CSSProperty::BorderBottomWidth, 5.0,
+ CFX_CSSNumberType::Pixels);
+}
+
+TEST_F(CFX_CSSStyleSheetTest, ParseBorderFull) {
+ LoadAndVerifyDecl(L"a { border: 5px solid red; }", {L"a"}, 4);
+ VerifyFloat(CFX_CSSProperty::BorderLeftWidth, 5.0, CFX_CSSNumberType::Pixels);
+ VerifyFloat(CFX_CSSProperty::BorderRightWidth, 5.0,
+ CFX_CSSNumberType::Pixels);
+ VerifyFloat(CFX_CSSProperty::BorderTopWidth, 5.0, CFX_CSSNumberType::Pixels);
+ VerifyFloat(CFX_CSSProperty::BorderBottomWidth, 5.0,
+ CFX_CSSNumberType::Pixels);
+}
+
+TEST_F(CFX_CSSStyleSheetTest, ParseBorderLeft) {
+ LoadAndVerifyDecl(L"a { border-left: 2.5pc; }", {L"a"}, 1);
+ VerifyFloat(CFX_CSSProperty::BorderLeftWidth, 2.5, CFX_CSSNumberType::Picas);
+}
+
+TEST_F(CFX_CSSStyleSheetTest, ParseBorderLeftThick) {
+ LoadAndVerifyDecl(L"a { border-left: thick; }", {L"a"}, 1);
+ VerifyEnum(CFX_CSSProperty::BorderLeftWidth, CFX_CSSPropertyValue::Thick);
+}
+
+TEST_F(CFX_CSSStyleSheetTest, ParseBorderRight) {
+ LoadAndVerifyDecl(L"a { border-right: 2.5pc; }", {L"a"}, 1);
+ VerifyFloat(CFX_CSSProperty::BorderRightWidth, 2.5, CFX_CSSNumberType::Picas);
+}
+
+TEST_F(CFX_CSSStyleSheetTest, ParseBorderTop) {
+ LoadAndVerifyDecl(L"a { border-top: 2.5pc; }", {L"a"}, 1);
+ VerifyFloat(CFX_CSSProperty::BorderTopWidth, 2.5, CFX_CSSNumberType::Picas);
+}
+
+TEST_F(CFX_CSSStyleSheetTest, ParseBorderBottom) {
+ LoadAndVerifyDecl(L"a { border-bottom: 2.5pc; }", {L"a"}, 1);
+ VerifyFloat(CFX_CSSProperty::BorderBottomWidth, 2.5,
+ CFX_CSSNumberType::Picas);
+}
diff --git a/core/fxcrt/css/cfx_csssyntaxparser.cpp b/core/fxcrt/css/cfx_csssyntaxparser.cpp
new file mode 100644
index 0000000000..c8082e87fb
--- /dev/null
+++ b/core/fxcrt/css/cfx_csssyntaxparser.cpp
@@ -0,0 +1,228 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// 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_csssyntaxparser.h"
+
+#include <algorithm>
+
+#include "core/fxcrt/css/cfx_cssdatatable.h"
+#include "core/fxcrt/css/cfx_cssdeclaration.h"
+#include "core/fxcrt/fx_codepage.h"
+#include "core/fxcrt/fx_extension.h"
+#include "third_party/base/logging.h"
+
+namespace {
+
+bool IsSelectorStart(wchar_t wch) {
+ return wch == '.' || wch == '#' || wch == '*' || FXSYS_iswalpha(wch);
+}
+
+} // namespace
+
+CFX_CSSSyntaxParser::CFX_CSSSyntaxParser(const wchar_t* pBuffer,
+ int32_t iBufferSize)
+ : CFX_CSSSyntaxParser(pBuffer, iBufferSize, 32, false) {}
+
+CFX_CSSSyntaxParser::CFX_CSSSyntaxParser(const wchar_t* pBuffer,
+ int32_t iBufferSize,
+ int32_t iTextDatSize,
+ bool bOnlyDeclaration)
+ : m_iTextDataLen(0),
+ m_dwCheck(0xFFFFFFFF),
+ m_eStatus(CFX_CSSSyntaxStatus::None) {
+ ASSERT(pBuffer && iBufferSize > 0 && iTextDatSize > 0);
+ m_eMode = bOnlyDeclaration ? CFX_CSSSyntaxMode::PropertyName
+ : CFX_CSSSyntaxMode::RuleSet;
+ m_TextData.InitWithSize(iTextDatSize);
+ m_TextPlane.AttachBuffer(pBuffer, iBufferSize);
+}
+
+CFX_CSSSyntaxParser::~CFX_CSSSyntaxParser() {}
+
+CFX_CSSSyntaxStatus CFX_CSSSyntaxParser::DoSyntaxParse() {
+ while (m_eStatus >= CFX_CSSSyntaxStatus::None) {
+ if (m_TextPlane.IsEOF()) {
+ if (m_eMode == CFX_CSSSyntaxMode::PropertyValue &&
+ m_TextData.GetLength() > 0) {
+ SaveTextData();
+ m_eStatus = CFX_CSSSyntaxStatus::PropertyValue;
+ return m_eStatus;
+ }
+ m_eStatus = CFX_CSSSyntaxStatus::EOS;
+ return m_eStatus;
+ }
+ wchar_t wch;
+ while (!m_TextPlane.IsEOF()) {
+ wch = m_TextPlane.GetChar();
+ switch (m_eMode) {
+ case CFX_CSSSyntaxMode::RuleSet:
+ switch (wch) {
+ case '}':
+ m_TextPlane.MoveNext();
+ if (RestoreMode())
+ return CFX_CSSSyntaxStatus::DeclClose;
+
+ m_eStatus = CFX_CSSSyntaxStatus::Error;
+ return m_eStatus;
+ case '/':
+ if (m_TextPlane.GetNextChar() == '*') {
+ m_ModeStack.push(m_eMode);
+ SwitchMode(CFX_CSSSyntaxMode::Comment);
+ break;
+ }
+ default:
+ if (wch <= ' ') {
+ m_TextPlane.MoveNext();
+ } else if (IsSelectorStart(wch)) {
+ SwitchMode(CFX_CSSSyntaxMode::Selector);
+ return CFX_CSSSyntaxStatus::StyleRule;
+ } else {
+ m_eStatus = CFX_CSSSyntaxStatus::Error;
+ return m_eStatus;
+ }
+ break;
+ }
+ break;
+ case CFX_CSSSyntaxMode::Selector:
+ switch (wch) {
+ case ',':
+ m_TextPlane.MoveNext();
+ SwitchMode(CFX_CSSSyntaxMode::Selector);
+ if (m_iTextDataLen > 0)
+ return CFX_CSSSyntaxStatus::Selector;
+ break;
+ case '{':
+ if (m_TextData.GetLength() > 0) {
+ SaveTextData();
+ return CFX_CSSSyntaxStatus::Selector;
+ }
+ m_TextPlane.MoveNext();
+ m_ModeStack.push(CFX_CSSSyntaxMode::RuleSet);
+ SwitchMode(CFX_CSSSyntaxMode::PropertyName);
+ return CFX_CSSSyntaxStatus::DeclOpen;
+ case '/':
+ if (m_TextPlane.GetNextChar() == '*') {
+ if (SwitchToComment() > 0)
+ return CFX_CSSSyntaxStatus::Selector;
+ break;
+ }
+ default:
+ AppendChar(wch);
+ break;
+ }
+ break;
+ case CFX_CSSSyntaxMode::PropertyName:
+ switch (wch) {
+ case ':':
+ m_TextPlane.MoveNext();
+ SwitchMode(CFX_CSSSyntaxMode::PropertyValue);
+ return CFX_CSSSyntaxStatus::PropertyName;
+ case '}':
+ m_TextPlane.MoveNext();
+ if (RestoreMode())
+ return CFX_CSSSyntaxStatus::DeclClose;
+
+ m_eStatus = CFX_CSSSyntaxStatus::Error;
+ return m_eStatus;
+ case '/':
+ if (m_TextPlane.GetNextChar() == '*') {
+ if (SwitchToComment() > 0)
+ return CFX_CSSSyntaxStatus::PropertyName;
+ break;
+ }
+ default:
+ AppendChar(wch);
+ break;
+ }
+ break;
+ case CFX_CSSSyntaxMode::PropertyValue:
+ switch (wch) {
+ case ';':
+ m_TextPlane.MoveNext();
+ case '}':
+ SwitchMode(CFX_CSSSyntaxMode::PropertyName);
+ return CFX_CSSSyntaxStatus::PropertyValue;
+ case '/':
+ if (m_TextPlane.GetNextChar() == '*') {
+ if (SwitchToComment() > 0)
+ return CFX_CSSSyntaxStatus::PropertyValue;
+ break;
+ }
+ default:
+ AppendChar(wch);
+ break;
+ }
+ break;
+ case CFX_CSSSyntaxMode::Comment:
+ if (wch == '/' && m_TextData.GetLength() > 0 &&
+ m_TextData.GetBuffer()[m_TextData.GetLength() - 1] == '*') {
+ RestoreMode();
+ } else {
+ m_TextData.AppendChar(wch);
+ }
+ m_TextPlane.MoveNext();
+ break;
+ case CFX_CSSSyntaxMode::UnknownRule:
+ if (wch == ';')
+ SwitchMode(CFX_CSSSyntaxMode::RuleSet);
+ m_TextPlane.MoveNext();
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ }
+ }
+ return m_eStatus;
+}
+
+bool CFX_CSSSyntaxParser::IsImportEnabled() const {
+ if ((m_dwCheck & CFX_CSSSYNTAXCHECK_AllowImport) == 0)
+ return false;
+ if (m_ModeStack.size() > 1)
+ return false;
+ return true;
+}
+
+bool CFX_CSSSyntaxParser::AppendChar(wchar_t wch) {
+ m_TextPlane.MoveNext();
+ if (m_TextData.GetLength() > 0 || wch > ' ') {
+ m_TextData.AppendChar(wch);
+ return true;
+ }
+ return false;
+}
+
+int32_t CFX_CSSSyntaxParser::SaveTextData() {
+ m_iTextDataLen = m_TextData.TrimEnd();
+ m_TextData.Clear();
+ return m_iTextDataLen;
+}
+
+void CFX_CSSSyntaxParser::SwitchMode(CFX_CSSSyntaxMode eMode) {
+ m_eMode = eMode;
+ SaveTextData();
+}
+
+int32_t CFX_CSSSyntaxParser::SwitchToComment() {
+ int32_t iLength = m_TextData.GetLength();
+ m_ModeStack.push(m_eMode);
+ SwitchMode(CFX_CSSSyntaxMode::Comment);
+ return iLength;
+}
+
+bool CFX_CSSSyntaxParser::RestoreMode() {
+ if (m_ModeStack.empty())
+ return false;
+
+ SwitchMode(m_ModeStack.top());
+ m_ModeStack.pop();
+ return true;
+}
+
+CFX_WideStringC CFX_CSSSyntaxParser::GetCurrentString() const {
+ return CFX_WideStringC(m_TextData.GetBuffer(), m_iTextDataLen);
+}
diff --git a/core/fxcrt/css/cfx_csssyntaxparser.h b/core/fxcrt/css/cfx_csssyntaxparser.h
new file mode 100644
index 0000000000..9ddedfe4a7
--- /dev/null
+++ b/core/fxcrt/css/cfx_csssyntaxparser.h
@@ -0,0 +1,75 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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
+
+#ifndef CORE_FXCRT_CSS_CFX_CSSSYNTAXPARSER_H_
+#define CORE_FXCRT_CSS_CFX_CSSSYNTAXPARSER_H_
+
+#include <stack>
+
+#include "core/fxcrt/css/cfx_cssexttextbuf.h"
+#include "core/fxcrt/css/cfx_csstextbuf.h"
+#include "core/fxcrt/fx_string.h"
+
+#define CFX_CSSSYNTAXCHECK_AllowCharset 1
+#define CFX_CSSSYNTAXCHECK_AllowImport 2
+
+enum class CFX_CSSSyntaxMode {
+ RuleSet,
+ Comment,
+ UnknownRule,
+ Selector,
+ PropertyName,
+ PropertyValue,
+};
+
+enum class CFX_CSSSyntaxStatus : uint8_t {
+ Error,
+ EOS,
+ None,
+ StyleRule,
+ Selector,
+ DeclOpen,
+ DeclClose,
+ PropertyName,
+ PropertyValue,
+};
+
+class CFX_CSSSyntaxParser {
+ public:
+ CFX_CSSSyntaxParser(const wchar_t* pBuffer, int32_t iBufferSize);
+ CFX_CSSSyntaxParser(const wchar_t* pBuffer,
+ int32_t iBufferSize,
+ int32_t iTextDatSize,
+ bool bOnlyDeclaration);
+ ~CFX_CSSSyntaxParser();
+
+ CFX_CSSSyntaxStatus DoSyntaxParse();
+ CFX_WideStringC GetCurrentString() const;
+
+ protected:
+ void SwitchMode(CFX_CSSSyntaxMode eMode);
+ int32_t SwitchToComment();
+
+ bool RestoreMode();
+ bool AppendChar(wchar_t wch);
+ int32_t SaveTextData();
+ bool IsCharsetEnabled() const {
+ return (m_dwCheck & CFX_CSSSYNTAXCHECK_AllowCharset) != 0;
+ }
+ void DisableCharset() { m_dwCheck = CFX_CSSSYNTAXCHECK_AllowImport; }
+ bool IsImportEnabled() const;
+ void DisableImport() { m_dwCheck = 0; }
+
+ CFX_CSSTextBuf m_TextData;
+ CFX_CSSExtTextBuf m_TextPlane;
+ int32_t m_iTextDataLen;
+ uint32_t m_dwCheck;
+ CFX_CSSSyntaxMode m_eMode;
+ CFX_CSSSyntaxStatus m_eStatus;
+ std::stack<CFX_CSSSyntaxMode> m_ModeStack;
+};
+
+#endif // CORE_FXCRT_CSS_CFX_CSSSYNTAXPARSER_H_
diff --git a/core/fxcrt/css/cfx_csstextbuf.cpp b/core/fxcrt/css/cfx_csstextbuf.cpp
new file mode 100644
index 0000000000..f2f3b94419
--- /dev/null
+++ b/core/fxcrt/css/cfx_csstextbuf.cpp
@@ -0,0 +1,49 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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_csstextbuf.h"
+
+#include "core/fxcrt/fx_memory.h"
+
+CFX_CSSTextBuf::CFX_CSSTextBuf()
+ : m_pBuffer(nullptr), m_iBufLen(0), m_iDatLen(0) {}
+
+CFX_CSSTextBuf::~CFX_CSSTextBuf() {
+ FX_Free(m_pBuffer);
+ m_pBuffer = nullptr;
+ m_iDatLen = m_iBufLen;
+}
+
+void CFX_CSSTextBuf::InitWithSize(int32_t iAllocSize) {
+ ExpandBuf(iAllocSize);
+}
+
+void CFX_CSSTextBuf::AppendChar(wchar_t wch) {
+ if (m_iDatLen >= m_iBufLen)
+ ExpandBuf(m_iBufLen * 2);
+
+ m_pBuffer[m_iDatLen++] = wch;
+}
+
+int32_t CFX_CSSTextBuf::TrimEnd() {
+ while (m_iDatLen > 0 && m_pBuffer[m_iDatLen - 1] <= ' ')
+ --m_iDatLen;
+ AppendChar(0);
+ return --m_iDatLen;
+}
+
+void CFX_CSSTextBuf::ExpandBuf(int32_t iDesiredSize) {
+ ASSERT(iDesiredSize > 0);
+ if (m_pBuffer && m_iBufLen == iDesiredSize)
+ return;
+
+ if (m_pBuffer)
+ m_pBuffer = FX_Realloc(wchar_t, m_pBuffer, iDesiredSize);
+ else
+ m_pBuffer = FX_Alloc(wchar_t, iDesiredSize);
+
+ m_iBufLen = iDesiredSize;
+}
diff --git a/core/fxcrt/css/cfx_csstextbuf.h b/core/fxcrt/css/cfx_csstextbuf.h
new file mode 100644
index 0000000000..e1b9c64e14
--- /dev/null
+++ b/core/fxcrt/css/cfx_csstextbuf.h
@@ -0,0 +1,35 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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
+
+#ifndef CORE_FXCRT_CSS_CFX_CSSTEXTBUF_H_
+#define CORE_FXCRT_CSS_CFX_CSSTEXTBUF_H_
+
+#include "core/fxcrt/fx_system.h"
+
+class CFX_CSSTextBuf {
+ public:
+ CFX_CSSTextBuf();
+ ~CFX_CSSTextBuf();
+
+ void InitWithSize(int32_t iAllocSize);
+ void AppendChar(wchar_t wch);
+
+ void Clear() { m_iDatLen = 0; }
+
+ int32_t TrimEnd();
+
+ int32_t GetLength() const { return m_iDatLen; }
+ const wchar_t* GetBuffer() const { return m_pBuffer; }
+
+ protected:
+ void ExpandBuf(int32_t iDesiredSize);
+
+ wchar_t* m_pBuffer;
+ int32_t m_iBufLen;
+ int32_t m_iDatLen;
+};
+
+#endif // CORE_FXCRT_CSS_CFX_CSSTEXTBUF_H_
diff --git a/core/fxcrt/css/cfx_cssvalue.cpp b/core/fxcrt/css/cfx_cssvalue.cpp
new file mode 100644
index 0000000000..a55fc742b0
--- /dev/null
+++ b/core/fxcrt/css/cfx_cssvalue.cpp
@@ -0,0 +1,9 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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_cssvalue.h"
+
+CFX_CSSValue::CFX_CSSValue(CFX_CSSPrimitiveType type) : m_value(type) {}
diff --git a/core/fxcrt/css/cfx_cssvalue.h b/core/fxcrt/css/cfx_cssvalue.h
new file mode 100644
index 0000000000..4f11e4e0d7
--- /dev/null
+++ b/core/fxcrt/css/cfx_cssvalue.h
@@ -0,0 +1,23 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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
+
+#ifndef CORE_FXCRT_CSS_CFX_CSSVALUE_H_
+#define CORE_FXCRT_CSS_CFX_CSSVALUE_H_
+
+#include "core/fxcrt/css/cfx_css.h"
+
+class CFX_CSSValue : public CFX_Retainable {
+ public:
+ CFX_CSSPrimitiveType GetType() const { return m_value; }
+
+ protected:
+ explicit CFX_CSSValue(CFX_CSSPrimitiveType type);
+
+ private:
+ CFX_CSSPrimitiveType m_value;
+};
+
+#endif // CORE_FXCRT_CSS_CFX_CSSVALUE_H_
diff --git a/core/fxcrt/css/cfx_cssvaluelist.cpp b/core/fxcrt/css/cfx_cssvaluelist.cpp
new file mode 100644
index 0000000000..18b5d82054
--- /dev/null
+++ b/core/fxcrt/css/cfx_cssvaluelist.cpp
@@ -0,0 +1,25 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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_cssvaluelist.h"
+
+#include <utility>
+
+#include "core/fxcrt/css/cfx_css.h"
+
+CFX_CSSValueList::CFX_CSSValueList(
+ std::vector<CFX_RetainPtr<CFX_CSSValue>>& list)
+ : CFX_CSSValue(CFX_CSSPrimitiveType::List), m_ppList(std::move(list)) {}
+
+CFX_CSSValueList::~CFX_CSSValueList() {}
+
+int32_t CFX_CSSValueList::CountValues() const {
+ return m_ppList.size();
+}
+
+CFX_RetainPtr<CFX_CSSValue> CFX_CSSValueList::GetValue(int32_t index) const {
+ return m_ppList[index];
+}
diff --git a/core/fxcrt/css/cfx_cssvaluelist.h b/core/fxcrt/css/cfx_cssvaluelist.h
new file mode 100644
index 0000000000..475abf4066
--- /dev/null
+++ b/core/fxcrt/css/cfx_cssvaluelist.h
@@ -0,0 +1,26 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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
+
+#ifndef CORE_FXCRT_CSS_CFX_CSSVALUELIST_H_
+#define CORE_FXCRT_CSS_CFX_CSSVALUELIST_H_
+
+#include <vector>
+
+#include "core/fxcrt/css/cfx_cssvalue.h"
+
+class CFX_CSSValueList : public CFX_CSSValue {
+ public:
+ explicit CFX_CSSValueList(std::vector<CFX_RetainPtr<CFX_CSSValue>>& list);
+ ~CFX_CSSValueList() override;
+
+ int32_t CountValues() const;
+ CFX_RetainPtr<CFX_CSSValue> GetValue(int32_t index) const;
+
+ protected:
+ std::vector<CFX_RetainPtr<CFX_CSSValue>> m_ppList;
+};
+
+#endif // CORE_FXCRT_CSS_CFX_CSSVALUELIST_H_
diff --git a/core/fxcrt/css/cfx_cssvaluelistparser.cpp b/core/fxcrt/css/cfx_cssvaluelistparser.cpp
new file mode 100644
index 0000000000..05204e5621
--- /dev/null
+++ b/core/fxcrt/css/cfx_cssvaluelistparser.cpp
@@ -0,0 +1,87 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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_cssvaluelistparser.h"
+
+#include "core/fxcrt/fx_extension.h"
+
+CFX_CSSValueListParser::CFX_CSSValueListParser(const wchar_t* psz,
+ int32_t iLen,
+ wchar_t separator)
+ : m_Separator(separator), m_pCur(psz), m_pEnd(psz + iLen) {
+ ASSERT(psz && iLen > 0);
+}
+
+bool CFX_CSSValueListParser::NextValue(CFX_CSSPrimitiveType& eType,
+ const wchar_t*& pStart,
+ int32_t& iLength) {
+ while (m_pCur < m_pEnd && (*m_pCur <= ' ' || *m_pCur == m_Separator))
+ ++m_pCur;
+
+ if (m_pCur >= m_pEnd)
+ return false;
+
+ eType = CFX_CSSPrimitiveType::Unknown;
+ pStart = m_pCur;
+ iLength = 0;
+ wchar_t wch = *m_pCur;
+ if (wch == '#') {
+ iLength = SkipTo(' ', false, false);
+ if (iLength == 4 || iLength == 7)
+ eType = CFX_CSSPrimitiveType::RGB;
+ } else if (std::iswdigit(wch) || wch == '.' || wch == '-' || wch == '+') {
+ while (m_pCur < m_pEnd && (*m_pCur > ' ' && *m_pCur != m_Separator))
+ ++m_pCur;
+
+ iLength = m_pCur - pStart;
+ eType = CFX_CSSPrimitiveType::Number;
+ } else if (wch == '\"' || wch == '\'') {
+ pStart++;
+ m_pCur++;
+ iLength = SkipTo(wch, false, false);
+ m_pCur++;
+ eType = CFX_CSSPrimitiveType::String;
+ } else if (m_pEnd - m_pCur > 5 && m_pCur[3] == '(') {
+ if (FXSYS_wcsnicmp(L"rgb", m_pCur, 3) == 0) {
+ iLength = SkipTo(')', false, false) + 1;
+ m_pCur++;
+ eType = CFX_CSSPrimitiveType::RGB;
+ }
+ } else {
+ iLength = SkipTo(m_Separator, true, true);
+ eType = CFX_CSSPrimitiveType::String;
+ }
+ return m_pCur <= m_pEnd && iLength > 0;
+}
+
+int32_t CFX_CSSValueListParser::SkipTo(wchar_t wch,
+ bool breakOnSpace,
+ bool matchBrackets) {
+ const wchar_t* pStart = m_pCur;
+ int32_t bracketCount = 0;
+ while (m_pCur < m_pEnd && *m_pCur != wch) {
+ if (breakOnSpace && *m_pCur <= ' ')
+ break;
+ if (!matchBrackets) {
+ m_pCur++;
+ continue;
+ }
+
+ if (*m_pCur == '(')
+ bracketCount++;
+ else if (*m_pCur == ')')
+ bracketCount--;
+
+ m_pCur++;
+ }
+
+ while (bracketCount > 0 && m_pCur < m_pEnd) {
+ if (*m_pCur == ')')
+ bracketCount--;
+ m_pCur++;
+ }
+ return m_pCur - pStart;
+}
diff --git a/core/fxcrt/css/cfx_cssvaluelistparser.h b/core/fxcrt/css/cfx_cssvaluelistparser.h
new file mode 100644
index 0000000000..514db9e192
--- /dev/null
+++ b/core/fxcrt/css/cfx_cssvaluelistparser.h
@@ -0,0 +1,30 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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
+
+#ifndef CORE_FXCRT_CSS_CFX_CSSVALUELISTPARSER_H_
+#define CORE_FXCRT_CSS_CFX_CSSVALUELISTPARSER_H_
+
+#include "core/fxcrt/css/cfx_css.h"
+#include "core/fxcrt/fx_system.h"
+
+class CFX_CSSValueListParser {
+ public:
+ CFX_CSSValueListParser(const wchar_t* psz, int32_t iLen, wchar_t separator);
+
+ bool NextValue(CFX_CSSPrimitiveType& eType,
+ const wchar_t*& pStart,
+ int32_t& iLength);
+
+ wchar_t m_Separator;
+
+ private:
+ int32_t SkipTo(wchar_t wch, bool breakOnSpace, bool matchBrackets);
+
+ const wchar_t* m_pCur;
+ const wchar_t* m_pEnd;
+};
+
+#endif // CORE_FXCRT_CSS_CFX_CSSVALUELISTPARSER_H_
diff --git a/core/fxcrt/css/cfx_cssvaluelistparser_unittest.cpp b/core/fxcrt/css/cfx_cssvaluelistparser_unittest.cpp
new file mode 100644
index 0000000000..510c96251d
--- /dev/null
+++ b/core/fxcrt/css/cfx_cssvaluelistparser_unittest.cpp
@@ -0,0 +1,141 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// 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_cssvaluelistparser.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/test_support.h"
+#include "third_party/base/ptr_util.h"
+
+TEST(CFX_CSSValueListParserTest, rgb_short) {
+ CFX_CSSPrimitiveType type;
+ const wchar_t* start;
+ int32_t len;
+
+ auto parser = pdfium::MakeUnique<CFX_CSSValueListParser>(L"#abc", 4, L' ');
+ EXPECT_TRUE(parser->NextValue(type, start, len));
+ EXPECT_EQ(CFX_CSSPrimitiveType::RGB, type);
+ EXPECT_EQ(L"#abc", CFX_WideString(start, len));
+ EXPECT_FALSE(parser->NextValue(type, start, len));
+
+ parser = pdfium::MakeUnique<CFX_CSSValueListParser>(L"#abcdef", 7, L' ');
+ EXPECT_TRUE(parser->NextValue(type, start, len));
+ EXPECT_EQ(CFX_CSSPrimitiveType::RGB, type);
+ EXPECT_EQ(L"#abcdef", CFX_WideString(start, len));
+ EXPECT_FALSE(parser->NextValue(type, start, len));
+
+ parser =
+ pdfium::MakeUnique<CFX_CSSValueListParser>(L"rgb(1, 255, 4)", 14, L' ');
+ EXPECT_TRUE(parser->NextValue(type, start, len));
+ EXPECT_EQ(CFX_CSSPrimitiveType::RGB, type);
+ EXPECT_EQ(L"rgb(1, 255, 4)", CFX_WideString(start, len));
+
+ parser = pdfium::MakeUnique<CFX_CSSValueListParser>(L"#abcdefghij", 11, L' ');
+ EXPECT_TRUE(parser->NextValue(type, start, len));
+ EXPECT_EQ(CFX_CSSPrimitiveType::Unknown, type);
+ EXPECT_EQ(L"#abcdefghij", CFX_WideString(start, len));
+ EXPECT_FALSE(parser->NextValue(type, start, len));
+}
+
+TEST(CFX_CSSValueListParserTest, number_parsing) {
+ CFX_CSSPrimitiveType type;
+ const wchar_t* start;
+ int32_t len;
+
+ auto parser = pdfium::MakeUnique<CFX_CSSValueListParser>(L"1234", 4, L' ');
+ EXPECT_TRUE(parser->NextValue(type, start, len));
+ EXPECT_EQ(CFX_CSSPrimitiveType::Number, type);
+ EXPECT_EQ(L"1234", CFX_WideString(start, len));
+
+ parser = pdfium::MakeUnique<CFX_CSSValueListParser>(L"-1234", 5, L' ');
+ EXPECT_TRUE(parser->NextValue(type, start, len));
+ EXPECT_EQ(CFX_CSSPrimitiveType::Number, type);
+ EXPECT_EQ(L"-1234", CFX_WideString(start, len));
+
+ parser = pdfium::MakeUnique<CFX_CSSValueListParser>(L"+1234", 5, L' ');
+ EXPECT_TRUE(parser->NextValue(type, start, len));
+ EXPECT_EQ(CFX_CSSPrimitiveType::Number, type);
+ EXPECT_EQ(L"+1234", CFX_WideString(start, len));
+
+ parser = pdfium::MakeUnique<CFX_CSSValueListParser>(L".1234", 5, L' ');
+ EXPECT_TRUE(parser->NextValue(type, start, len));
+ EXPECT_EQ(CFX_CSSPrimitiveType::Number, type);
+ EXPECT_EQ(L".1234", CFX_WideString(start, len));
+
+ parser = pdfium::MakeUnique<CFX_CSSValueListParser>(L"4321.1234", 9, L' ');
+ EXPECT_TRUE(parser->NextValue(type, start, len));
+ EXPECT_EQ(CFX_CSSPrimitiveType::Number, type);
+ EXPECT_EQ(L"4321.1234", CFX_WideString(start, len));
+
+ // TODO(dsinclair): These should probably fail but currently don't.
+ parser = pdfium::MakeUnique<CFX_CSSValueListParser>(L"4321.12.34", 10, L' ');
+ EXPECT_TRUE(parser->NextValue(type, start, len));
+ EXPECT_EQ(CFX_CSSPrimitiveType::Number, type);
+ EXPECT_EQ(L"4321.12.34", CFX_WideString(start, len));
+
+ parser = pdfium::MakeUnique<CFX_CSSValueListParser>(L"43a1.12.34", 10, L' ');
+ EXPECT_TRUE(parser->NextValue(type, start, len));
+ EXPECT_EQ(CFX_CSSPrimitiveType::Number, type);
+ EXPECT_EQ(L"43a1.12.34", CFX_WideString(start, len));
+}
+
+TEST(CFX_CSSValueListParserTest, string_parsing) {
+ CFX_CSSPrimitiveType type;
+ const wchar_t* start;
+ int32_t len;
+
+ auto parser =
+ pdfium::MakeUnique<CFX_CSSValueListParser>(L"'string'", 8, L' ');
+ EXPECT_TRUE(parser->NextValue(type, start, len));
+ EXPECT_EQ(CFX_CSSPrimitiveType::String, type);
+ EXPECT_EQ(L"string", CFX_WideString(start, len));
+
+ parser = pdfium::MakeUnique<CFX_CSSValueListParser>(L"\"another string\"", 16,
+ L' ');
+ EXPECT_TRUE(parser->NextValue(type, start, len));
+ EXPECT_EQ(CFX_CSSPrimitiveType::String, type);
+ EXPECT_EQ(L"another string", CFX_WideString(start, len));
+
+ parser = pdfium::MakeUnique<CFX_CSSValueListParser>(L"standalone", 10, L' ');
+ EXPECT_TRUE(parser->NextValue(type, start, len));
+ EXPECT_EQ(CFX_CSSPrimitiveType::String, type);
+ EXPECT_EQ(L"standalone", CFX_WideString(start, len));
+}
+
+TEST(CFX_CSSValueListParserTest, multiparsing) {
+ CFX_CSSPrimitiveType type;
+ const wchar_t* start;
+ int32_t len;
+
+ auto parser = pdfium::MakeUnique<CFX_CSSValueListParser>(L"1, 2, 3", 7, L',');
+ EXPECT_TRUE(parser->NextValue(type, start, len));
+ EXPECT_EQ(CFX_CSSPrimitiveType::Number, type);
+ EXPECT_EQ(L"1", CFX_WideString(start, len));
+
+ EXPECT_TRUE(parser->NextValue(type, start, len));
+ EXPECT_EQ(CFX_CSSPrimitiveType::Number, type);
+ EXPECT_EQ(L"2", CFX_WideString(start, len));
+
+ EXPECT_TRUE(parser->NextValue(type, start, len));
+ EXPECT_EQ(CFX_CSSPrimitiveType::Number, type);
+ EXPECT_EQ(L"3", CFX_WideString(start, len));
+
+ EXPECT_FALSE(parser->NextValue(type, start, len));
+
+ parser = pdfium::MakeUnique<CFX_CSSValueListParser>(L"'str', rgb(1, 2, 3), 4",
+ 22, L',');
+ EXPECT_TRUE(parser->NextValue(type, start, len));
+ EXPECT_EQ(CFX_CSSPrimitiveType::String, type);
+ EXPECT_EQ(L"str", CFX_WideString(start, len));
+
+ EXPECT_TRUE(parser->NextValue(type, start, len));
+ EXPECT_EQ(CFX_CSSPrimitiveType::RGB, type);
+ EXPECT_EQ(L"rgb(1, 2, 3)", CFX_WideString(start, len));
+
+ EXPECT_TRUE(parser->NextValue(type, start, len));
+ EXPECT_EQ(CFX_CSSPrimitiveType::Number, type);
+ EXPECT_EQ(L"4", CFX_WideString(start, len));
+}