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