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