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