1 // Copyright 2014 The PDFium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "core/fxcrt/css/cfx_cssdeclaration.h"
8
9 #include <math.h>
10
11 #include <array>
12 #include <utility>
13
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"
28
29 namespace {
30
Hex2Dec(uint8_t hexHigh,uint8_t hexLow)31 uint8_t Hex2Dec(uint8_t hexHigh, uint8_t hexLow) {
32 return (FXSYS_HexCharToInt(hexHigh) << 4) + FXSYS_HexCharToInt(hexLow);
33 }
34
ParseCSSNumber(WideStringView view)35 std::optional<CFX_CSSNumber> ParseCSSNumber(WideStringView view) {
36 DCHECK(!view.IsEmpty());
37
38 size_t nUsedLen = 0;
39 float value = FXSYS_wcstof(view, &nUsedLen);
40 if (nUsedLen == 0 || !isfinite(value)) {
41 return std::nullopt;
42 }
43 view = view.Substr(nUsedLen);
44 if (view.Front() == '%') { // NOTE: empty-tolerant Front().
45 return CFX_CSSNumber{CFX_CSSNumber::Unit::kPercent, value};
46 }
47 if (view.GetLength() == 2) {
48 const CFX_CSSData::LengthUnit* pUnit =
49 CFX_CSSData::GetLengthUnitByName(view.First(2));
50 if (pUnit) {
51 return CFX_CSSNumber{pUnit->type, value};
52 }
53 }
54 return CFX_CSSNumber{CFX_CSSNumber::Unit::kNumber, value};
55 }
56
57 } // namespace
58
59 // static
ParseCSSString(WideStringView value)60 std::optional<WideStringView> CFX_CSSDeclaration::ParseCSSString(
61 WideStringView value) {
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);
67 }
68 }
69 if (value.IsEmpty()) {
70 return std::nullopt;
71 }
72 return value;
73 }
74
75 // static.
ParseCSSColor(WideStringView value)76 std::optional<FX_ARGB> CFX_CSSDeclaration::ParseCSSColor(WideStringView value) {
77 if (value.Front() == '#') { // Note: empty-tolerant Front().
78 switch (value.GetLength()) {
79 case 4: {
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]);
83 return ArgbEncode(255, red, green, blue);
84 }
85 case 7: {
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]);
89 return ArgbEncode(255, red, green, blue);
90 }
91 default:
92 return std::nullopt;
93 }
94 }
95
96 if (value.GetLength() >= 10) {
97 if (!value.First(4).EqualsASCIINoCase("rgb(") || value.Back() != ')') {
98 return std::nullopt;
99 }
100 std::array<uint8_t, 3> rgb = {};
101 CFX_CSSValueListParser list(value.Substr(4, value.GetLength() - 5), ',');
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) {
106 return std::nullopt;
107 }
108 auto maybe_number = ParseCSSNumber(maybe_value.value().string_view);
109 if (!maybe_number.has_value()) {
110 return std::nullopt;
111 }
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);
115 }
116 return ArgbEncode(255, rgb[0], rgb[1], rgb[2]);
117 }
118
119 const CFX_CSSData::Color* pColor = CFX_CSSData::GetColorByName(value);
120 if (!pColor) {
121 return std::nullopt;
122 }
123 return pColor->value;
124 }
125
126 CFX_CSSDeclaration::CFX_CSSDeclaration() = default;
127
128 CFX_CSSDeclaration::~CFX_CSSDeclaration() = default;
129
GetProperty(CFX_CSSProperty eProperty,bool * bImportant) const130 RetainPtr<CFX_CSSValue> CFX_CSSDeclaration::GetProperty(
131 CFX_CSSProperty eProperty,
132 bool* bImportant) const {
133 for (const auto& p : properties_) {
134 if (p->eProperty == eProperty) {
135 *bImportant = p->bImportant;
136 return p->pValue;
137 }
138 }
139 return nullptr;
140 }
141
AddPropertyHolder(CFX_CSSProperty eProperty,RetainPtr<CFX_CSSValue> pValue,bool bImportant)142 void CFX_CSSDeclaration::AddPropertyHolder(CFX_CSSProperty eProperty,
143 RetainPtr<CFX_CSSValue> pValue,
144 bool bImportant) {
145 auto pHolder = std::make_unique<CFX_CSSPropertyHolder>();
146 pHolder->bImportant = bImportant;
147 pHolder->eProperty = eProperty;
148 pHolder->pValue = std::move(pValue);
149 properties_.push_back(std::move(pHolder));
150 }
151
AddProperty(const CFX_CSSData::Property * property,WideStringView value)152 void CFX_CSSDeclaration::AddProperty(const CFX_CSSData::Property* property,
153 WideStringView value) {
154 DCHECK(!value.IsEmpty());
155
156 bool bImportant = false;
157 WideStringView last_ten = value.Last(10); // NOTE: empty-tolerant Last().
158 if (last_ten.EqualsASCIINoCase("!important")) {
159 value = value.First(value.GetLength() - 10);
160 if (value.IsEmpty()) {
161 return;
162 }
163 bImportant = true;
164 }
165 const CFX_CSSValueTypeMask dwType = property->dwTypes;
166 switch (dwType & 0x0F) {
167 case CFX_CSSVALUETYPE_Primitive: {
168 static constexpr CFX_CSSVALUETYPE kValueGuessOrder[] = {
169 CFX_CSSVALUETYPE_MaybeNumber,
170 CFX_CSSVALUETYPE_MaybeEnum,
171 CFX_CSSVALUETYPE_MaybeColor,
172 CFX_CSSVALUETYPE_MaybeString,
173 };
174 for (CFX_CSSVALUETYPE guess : kValueGuessOrder) {
175 const CFX_CSSValueTypeMask dwMatch = dwType & guess;
176 if (dwMatch == 0) {
177 continue;
178 }
179 RetainPtr<CFX_CSSValue> pCSSValue;
180 switch (dwMatch) {
181 case CFX_CSSVALUETYPE_MaybeNumber:
182 pCSSValue = ParseNumber(value);
183 break;
184 case CFX_CSSVALUETYPE_MaybeEnum:
185 pCSSValue = ParseEnum(value);
186 break;
187 case CFX_CSSVALUETYPE_MaybeColor:
188 pCSSValue = ParseColor(value);
189 break;
190 case CFX_CSSVALUETYPE_MaybeString:
191 pCSSValue = ParseString(value);
192 break;
193 default:
194 break;
195 }
196 if (pCSSValue) {
197 AddPropertyHolder(property->eName, pCSSValue, bImportant);
198 return;
199 }
200 if ((dwType & ~guess) == CFX_CSSVALUETYPE_Primitive) {
201 return;
202 }
203 }
204 break;
205 }
206 case CFX_CSSVALUETYPE_Shorthand: {
207 switch (property->eName) {
208 case CFX_CSSProperty::Font: {
209 ParseFontProperty(value, bImportant);
210 return;
211 }
212 case CFX_CSSProperty::Border: {
213 RetainPtr<CFX_CSSValue> pWidth = ParseBorderProperty(value);
214 AddPropertyHolder(CFX_CSSProperty::BorderLeftWidth, pWidth,
215 bImportant);
216 AddPropertyHolder(CFX_CSSProperty::BorderTopWidth, pWidth,
217 bImportant);
218 AddPropertyHolder(CFX_CSSProperty::BorderRightWidth, pWidth,
219 bImportant);
220 AddPropertyHolder(CFX_CSSProperty::BorderBottomWidth, pWidth,
221 bImportant);
222 return;
223 }
224 case CFX_CSSProperty::BorderLeft: {
225 AddPropertyHolder(CFX_CSSProperty::BorderLeftWidth,
226 ParseBorderProperty(value), bImportant);
227 break;
228 }
229 case CFX_CSSProperty::BorderTop: {
230 AddPropertyHolder(CFX_CSSProperty::BorderTopWidth,
231 ParseBorderProperty(value), bImportant);
232 return;
233 }
234 case CFX_CSSProperty::BorderRight: {
235 AddPropertyHolder(CFX_CSSProperty::BorderRightWidth,
236 ParseBorderProperty(value), bImportant);
237 return;
238 }
239 case CFX_CSSProperty::BorderBottom: {
240 AddPropertyHolder(CFX_CSSProperty::BorderBottomWidth,
241 ParseBorderProperty(value), bImportant);
242 return;
243 }
244 default:
245 break;
246 }
247 break;
248 }
249 case CFX_CSSVALUETYPE_List:
250 ParseValueListProperty(property, value, bImportant);
251 return;
252 default:
253 NOTREACHED_NORETURN();
254 }
255 }
256
AddProperty(const WideString & prop,const WideString & value)257 void CFX_CSSDeclaration::AddProperty(const WideString& prop,
258 const WideString& value) {
259 custom_properties_.push_back(
260 std::make_unique<CFX_CSSCustomProperty>(prop, value));
261 }
262
ParseNumber(WideStringView view)263 RetainPtr<CFX_CSSValue> CFX_CSSDeclaration::ParseNumber(WideStringView view) {
264 std::optional<CFX_CSSNumber> maybe_number = ParseCSSNumber(view);
265 if (!maybe_number.has_value()) {
266 return nullptr;
267 }
268 return pdfium::MakeRetain<CFX_CSSNumberValue>(maybe_number.value());
269 }
270
ParseEnum(WideStringView value)271 RetainPtr<CFX_CSSValue> CFX_CSSDeclaration::ParseEnum(WideStringView value) {
272 const CFX_CSSData::PropertyValue* pValue =
273 CFX_CSSData::GetPropertyValueByName(value);
274 return pValue ? pdfium::MakeRetain<CFX_CSSEnumValue>(pValue->eName) : nullptr;
275 }
276
ParseColor(WideStringView value)277 RetainPtr<CFX_CSSValue> CFX_CSSDeclaration::ParseColor(WideStringView value) {
278 auto maybe_color = ParseCSSColor(value);
279 if (!maybe_color.has_value()) {
280 return nullptr;
281 }
282 return pdfium::MakeRetain<CFX_CSSColorValue>(maybe_color.value());
283 }
284
ParseString(WideStringView value)285 RetainPtr<CFX_CSSValue> CFX_CSSDeclaration::ParseString(WideStringView value) {
286 auto maybe_string = ParseCSSString(value);
287 if (!maybe_string.has_value() || maybe_string.value().IsEmpty()) {
288 return nullptr;
289 }
290 return pdfium::MakeRetain<CFX_CSSStringValue>(maybe_string.value());
291 }
292
ParseValueListProperty(const CFX_CSSData::Property * pProperty,WideStringView value,bool bImportant)293 void CFX_CSSDeclaration::ParseValueListProperty(
294 const CFX_CSSData::Property* pProperty,
295 WideStringView value,
296 bool bImportant) {
297 wchar_t separator =
298 (pProperty->eName == CFX_CSSProperty::FontFamily) ? ',' : ' ';
299 CFX_CSSValueListParser parser(value, separator);
300 const CFX_CSSValueTypeMask dwType = pProperty->dwTypes;
301 std::vector<RetainPtr<CFX_CSSValue>> list;
302 while (1) {
303 auto maybe_next = parser.NextValue();
304 if (!maybe_next.has_value()) {
305 break;
306 }
307 switch (maybe_next.value().type) {
308 case CFX_CSSValue::PrimitiveType::kNumber:
309 if (dwType & CFX_CSSVALUETYPE_MaybeNumber) {
310 auto maybe_number = ParseCSSNumber(maybe_next.value().string_view);
311 if (maybe_number.has_value()) {
312 list.push_back(
313 pdfium::MakeRetain<CFX_CSSNumberValue>(maybe_number.value()));
314 }
315 }
316 break;
317 case CFX_CSSValue::PrimitiveType::kString:
318 if (dwType & CFX_CSSVALUETYPE_MaybeColor) {
319 auto maybe_color = ParseCSSColor(maybe_next.value().string_view);
320 if (maybe_color.has_value()) {
321 list.push_back(
322 pdfium::MakeRetain<CFX_CSSColorValue>(maybe_color.value()));
323 continue;
324 }
325 }
326 if (dwType & CFX_CSSVALUETYPE_MaybeEnum) {
327 const CFX_CSSData::PropertyValue* pPropValue =
328 CFX_CSSData::GetPropertyValueByName(
329 maybe_next.value().string_view);
330 if (pPropValue) {
331 list.push_back(
332 pdfium::MakeRetain<CFX_CSSEnumValue>(pPropValue->eName));
333 continue;
334 }
335 }
336 if (dwType & CFX_CSSVALUETYPE_MaybeString) {
337 list.push_back(pdfium::MakeRetain<CFX_CSSStringValue>(
338 maybe_next.value().string_view));
339 }
340 break;
341 case CFX_CSSValue::PrimitiveType::kRGB:
342 if (dwType & CFX_CSSVALUETYPE_MaybeColor) {
343 FX_ARGB color =
344 ParseCSSColor(maybe_next.value().string_view).value_or(0);
345 list.push_back(pdfium::MakeRetain<CFX_CSSColorValue>(color));
346 }
347 break;
348 default:
349 break;
350 }
351 }
352 if (list.empty()) {
353 return;
354 }
355 switch (pProperty->eName) {
356 case CFX_CSSProperty::BorderWidth:
357 Add4ValuesProperty(list, bImportant, CFX_CSSProperty::BorderLeftWidth,
358 CFX_CSSProperty::BorderTopWidth,
359 CFX_CSSProperty::BorderRightWidth,
360 CFX_CSSProperty::BorderBottomWidth);
361 return;
362 case CFX_CSSProperty::Margin:
363 Add4ValuesProperty(list, bImportant, CFX_CSSProperty::MarginLeft,
364 CFX_CSSProperty::MarginTop,
365 CFX_CSSProperty::MarginRight,
366 CFX_CSSProperty::MarginBottom);
367 return;
368 case CFX_CSSProperty::Padding:
369 Add4ValuesProperty(list, bImportant, CFX_CSSProperty::PaddingLeft,
370 CFX_CSSProperty::PaddingTop,
371 CFX_CSSProperty::PaddingRight,
372 CFX_CSSProperty::PaddingBottom);
373 return;
374 default: {
375 auto value_list = pdfium::MakeRetain<CFX_CSSValueList>(std::move(list));
376 AddPropertyHolder(pProperty->eName, std::move(value_list), bImportant);
377 return;
378 }
379 }
380 }
381
Add4ValuesProperty(const std::vector<RetainPtr<CFX_CSSValue>> & list,bool bImportant,CFX_CSSProperty eLeft,CFX_CSSProperty eTop,CFX_CSSProperty eRight,CFX_CSSProperty eBottom)382 void CFX_CSSDeclaration::Add4ValuesProperty(
383 const std::vector<RetainPtr<CFX_CSSValue>>& list,
384 bool bImportant,
385 CFX_CSSProperty eLeft,
386 CFX_CSSProperty eTop,
387 CFX_CSSProperty eRight,
388 CFX_CSSProperty eBottom) {
389 switch (list.size()) {
390 case 1:
391 AddPropertyHolder(eLeft, list[0], bImportant);
392 AddPropertyHolder(eTop, list[0], bImportant);
393 AddPropertyHolder(eRight, list[0], bImportant);
394 AddPropertyHolder(eBottom, list[0], bImportant);
395 return;
396 case 2:
397 AddPropertyHolder(eLeft, list[1], bImportant);
398 AddPropertyHolder(eTop, list[0], bImportant);
399 AddPropertyHolder(eRight, list[1], bImportant);
400 AddPropertyHolder(eBottom, list[0], bImportant);
401 return;
402 case 3:
403 AddPropertyHolder(eLeft, list[1], bImportant);
404 AddPropertyHolder(eTop, list[0], bImportant);
405 AddPropertyHolder(eRight, list[1], bImportant);
406 AddPropertyHolder(eBottom, list[2], bImportant);
407 return;
408 case 4:
409 AddPropertyHolder(eLeft, list[3], bImportant);
410 AddPropertyHolder(eTop, list[0], bImportant);
411 AddPropertyHolder(eRight, list[1], bImportant);
412 AddPropertyHolder(eBottom, list[2], bImportant);
413 return;
414 default:
415 break;
416 }
417 }
418
ParseBorderProperty(WideStringView value) const419 RetainPtr<CFX_CSSValue> CFX_CSSDeclaration::ParseBorderProperty(
420 WideStringView value) const {
421 RetainPtr<CFX_CSSValue> pWidth;
422 CFX_CSSValueListParser parser(value, ' ');
423 while (1) {
424 auto maybe_next = parser.NextValue();
425 if (!maybe_next.has_value()) {
426 break;
427 }
428 switch (maybe_next.value().type) {
429 case CFX_CSSValue::PrimitiveType::kNumber: {
430 if (pWidth) {
431 continue;
432 }
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());
436 }
437 break;
438 }
439 case CFX_CSSValue::PrimitiveType::kString: {
440 const CFX_CSSData::Color* pColorItem =
441 CFX_CSSData::GetColorByName(maybe_next.value().string_view);
442 if (pColorItem) {
443 continue;
444 }
445 const CFX_CSSData::PropertyValue* pValue =
446 CFX_CSSData::GetPropertyValueByName(maybe_next.value().string_view);
447 if (!pValue) {
448 continue;
449 }
450 switch (pValue->eName) {
451 case CFX_CSSPropertyValue::Thin:
452 case CFX_CSSPropertyValue::Thick:
453 case CFX_CSSPropertyValue::Medium:
454 if (!pWidth)
455 pWidth = pdfium::MakeRetain<CFX_CSSEnumValue>(pValue->eName);
456 break;
457 default:
458 break;
459 }
460 break;
461 }
462 default:
463 break;
464 }
465 }
466 if (pWidth) {
467 return pWidth;
468 }
469 return pdfium::MakeRetain<CFX_CSSNumberValue>(
470 CFX_CSSNumber{CFX_CSSNumber::Unit::kNumber, 0.0f});
471 }
472
ParseFontProperty(WideStringView value,bool bImportant)473 void CFX_CSSDeclaration::ParseFontProperty(WideStringView value,
474 bool bImportant) {
475 RetainPtr<CFX_CSSValue> pStyle;
476 RetainPtr<CFX_CSSValue> pVariant;
477 RetainPtr<CFX_CSSValue> pWeight;
478 RetainPtr<CFX_CSSValue> pFontSize;
479 RetainPtr<CFX_CSSValue> pLineHeight;
480 std::vector<RetainPtr<CFX_CSSValue>> family_list;
481 CFX_CSSValueListParser parser(value, '/');
482 while (1) {
483 auto maybe_next = parser.NextValue();
484 if (!maybe_next.has_value()) {
485 break;
486 }
487 switch (maybe_next.value().type) {
488 case CFX_CSSValue::PrimitiveType::kString: {
489 const CFX_CSSData::PropertyValue* pValue =
490 CFX_CSSData::GetPropertyValueByName(maybe_next.value().string_view);
491 if (pValue) {
492 switch (pValue->eName) {
493 case CFX_CSSPropertyValue::XxSmall:
494 case CFX_CSSPropertyValue::XSmall:
495 case CFX_CSSPropertyValue::Small:
496 case CFX_CSSPropertyValue::Medium:
497 case CFX_CSSPropertyValue::Large:
498 case CFX_CSSPropertyValue::XLarge:
499 case CFX_CSSPropertyValue::XxLarge:
500 case CFX_CSSPropertyValue::Smaller:
501 case CFX_CSSPropertyValue::Larger:
502 if (!pFontSize)
503 pFontSize = pdfium::MakeRetain<CFX_CSSEnumValue>(pValue->eName);
504 continue;
505 case CFX_CSSPropertyValue::Bold:
506 case CFX_CSSPropertyValue::Bolder:
507 case CFX_CSSPropertyValue::Lighter:
508 if (!pWeight)
509 pWeight = pdfium::MakeRetain<CFX_CSSEnumValue>(pValue->eName);
510 continue;
511 case CFX_CSSPropertyValue::Italic:
512 case CFX_CSSPropertyValue::Oblique:
513 if (!pStyle)
514 pStyle = pdfium::MakeRetain<CFX_CSSEnumValue>(pValue->eName);
515 continue;
516 case CFX_CSSPropertyValue::SmallCaps:
517 if (!pVariant)
518 pVariant = pdfium::MakeRetain<CFX_CSSEnumValue>(pValue->eName);
519 continue;
520 case CFX_CSSPropertyValue::Normal:
521 if (!pStyle)
522 pStyle = pdfium::MakeRetain<CFX_CSSEnumValue>(pValue->eName);
523 else if (!pVariant)
524 pVariant = pdfium::MakeRetain<CFX_CSSEnumValue>(pValue->eName);
525 else if (!pWeight)
526 pWeight = pdfium::MakeRetain<CFX_CSSEnumValue>(pValue->eName);
527 else if (!pFontSize)
528 pFontSize = pdfium::MakeRetain<CFX_CSSEnumValue>(pValue->eName);
529 else if (!pLineHeight)
530 pLineHeight =
531 pdfium::MakeRetain<CFX_CSSEnumValue>(pValue->eName);
532 continue;
533 default:
534 break;
535 }
536 }
537 if (pFontSize) {
538 family_list.push_back(pdfium::MakeRetain<CFX_CSSStringValue>(
539 maybe_next.value().string_view));
540 }
541 parser.UseCommaSeparator();
542 break;
543 }
544 case CFX_CSSValue::PrimitiveType::kNumber: {
545 auto maybe_number = ParseCSSNumber(maybe_next.value().string_view);
546 if (!maybe_number.has_value()) {
547 break;
548 }
549 if (maybe_number.value().unit == CFX_CSSNumber::Unit::kNumber) {
550 switch (static_cast<int32_t>(maybe_number.value().value)) {
551 case 100:
552 case 200:
553 case 300:
554 case 400:
555 case 500:
556 case 600:
557 case 700:
558 case 800:
559 case 900:
560 if (!pWeight) {
561 pWeight = pdfium::MakeRetain<CFX_CSSNumberValue>(
562 maybe_number.value());
563 }
564 continue;
565 }
566 }
567 if (!pFontSize) {
568 pFontSize =
569 pdfium::MakeRetain<CFX_CSSNumberValue>(maybe_number.value());
570 } else if (!pLineHeight) {
571 pLineHeight =
572 pdfium::MakeRetain<CFX_CSSNumberValue>(maybe_number.value());
573 }
574 break;
575 }
576 default:
577 break;
578 }
579 }
580
581 if (!pStyle) {
582 pStyle = pdfium::MakeRetain<CFX_CSSEnumValue>(CFX_CSSPropertyValue::Normal);
583 }
584 if (!pVariant) {
585 pVariant =
586 pdfium::MakeRetain<CFX_CSSEnumValue>(CFX_CSSPropertyValue::Normal);
587 }
588 if (!pWeight) {
589 pWeight =
590 pdfium::MakeRetain<CFX_CSSEnumValue>(CFX_CSSPropertyValue::Normal);
591 }
592 if (!pFontSize) {
593 pFontSize =
594 pdfium::MakeRetain<CFX_CSSEnumValue>(CFX_CSSPropertyValue::Medium);
595 }
596 if (!pLineHeight) {
597 pLineHeight =
598 pdfium::MakeRetain<CFX_CSSEnumValue>(CFX_CSSPropertyValue::Normal);
599 }
600
601 AddPropertyHolder(CFX_CSSProperty::FontStyle, pStyle, bImportant);
602 AddPropertyHolder(CFX_CSSProperty::FontVariant, pVariant, bImportant);
603 AddPropertyHolder(CFX_CSSProperty::FontWeight, pWeight, bImportant);
604 AddPropertyHolder(CFX_CSSProperty::FontSize, pFontSize, bImportant);
605 AddPropertyHolder(CFX_CSSProperty::LineHeight, pLineHeight, bImportant);
606 if (!family_list.empty()) {
607 auto value_list =
608 pdfium::MakeRetain<CFX_CSSValueList>(std::move(family_list));
609 AddPropertyHolder(CFX_CSSProperty::FontFamily, value_list, bImportant);
610 }
611 }
612
PropertyCountForTesting() const613 size_t CFX_CSSDeclaration::PropertyCountForTesting() const {
614 return properties_.size();
615 }
616