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