Home | History | Annotate | Download | only in css
      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"
      9 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 }
     20 FX_POSITION CFDE_CSSDeclaration::GetStartPosition() const {
     21   return (FX_POSITION)m_pFirstProperty;
     22 }
     23 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 }
     34 FX_POSITION CFDE_CSSDeclaration::GetStartCustom() const {
     35   return (FX_POSITION)m_pFirstCustom;
     36 }
     37 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 }
     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 }
     74 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 }
     84 inline IFDE_CSSPrimitiveValue* CFDE_CSSDeclaration::NewEnumValue(
     85     IFX_MEMAllocator* pStaticStore,
     86     FDE_CSSPROPERTYVALUE eValue) const {
     87   return FDE_NewWith(pStaticStore) CFDE_CSSPrimitiveValue(eValue);
     88 }
     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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    653 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 }
    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 }
    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 }
    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 }
    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 }
   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 }
   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 }
   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 }
   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