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