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