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/fde/css/cfde_cssstyleselector.h"
      8 
      9 #include <algorithm>
     10 #include <utility>
     11 
     12 #include "third_party/base/ptr_util.h"
     13 #include "xfa/fde/css/cfde_csscolorvalue.h"
     14 #include "xfa/fde/css/cfde_csscomputedstyle.h"
     15 #include "xfa/fde/css/cfde_csscustomproperty.h"
     16 #include "xfa/fde/css/cfde_cssdeclaration.h"
     17 #include "xfa/fde/css/cfde_cssenumvalue.h"
     18 #include "xfa/fde/css/cfde_csspropertyholder.h"
     19 #include "xfa/fde/css/cfde_cssselector.h"
     20 #include "xfa/fde/css/cfde_cssstylesheet.h"
     21 #include "xfa/fde/css/cfde_csssyntaxparser.h"
     22 #include "xfa/fde/css/cfde_cssvaluelist.h"
     23 #include "xfa/fxfa/app/cxfa_csstagprovider.h"
     24 
     25 CFDE_CSSStyleSelector::CFDE_CSSStyleSelector(CFGAS_FontMgr* pFontMgr)
     26     : m_pFontMgr(pFontMgr), m_fDefFontSize(12.0f) {}
     27 
     28 CFDE_CSSStyleSelector::~CFDE_CSSStyleSelector() {}
     29 
     30 void CFDE_CSSStyleSelector::SetDefFontSize(FX_FLOAT fFontSize) {
     31   ASSERT(fFontSize > 0);
     32   m_fDefFontSize = fFontSize;
     33 }
     34 
     35 CFX_RetainPtr<CFDE_CSSComputedStyle> CFDE_CSSStyleSelector::CreateComputedStyle(
     36     CFDE_CSSComputedStyle* pParentStyle) {
     37   auto pStyle = pdfium::MakeRetain<CFDE_CSSComputedStyle>();
     38   if (pParentStyle)
     39     pStyle->m_InheritedData = pParentStyle->m_InheritedData;
     40   return pStyle;
     41 }
     42 
     43 void CFDE_CSSStyleSelector::SetUAStyleSheet(
     44     std::unique_ptr<CFDE_CSSStyleSheet> pSheet) {
     45   m_UAStyles = std::move(pSheet);
     46 }
     47 
     48 void CFDE_CSSStyleSelector::UpdateStyleIndex() {
     49   m_UARules.Clear();
     50   m_UARules.AddRulesFrom(m_UAStyles.get(), m_pFontMgr);
     51 }
     52 
     53 std::vector<const CFDE_CSSDeclaration*>
     54 CFDE_CSSStyleSelector::MatchDeclarations(const CFX_WideString& tagname) {
     55   std::vector<const CFDE_CSSDeclaration*> matchedDecls;
     56   if (m_UARules.CountSelectors() == 0 || tagname.IsEmpty())
     57     return matchedDecls;
     58 
     59   auto rules = m_UARules.GetTagRuleData(tagname);
     60   if (!rules)
     61     return matchedDecls;
     62 
     63   for (const auto& d : *rules) {
     64     if (MatchSelector(tagname, d->pSelector))
     65       matchedDecls.push_back(d->pDeclaration);
     66   }
     67   return matchedDecls;
     68 }
     69 
     70 bool CFDE_CSSStyleSelector::MatchSelector(const CFX_WideString& tagname,
     71                                           CFDE_CSSSelector* pSel) {
     72   // TODO(dsinclair): The code only supports a single level of selector at this
     73   // point. None of the code using selectors required the complexity so lets
     74   // just say we don't support them to simplify the code for now.
     75   if (!pSel || pSel->GetNextSelector() ||
     76       pSel->GetType() == FDE_CSSSelectorType::Descendant) {
     77     return false;
     78   }
     79   return pSel->GetNameHash() == FX_HashCode_GetW(tagname.c_str(), true);
     80 }
     81 
     82 void CFDE_CSSStyleSelector::ComputeStyle(
     83     const std::vector<const CFDE_CSSDeclaration*>& declArray,
     84     const CFX_WideString& styleString,
     85     const CFX_WideString& alignString,
     86     CFDE_CSSComputedStyle* pDest) {
     87   std::unique_ptr<CFDE_CSSDeclaration> pDecl;
     88   if (!styleString.IsEmpty() || !alignString.IsEmpty()) {
     89     pDecl = pdfium::MakeUnique<CFDE_CSSDeclaration>();
     90 
     91     if (!styleString.IsEmpty())
     92       AppendInlineStyle(pDecl.get(), styleString);
     93     if (!alignString.IsEmpty()) {
     94       pDecl->AddProperty(FDE_GetCSSPropertyByEnum(FDE_CSSProperty::TextAlign),
     95                          alignString.AsStringC());
     96     }
     97   }
     98   ApplyDeclarations(declArray, pDecl.get(), pDest);
     99 }
    100 
    101 void CFDE_CSSStyleSelector::ApplyDeclarations(
    102     const std::vector<const CFDE_CSSDeclaration*>& declArray,
    103     const CFDE_CSSDeclaration* extraDecl,
    104     CFDE_CSSComputedStyle* pComputedStyle) {
    105   std::vector<const CFDE_CSSPropertyHolder*> importants;
    106   std::vector<const CFDE_CSSPropertyHolder*> normals;
    107   std::vector<const CFDE_CSSCustomProperty*> customs;
    108 
    109   for (auto& decl : declArray)
    110     ExtractValues(decl, &importants, &normals, &customs);
    111 
    112   if (extraDecl)
    113     ExtractValues(extraDecl, &importants, &normals, &customs);
    114 
    115   for (auto& prop : normals)
    116     ApplyProperty(prop->eProperty, prop->pValue, pComputedStyle);
    117 
    118   for (auto& prop : customs)
    119     pComputedStyle->AddCustomStyle(*prop);
    120 
    121   for (auto& prop : importants)
    122     ApplyProperty(prop->eProperty, prop->pValue, pComputedStyle);
    123 }
    124 
    125 void CFDE_CSSStyleSelector::ExtractValues(
    126     const CFDE_CSSDeclaration* decl,
    127     std::vector<const CFDE_CSSPropertyHolder*>* importants,
    128     std::vector<const CFDE_CSSPropertyHolder*>* normals,
    129     std::vector<const CFDE_CSSCustomProperty*>* custom) {
    130   for (const auto& holder : *decl) {
    131     if (holder->bImportant)
    132       importants->push_back(holder.get());
    133     else
    134       normals->push_back(holder.get());
    135   }
    136   for (auto it = decl->custom_begin(); it != decl->custom_end(); it++)
    137     custom->push_back(it->get());
    138 }
    139 
    140 void CFDE_CSSStyleSelector::AppendInlineStyle(CFDE_CSSDeclaration* pDecl,
    141                                               const CFX_WideString& style) {
    142   ASSERT(pDecl && !style.IsEmpty());
    143 
    144   auto pSyntax = pdfium::MakeUnique<CFDE_CSSSyntaxParser>();
    145   if (!pSyntax->Init(style.c_str(), style.GetLength(), 32, true))
    146     return;
    147 
    148   int32_t iLen2 = 0;
    149   const FDE_CSSPropertyTable* table = nullptr;
    150   CFX_WideString wsName;
    151   while (1) {
    152     FDE_CSSSyntaxStatus eStatus = pSyntax->DoSyntaxParse();
    153     if (eStatus == FDE_CSSSyntaxStatus::PropertyName) {
    154       CFX_WideStringC strValue = pSyntax->GetCurrentString();
    155       table = FDE_GetCSSPropertyByName(strValue);
    156       if (!table)
    157         wsName = CFX_WideString(strValue);
    158     } else if (eStatus == FDE_CSSSyntaxStatus::PropertyValue) {
    159       if (table || iLen2 > 0) {
    160         CFX_WideStringC strValue = pSyntax->GetCurrentString();
    161         if (!strValue.IsEmpty()) {
    162           if (table)
    163             pDecl->AddProperty(table, strValue);
    164           else if (iLen2 > 0)
    165             pDecl->AddProperty(wsName, CFX_WideString(strValue));
    166         }
    167       }
    168     } else {
    169       break;
    170     }
    171   }
    172 }
    173 
    174 void CFDE_CSSStyleSelector::ApplyProperty(
    175     FDE_CSSProperty eProperty,
    176     const CFX_RetainPtr<CFDE_CSSValue>& pValue,
    177     CFDE_CSSComputedStyle* pComputedStyle) {
    178   if (pValue->GetType() != FDE_CSSPrimitiveType::List) {
    179     FDE_CSSPrimitiveType eType = pValue->GetType();
    180     switch (eProperty) {
    181       case FDE_CSSProperty::Display:
    182         if (eType == FDE_CSSPrimitiveType::Enum) {
    183           pComputedStyle->m_NonInheritedData.m_eDisplay =
    184               ToDisplay(pValue.As<CFDE_CSSEnumValue>()->Value());
    185         }
    186         break;
    187       case FDE_CSSProperty::FontSize: {
    188         FX_FLOAT& fFontSize = pComputedStyle->m_InheritedData.m_fFontSize;
    189         if (eType == FDE_CSSPrimitiveType::Number) {
    190           fFontSize = pValue.As<CFDE_CSSNumberValue>()->Apply(fFontSize);
    191         } else if (eType == FDE_CSSPrimitiveType::Enum) {
    192           fFontSize =
    193               ToFontSize(pValue.As<CFDE_CSSEnumValue>()->Value(), fFontSize);
    194         }
    195       } break;
    196       case FDE_CSSProperty::LineHeight:
    197         if (eType == FDE_CSSPrimitiveType::Number) {
    198           CFX_RetainPtr<CFDE_CSSNumberValue> v =
    199               pValue.As<CFDE_CSSNumberValue>();
    200           if (v->Kind() == FDE_CSSNumberType::Number) {
    201             pComputedStyle->m_InheritedData.m_fLineHeight =
    202                 v->Value() * pComputedStyle->m_InheritedData.m_fFontSize;
    203           } else {
    204             pComputedStyle->m_InheritedData.m_fLineHeight =
    205                 v->Apply(pComputedStyle->m_InheritedData.m_fFontSize);
    206           }
    207         }
    208         break;
    209       case FDE_CSSProperty::TextAlign:
    210         if (eType == FDE_CSSPrimitiveType::Enum) {
    211           pComputedStyle->m_InheritedData.m_eTextAlign =
    212               ToTextAlign(pValue.As<CFDE_CSSEnumValue>()->Value());
    213         }
    214         break;
    215       case FDE_CSSProperty::TextIndent:
    216         SetLengthWithPercent(pComputedStyle->m_InheritedData.m_TextIndent,
    217                              eType, pValue,
    218                              pComputedStyle->m_InheritedData.m_fFontSize);
    219         break;
    220       case FDE_CSSProperty::FontWeight:
    221         if (eType == FDE_CSSPrimitiveType::Enum) {
    222           pComputedStyle->m_InheritedData.m_wFontWeight =
    223               ToFontWeight(pValue.As<CFDE_CSSEnumValue>()->Value());
    224         } else if (eType == FDE_CSSPrimitiveType::Number) {
    225           int32_t iValue =
    226               (int32_t)pValue.As<CFDE_CSSNumberValue>()->Value() / 100;
    227           if (iValue >= 1 && iValue <= 9) {
    228             pComputedStyle->m_InheritedData.m_wFontWeight = iValue * 100;
    229           }
    230         }
    231         break;
    232       case FDE_CSSProperty::FontStyle:
    233         if (eType == FDE_CSSPrimitiveType::Enum) {
    234           pComputedStyle->m_InheritedData.m_eFontStyle =
    235               ToFontStyle(pValue.As<CFDE_CSSEnumValue>()->Value());
    236         }
    237         break;
    238       case FDE_CSSProperty::Color:
    239         if (eType == FDE_CSSPrimitiveType::RGB) {
    240           pComputedStyle->m_InheritedData.m_dwFontColor =
    241               pValue.As<CFDE_CSSColorValue>()->Value();
    242         }
    243         break;
    244       case FDE_CSSProperty::MarginLeft:
    245         if (SetLengthWithPercent(
    246                 pComputedStyle->m_NonInheritedData.m_MarginWidth.left, eType,
    247                 pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
    248           pComputedStyle->m_NonInheritedData.m_bHasMargin = true;
    249         }
    250         break;
    251       case FDE_CSSProperty::MarginTop:
    252         if (SetLengthWithPercent(
    253                 pComputedStyle->m_NonInheritedData.m_MarginWidth.top, eType,
    254                 pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
    255           pComputedStyle->m_NonInheritedData.m_bHasMargin = true;
    256         }
    257         break;
    258       case FDE_CSSProperty::MarginRight:
    259         if (SetLengthWithPercent(
    260                 pComputedStyle->m_NonInheritedData.m_MarginWidth.right, eType,
    261                 pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
    262           pComputedStyle->m_NonInheritedData.m_bHasMargin = true;
    263         }
    264         break;
    265       case FDE_CSSProperty::MarginBottom:
    266         if (SetLengthWithPercent(
    267                 pComputedStyle->m_NonInheritedData.m_MarginWidth.bottom, eType,
    268                 pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
    269           pComputedStyle->m_NonInheritedData.m_bHasMargin = true;
    270         }
    271         break;
    272       case FDE_CSSProperty::PaddingLeft:
    273         if (SetLengthWithPercent(
    274                 pComputedStyle->m_NonInheritedData.m_PaddingWidth.left, eType,
    275                 pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
    276           pComputedStyle->m_NonInheritedData.m_bHasPadding = true;
    277         }
    278         break;
    279       case FDE_CSSProperty::PaddingTop:
    280         if (SetLengthWithPercent(
    281                 pComputedStyle->m_NonInheritedData.m_PaddingWidth.top, eType,
    282                 pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
    283           pComputedStyle->m_NonInheritedData.m_bHasPadding = true;
    284         }
    285         break;
    286       case FDE_CSSProperty::PaddingRight:
    287         if (SetLengthWithPercent(
    288                 pComputedStyle->m_NonInheritedData.m_PaddingWidth.right, eType,
    289                 pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
    290           pComputedStyle->m_NonInheritedData.m_bHasPadding = true;
    291         }
    292         break;
    293       case FDE_CSSProperty::PaddingBottom:
    294         if (SetLengthWithPercent(
    295                 pComputedStyle->m_NonInheritedData.m_PaddingWidth.bottom, eType,
    296                 pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
    297           pComputedStyle->m_NonInheritedData.m_bHasPadding = true;
    298         }
    299         break;
    300       case FDE_CSSProperty::BorderLeftWidth:
    301         if (SetLengthWithPercent(
    302                 pComputedStyle->m_NonInheritedData.m_BorderWidth.left, eType,
    303                 pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
    304           pComputedStyle->m_NonInheritedData.m_bHasBorder = true;
    305         }
    306         break;
    307       case FDE_CSSProperty::BorderTopWidth:
    308         if (SetLengthWithPercent(
    309                 pComputedStyle->m_NonInheritedData.m_BorderWidth.top, eType,
    310                 pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
    311           pComputedStyle->m_NonInheritedData.m_bHasBorder = true;
    312         }
    313         break;
    314       case FDE_CSSProperty::BorderRightWidth:
    315         if (SetLengthWithPercent(
    316                 pComputedStyle->m_NonInheritedData.m_BorderWidth.right, eType,
    317                 pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
    318           pComputedStyle->m_NonInheritedData.m_bHasBorder = true;
    319         }
    320         break;
    321       case FDE_CSSProperty::BorderBottomWidth:
    322         if (SetLengthWithPercent(
    323                 pComputedStyle->m_NonInheritedData.m_BorderWidth.bottom, eType,
    324                 pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
    325           pComputedStyle->m_NonInheritedData.m_bHasBorder = true;
    326         }
    327         break;
    328       case FDE_CSSProperty::VerticalAlign:
    329         if (eType == FDE_CSSPrimitiveType::Enum) {
    330           pComputedStyle->m_NonInheritedData.m_eVerticalAlign =
    331               ToVerticalAlign(pValue.As<CFDE_CSSEnumValue>()->Value());
    332         } else if (eType == FDE_CSSPrimitiveType::Number) {
    333           pComputedStyle->m_NonInheritedData.m_eVerticalAlign =
    334               FDE_CSSVerticalAlign::Number;
    335           pComputedStyle->m_NonInheritedData.m_fVerticalAlign =
    336               pValue.As<CFDE_CSSNumberValue>()->Apply(
    337                   pComputedStyle->m_InheritedData.m_fFontSize);
    338         }
    339         break;
    340       case FDE_CSSProperty::FontVariant:
    341         if (eType == FDE_CSSPrimitiveType::Enum) {
    342           pComputedStyle->m_InheritedData.m_eFontVariant =
    343               ToFontVariant(pValue.As<CFDE_CSSEnumValue>()->Value());
    344         }
    345         break;
    346       case FDE_CSSProperty::LetterSpacing:
    347         if (eType == FDE_CSSPrimitiveType::Enum) {
    348           pComputedStyle->m_InheritedData.m_LetterSpacing.Set(
    349               FDE_CSSLengthUnit::Normal);
    350         } else if (eType == FDE_CSSPrimitiveType::Number) {
    351           if (pValue.As<CFDE_CSSNumberValue>()->Kind() ==
    352               FDE_CSSNumberType::Percent) {
    353             break;
    354           }
    355 
    356           SetLengthWithPercent(pComputedStyle->m_InheritedData.m_LetterSpacing,
    357                                eType, pValue,
    358                                pComputedStyle->m_InheritedData.m_fFontSize);
    359         }
    360         break;
    361       case FDE_CSSProperty::WordSpacing:
    362         if (eType == FDE_CSSPrimitiveType::Enum) {
    363           pComputedStyle->m_InheritedData.m_WordSpacing.Set(
    364               FDE_CSSLengthUnit::Normal);
    365         } else if (eType == FDE_CSSPrimitiveType::Number) {
    366           if (pValue.As<CFDE_CSSNumberValue>()->Kind() ==
    367               FDE_CSSNumberType::Percent) {
    368             break;
    369           }
    370           SetLengthWithPercent(pComputedStyle->m_InheritedData.m_WordSpacing,
    371                                eType, pValue,
    372                                pComputedStyle->m_InheritedData.m_fFontSize);
    373         }
    374         break;
    375       case FDE_CSSProperty::Top:
    376         SetLengthWithPercent(pComputedStyle->m_NonInheritedData.m_Top, eType,
    377                              pValue,
    378                              pComputedStyle->m_InheritedData.m_fFontSize);
    379         break;
    380       case FDE_CSSProperty::Bottom:
    381         SetLengthWithPercent(pComputedStyle->m_NonInheritedData.m_Bottom, eType,
    382                              pValue,
    383                              pComputedStyle->m_InheritedData.m_fFontSize);
    384         break;
    385       case FDE_CSSProperty::Left:
    386         SetLengthWithPercent(pComputedStyle->m_NonInheritedData.m_Left, eType,
    387                              pValue,
    388                              pComputedStyle->m_InheritedData.m_fFontSize);
    389         break;
    390       case FDE_CSSProperty::Right:
    391         SetLengthWithPercent(pComputedStyle->m_NonInheritedData.m_Right, eType,
    392                              pValue,
    393                              pComputedStyle->m_InheritedData.m_fFontSize);
    394         break;
    395       default:
    396         break;
    397     }
    398   } else if (pValue->GetType() == FDE_CSSPrimitiveType::List) {
    399     CFX_RetainPtr<CFDE_CSSValueList> pList = pValue.As<CFDE_CSSValueList>();
    400     int32_t iCount = pList->CountValues();
    401     if (iCount > 0) {
    402       switch (eProperty) {
    403         case FDE_CSSProperty::FontFamily:
    404           pComputedStyle->m_InheritedData.m_pFontFamily = pList;
    405           break;
    406         case FDE_CSSProperty::TextDecoration:
    407           pComputedStyle->m_NonInheritedData.m_dwTextDecoration =
    408               ToTextDecoration(pList);
    409           break;
    410         default:
    411           break;
    412       }
    413     }
    414   } else {
    415     ASSERT(false);
    416   }
    417 }
    418 
    419 FDE_CSSDisplay CFDE_CSSStyleSelector::ToDisplay(FDE_CSSPropertyValue eValue) {
    420   switch (eValue) {
    421     case FDE_CSSPropertyValue::Block:
    422       return FDE_CSSDisplay::Block;
    423     case FDE_CSSPropertyValue::None:
    424       return FDE_CSSDisplay::None;
    425     case FDE_CSSPropertyValue::ListItem:
    426       return FDE_CSSDisplay::ListItem;
    427     case FDE_CSSPropertyValue::InlineTable:
    428       return FDE_CSSDisplay::InlineTable;
    429     case FDE_CSSPropertyValue::InlineBlock:
    430       return FDE_CSSDisplay::InlineBlock;
    431     case FDE_CSSPropertyValue::Inline:
    432     default:
    433       return FDE_CSSDisplay::Inline;
    434   }
    435 }
    436 
    437 FDE_CSSTextAlign CFDE_CSSStyleSelector::ToTextAlign(
    438     FDE_CSSPropertyValue eValue) {
    439   switch (eValue) {
    440     case FDE_CSSPropertyValue::Center:
    441       return FDE_CSSTextAlign::Center;
    442     case FDE_CSSPropertyValue::Right:
    443       return FDE_CSSTextAlign::Right;
    444     case FDE_CSSPropertyValue::Justify:
    445       return FDE_CSSTextAlign::Justify;
    446     case FDE_CSSPropertyValue::Left:
    447     default:
    448       return FDE_CSSTextAlign::Left;
    449   }
    450 }
    451 
    452 uint16_t CFDE_CSSStyleSelector::ToFontWeight(FDE_CSSPropertyValue eValue) {
    453   switch (eValue) {
    454     case FDE_CSSPropertyValue::Bold:
    455       return 700;
    456     case FDE_CSSPropertyValue::Bolder:
    457       return 900;
    458     case FDE_CSSPropertyValue::Lighter:
    459       return 200;
    460     case FDE_CSSPropertyValue::Normal:
    461     default:
    462       return 400;
    463   }
    464 }
    465 
    466 FDE_CSSFontStyle CFDE_CSSStyleSelector::ToFontStyle(
    467     FDE_CSSPropertyValue eValue) {
    468   switch (eValue) {
    469     case FDE_CSSPropertyValue::Italic:
    470     case FDE_CSSPropertyValue::Oblique:
    471       return FDE_CSSFontStyle::Italic;
    472     default:
    473       return FDE_CSSFontStyle::Normal;
    474   }
    475 }
    476 
    477 bool CFDE_CSSStyleSelector::SetLengthWithPercent(
    478     FDE_CSSLength& width,
    479     FDE_CSSPrimitiveType eType,
    480     const CFX_RetainPtr<CFDE_CSSValue>& pValue,
    481     FX_FLOAT fFontSize) {
    482   if (eType == FDE_CSSPrimitiveType::Number) {
    483     CFX_RetainPtr<CFDE_CSSNumberValue> v = pValue.As<CFDE_CSSNumberValue>();
    484     if (v->Kind() == FDE_CSSNumberType::Percent) {
    485       width.Set(FDE_CSSLengthUnit::Percent,
    486                 pValue.As<CFDE_CSSNumberValue>()->Value() / 100.0f);
    487       return width.NonZero();
    488     }
    489 
    490     FX_FLOAT fValue = v->Apply(fFontSize);
    491     width.Set(FDE_CSSLengthUnit::Point, fValue);
    492     return width.NonZero();
    493   } else if (eType == FDE_CSSPrimitiveType::Enum) {
    494     switch (pValue.As<CFDE_CSSEnumValue>()->Value()) {
    495       case FDE_CSSPropertyValue::Auto:
    496         width.Set(FDE_CSSLengthUnit::Auto);
    497         return true;
    498       case FDE_CSSPropertyValue::None:
    499         width.Set(FDE_CSSLengthUnit::None);
    500         return true;
    501       case FDE_CSSPropertyValue::Thin:
    502         width.Set(FDE_CSSLengthUnit::Point, 2);
    503         return true;
    504       case FDE_CSSPropertyValue::Medium:
    505         width.Set(FDE_CSSLengthUnit::Point, 3);
    506         return true;
    507       case FDE_CSSPropertyValue::Thick:
    508         width.Set(FDE_CSSLengthUnit::Point, 4);
    509         return true;
    510       default:
    511         return false;
    512     }
    513   }
    514   return false;
    515 }
    516 
    517 FX_FLOAT CFDE_CSSStyleSelector::ToFontSize(FDE_CSSPropertyValue eValue,
    518                                            FX_FLOAT fCurFontSize) {
    519   switch (eValue) {
    520     case FDE_CSSPropertyValue::XxSmall:
    521       return m_fDefFontSize / 1.2f / 1.2f / 1.2f;
    522     case FDE_CSSPropertyValue::XSmall:
    523       return m_fDefFontSize / 1.2f / 1.2f;
    524     case FDE_CSSPropertyValue::Small:
    525       return m_fDefFontSize / 1.2f;
    526     case FDE_CSSPropertyValue::Medium:
    527       return m_fDefFontSize;
    528     case FDE_CSSPropertyValue::Large:
    529       return m_fDefFontSize * 1.2f;
    530     case FDE_CSSPropertyValue::XLarge:
    531       return m_fDefFontSize * 1.2f * 1.2f;
    532     case FDE_CSSPropertyValue::XxLarge:
    533       return m_fDefFontSize * 1.2f * 1.2f * 1.2f;
    534     case FDE_CSSPropertyValue::Larger:
    535       return fCurFontSize * 1.2f;
    536     case FDE_CSSPropertyValue::Smaller:
    537       return fCurFontSize / 1.2f;
    538     default:
    539       return fCurFontSize;
    540   }
    541 }
    542 
    543 FDE_CSSVerticalAlign CFDE_CSSStyleSelector::ToVerticalAlign(
    544     FDE_CSSPropertyValue eValue) {
    545   switch (eValue) {
    546     case FDE_CSSPropertyValue::Middle:
    547       return FDE_CSSVerticalAlign::Middle;
    548     case FDE_CSSPropertyValue::Bottom:
    549       return FDE_CSSVerticalAlign::Bottom;
    550     case FDE_CSSPropertyValue::Super:
    551       return FDE_CSSVerticalAlign::Super;
    552     case FDE_CSSPropertyValue::Sub:
    553       return FDE_CSSVerticalAlign::Sub;
    554     case FDE_CSSPropertyValue::Top:
    555       return FDE_CSSVerticalAlign::Top;
    556     case FDE_CSSPropertyValue::TextTop:
    557       return FDE_CSSVerticalAlign::TextTop;
    558     case FDE_CSSPropertyValue::TextBottom:
    559       return FDE_CSSVerticalAlign::TextBottom;
    560     case FDE_CSSPropertyValue::Baseline:
    561     default:
    562       return FDE_CSSVerticalAlign::Baseline;
    563   }
    564 }
    565 
    566 uint32_t CFDE_CSSStyleSelector::ToTextDecoration(
    567     const CFX_RetainPtr<CFDE_CSSValueList>& pValue) {
    568   uint32_t dwDecoration = 0;
    569   for (int32_t i = pValue->CountValues() - 1; i >= 0; --i) {
    570     const CFX_RetainPtr<CFDE_CSSValue> pVal = pValue->GetValue(i);
    571     if (pVal->GetType() != FDE_CSSPrimitiveType::Enum)
    572       continue;
    573 
    574     switch (pVal.As<CFDE_CSSEnumValue>()->Value()) {
    575       case FDE_CSSPropertyValue::Underline:
    576         dwDecoration |= FDE_CSSTEXTDECORATION_Underline;
    577         break;
    578       case FDE_CSSPropertyValue::LineThrough:
    579         dwDecoration |= FDE_CSSTEXTDECORATION_LineThrough;
    580         break;
    581       case FDE_CSSPropertyValue::Overline:
    582         dwDecoration |= FDE_CSSTEXTDECORATION_Overline;
    583         break;
    584       case FDE_CSSPropertyValue::Blink:
    585         dwDecoration |= FDE_CSSTEXTDECORATION_Blink;
    586         break;
    587       case FDE_CSSPropertyValue::Double:
    588         dwDecoration |= FDE_CSSTEXTDECORATION_Double;
    589         break;
    590       default:
    591         break;
    592     }
    593   }
    594   return dwDecoration;
    595 }
    596 
    597 FDE_CSSFontVariant CFDE_CSSStyleSelector::ToFontVariant(
    598     FDE_CSSPropertyValue eValue) {
    599   return eValue == FDE_CSSPropertyValue::SmallCaps
    600              ? FDE_CSSFontVariant::SmallCaps
    601              : FDE_CSSFontVariant::Normal;
    602 }
    603