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