7#include "core/fxcrt/css/cfx_cssdeclaration.h"
14#include "core/fxcrt/check.h"
15#include "core/fxcrt/check_op.h"
16#include "core/fxcrt/compiler_specific.h"
17#include "core/fxcrt/css/cfx_csscolorvalue.h"
18#include "core/fxcrt/css/cfx_csscustomproperty.h"
19#include "core/fxcrt/css/cfx_cssenumvalue.h"
20#include "core/fxcrt/css/cfx_cssnumbervalue.h"
21#include "core/fxcrt/css/cfx_csspropertyholder.h"
22#include "core/fxcrt/css/cfx_cssstringvalue.h"
23#include "core/fxcrt/css/cfx_cssvaluelist.h"
24#include "core/fxcrt/css/cfx_cssvaluelistparser.h"
25#include "core/fxcrt/fx_extension.h"
26#include "core/fxcrt/fx_system.h"
27#include "core/fxcrt/notreached.h"
31uint8_t Hex2Dec(uint8_t hexHigh, uint8_t hexLow) {
39 float value = FXSYS_wcstof(view, &nUsedLen);
40 if (nUsedLen == 0 || !isfinite(value)) {
43 view = view.Substr(nUsedLen);
44 if (view.Front() ==
'%') {
47 if (view.GetLength() == 2) {
62 if (value.GetLength() >= 2) {
63 wchar_t first = value.Front();
64 wchar_t last = value.Back();
65 if ((first ==
'\"' && last ==
'\"') || (first ==
'\'' && last ==
'\'')) {
66 value = value.Substr(1, value.GetLength() - 2);
69 if (value.IsEmpty()) {
77 if (value.Front() ==
'#') {
78 switch (value.GetLength()) {
80 uint8_t red = Hex2Dec((uint8_t)value[1], (uint8_t)value[1]);
81 uint8_t green = Hex2Dec((uint8_t)value[2], (uint8_t)value[2]);
82 uint8_t blue = Hex2Dec((uint8_t)value[3], (uint8_t)value[3]);
86 uint8_t red = Hex2Dec((uint8_t)value[1], (uint8_t)value[2]);
87 uint8_t green = Hex2Dec((uint8_t)value[3], (uint8_t)value[4]);
88 uint8_t blue = Hex2Dec((uint8_t)value[5], (uint8_t)value[6]);
96 if (value.GetLength() >= 10) {
97 if (!value.First(4).EqualsASCIINoCase(
"rgb(") || value.Back() !=
')') {
100 std::array<uint8_t, 3> rgb = {};
102 for (
auto& component : rgb) {
103 auto maybe_value = list.NextValue();
104 if (!maybe_value.has_value() ||
105 maybe_value.value().type != CFX_CSSValue::PrimitiveType::kNumber) {
108 auto maybe_number = ParseCSSNumber(maybe_value.value().string_view);
109 if (!maybe_number.has_value()) {
112 component = maybe_number.value().unit == CFX_CSSNumber::Unit::kPercent
113 ? FXSYS_roundf(maybe_number.value().value * 2.55f)
114 : FXSYS_roundf(maybe_number.value().value);
116 return ArgbEncode(255, rgb[0], rgb[1], rgb[2]);
132 bool* bImportant)
const {
133 for (
const auto& p : properties_) {
134 if (p->eProperty == eProperty) {
135 *bImportant = p->bImportant;
146 pHolder->bImportant = bImportant;
147 pHolder->eProperty = eProperty;
148 pHolder->pValue =
std::move(pValue);
149 properties_.push_back(std::move(pHolder));
156 bool bImportant =
false;
158 if (last_ten.EqualsASCIINoCase(
"!important")) {
159 value = value.First(value.GetLength() - 10);
160 if (value.IsEmpty()) {
165 const CFX_CSSValueTypeMask dwType = property->dwTypes;
166 switch (dwType & 0x0F) {
175 const CFX_CSSValueTypeMask dwMatch = dwType & guess;
182 pCSSValue = ParseNumber(value);
185 pCSSValue = ParseEnum(value);
188 pCSSValue = ParseColor(value);
191 pCSSValue = ParseString(value);
197 AddPropertyHolder(property
->eName, pCSSValue, bImportant);
209 ParseFontProperty(value, bImportant);
226 ParseBorderProperty(value), bImportant);
231 ParseBorderProperty(value), bImportant);
236 ParseBorderProperty(value), bImportant);
241 ParseBorderProperty(value), bImportant);
250 ParseValueListProperty(property, value, bImportant);
259 custom_properties_.push_back(
260 std::make_unique<CFX_CSSCustomProperty>(prop, value));
265 if (!maybe_number.has_value()) {
268 return pdfium::MakeRetain<CFX_CSSNumberValue>(maybe_number.value());
274 return pValue ?
pdfium::MakeRetain<CFX_CSSEnumValue>(pValue
->eName) :
nullptr;
278 auto maybe_color = ParseCSSColor(value);
279 if (!maybe_color.has_value()) {
282 return pdfium::MakeRetain<CFX_CSSColorValue>(maybe_color.value());
286 auto maybe_string = ParseCSSString(value);
287 if (!maybe_string.has_value() || maybe_string.value().IsEmpty()) {
290 return pdfium::MakeRetain<CFX_CSSStringValue>(maybe_string.value());
300 const CFX_CSSValueTypeMask dwType = pProperty->dwTypes;
301 std::vector<RetainPtr<CFX_CSSValue>> list;
304 if (!maybe_next.has_value()) {
307 switch (maybe_next.value().type) {
310 auto maybe_number = ParseCSSNumber(maybe_next.value().string_view);
311 if (maybe_number.has_value()) {
313 pdfium::MakeRetain<CFX_CSSNumberValue>(maybe_number.value()));
319 auto maybe_color = ParseCSSColor(maybe_next.value().string_view);
320 if (maybe_color.has_value()) {
322 pdfium::MakeRetain<CFX_CSSColorValue>(maybe_color.value()));
329 maybe_next.value().string_view
);
337 list.push_back(
pdfium::MakeRetain<CFX_CSSStringValue>(
338 maybe_next.value().string_view));
344 ParseCSSColor(maybe_next.value().string_view).value_or(0);
345 list.push_back(
pdfium::MakeRetain<CFX_CSSColorValue>(color));
356 case CFX_CSSProperty::BorderWidth:
357 Add4ValuesProperty(list, bImportant, CFX_CSSProperty::BorderLeftWidth,
358 CFX_CSSProperty::BorderTopWidth,
359 CFX_CSSProperty::BorderRightWidth,
360 CFX_CSSProperty::BorderBottomWidth);
362 case CFX_CSSProperty::Margin:
363 Add4ValuesProperty(list, bImportant, CFX_CSSProperty::MarginLeft,
364 CFX_CSSProperty::MarginTop,
365 CFX_CSSProperty::MarginRight,
366 CFX_CSSProperty::MarginBottom);
368 case CFX_CSSProperty::Padding:
369 Add4ValuesProperty(list, bImportant, CFX_CSSProperty::PaddingLeft,
370 CFX_CSSProperty::PaddingTop,
371 CFX_CSSProperty::PaddingRight,
372 CFX_CSSProperty::PaddingBottom);
375 auto value_list =
pdfium::MakeRetain<CFX_CSSValueList>(
std::move(list));
376 AddPropertyHolder(pProperty
->eName,
std::move(value_list), bImportant);
383 const std::vector<RetainPtr<CFX_CSSValue>>& list,
389 switch (list.size()) {
391 AddPropertyHolder(eLeft, list[0], bImportant);
392 AddPropertyHolder(eTop, list[0], bImportant);
393 AddPropertyHolder(eRight, list[0], bImportant);
394 AddPropertyHolder(eBottom, list[0], bImportant);
397 AddPropertyHolder(eLeft, list[1], bImportant);
398 AddPropertyHolder(eTop, list[0], bImportant);
399 AddPropertyHolder(eRight, list[1], bImportant);
400 AddPropertyHolder(eBottom, list[0], bImportant);
403 AddPropertyHolder(eLeft, list[1], bImportant);
404 AddPropertyHolder(eTop, list[0], bImportant);
405 AddPropertyHolder(eRight, list[1], bImportant);
406 AddPropertyHolder(eBottom, list[2], bImportant);
409 AddPropertyHolder(eLeft, list[3], bImportant);
410 AddPropertyHolder(eTop, list[0], bImportant);
411 AddPropertyHolder(eRight, list[1], bImportant);
412 AddPropertyHolder(eBottom, list[2], bImportant);
425 if (!maybe_next.has_value()) {
428 switch (maybe_next.value().type) {
433 auto maybe_number = ParseCSSNumber(maybe_next.value().string_view);
434 if (maybe_number.has_value()) {
435 pWidth =
pdfium::MakeRetain<CFX_CSSNumberValue>(maybe_number.value());
455 pWidth =
pdfium::MakeRetain<CFX_CSSEnumValue>(pValue
->eName);
469 return pdfium::MakeRetain<CFX_CSSNumberValue>(
480 std::vector<RetainPtr<CFX_CSSValue>> family_list;
484 if (!maybe_next.has_value()) {
487 switch (maybe_next.value().type) {
503 pFontSize =
pdfium::MakeRetain<CFX_CSSEnumValue>(pValue
->eName);
509 pWeight =
pdfium::MakeRetain<CFX_CSSEnumValue>(pValue
->eName);
514 pStyle =
pdfium::MakeRetain<CFX_CSSEnumValue>(pValue
->eName);
518 pVariant =
pdfium::MakeRetain<CFX_CSSEnumValue>(pValue
->eName);
522 pStyle =
pdfium::MakeRetain<CFX_CSSEnumValue>(pValue
->eName);
524 pVariant =
pdfium::MakeRetain<CFX_CSSEnumValue>(pValue
->eName);
526 pWeight =
pdfium::MakeRetain<CFX_CSSEnumValue>(pValue
->eName);
528 pFontSize =
pdfium::MakeRetain<CFX_CSSEnumValue>(pValue
->eName);
529 else if (!pLineHeight)
538 family_list.push_back(
pdfium::MakeRetain<CFX_CSSStringValue>(
539 maybe_next.value().string_view));
545 auto maybe_number = ParseCSSNumber(maybe_next.value().string_view);
546 if (!maybe_number.has_value()) {
550 switch (
static_cast<int32_t>(maybe_number.value().value)) {
561 pWeight =
pdfium::MakeRetain<CFX_CSSNumberValue>(
562 maybe_number.value());
569 pdfium::MakeRetain<CFX_CSSNumberValue>(maybe_number.value());
570 }
else if (!pLineHeight) {
572 pdfium::MakeRetain<CFX_CSSNumberValue>(maybe_number.value());
605 AddPropertyHolder(
CFX_CSSProperty::LineHeight, pLineHeight, bImportant);
606 if (!family_list.empty()) {
608 pdfium::MakeRetain<CFX_CSSValueList>(
std::move(family_list));
609 AddPropertyHolder(
CFX_CSSProperty::FontFamily, value_list, bImportant);
614 return properties_.size();
@ CFX_CSSVALUETYPE_Shorthand
@ CFX_CSSVALUETYPE_Primitive
@ CFX_CSSVALUETYPE_MaybeEnum
@ CFX_CSSVALUETYPE_MaybeString
@ CFX_CSSVALUETYPE_MaybeColor
@ CFX_CSSVALUETYPE_MaybeNumber
static const Color * GetColorByName(WideStringView wsName)
static const LengthUnit * GetLengthUnitByName(WideStringView wsName)
static const PropertyValue * GetPropertyValueByName(WideStringView wsName)
void AddProperty(const CFX_CSSData::Property *property, WideStringView value)
static std::optional< WideStringView > ParseCSSString(WideStringView value)
void AddProperty(const WideString &prop, const WideString &value)
size_t PropertyCountForTesting() const
static std::optional< FX_ARGB > ParseCSSColor(WideStringView value)
RetainPtr< CFX_CSSValue > GetProperty(CFX_CSSProperty eProperty, bool *bImportant) const
std::optional< Result > NextValue()
constexpr FX_ARGB ArgbEncode(uint32_t a, uint32_t r, uint32_t g, uint32_t b)
int FXSYS_HexCharToInt(char c)
#define NOTREACHED_NORETURN()
fxcrt::WideStringView WideStringView
CFX_CSSPropertyValue eName
fxcrt::WideString WideString