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/src/foxitlib.h"
8 #include "fde_cssdeclaration.h"
GetProperty(FDE_CSSPROPERTY eProperty,FX_BOOL & bImportant) const9 IFDE_CSSValue* CFDE_CSSDeclaration::GetProperty(FDE_CSSPROPERTY eProperty,
10                                                 FX_BOOL& bImportant) const {
11   for (FDE_LPCSSPROPERTYHOLDER pHolder = m_pFirstProperty; pHolder;
12        pHolder = pHolder->pNext) {
13     if (pHolder->eProperty == eProperty) {
14       bImportant = pHolder->bImportant;
15       return pHolder->pValue;
16     }
17   }
18   return NULL;
19 }
GetStartPosition() const20 FX_POSITION CFDE_CSSDeclaration::GetStartPosition() const {
21   return (FX_POSITION)m_pFirstProperty;
22 }
GetNextProperty(FX_POSITION & pos,FDE_CSSPROPERTY & eProperty,IFDE_CSSValue * & pValue,FX_BOOL & bImportant) const23 void CFDE_CSSDeclaration::GetNextProperty(FX_POSITION& pos,
24                                           FDE_CSSPROPERTY& eProperty,
25                                           IFDE_CSSValue*& pValue,
26                                           FX_BOOL& bImportant) const {
27   FDE_LPCSSPROPERTYHOLDER pHolder = (FDE_LPCSSPROPERTYHOLDER)pos;
28   FXSYS_assert(pHolder != NULL);
29   bImportant = pHolder->bImportant;
30   eProperty = (FDE_CSSPROPERTY)pHolder->eProperty;
31   pValue = pHolder->pValue;
32   pos = (FX_POSITION)pHolder->pNext;
33 }
GetStartCustom() const34 FX_POSITION CFDE_CSSDeclaration::GetStartCustom() const {
35   return (FX_POSITION)m_pFirstCustom;
36 }
GetNextCustom(FX_POSITION & pos,CFX_WideString & wsName,CFX_WideString & wsValue) const37 void CFDE_CSSDeclaration::GetNextCustom(FX_POSITION& pos,
38                                         CFX_WideString& wsName,
39                                         CFX_WideString& wsValue) const {
40   FDE_LPCSSCUSTOMPROPERTY pProperty = (FDE_LPCSSCUSTOMPROPERTY)pos;
41   if (pProperty == NULL) {
42     return;
43   }
44   wsName = pProperty->pwsName;
45   wsValue = pProperty->pwsValue;
46   pos = (FX_POSITION)pProperty->pNext;
47 }
CopyToLocal(FDE_LPCCSSPROPERTYARGS pArgs,const FX_WCHAR * pszValue,int32_t iValueLen)48 const FX_WCHAR* CFDE_CSSDeclaration::CopyToLocal(FDE_LPCCSSPROPERTYARGS pArgs,
49                                                  const FX_WCHAR* pszValue,
50                                                  int32_t iValueLen) {
51   FXSYS_assert(iValueLen > 0);
52   CFX_MapPtrToPtr* pCache = pArgs->pStringCache;
53   void* pKey = NULL;
54   if (pCache) {
55     void* pszCached = NULL;
56     pKey =
57         (void*)(uintptr_t)FX_HashCode_String_GetW(pszValue, iValueLen, FALSE);
58     if (pCache->Lookup(pKey, pszCached)) {
59       return (const FX_WCHAR*)pszCached;
60     }
61   }
62   FX_WCHAR* psz =
63       (FX_WCHAR*)pArgs->pStaticStore->Alloc((iValueLen + 1) * sizeof(FX_WCHAR));
64   if (psz == NULL) {
65     return NULL;
66   }
67   FXSYS_wcsncpy(psz, pszValue, iValueLen);
68   psz[iValueLen] = '\0';
69   if (pCache) {
70     pCache->SetAt(pKey, psz);
71   }
72   return psz;
73 }
NewNumberValue(IFX_MEMAllocator * pStaticStore,FDE_CSSPRIMITIVETYPE eUnit,FX_FLOAT fValue) const74 IFDE_CSSPrimitiveValue* CFDE_CSSDeclaration::NewNumberValue(
75     IFX_MEMAllocator* pStaticStore,
76     FDE_CSSPRIMITIVETYPE eUnit,
77     FX_FLOAT fValue) const {
78   static CFDE_CSSPrimitiveValue s_ZeroValue(FDE_CSSPRIMITIVETYPE_Number, 0.0f);
79   if (eUnit == FDE_CSSPRIMITIVETYPE_Number && FXSYS_fabs(fValue) < 0.001f) {
80     return &s_ZeroValue;
81   }
82   return FDE_NewWith(pStaticStore) CFDE_CSSPrimitiveValue(eUnit, fValue);
83 }
NewEnumValue(IFX_MEMAllocator * pStaticStore,FDE_CSSPROPERTYVALUE eValue) const84 inline IFDE_CSSPrimitiveValue* CFDE_CSSDeclaration::NewEnumValue(
85     IFX_MEMAllocator* pStaticStore,
86     FDE_CSSPROPERTYVALUE eValue) const {
87   return FDE_NewWith(pStaticStore) CFDE_CSSPrimitiveValue(eValue);
88 }
AddPropertyHolder(IFX_MEMAllocator * pStaticStore,FDE_CSSPROPERTY eProperty,IFDE_CSSValue * pValue,FX_BOOL bImportant)89 void CFDE_CSSDeclaration::AddPropertyHolder(IFX_MEMAllocator* pStaticStore,
90                                             FDE_CSSPROPERTY eProperty,
91                                             IFDE_CSSValue* pValue,
92                                             FX_BOOL bImportant) {
93   FDE_LPCSSPROPERTYHOLDER pHolder =
94       FDE_NewWith(pStaticStore) FDE_CSSPROPERTYHOLDER;
95   pHolder->bImportant = bImportant;
96   pHolder->eProperty = eProperty;
97   pHolder->pValue = pValue;
98   pHolder->pNext = NULL;
99   if (m_pLastProperty == NULL) {
100     m_pLastProperty = m_pFirstProperty = pHolder;
101   } else {
102     m_pLastProperty->pNext = pHolder;
103     m_pLastProperty = pHolder;
104   }
105 }
AddProperty(FDE_LPCCSSPROPERTYARGS pArgs,const FX_WCHAR * pszValue,int32_t iValueLen)106 FX_BOOL CFDE_CSSDeclaration::AddProperty(FDE_LPCCSSPROPERTYARGS pArgs,
107                                          const FX_WCHAR* pszValue,
108                                          int32_t iValueLen) {
109   FXSYS_assert(iValueLen > 0);
110   FX_BOOL bImportant = FALSE;
111   if (iValueLen >= 10 && pszValue[iValueLen - 10] == '!' &&
112       FX_wcsnicmp(L"important", pszValue + iValueLen - 9, 9) == 0) {
113     if ((iValueLen -= 10) == 0) {
114       return FALSE;
115     }
116     bImportant = TRUE;
117   }
118   const FX_DWORD dwType = pArgs->pProperty->dwType;
119   switch (dwType & 0x0F) {
120     case FDE_CSSVALUETYPE_Primitive: {
121       static const FX_DWORD g_ValueGuessOrder[] = {
122           FDE_CSSVALUETYPE_MaybeNumber,   FDE_CSSVALUETYPE_MaybeEnum,
123           FDE_CSSVALUETYPE_MaybeColor,    FDE_CSSVALUETYPE_MaybeURI,
124           FDE_CSSVALUETYPE_MaybeFunction, FDE_CSSVALUETYPE_MaybeString,
125       };
126       static const int32_t g_ValueGuessCount =
127           sizeof(g_ValueGuessOrder) / sizeof(FX_DWORD);
128       for (int32_t i = 0; i < g_ValueGuessCount; ++i) {
129         const FX_DWORD dwMatch = dwType & g_ValueGuessOrder[i];
130         if (dwMatch == 0) {
131           continue;
132         }
133         IFDE_CSSValue* pCSSValue = NULL;
134         switch (dwMatch) {
135           case FDE_CSSVALUETYPE_MaybeFunction:
136             pCSSValue = ParseFunction(pArgs, pszValue, iValueLen);
137             break;
138           case FDE_CSSVALUETYPE_MaybeNumber:
139             pCSSValue = ParseNumber(pArgs, pszValue, iValueLen);
140             break;
141           case FDE_CSSVALUETYPE_MaybeEnum:
142             pCSSValue = ParseEnum(pArgs, pszValue, iValueLen);
143             break;
144           case FDE_CSSVALUETYPE_MaybeColor:
145             pCSSValue = ParseColor(pArgs, pszValue, iValueLen);
146             break;
147           case FDE_CSSVALUETYPE_MaybeURI:
148             pCSSValue = ParseURI(pArgs, pszValue, iValueLen);
149             break;
150           case FDE_CSSVALUETYPE_MaybeString:
151             pCSSValue = ParseString(pArgs, pszValue, iValueLen);
152             break;
153           default:
154             break;
155         }
156         if (pCSSValue != NULL) {
157           AddPropertyHolder(pArgs->pStaticStore, pArgs->pProperty->eName,
158                             pCSSValue, bImportant);
159           return TRUE;
160         }
161         if (FDE_IsOnlyValue(dwType, g_ValueGuessOrder[i])) {
162           return FALSE;
163         }
164       }
165     } break;
166     case FDE_CSSVALUETYPE_Shorthand: {
167       IFX_MEMAllocator* pStaticStore = pArgs->pStaticStore;
168       IFDE_CSSValue *pColor, *pStyle, *pWidth;
169       switch (pArgs->pProperty->eName) {
170         case FDE_CSSPROPERTY_Font:
171           return ParseFontProperty(pArgs, pszValue, iValueLen, bImportant);
172         case FDE_CSSPROPERTY_Background:
173           return ParseBackgroundProperty(pArgs, pszValue, iValueLen,
174                                          bImportant);
175         case FDE_CSSPROPERTY_ListStyle:
176           return ParseListStyleProperty(pArgs, pszValue, iValueLen, bImportant);
177         case FDE_CSSPROPERTY_Border:
178           if (ParseBorderPropoerty(pStaticStore, pszValue, iValueLen, pColor,
179                                    pStyle, pWidth)) {
180             AddBorderProperty(pStaticStore, pColor, pStyle, pWidth, bImportant,
181                               FDE_CSSPROPERTY_BorderLeftColor,
182                               FDE_CSSPROPERTY_BorderLeftStyle,
183                               FDE_CSSPROPERTY_BorderLeftWidth);
184             AddBorderProperty(pStaticStore, pColor, pStyle, pWidth, bImportant,
185                               FDE_CSSPROPERTY_BorderTopColor,
186                               FDE_CSSPROPERTY_BorderTopStyle,
187                               FDE_CSSPROPERTY_BorderTopWidth);
188             AddBorderProperty(pStaticStore, pColor, pStyle, pWidth, bImportant,
189                               FDE_CSSPROPERTY_BorderRightColor,
190                               FDE_CSSPROPERTY_BorderRightStyle,
191                               FDE_CSSPROPERTY_BorderRightWidth);
192             AddBorderProperty(pStaticStore, pColor, pStyle, pWidth, bImportant,
193                               FDE_CSSPROPERTY_BorderBottomColor,
194                               FDE_CSSPROPERTY_BorderBottomStyle,
195                               FDE_CSSPROPERTY_BorderBottomWidth);
196             return TRUE;
197           }
198           break;
199         case FDE_CSSPROPERTY_BorderLeft:
200           if (ParseBorderPropoerty(pStaticStore, pszValue, iValueLen, pColor,
201                                    pStyle, pWidth)) {
202             AddBorderProperty(pStaticStore, pColor, pStyle, pWidth, bImportant,
203                               FDE_CSSPROPERTY_BorderLeftColor,
204                               FDE_CSSPROPERTY_BorderLeftStyle,
205                               FDE_CSSPROPERTY_BorderLeftWidth);
206             return TRUE;
207           }
208           break;
209         case FDE_CSSPROPERTY_BorderTop:
210           if (ParseBorderPropoerty(pStaticStore, pszValue, iValueLen, pColor,
211                                    pStyle, pWidth)) {
212             AddBorderProperty(pStaticStore, pColor, pStyle, pWidth, bImportant,
213                               FDE_CSSPROPERTY_BorderTopColor,
214                               FDE_CSSPROPERTY_BorderTopStyle,
215                               FDE_CSSPROPERTY_BorderTopWidth);
216             return TRUE;
217           }
218           break;
219         case FDE_CSSPROPERTY_BorderRight:
220           if (ParseBorderPropoerty(pStaticStore, pszValue, iValueLen, pColor,
221                                    pStyle, pWidth)) {
222             AddBorderProperty(pStaticStore, pColor, pStyle, pWidth, bImportant,
223                               FDE_CSSPROPERTY_BorderRightColor,
224                               FDE_CSSPROPERTY_BorderRightStyle,
225                               FDE_CSSPROPERTY_BorderRightWidth);
226             return TRUE;
227           }
228           break;
229         case FDE_CSSPROPERTY_BorderBottom:
230           if (ParseBorderPropoerty(pStaticStore, pszValue, iValueLen, pColor,
231                                    pStyle, pWidth)) {
232             AddBorderProperty(pStaticStore, pColor, pStyle, pWidth, bImportant,
233                               FDE_CSSPROPERTY_BorderBottomColor,
234                               FDE_CSSPROPERTY_BorderBottomStyle,
235                               FDE_CSSPROPERTY_BorderBottomWidth);
236             return TRUE;
237           }
238           break;
239         case FDE_CSSPROPERTY_Overflow:
240           return ParseOverflowProperty(pArgs, pszValue, iValueLen, bImportant);
241         case FDE_CSSPROPERTY_ColumnRule:
242           return ParseColumnRuleProperty(pArgs, pszValue, iValueLen,
243                                          bImportant);
244         default:
245           break;
246       }
247     } break;
248     case FDE_CSSVALUETYPE_List:
249       switch (pArgs->pProperty->eName) {
250         case FDE_CSSPROPERTY_CounterIncrement:
251         case FDE_CSSPROPERTY_CounterReset:
252           return ParseCounterProperty(pArgs, pszValue, iValueLen, bImportant);
253         case FDE_CSSPROPERTY_Content:
254           return ParseContentProperty(pArgs, pszValue, iValueLen, bImportant);
255         default:
256           return ParseValueListProperty(pArgs, pszValue, iValueLen, bImportant);
257       }
258     default:
259       FXSYS_assert(FALSE);
260       break;
261   }
262   return FALSE;
263 }
AddProperty(FDE_LPCCSSPROPERTYARGS pArgs,const FX_WCHAR * pszName,int32_t iNameLen,const FX_WCHAR * pszValue,int32_t iValueLen)264 FX_BOOL CFDE_CSSDeclaration::AddProperty(FDE_LPCCSSPROPERTYARGS pArgs,
265                                          const FX_WCHAR* pszName,
266                                          int32_t iNameLen,
267                                          const FX_WCHAR* pszValue,
268                                          int32_t iValueLen) {
269   FDE_LPCSSCUSTOMPROPERTY pProperty =
270       FDE_NewWith(pArgs->pStaticStore) FDE_CSSCUSTOMPROPERTY;
271   pProperty->pwsName = CopyToLocal(pArgs, pszName, iNameLen);
272   pProperty->pwsValue = CopyToLocal(pArgs, pszValue, iValueLen);
273   pProperty->pNext = NULL;
274   if (m_pLastCustom == NULL) {
275     m_pLastCustom = m_pFirstCustom = pProperty;
276   } else {
277     m_pLastCustom->pNext = pProperty;
278     m_pLastCustom = pProperty;
279   }
280   return TRUE;
281 }
ParseNumber(FDE_LPCCSSPROPERTYARGS pArgs,const FX_WCHAR * pszValue,int32_t iValueLen)282 IFDE_CSSValue* CFDE_CSSDeclaration::ParseNumber(FDE_LPCCSSPROPERTYARGS pArgs,
283                                                 const FX_WCHAR* pszValue,
284                                                 int32_t iValueLen) {
285   FX_FLOAT fValue;
286   FDE_CSSPRIMITIVETYPE eUnit;
287   if (!FDE_ParseCSSNumber(pszValue, iValueLen, fValue, eUnit)) {
288     return NULL;
289   }
290   return NewNumberValue(pArgs->pStaticStore, eUnit, fValue);
291 }
ParseEnum(FDE_LPCCSSPROPERTYARGS pArgs,const FX_WCHAR * pszValue,int32_t iValueLen)292 IFDE_CSSValue* CFDE_CSSDeclaration::ParseEnum(FDE_LPCCSSPROPERTYARGS pArgs,
293                                               const FX_WCHAR* pszValue,
294                                               int32_t iValueLen) {
295   FDE_LPCCSSPROPERTYVALUETABLE pValue =
296       FDE_GetCSSPropertyValueByName(pszValue, iValueLen);
297   return pValue ? NewEnumValue(pArgs->pStaticStore, pValue->eName) : NULL;
298 }
ParseColor(FDE_LPCCSSPROPERTYARGS pArgs,const FX_WCHAR * pszValue,int32_t iValueLen)299 IFDE_CSSValue* CFDE_CSSDeclaration::ParseColor(FDE_LPCCSSPROPERTYARGS pArgs,
300                                                const FX_WCHAR* pszValue,
301                                                int32_t iValueLen) {
302   FX_ARGB dwColor;
303   if (!FDE_ParseCSSColor(pszValue, iValueLen, dwColor)) {
304     return NULL;
305   }
306   return FDE_NewWith(pArgs->pStaticStore) CFDE_CSSPrimitiveValue(dwColor);
307 }
ParseURI(FDE_LPCCSSPROPERTYARGS pArgs,const FX_WCHAR * pszValue,int32_t iValueLen)308 IFDE_CSSValue* CFDE_CSSDeclaration::ParseURI(FDE_LPCCSSPROPERTYARGS pArgs,
309                                              const FX_WCHAR* pszValue,
310                                              int32_t iValueLen) {
311   int32_t iOffset;
312   if (!FDE_ParseCSSURI(pszValue, iValueLen, iOffset, iValueLen)) {
313     return NULL;
314   }
315   if (iValueLen <= 0) {
316     return NULL;
317   }
318   pszValue = CopyToLocal(pArgs, pszValue + iOffset, iValueLen);
319   return pszValue
320              ? FDE_NewWith(pArgs->pStaticStore)
321                    CFDE_CSSPrimitiveValue(FDE_CSSPRIMITIVETYPE_URI, pszValue)
322              : NULL;
323 }
ParseString(FDE_LPCCSSPROPERTYARGS pArgs,const FX_WCHAR * pszValue,int32_t iValueLen)324 IFDE_CSSValue* CFDE_CSSDeclaration::ParseString(FDE_LPCCSSPROPERTYARGS pArgs,
325                                                 const FX_WCHAR* pszValue,
326                                                 int32_t iValueLen) {
327   int32_t iOffset;
328   if (!FDE_ParseCSSString(pszValue, iValueLen, iOffset, iValueLen)) {
329     return NULL;
330   }
331   if (iValueLen <= 0) {
332     return NULL;
333   }
334   pszValue = CopyToLocal(pArgs, pszValue + iOffset, iValueLen);
335   return pszValue
336              ? FDE_NewWith(pArgs->pStaticStore)
337                    CFDE_CSSPrimitiveValue(FDE_CSSPRIMITIVETYPE_String, pszValue)
338              : NULL;
339 }
ParseFunction(FDE_LPCCSSPROPERTYARGS pArgs,const FX_WCHAR * pszValue,int32_t iValueLen)340 IFDE_CSSValue* CFDE_CSSDeclaration::ParseFunction(FDE_LPCCSSPROPERTYARGS pArgs,
341                                                   const FX_WCHAR* pszValue,
342                                                   int32_t iValueLen) {
343   if (pszValue[iValueLen - 1] != ')') {
344     return NULL;
345   }
346   int32_t iStartBracket = 0;
347   while (pszValue[iStartBracket] != '(') {
348     if (iStartBracket < iValueLen) {
349       iStartBracket++;
350     } else {
351       return NULL;
352     }
353   }
354   if (iStartBracket == 0) {
355     return NULL;
356   }
357   const FX_WCHAR* pszFuncName = CopyToLocal(pArgs, pszValue, iStartBracket);
358   pszValue += (iStartBracket + 1);
359   iValueLen -= (iStartBracket + 2);
360   CFDE_CSSValueArray argumentArr;
361   CFDE_CSSValueListParser parser(pszValue, iValueLen, ',');
362   FDE_CSSPRIMITIVETYPE ePrimitiveType;
363   while (parser.NextValue(ePrimitiveType, pszValue, iValueLen)) {
364     switch (ePrimitiveType) {
365       case FDE_CSSPRIMITIVETYPE_String: {
366         FDE_LPCCSSPROPERTYVALUETABLE pPropertyValue =
367             FDE_GetCSSPropertyValueByName(pszValue, iValueLen);
368         if (pPropertyValue != NULL) {
369           argumentArr.Add(
370               NewEnumValue(pArgs->pStaticStore, pPropertyValue->eName));
371           continue;
372         }
373         IFDE_CSSValue* pFunctionValue =
374             ParseFunction(pArgs, pszValue, iValueLen);
375         if (pFunctionValue != NULL) {
376           argumentArr.Add(pFunctionValue);
377           continue;
378         }
379         argumentArr.Add(FDE_NewWith(pArgs->pStaticStore) CFDE_CSSPrimitiveValue(
380             FDE_CSSPRIMITIVETYPE_String,
381             CopyToLocal(pArgs, pszValue, iValueLen)));
382       } break;
383       case FDE_CSSPRIMITIVETYPE_Number: {
384         FX_FLOAT fValue;
385         if (FDE_ParseCSSNumber(pszValue, iValueLen, fValue, ePrimitiveType)) {
386           argumentArr.Add(
387               NewNumberValue(pArgs->pStaticStore, ePrimitiveType, fValue));
388         }
389       } break;
390       default:
391         argumentArr.Add(FDE_NewWith(pArgs->pStaticStore) CFDE_CSSPrimitiveValue(
392             FDE_CSSPRIMITIVETYPE_String,
393             CopyToLocal(pArgs, pszValue, iValueLen)));
394         break;
395     }
396   }
397   IFDE_CSSValueList* pArgumentList = FDE_NewWith(pArgs->pStaticStore)
398       CFDE_CSSValueList(pArgs->pStaticStore, argumentArr);
399   CFDE_CSSFunction* pFunction = FDE_NewWith(pArgs->pStaticStore)
400       CFDE_CSSFunction(pszFuncName, pArgumentList);
401   return FDE_NewWith(pArgs->pStaticStore) CFDE_CSSPrimitiveValue(pFunction);
402 }
ParseContentProperty(FDE_LPCCSSPROPERTYARGS pArgs,const FX_WCHAR * pszValue,int32_t iValueLen,FX_BOOL bImportant)403 FX_BOOL CFDE_CSSDeclaration::ParseContentProperty(FDE_LPCCSSPROPERTYARGS pArgs,
404                                                   const FX_WCHAR* pszValue,
405                                                   int32_t iValueLen,
406                                                   FX_BOOL bImportant) {
407   IFX_MEMAllocator* pStaticStore = (IFX_MEMAllocator*)pArgs->pStaticStore;
408   CFDE_CSSValueListParser parser(pszValue, iValueLen, ' ');
409   FDE_CSSPRIMITIVETYPE eType;
410   CFDE_CSSValueArray list;
411   while (parser.NextValue(eType, pszValue, iValueLen)) {
412     switch (eType) {
413       case FDE_CSSPRIMITIVETYPE_URI:
414         list.Add(FDE_NewWith(pStaticStore) CFDE_CSSPrimitiveValue(
415             eType, CopyToLocal(pArgs, pszValue, iValueLen)));
416         break;
417       case FDE_CSSPRIMITIVETYPE_Number:
418         return FALSE;
419       case FDE_CSSPRIMITIVETYPE_String: {
420         FDE_LPCCSSPROPERTYVALUETABLE pValue =
421             FDE_GetCSSPropertyValueByName(pszValue, iValueLen);
422         if (pValue != NULL) {
423           switch (pValue->eName) {
424             case FDE_CSSPROPERTYVALUE_Normal:
425             case FDE_CSSPROPERTYVALUE_None: {
426               if (list.GetSize() == 0) {
427                 list.Add(NewEnumValue(pStaticStore, pValue->eName));
428               } else {
429                 return FALSE;
430               }
431             } break;
432             case FDE_CSSPROPERTYVALUE_OpenQuote:
433             case FDE_CSSPROPERTYVALUE_CloseQuote:
434             case FDE_CSSPROPERTYVALUE_NoOpenQuote:
435             case FDE_CSSPROPERTYVALUE_NoCloseQuote:
436               list.Add(NewEnumValue(pStaticStore, pValue->eName));
437               break;
438             default:
439               return FALSE;
440           }
441           continue;
442         }
443         IFDE_CSSValue* pFunction = ParseFunction(pArgs, pszValue, iValueLen);
444         if (pFunction != NULL) {
445           list.Add(pFunction);
446           continue;
447         }
448         list.Add(FDE_NewWith(pStaticStore) CFDE_CSSPrimitiveValue(
449             eType, CopyToLocal(pArgs, pszValue, iValueLen)));
450       } break;
451       case FDE_CSSPRIMITIVETYPE_RGB:
452         return FALSE;
453       default:
454         break;
455     }
456   }
457   if (list.GetSize() == 0) {
458     return FALSE;
459   }
460   AddPropertyHolder(pStaticStore, pArgs->pProperty->eName,
461                     FDE_NewWith(pStaticStore)
462                         CFDE_CSSValueList(pStaticStore, list),
463                     bImportant);
464   return TRUE;
465 }
ParseCounterProperty(FDE_LPCCSSPROPERTYARGS pArgs,const FX_WCHAR * pszValue,int32_t iValueLen,FX_BOOL bImportant)466 FX_BOOL CFDE_CSSDeclaration::ParseCounterProperty(FDE_LPCCSSPROPERTYARGS pArgs,
467                                                   const FX_WCHAR* pszValue,
468                                                   int32_t iValueLen,
469                                                   FX_BOOL bImportant) {
470   IFX_MEMAllocator* pStaticStore = pArgs->pStaticStore;
471   CFDE_CSSValueListParser parser(pszValue, iValueLen, ' ');
472   CFDE_CSSValueArray list;
473   CFDE_CSSValueArray listFull;
474   FDE_CSSPRIMITIVETYPE eType;
475   while (parser.NextValue(eType, pszValue, iValueLen)) {
476     switch (eType) {
477       case FDE_CSSPRIMITIVETYPE_Number: {
478         FX_FLOAT fValue;
479         if (FDE_ParseCSSNumber(pszValue, iValueLen, fValue, eType)) {
480           if (list.GetSize() == 1) {
481             list.Add(NewNumberValue(pStaticStore, eType, fValue));
482             listFull.Add(FDE_NewWith(pStaticStore)
483                              CFDE_CSSValueList(pStaticStore, list));
484             list.RemoveAll();
485           } else {
486             return FALSE;
487           }
488         }
489       } break;
490       case FDE_CSSPRIMITIVETYPE_String: {
491         if (list.GetSize() == 0) {
492           pszValue = CopyToLocal(pArgs, pszValue, iValueLen);
493           list.Add(FDE_NewWith(pStaticStore) CFDE_CSSPrimitiveValue(
494               FDE_CSSPRIMITIVETYPE_String, pszValue));
495         } else {
496           listFull.Add(FDE_NewWith(pStaticStore)
497                            CFDE_CSSValueList(pStaticStore, list));
498           list.RemoveAll();
499           pszValue = CopyToLocal(pArgs, pszValue, iValueLen);
500           list.Add(FDE_NewWith(pStaticStore) CFDE_CSSPrimitiveValue(
501               FDE_CSSPRIMITIVETYPE_String, pszValue));
502         }
503       } break;
504       default:
505         break;
506     }
507   }
508   if (list.GetSize() == 1) {
509     listFull.Add(FDE_NewWith(pStaticStore)
510                      CFDE_CSSValueList(pStaticStore, list));
511   }
512   if (listFull.GetSize() == 0) {
513     return FALSE;
514   }
515   AddPropertyHolder(pStaticStore, pArgs->pProperty->eName,
516                     FDE_NewWith(pStaticStore)
517                         CFDE_CSSValueList(pStaticStore, listFull),
518                     bImportant);
519   return TRUE;
520 }
ParseValueListProperty(FDE_LPCCSSPROPERTYARGS pArgs,const FX_WCHAR * pszValue,int32_t iValueLen,FX_BOOL bImportant)521 FX_BOOL CFDE_CSSDeclaration::ParseValueListProperty(
522     FDE_LPCCSSPROPERTYARGS pArgs,
523     const FX_WCHAR* pszValue,
524     int32_t iValueLen,
525     FX_BOOL bImportant) {
526   IFX_MEMAllocator* pStaticStore = pArgs->pStaticStore;
527   FX_WCHAR separator =
528       (pArgs->pProperty->eName == FDE_CSSPROPERTY_FontFamily) ? ',' : ' ';
529   CFDE_CSSValueListParser parser(pszValue, iValueLen, separator);
530   const FX_DWORD dwType = pArgs->pProperty->dwType;
531   FDE_CSSPRIMITIVETYPE eType;
532   CFDE_CSSValueArray list;
533   while (parser.NextValue(eType, pszValue, iValueLen)) {
534     switch (eType) {
535       case FDE_CSSPRIMITIVETYPE_Number:
536         if (dwType & FDE_CSSVALUETYPE_MaybeNumber) {
537           FX_FLOAT fValue;
538           if (FDE_ParseCSSNumber(pszValue, iValueLen, fValue, eType)) {
539             list.Add(NewNumberValue(pStaticStore, eType, fValue));
540           }
541         }
542         break;
543       case FDE_CSSPRIMITIVETYPE_String:
544         if (dwType & FDE_CSSVALUETYPE_MaybeColor) {
545           FX_ARGB dwColor;
546           if (FDE_ParseCSSColor(pszValue, iValueLen, dwColor)) {
547             list.Add(FDE_NewWith(pStaticStore) CFDE_CSSPrimitiveValue(dwColor));
548             continue;
549           }
550         }
551         if (dwType & FDE_CSSVALUETYPE_MaybeEnum) {
552           FDE_LPCCSSPROPERTYVALUETABLE pValue =
553               FDE_GetCSSPropertyValueByName(pszValue, iValueLen);
554           if (pValue != NULL) {
555             list.Add(NewEnumValue(pStaticStore, pValue->eName));
556             continue;
557           }
558         }
559         if (dwType & FDE_CSSVALUETYPE_MaybeString) {
560           pszValue = CopyToLocal(pArgs, pszValue, iValueLen);
561           list.Add(FDE_NewWith(pStaticStore) CFDE_CSSPrimitiveValue(
562               FDE_CSSPRIMITIVETYPE_String, pszValue));
563         }
564         break;
565       case FDE_CSSPRIMITIVETYPE_RGB:
566         if (dwType & FDE_CSSVALUETYPE_MaybeColor) {
567           FX_ARGB dwColor;
568           if (FDE_ParseCSSColor(pszValue, iValueLen, dwColor)) {
569             list.Add(FDE_NewWith(pStaticStore) CFDE_CSSPrimitiveValue(dwColor));
570           }
571         }
572         break;
573       default:
574         break;
575     }
576   }
577   if (list.GetSize() == 0) {
578     return FALSE;
579   }
580   switch (pArgs->pProperty->eName) {
581     case FDE_CSSPROPERTY_BorderColor:
582       return Add4ValuesProperty(
583           pStaticStore, list, bImportant, FDE_CSSPROPERTY_BorderLeftColor,
584           FDE_CSSPROPERTY_BorderTopColor, FDE_CSSPROPERTY_BorderRightColor,
585           FDE_CSSPROPERTY_BorderBottomColor);
586     case FDE_CSSPROPERTY_BorderStyle:
587       return Add4ValuesProperty(
588           pStaticStore, list, bImportant, FDE_CSSPROPERTY_BorderLeftStyle,
589           FDE_CSSPROPERTY_BorderTopStyle, FDE_CSSPROPERTY_BorderRightStyle,
590           FDE_CSSPROPERTY_BorderBottomStyle);
591     case FDE_CSSPROPERTY_BorderWidth:
592       return Add4ValuesProperty(
593           pStaticStore, list, bImportant, FDE_CSSPROPERTY_BorderLeftWidth,
594           FDE_CSSPROPERTY_BorderTopWidth, FDE_CSSPROPERTY_BorderRightWidth,
595           FDE_CSSPROPERTY_BorderBottomWidth);
596     case FDE_CSSPROPERTY_Margin:
597       return Add4ValuesProperty(
598           pStaticStore, list, bImportant, FDE_CSSPROPERTY_MarginLeft,
599           FDE_CSSPROPERTY_MarginTop, FDE_CSSPROPERTY_MarginRight,
600           FDE_CSSPROPERTY_MarginBottom);
601     case FDE_CSSPROPERTY_Padding:
602       return Add4ValuesProperty(
603           pStaticStore, list, bImportant, FDE_CSSPROPERTY_PaddingLeft,
604           FDE_CSSPROPERTY_PaddingTop, FDE_CSSPROPERTY_PaddingRight,
605           FDE_CSSPROPERTY_PaddingBottom);
606     default: {
607       CFDE_CSSValueList* pList =
608           FDE_NewWith(pStaticStore) CFDE_CSSValueList(pStaticStore, list);
609       AddPropertyHolder(pStaticStore, pArgs->pProperty->eName, pList,
610                         bImportant);
611       return TRUE;
612     } break;
613   }
614   return FALSE;
615 }
Add4ValuesProperty(IFX_MEMAllocator * pStaticStore,const CFDE_CSSValueArray & list,FX_BOOL bImportant,FDE_CSSPROPERTY eLeft,FDE_CSSPROPERTY eTop,FDE_CSSPROPERTY eRight,FDE_CSSPROPERTY eBottom)616 FX_BOOL CFDE_CSSDeclaration::Add4ValuesProperty(IFX_MEMAllocator* pStaticStore,
617                                                 const CFDE_CSSValueArray& list,
618                                                 FX_BOOL bImportant,
619                                                 FDE_CSSPROPERTY eLeft,
620                                                 FDE_CSSPROPERTY eTop,
621                                                 FDE_CSSPROPERTY eRight,
622                                                 FDE_CSSPROPERTY eBottom) {
623   switch (list.GetSize()) {
624     case 1:
625       AddPropertyHolder(pStaticStore, eLeft, list[0], bImportant);
626       AddPropertyHolder(pStaticStore, eTop, list[0], bImportant);
627       AddPropertyHolder(pStaticStore, eRight, list[0], bImportant);
628       AddPropertyHolder(pStaticStore, eBottom, list[0], bImportant);
629       return TRUE;
630     case 2:
631       AddPropertyHolder(pStaticStore, eLeft, list[1], bImportant);
632       AddPropertyHolder(pStaticStore, eTop, list[0], bImportant);
633       AddPropertyHolder(pStaticStore, eRight, list[1], bImportant);
634       AddPropertyHolder(pStaticStore, eBottom, list[0], bImportant);
635       return TRUE;
636     case 3:
637       AddPropertyHolder(pStaticStore, eLeft, list[1], bImportant);
638       AddPropertyHolder(pStaticStore, eTop, list[0], bImportant);
639       AddPropertyHolder(pStaticStore, eRight, list[1], bImportant);
640       AddPropertyHolder(pStaticStore, eBottom, list[2], bImportant);
641       return TRUE;
642     case 4:
643       AddPropertyHolder(pStaticStore, eLeft, list[3], bImportant);
644       AddPropertyHolder(pStaticStore, eTop, list[0], bImportant);
645       AddPropertyHolder(pStaticStore, eRight, list[1], bImportant);
646       AddPropertyHolder(pStaticStore, eBottom, list[2], bImportant);
647       return TRUE;
648     default:
649       break;
650   }
651   return FALSE;
652 }
ParseBorderPropoerty(IFX_MEMAllocator * pStaticStore,const FX_WCHAR * pszValue,int32_t iValueLen,IFDE_CSSValue * & pColor,IFDE_CSSValue * & pStyle,IFDE_CSSValue * & pWidth) const653 FX_BOOL CFDE_CSSDeclaration::ParseBorderPropoerty(
654     IFX_MEMAllocator* pStaticStore,
655     const FX_WCHAR* pszValue,
656     int32_t iValueLen,
657     IFDE_CSSValue*& pColor,
658     IFDE_CSSValue*& pStyle,
659     IFDE_CSSValue*& pWidth) const {
660   pColor = pStyle = pWidth = NULL;
661   CFDE_CSSValueListParser parser(pszValue, iValueLen, ' ');
662   FDE_CSSPRIMITIVETYPE eType;
663   while (parser.NextValue(eType, pszValue, iValueLen)) {
664     switch (eType) {
665       case FDE_CSSPRIMITIVETYPE_Number:
666         if (pWidth == NULL) {
667           FX_FLOAT fValue;
668           if (FDE_ParseCSSNumber(pszValue, iValueLen, fValue, eType)) {
669             pWidth = NewNumberValue(pStaticStore, eType, fValue);
670           }
671         }
672         break;
673       case FDE_CSSPRIMITIVETYPE_RGB:
674         if (pColor == NULL) {
675           FX_ARGB dwColor;
676           if (FDE_ParseCSSColor(pszValue, iValueLen, dwColor)) {
677             pColor = FDE_NewWith(pStaticStore) CFDE_CSSPrimitiveValue(dwColor);
678           }
679         }
680         break;
681       case FDE_CSSPRIMITIVETYPE_String: {
682         FDE_LPCCSSCOLORTABLE pColorItem =
683             FDE_GetCSSColorByName(pszValue, iValueLen);
684         if (pColorItem != NULL) {
685           if (pColor == NULL) {
686             pColor = FDE_NewWith(pStaticStore)
687                 CFDE_CSSPrimitiveValue(pColorItem->dwValue);
688           }
689           continue;
690         }
691         FDE_LPCCSSPROPERTYVALUETABLE pValue =
692             FDE_GetCSSPropertyValueByName(pszValue, iValueLen);
693         if (pValue == NULL) {
694           continue;
695         }
696         switch (pValue->eName) {
697           case FDE_CSSPROPERTYVALUE_Transparent:
698             if (pColor == NULL) {
699               pColor =
700                   FDE_NewWith(pStaticStore) CFDE_CSSPrimitiveValue((FX_ARGB)0);
701             }
702             break;
703           case FDE_CSSPROPERTYVALUE_Thin:
704           case FDE_CSSPROPERTYVALUE_Thick:
705           case FDE_CSSPROPERTYVALUE_Medium:
706             if (pWidth == NULL) {
707               pWidth = NewEnumValue(pStaticStore, pValue->eName);
708             }
709             break;
710           case FDE_CSSPROPERTYVALUE_None:
711           case FDE_CSSPROPERTYVALUE_Hidden:
712           case FDE_CSSPROPERTYVALUE_Dotted:
713           case FDE_CSSPROPERTYVALUE_Dashed:
714           case FDE_CSSPROPERTYVALUE_Solid:
715           case FDE_CSSPROPERTYVALUE_Double:
716           case FDE_CSSPROPERTYVALUE_Groove:
717           case FDE_CSSPROPERTYVALUE_Ridge:
718           case FDE_CSSPROPERTYVALUE_Inset:
719           case FDE_CSSPROPERTYVALUE_Outset:
720             if (pStyle == NULL) {
721               pStyle = NewEnumValue(pStaticStore, pValue->eName);
722             }
723             break;
724           default:
725             break;
726         }
727       }; break;
728       default:
729         break;
730     }
731   }
732   if (pColor == NULL) {
733     pColor = FDE_NewWith(pStaticStore) CFDE_CSSPrimitiveValue((FX_ARGB)0);
734   }
735   if (pStyle == NULL) {
736     pStyle = NewEnumValue(pStaticStore, FDE_CSSPROPERTYVALUE_None);
737   }
738   if (pWidth == NULL) {
739     pWidth = NewNumberValue(pStaticStore, FDE_CSSPRIMITIVETYPE_Number, 0.0f);
740   }
741   return TRUE;
742 }
AddBorderProperty(IFX_MEMAllocator * pStaticStore,IFDE_CSSValue * pColor,IFDE_CSSValue * pStyle,IFDE_CSSValue * pWidth,FX_BOOL bImportant,FDE_CSSPROPERTY eColor,FDE_CSSPROPERTY eStyle,FDE_CSSPROPERTY eWidth)743 void CFDE_CSSDeclaration::AddBorderProperty(IFX_MEMAllocator* pStaticStore,
744                                             IFDE_CSSValue* pColor,
745                                             IFDE_CSSValue* pStyle,
746                                             IFDE_CSSValue* pWidth,
747                                             FX_BOOL bImportant,
748                                             FDE_CSSPROPERTY eColor,
749                                             FDE_CSSPROPERTY eStyle,
750                                             FDE_CSSPROPERTY eWidth) {
751   AddPropertyHolder(pStaticStore, eStyle, pStyle, bImportant);
752   AddPropertyHolder(pStaticStore, eWidth, pWidth, bImportant);
753   AddPropertyHolder(pStaticStore, eColor, pColor, bImportant);
754 }
ParseListStyleProperty(FDE_LPCCSSPROPERTYARGS pArgs,const FX_WCHAR * pszValue,int32_t iValueLen,FX_BOOL bImportant)755 FX_BOOL CFDE_CSSDeclaration::ParseListStyleProperty(
756     FDE_LPCCSSPROPERTYARGS pArgs,
757     const FX_WCHAR* pszValue,
758     int32_t iValueLen,
759     FX_BOOL bImportant) {
760   IFX_MEMAllocator* pStaticStore = pArgs->pStaticStore;
761   CFDE_CSSValueListParser parser(pszValue, iValueLen, ' ');
762   IFDE_CSSPrimitiveValue *pType = NULL, *pImage = NULL, *pPosition = NULL;
763   FDE_CSSPRIMITIVETYPE eType;
764   while (parser.NextValue(eType, pszValue, iValueLen)) {
765     switch (eType) {
766       case FDE_CSSPRIMITIVETYPE_URI:
767         if (pImage == NULL) {
768           pImage = FDE_NewWith(pStaticStore) CFDE_CSSPrimitiveValue(
769               eType, CopyToLocal(pArgs, pszValue, iValueLen));
770         }
771         break;
772       case FDE_CSSPRIMITIVETYPE_String: {
773         FDE_LPCCSSPROPERTYVALUETABLE pValue =
774             FDE_GetCSSPropertyValueByName(pszValue, iValueLen);
775         if (pValue == NULL) {
776           break;
777         }
778         switch (pValue->eName) {
779           case FDE_CSSPROPERTYVALUE_None:
780             if (pImage == NULL) {
781               pImage = NewEnumValue(pStaticStore, pValue->eName);
782             } else if (pType == NULL) {
783               pImage = NewEnumValue(pStaticStore, pValue->eName);
784             }
785             break;
786           case FDE_CSSPROPERTYVALUE_Inside:
787           case FDE_CSSPROPERTYVALUE_Outside:
788             if (pPosition == NULL) {
789               pPosition = NewEnumValue(pStaticStore, pValue->eName);
790             }
791             break;
792           case FDE_CSSPROPERTYVALUE_Disc:
793           case FDE_CSSPROPERTYVALUE_Circle:
794           case FDE_CSSPROPERTYVALUE_Square:
795           case FDE_CSSPROPERTYVALUE_Decimal:
796           case FDE_CSSPROPERTYVALUE_DecimalLeadingZero:
797           case FDE_CSSPROPERTYVALUE_LowerRoman:
798           case FDE_CSSPROPERTYVALUE_UpperRoman:
799           case FDE_CSSPROPERTYVALUE_LowerGreek:
800           case FDE_CSSPROPERTYVALUE_LowerLatin:
801           case FDE_CSSPROPERTYVALUE_UpperLatin:
802           case FDE_CSSPROPERTYVALUE_Armenian:
803           case FDE_CSSPROPERTYVALUE_Georgian:
804           case FDE_CSSPROPERTYVALUE_LowerAlpha:
805           case FDE_CSSPROPERTYVALUE_UpperAlpha:
806             if (pType == NULL) {
807               pType = NewEnumValue(pStaticStore, pValue->eName);
808             }
809             break;
810           default:
811             break;
812         }
813       }; break;
814       default:
815         break;
816     }
817   }
818   if (pPosition == NULL) {
819     pPosition = NewEnumValue(pStaticStore, FDE_CSSPROPERTYVALUE_Outside);
820   }
821   if (pImage == NULL) {
822     pImage = NewEnumValue(pStaticStore, FDE_CSSPROPERTYVALUE_None);
823   }
824   if (pType == NULL) {
825     pType = NewEnumValue(pStaticStore, FDE_CSSPROPERTYVALUE_None);
826   }
827   AddPropertyHolder(pStaticStore, FDE_CSSPROPERTY_ListStylePosition, pPosition,
828                     bImportant);
829   AddPropertyHolder(pStaticStore, FDE_CSSPROPERTY_ListStyleImage, pImage,
830                     bImportant);
831   AddPropertyHolder(pStaticStore, FDE_CSSPROPERTY_ListStyleType, pType,
832                     bImportant);
833   return TRUE;
834 }
ParseBackgroundProperty(FDE_LPCCSSPROPERTYARGS pArgs,const FX_WCHAR * pszValue,int32_t iValueLen,FX_BOOL bImportant)835 FX_BOOL CFDE_CSSDeclaration::ParseBackgroundProperty(
836     FDE_LPCCSSPROPERTYARGS pArgs,
837     const FX_WCHAR* pszValue,
838     int32_t iValueLen,
839     FX_BOOL bImportant) {
840   IFX_MEMAllocator* pStaticStore = pArgs->pStaticStore;
841   CFDE_CSSValueListParser parser(pszValue, iValueLen, ' ');
842   IFDE_CSSPrimitiveValue *pColor = NULL, *pImage = NULL, *pRepeat = NULL;
843   IFDE_CSSPrimitiveValue *pPosX = NULL, *pPosY = NULL, *pAttachment = NULL;
844   FDE_CSSPRIMITIVETYPE eType;
845   while (parser.NextValue(eType, pszValue, iValueLen)) {
846     switch (eType) {
847       case FDE_CSSPRIMITIVETYPE_URI:
848         if (pImage == NULL) {
849           pImage = FDE_NewWith(pStaticStore) CFDE_CSSPrimitiveValue(
850               eType, CopyToLocal(pArgs, pszValue, iValueLen));
851         }
852         break;
853       case FDE_CSSPRIMITIVETYPE_Number: {
854         FX_FLOAT fValue;
855         if (!FDE_ParseCSSNumber(pszValue, iValueLen, fValue, eType)) {
856           break;
857         }
858         if (pPosX == NULL) {
859           pPosX = NewNumberValue(pStaticStore, eType, fValue);
860         } else if (pPosY == NULL) {
861           pPosY = NewNumberValue(pStaticStore, eType, fValue);
862         }
863       } break;
864       case FDE_CSSPRIMITIVETYPE_String: {
865         FDE_LPCCSSPROPERTYVALUETABLE pValue =
866             FDE_GetCSSPropertyValueByName(pszValue, iValueLen);
867         if (pValue != NULL) {
868           switch (pValue->eName) {
869             case FDE_CSSPROPERTYVALUE_None:
870               if (pImage == NULL) {
871                 pImage = NewEnumValue(pStaticStore, pValue->eName);
872               }
873               break;
874             case FDE_CSSPROPERTYVALUE_Transparent:
875               if (pColor == NULL) {
876                 pColor = FDE_NewWith(pStaticStore)
877                     CFDE_CSSPrimitiveValue((FX_ARGB)0);
878               }
879               break;
880             case FDE_CSSPROPERTYVALUE_Fixed:
881             case FDE_CSSPROPERTYVALUE_Scroll:
882               if (pAttachment == NULL) {
883                 pAttachment = NewEnumValue(pStaticStore, pValue->eName);
884               }
885               break;
886             case FDE_CSSPROPERTYVALUE_Repeat:
887             case FDE_CSSPROPERTYVALUE_RepeatX:
888             case FDE_CSSPROPERTYVALUE_RepeatY:
889             case FDE_CSSPROPERTYVALUE_NoRepeat:
890               if (pRepeat == NULL) {
891                 pRepeat = NewEnumValue(pStaticStore, pValue->eName);
892               }
893               break;
894             case FDE_CSSPROPERTYVALUE_Left:
895             case FDE_CSSPROPERTYVALUE_Right:
896               if (pPosX == NULL) {
897                 pPosX = NewEnumValue(pStaticStore, pValue->eName);
898               }
899               break;
900             case FDE_CSSPROPERTYVALUE_Top:
901             case FDE_CSSPROPERTYVALUE_Bottom:
902               if (pPosY == NULL) {
903                 pPosX = NewEnumValue(pStaticStore, pValue->eName);
904               }
905               break;
906             case FDE_CSSPROPERTYVALUE_Center:
907               if (pPosX == NULL) {
908                 pPosX = NewEnumValue(pStaticStore, pValue->eName);
909               } else if (pPosY == NULL) {
910                 pPosX = NewEnumValue(pStaticStore, pValue->eName);
911               }
912               break;
913             default:
914               break;
915           }
916           break;
917         }
918         FDE_LPCCSSCOLORTABLE pColorItem =
919             FDE_GetCSSColorByName(pszValue, iValueLen);
920         if (pColorItem != NULL)
921           if (pColor == NULL) {
922             pColor = FDE_NewWith(pStaticStore)
923                 CFDE_CSSPrimitiveValue(pColorItem->dwValue);
924           }
925       } break;
926       case FDE_CSSPRIMITIVETYPE_RGB:
927         if (pColor == NULL) {
928           FX_ARGB dwColor;
929           if (FDE_ParseCSSColor(pszValue, iValueLen, dwColor)) {
930             pColor = FDE_NewWith(pStaticStore) CFDE_CSSPrimitiveValue(dwColor);
931           }
932         }
933         break;
934       default:
935         break;
936     }
937   }
938   if (pColor == NULL) {
939     pColor = FDE_NewWith(pStaticStore) CFDE_CSSPrimitiveValue((FX_ARGB)0);
940   }
941   if (pImage == NULL) {
942     pImage = NewEnumValue(pStaticStore, FDE_CSSPROPERTYVALUE_None);
943   }
944   if (pRepeat == NULL) {
945     pRepeat = NewEnumValue(pStaticStore, FDE_CSSPROPERTYVALUE_Repeat);
946   }
947   if (pAttachment == NULL) {
948     pAttachment = NewEnumValue(pStaticStore, FDE_CSSPROPERTYVALUE_Scroll);
949   }
950   if (pPosX == NULL) {
951     pPosX = NewNumberValue(pStaticStore, FDE_CSSPRIMITIVETYPE_Number, 0.0f);
952     pPosY = NewNumberValue(pStaticStore, FDE_CSSPRIMITIVETYPE_Number, 0.0f);
953   } else if (pPosY == NULL) {
954     pPosY = NewNumberValue(pStaticStore, FDE_CSSPRIMITIVETYPE_Number, 0.0f);
955   }
956   CFDE_CSSValueArray position;
957   position.Add(pPosX);
958   position.Add(pPosY);
959   CFDE_CSSValueList* pPosList =
960       FDE_NewWith(pStaticStore) CFDE_CSSValueList(pStaticStore, position);
961   AddPropertyHolder(pStaticStore, FDE_CSSPROPERTY_BackgroundColor, pColor,
962                     bImportant);
963   AddPropertyHolder(pStaticStore, FDE_CSSPROPERTY_BackgroundImage, pImage,
964                     bImportant);
965   AddPropertyHolder(pStaticStore, FDE_CSSPROPERTY_BackgroundRepeat, pRepeat,
966                     bImportant);
967   AddPropertyHolder(pStaticStore, FDE_CSSPROPERTY_BackgroundPosition, pPosList,
968                     bImportant);
969   AddPropertyHolder(pStaticStore, FDE_CSSPROPERTY_BackgroundAttachment,
970                     pAttachment, bImportant);
971   return TRUE;
972 }
ParseFontProperty(FDE_LPCCSSPROPERTYARGS pArgs,const FX_WCHAR * pszValue,int32_t iValueLen,FX_BOOL bImportant)973 FX_BOOL CFDE_CSSDeclaration::ParseFontProperty(FDE_LPCCSSPROPERTYARGS pArgs,
974                                                const FX_WCHAR* pszValue,
975                                                int32_t iValueLen,
976                                                FX_BOOL bImportant) {
977   IFX_MEMAllocator* pStaticStore = pArgs->pStaticStore;
978   CFDE_CSSValueListParser parser(pszValue, iValueLen, '/');
979   IFDE_CSSPrimitiveValue *pStyle = NULL, *pVariant = NULL, *pWeight = NULL;
980   IFDE_CSSPrimitiveValue *pFontSize = NULL, *pLineHeight = NULL;
981   CFDE_CSSValueArray familyList;
982   FDE_CSSPRIMITIVETYPE eType;
983   while (parser.NextValue(eType, pszValue, iValueLen)) {
984     switch (eType) {
985       case FDE_CSSPRIMITIVETYPE_String: {
986         FDE_LPCCSSPROPERTYVALUETABLE pValue =
987             FDE_GetCSSPropertyValueByName(pszValue, iValueLen);
988         if (pValue != NULL) {
989           switch (pValue->eName) {
990             case FDE_CSSPROPERTYVALUE_XxSmall:
991             case FDE_CSSPROPERTYVALUE_XSmall:
992             case FDE_CSSPROPERTYVALUE_Small:
993             case FDE_CSSPROPERTYVALUE_Medium:
994             case FDE_CSSPROPERTYVALUE_Large:
995             case FDE_CSSPROPERTYVALUE_XLarge:
996             case FDE_CSSPROPERTYVALUE_XxLarge:
997             case FDE_CSSPROPERTYVALUE_Smaller:
998             case FDE_CSSPROPERTYVALUE_Larger:
999               if (pFontSize == NULL) {
1000                 pFontSize = NewEnumValue(pStaticStore, pValue->eName);
1001               }
1002               continue;
1003             case FDE_CSSPROPERTYVALUE_Bold:
1004             case FDE_CSSPROPERTYVALUE_Bolder:
1005             case FDE_CSSPROPERTYVALUE_Lighter:
1006               if (pWeight == NULL) {
1007                 pWeight = NewEnumValue(pStaticStore, pValue->eName);
1008               }
1009               continue;
1010             case FDE_CSSPROPERTYVALUE_Italic:
1011             case FDE_CSSPROPERTYVALUE_Oblique:
1012               if (pStyle == NULL) {
1013                 pStyle = NewEnumValue(pStaticStore, pValue->eName);
1014               }
1015               continue;
1016             case FDE_CSSPROPERTYVALUE_SmallCaps:
1017               if (pVariant == NULL) {
1018                 pVariant = NewEnumValue(pStaticStore, pValue->eName);
1019               }
1020               continue;
1021             case FDE_CSSPROPERTYVALUE_Normal:
1022               if (pStyle == NULL) {
1023                 pStyle = NewEnumValue(pStaticStore, pValue->eName);
1024               } else if (pVariant == NULL) {
1025                 pVariant = NewEnumValue(pStaticStore, pValue->eName);
1026               } else if (pWeight == NULL) {
1027                 pWeight = NewEnumValue(pStaticStore, pValue->eName);
1028               } else if (pFontSize == NULL) {
1029                 pFontSize = NewEnumValue(pStaticStore, pValue->eName);
1030               } else if (pLineHeight == NULL) {
1031                 pLineHeight = NewEnumValue(pStaticStore, pValue->eName);
1032               }
1033               continue;
1034             default:
1035               break;
1036           }
1037         }
1038         if (pFontSize != NULL) {
1039           familyList.Add(FDE_NewWith(pStaticStore) CFDE_CSSPrimitiveValue(
1040               eType, CopyToLocal(pArgs, pszValue, iValueLen)));
1041         }
1042         parser.m_Separator = ',';
1043       } break;
1044       case FDE_CSSPRIMITIVETYPE_Number: {
1045         FX_FLOAT fValue;
1046         if (!FDE_ParseCSSNumber(pszValue, iValueLen, fValue, eType)) {
1047           break;
1048         }
1049         if (eType == FDE_CSSPRIMITIVETYPE_Number) {
1050           switch ((int32_t)fValue) {
1051             case 100:
1052             case 200:
1053             case 300:
1054             case 400:
1055             case 500:
1056             case 600:
1057             case 700:
1058             case 800:
1059             case 900:
1060               if (pWeight == NULL) {
1061                 pWeight = NewNumberValue(pStaticStore,
1062                                          FDE_CSSPRIMITIVETYPE_Number, fValue);
1063               }
1064               continue;
1065           }
1066         }
1067         if (pFontSize == NULL) {
1068           pFontSize = NewNumberValue(pStaticStore, eType, fValue);
1069         } else if (pLineHeight == NULL) {
1070           pLineHeight = NewNumberValue(pStaticStore, eType, fValue);
1071         }
1072       } break;
1073       default:
1074         break;
1075     }
1076   }
1077   if (pStyle == NULL) {
1078     pStyle = NewEnumValue(pStaticStore, FDE_CSSPROPERTYVALUE_Normal);
1079   }
1080   if (pVariant == NULL) {
1081     pVariant = NewEnumValue(pStaticStore, FDE_CSSPROPERTYVALUE_Normal);
1082   }
1083   if (pWeight == NULL) {
1084     pWeight = NewEnumValue(pStaticStore, FDE_CSSPROPERTYVALUE_Normal);
1085   }
1086   if (pFontSize == NULL) {
1087     pFontSize = NewEnumValue(pStaticStore, FDE_CSSPROPERTYVALUE_Medium);
1088   }
1089   if (pLineHeight == NULL) {
1090     pLineHeight = NewEnumValue(pStaticStore, FDE_CSSPROPERTYVALUE_Normal);
1091   }
1092   AddPropertyHolder(pStaticStore, FDE_CSSPROPERTY_FontStyle, pStyle,
1093                     bImportant);
1094   AddPropertyHolder(pStaticStore, FDE_CSSPROPERTY_FontVariant, pVariant,
1095                     bImportant);
1096   AddPropertyHolder(pStaticStore, FDE_CSSPROPERTY_FontWeight, pWeight,
1097                     bImportant);
1098   AddPropertyHolder(pStaticStore, FDE_CSSPROPERTY_FontSize, pFontSize,
1099                     bImportant);
1100   AddPropertyHolder(pStaticStore, FDE_CSSPROPERTY_LineHeight, pLineHeight,
1101                     bImportant);
1102   if (familyList.GetSize() > 0) {
1103     CFDE_CSSValueList* pList =
1104         FDE_NewWith(pStaticStore) CFDE_CSSValueList(pStaticStore, familyList);
1105     AddPropertyHolder(pStaticStore, FDE_CSSPROPERTY_FontFamily, pList,
1106                       bImportant);
1107   }
1108   return TRUE;
1109 }
ParseColumnRuleProperty(FDE_LPCCSSPROPERTYARGS pArgs,const FX_WCHAR * pszValue,int32_t iValueLen,FX_BOOL bImportant)1110 FX_BOOL CFDE_CSSDeclaration::ParseColumnRuleProperty(
1111     FDE_LPCCSSPROPERTYARGS pArgs,
1112     const FX_WCHAR* pszValue,
1113     int32_t iValueLen,
1114     FX_BOOL bImportant) {
1115   IFX_MEMAllocator* pStaticStore = pArgs->pStaticStore;
1116   CFDE_CSSValueListParser parser(pszValue, iValueLen, ' ');
1117   IFDE_CSSPrimitiveValue* pColumnRuleWidth = NULL;
1118   IFDE_CSSPrimitiveValue* pColumnRuleStyle = NULL;
1119   IFDE_CSSPrimitiveValue* pColumnRuleColor = NULL;
1120   FDE_CSSPRIMITIVETYPE eType;
1121   while (parser.NextValue(eType, pszValue, iValueLen)) {
1122     switch (eType) {
1123       case FDE_CSSPRIMITIVETYPE_String: {
1124         FDE_LPCCSSPROPERTYVALUETABLE pValue =
1125             FDE_GetCSSPropertyValueByName(pszValue, iValueLen);
1126         if (pValue != NULL) {
1127           switch (pValue->eName) {
1128             case FDE_CSSPROPERTYVALUE_None:
1129             case FDE_CSSPROPERTYVALUE_Hidden:
1130             case FDE_CSSPROPERTYVALUE_Dotted:
1131             case FDE_CSSPROPERTYVALUE_Dashed:
1132             case FDE_CSSPROPERTYVALUE_Solid:
1133             case FDE_CSSPROPERTYVALUE_Double:
1134             case FDE_CSSPROPERTYVALUE_Groove:
1135             case FDE_CSSPROPERTYVALUE_Ridge:
1136             case FDE_CSSPROPERTYVALUE_Inset:
1137             case FDE_CSSPROPERTYVALUE_Outset:
1138               if (pColumnRuleStyle == NULL) {
1139                 pColumnRuleStyle = NewEnumValue(pStaticStore, pValue->eName);
1140               }
1141               break;
1142             case FDE_CSSPROPERTYVALUE_Transparent:
1143               if (pColumnRuleColor == NULL) {
1144                 pColumnRuleColor = NewEnumValue(pStaticStore, pValue->eName);
1145               }
1146               break;
1147             case FDE_CSSPROPERTYVALUE_Thin:
1148             case FDE_CSSPROPERTYVALUE_Medium:
1149             case FDE_CSSPROPERTYVALUE_Thick:
1150               if (pColumnRuleWidth == NULL) {
1151                 pColumnRuleWidth = NewEnumValue(pStaticStore, pValue->eName);
1152               }
1153               break;
1154             default:
1155               break;
1156           }
1157           continue;
1158         }
1159         FX_ARGB dwColor;
1160         if (FDE_ParseCSSColor(pszValue, iValueLen, dwColor) &&
1161             pColumnRuleColor == NULL) {
1162           pColumnRuleColor = FDE_NewWith(pStaticStore)
1163               CFDE_CSSPrimitiveValue((FX_ARGB)dwColor);
1164           continue;
1165         }
1166       } break;
1167       case FDE_CSSPRIMITIVETYPE_Number: {
1168         FX_FLOAT fValue;
1169         if (FDE_ParseCSSNumber(pszValue, iValueLen, fValue, eType) &&
1170             pColumnRuleWidth == NULL) {
1171           pColumnRuleWidth = NewNumberValue(pStaticStore, eType, fValue);
1172         }
1173       } break;
1174       case FDE_CSSPRIMITIVETYPE_RGB: {
1175         FX_ARGB dwColor;
1176         if (pColumnRuleColor == NULL &&
1177             FDE_ParseCSSColor(pszValue, iValueLen, dwColor)) {
1178           pColumnRuleColor = FDE_NewWith(pStaticStore)
1179               CFDE_CSSPrimitiveValue((FX_ARGB)dwColor);
1180         }
1181       } break;
1182       default:
1183         break;
1184     }
1185   }
1186   if (pColumnRuleColor == NULL && pColumnRuleStyle == NULL &&
1187       pColumnRuleWidth == NULL) {
1188     return FALSE;
1189   }
1190   if (pColumnRuleStyle == NULL) {
1191     pColumnRuleStyle = NewEnumValue(pStaticStore, FDE_CSSPROPERTYVALUE_None);
1192   }
1193   if (pColumnRuleWidth == NULL) {
1194     pColumnRuleWidth = NewEnumValue(pStaticStore, FDE_CSSPROPERTYVALUE_Medium);
1195   }
1196   if (pColumnRuleColor == NULL) {
1197     pColumnRuleColor =
1198         FDE_NewWith(pStaticStore) CFDE_CSSPrimitiveValue((FX_ARGB)0);
1199   }
1200   AddPropertyHolder(pStaticStore, FDE_CSSPROPERTY_ColumnRuleStyle,
1201                     pColumnRuleStyle, bImportant);
1202   AddPropertyHolder(pStaticStore, FDE_CSSPROPERTY_ColumnRuleWidth,
1203                     pColumnRuleWidth, bImportant);
1204   AddPropertyHolder(pStaticStore, FDE_CSSPROPERTY_ColumnRuleColor,
1205                     pColumnRuleColor, bImportant);
1206   return TRUE;
1207 }
ParseTextEmphasisProperty(FDE_LPCCSSPROPERTYARGS pArgs,const FX_WCHAR * pszValue,int32_t iValueLen,FX_BOOL bImportant)1208 FX_BOOL CFDE_CSSDeclaration::ParseTextEmphasisProperty(
1209     FDE_LPCCSSPROPERTYARGS pArgs,
1210     const FX_WCHAR* pszValue,
1211     int32_t iValueLen,
1212     FX_BOOL bImportant) {
1213   IFX_MEMAllocator* pStaticStore = pArgs->pStaticStore;
1214   CFDE_CSSValueListParser parser(pszValue, iValueLen, ' ');
1215   CFDE_CSSValueArray arrEmphasisStyle;
1216   FDE_CSSPRIMITIVETYPE eType;
1217   IFDE_CSSPrimitiveValue* pEmphasisColor = NULL;
1218   while (parser.NextValue(eType, pszValue, iValueLen)) {
1219     switch (eType) {
1220       case FDE_CSSPRIMITIVETYPE_String: {
1221         FDE_LPCCSSPROPERTYVALUETABLE pValue =
1222             FDE_GetCSSPropertyValueByName(pszValue, iValueLen);
1223         if (pValue != NULL) {
1224           arrEmphasisStyle.Add(NewEnumValue(pStaticStore, pValue->eName));
1225           continue;
1226         }
1227         FX_ARGB dwColor;
1228         if (FDE_ParseCSSColor(pszValue, iValueLen, dwColor)) {
1229           pEmphasisColor =
1230               FDE_NewWith(pStaticStore) CFDE_CSSPrimitiveValue(dwColor);
1231           continue;
1232         }
1233         pszValue = CopyToLocal(pArgs, pszValue, iValueLen);
1234         arrEmphasisStyle.Add(FDE_NewWith(pStaticStore) CFDE_CSSPrimitiveValue(
1235             FDE_CSSPRIMITIVETYPE_String, pszValue));
1236       } break;
1237       case FDE_CSSPRIMITIVETYPE_RGB: {
1238         FX_ARGB dwColor;
1239         if (FDE_ParseCSSColor(pszValue, iValueLen, dwColor)) {
1240           pEmphasisColor =
1241               FDE_NewWith(pStaticStore) CFDE_CSSPrimitiveValue(dwColor);
1242         }
1243       } break;
1244       default:
1245         break;
1246     }
1247   }
1248   if (arrEmphasisStyle.GetSize() != 0) {
1249     AddPropertyHolder(pStaticStore, FDE_CSSPROPERTY_TextEmphasisStyle,
1250                       FDE_NewWith(pStaticStore)
1251                           CFDE_CSSValueList(pStaticStore, arrEmphasisStyle),
1252                       bImportant);
1253   }
1254   if (pEmphasisColor != NULL) {
1255     AddPropertyHolder(pStaticStore, FDE_CSSPROPERTY_TextEmphasisColor,
1256                       pEmphasisColor, bImportant);
1257   }
1258   return TRUE;
1259 }
ParseColumnsProperty(FDE_LPCCSSPROPERTYARGS pArgs,const FX_WCHAR * pszValue,int32_t iValueLen,FX_BOOL bImportant)1260 FX_BOOL CFDE_CSSDeclaration::ParseColumnsProperty(FDE_LPCCSSPROPERTYARGS pArgs,
1261                                                   const FX_WCHAR* pszValue,
1262                                                   int32_t iValueLen,
1263                                                   FX_BOOL bImportant) {
1264   IFX_MEMAllocator* pStaticStore = pArgs->pStaticStore;
1265   CFDE_CSSValueListParser parser(pszValue, iValueLen, ' ');
1266   IFDE_CSSPrimitiveValue* pColumnWidth = NULL;
1267   IFDE_CSSPrimitiveValue* pColumnCount = NULL;
1268   FDE_CSSPRIMITIVETYPE eType;
1269   while (parser.NextValue(eType, pszValue, iValueLen)) {
1270     switch (eType) {
1271       case FDE_CSSPRIMITIVETYPE_String: {
1272         FDE_LPCCSSPROPERTYVALUETABLE pValue =
1273             FDE_GetCSSPropertyValueByName(pszValue, iValueLen);
1274         if (pValue == NULL && pValue->eName == FDE_CSSPROPERTYVALUE_Auto) {
1275           pColumnWidth = NewEnumValue(pStaticStore, pValue->eName);
1276         }
1277       } break;
1278       case FDE_CSSPRIMITIVETYPE_Number: {
1279         FX_FLOAT fValue;
1280         if (FDE_ParseCSSNumber(pszValue, iValueLen, fValue, eType)) {
1281           switch (eType) {
1282             case FDE_CSSPRIMITIVETYPE_Number:
1283               if (pColumnCount == NULL) {
1284                 pColumnCount = NewNumberValue(pStaticStore, eType, fValue);
1285               }
1286               break;
1287             default:
1288               if (pColumnWidth == NULL) {
1289                 pColumnWidth = NewNumberValue(pStaticStore, eType, fValue);
1290               }
1291               break;
1292           }
1293         }
1294       } break;
1295       default:
1296         break;
1297     }
1298   }
1299   if (pColumnWidth == NULL && pColumnCount == NULL) {
1300     return FALSE;
1301   } else if (pColumnWidth == NULL) {
1302     pColumnWidth = NewEnumValue(pStaticStore, FDE_CSSPROPERTYVALUE_Auto);
1303   } else if (pColumnCount == NULL) {
1304     pColumnCount = NewEnumValue(pStaticStore, FDE_CSSPROPERTYVALUE_Auto);
1305   }
1306   AddPropertyHolder(pStaticStore, FDE_CSSPROPERTY_ColumnWidth, pColumnWidth,
1307                     bImportant);
1308   AddPropertyHolder(pStaticStore, FDE_CSSPROPERTY_ColumnCount, pColumnCount,
1309                     bImportant);
1310   return TRUE;
1311 }
ParseOverflowProperty(FDE_LPCCSSPROPERTYARGS pArgs,const FX_WCHAR * pszValue,int32_t iValueLen,FX_BOOL bImportant)1312 FX_BOOL CFDE_CSSDeclaration::ParseOverflowProperty(FDE_LPCCSSPROPERTYARGS pArgs,
1313                                                    const FX_WCHAR* pszValue,
1314                                                    int32_t iValueLen,
1315                                                    FX_BOOL bImportant) {
1316   IFX_MEMAllocator* pStaticStore = pArgs->pStaticStore;
1317   CFDE_CSSValueListParser parser(pszValue, iValueLen, ' ');
1318   IFDE_CSSPrimitiveValue* pOverflowX = NULL;
1319   IFDE_CSSPrimitiveValue* pOverflowY = NULL;
1320   FDE_CSSPRIMITIVETYPE eType;
1321   while (parser.NextValue(eType, pszValue, iValueLen)) {
1322     if (eType == FDE_CSSPRIMITIVETYPE_String) {
1323       FDE_LPCCSSPROPERTYVALUETABLE pValue =
1324           FDE_GetCSSPropertyValueByName(pszValue, iValueLen);
1325       if (pValue != NULL) {
1326         switch (pValue->eName) {
1327           case FDE_CSSOVERFLOW_Visible:
1328           case FDE_CSSOVERFLOW_Hidden:
1329           case FDE_CSSOVERFLOW_Scroll:
1330           case FDE_CSSOVERFLOW_Auto:
1331           case FDE_CSSOVERFLOW_NoDisplay:
1332           case FDE_CSSOVERFLOW_NoContent:
1333             if (pOverflowX != NULL && pOverflowY != NULL) {
1334               return FALSE;
1335             } else if (pOverflowX == NULL) {
1336               pOverflowX = NewEnumValue(pStaticStore, pValue->eName);
1337             } else if (pOverflowY == NULL) {
1338               pOverflowY = NewEnumValue(pStaticStore, pValue->eName);
1339             }
1340             break;
1341           default:
1342             break;
1343         }
1344       }
1345     }
1346   }
1347   if (pOverflowX == NULL && pOverflowY == NULL) {
1348     return FALSE;
1349   } else if (pOverflowY == NULL) {
1350     pOverflowY = NewEnumValue(pStaticStore, pOverflowX->GetEnum());
1351   }
1352   AddPropertyHolder(pStaticStore, FDE_CSSPROPERTY_OverflowX, pOverflowX,
1353                     bImportant);
1354   AddPropertyHolder(pStaticStore, FDE_CSSPROPERTY_OverflowY, pOverflowY,
1355                     bImportant);
1356   return TRUE;
1357 }
1358