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