• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "xfa/fde/css/cfde_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 
CFDE_CSSStyleSelector(CFGAS_FontMgr * pFontMgr)25 CFDE_CSSStyleSelector::CFDE_CSSStyleSelector(CFGAS_FontMgr* pFontMgr)
26     : m_pFontMgr(pFontMgr), m_fDefFontSize(12.0f) {}
27 
~CFDE_CSSStyleSelector()28 CFDE_CSSStyleSelector::~CFDE_CSSStyleSelector() {}
29 
SetDefFontSize(FX_FLOAT fFontSize)30 void CFDE_CSSStyleSelector::SetDefFontSize(FX_FLOAT fFontSize) {
31   ASSERT(fFontSize > 0);
32   m_fDefFontSize = fFontSize;
33 }
34 
CreateComputedStyle(CFDE_CSSComputedStyle * pParentStyle)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 
SetUAStyleSheet(std::unique_ptr<CFDE_CSSStyleSheet> pSheet)43 void CFDE_CSSStyleSelector::SetUAStyleSheet(
44     std::unique_ptr<CFDE_CSSStyleSheet> pSheet) {
45   m_UAStyles = std::move(pSheet);
46 }
47 
UpdateStyleIndex()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*>
MatchDeclarations(const CFX_WideString & tagname)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 
MatchSelector(const CFX_WideString & tagname,CFDE_CSSSelector * pSel)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 
ComputeStyle(const std::vector<const CFDE_CSSDeclaration * > & declArray,const CFX_WideString & styleString,const CFX_WideString & alignString,CFDE_CSSComputedStyle * pDest)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 
ApplyDeclarations(const std::vector<const CFDE_CSSDeclaration * > & declArray,const CFDE_CSSDeclaration * extraDecl,CFDE_CSSComputedStyle * pComputedStyle)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 
ExtractValues(const CFDE_CSSDeclaration * decl,std::vector<const CFDE_CSSPropertyHolder * > * importants,std::vector<const CFDE_CSSPropertyHolder * > * normals,std::vector<const CFDE_CSSCustomProperty * > * custom)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 
AppendInlineStyle(CFDE_CSSDeclaration * pDecl,const CFX_WideString & style)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 
ApplyProperty(FDE_CSSProperty eProperty,const CFX_RetainPtr<CFDE_CSSValue> & pValue,CFDE_CSSComputedStyle * pComputedStyle)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 
ToDisplay(FDE_CSSPropertyValue eValue)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 
ToTextAlign(FDE_CSSPropertyValue eValue)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 
ToFontWeight(FDE_CSSPropertyValue eValue)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 
ToFontStyle(FDE_CSSPropertyValue eValue)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 
SetLengthWithPercent(FDE_CSSLength & width,FDE_CSSPrimitiveType eType,const CFX_RetainPtr<CFDE_CSSValue> & pValue,FX_FLOAT fFontSize)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 
ToFontSize(FDE_CSSPropertyValue eValue,FX_FLOAT fCurFontSize)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 
ToVerticalAlign(FDE_CSSPropertyValue eValue)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 
ToTextDecoration(const CFX_RetainPtr<CFDE_CSSValueList> & pValue)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 
ToFontVariant(FDE_CSSPropertyValue eValue)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