From 9f0e85ac36826e39a242f8039c2b2c333ee99f4f Mon Sep 17 00:00:00 2001 From: Dan Sinclair Date: Tue, 8 Aug 2017 13:23:24 -0400 Subject: Move CSS code to core The xfa/fde/css code has no other links into xfa/. This CL moves the css code to core/fxcrt/css and sets to only build when pdf_enable_xfa is enabled. Change-Id: Iefd208e1f83a28b80b567c574e841e87bce310be Reviewed-on: https://pdfium-review.googlesource.com/9251 Commit-Queue: dsinclair Reviewed-by: Tom Sepez --- core/fxcrt/css/cfx_cssstylesheet_unittest.cpp | 239 ++++++++++++++++++++++++++ 1 file changed, 239 insertions(+) create mode 100644 core/fxcrt/css/cfx_cssstylesheet_unittest.cpp (limited to 'core/fxcrt/css/cfx_cssstylesheet_unittest.cpp') 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 +#include + +#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(); + decl_ = nullptr; + } + + void TearDown() override { decl_ = nullptr; } + + void LoadAndVerifyDecl(const wchar_t* buf, + const std::vector& 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 v = decl_->GetProperty(prop, &important); + EXPECT_EQ(v->GetType(), CFX_CSSPrimitiveType::Number); + EXPECT_EQ(v.As()->Kind(), type); + EXPECT_EQ(v.As()->Value(), val); + } + + void VerifyEnum(CFX_CSSProperty prop, CFX_CSSPropertyValue val) { + ASSERT(decl_); + + bool important; + CFX_RetainPtr v = decl_->GetProperty(prop, &important); + EXPECT_EQ(v->GetType(), CFX_CSSPrimitiveType::Enum); + EXPECT_EQ(v.As()->Value(), val); + } + + void VerifyList(CFX_CSSProperty prop, + std::vector values) { + ASSERT(decl_); + + bool important; + CFX_RetainPtr list = + decl_->GetProperty(prop, &important).As(); + EXPECT_EQ(list->CountValues(), pdfium::CollectionSize(values)); + + for (size_t i = 0; i < values.size(); i++) { + CFX_RetainPtr val = list->GetValue(i); + EXPECT_EQ(val->GetType(), CFX_CSSPrimitiveType::Enum); + EXPECT_EQ(val.As()->Value(), values[i]); + } + } + + std::unique_ptr 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); +} -- cgit v1.2.3