1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "core/fxcrt/css/cfx_cssstyleselector.h"
8
9 #include <algorithm>
10 #include <utility>
11
12 #include "core/fxcrt/css/cfx_csscolorvalue.h"
13 #include "core/fxcrt/css/cfx_csscomputedstyle.h"
14 #include "core/fxcrt/css/cfx_csscustomproperty.h"
15 #include "core/fxcrt/css/cfx_cssdeclaration.h"
16 #include "core/fxcrt/css/cfx_cssenumvalue.h"
17 #include "core/fxcrt/css/cfx_csspropertyholder.h"
18 #include "core/fxcrt/css/cfx_cssselector.h"
19 #include "core/fxcrt/css/cfx_cssstylesheet.h"
20 #include "core/fxcrt/css/cfx_csssyntaxparser.h"
21 #include "core/fxcrt/css/cfx_cssvaluelist.h"
22 #include "third_party/base/logging.h"
23 #include "third_party/base/ptr_util.h"
24
CFX_CSSStyleSelector()25 CFX_CSSStyleSelector::CFX_CSSStyleSelector() : m_fDefFontSize(12.0f) {}
26
~CFX_CSSStyleSelector()27 CFX_CSSStyleSelector::~CFX_CSSStyleSelector() {}
28
SetDefFontSize(float fFontSize)29 void CFX_CSSStyleSelector::SetDefFontSize(float fFontSize) {
30 ASSERT(fFontSize > 0);
31 m_fDefFontSize = fFontSize;
32 }
33
CreateComputedStyle(CFX_CSSComputedStyle * pParentStyle)34 RetainPtr<CFX_CSSComputedStyle> CFX_CSSStyleSelector::CreateComputedStyle(
35 CFX_CSSComputedStyle* pParentStyle) {
36 auto pStyle = pdfium::MakeRetain<CFX_CSSComputedStyle>();
37 if (pParentStyle)
38 pStyle->m_InheritedData = pParentStyle->m_InheritedData;
39 return pStyle;
40 }
41
SetUAStyleSheet(std::unique_ptr<CFX_CSSStyleSheet> pSheet)42 void CFX_CSSStyleSelector::SetUAStyleSheet(
43 std::unique_ptr<CFX_CSSStyleSheet> pSheet) {
44 m_UAStyles = std::move(pSheet);
45 }
46
UpdateStyleIndex()47 void CFX_CSSStyleSelector::UpdateStyleIndex() {
48 m_UARules.Clear();
49 m_UARules.AddRulesFrom(m_UAStyles.get());
50 }
51
MatchDeclarations(const WideString & tagname)52 std::vector<const CFX_CSSDeclaration*> CFX_CSSStyleSelector::MatchDeclarations(
53 const WideString& tagname) {
54 std::vector<const CFX_CSSDeclaration*> matchedDecls;
55 if (m_UARules.CountSelectors() == 0 || tagname.IsEmpty())
56 return matchedDecls;
57
58 auto* rules = m_UARules.GetTagRuleData(tagname);
59 if (!rules)
60 return matchedDecls;
61
62 for (const auto& d : *rules) {
63 if (MatchSelector(tagname, d->pSelector))
64 matchedDecls.push_back(d->pDeclaration);
65 }
66 return matchedDecls;
67 }
68
MatchSelector(const WideString & tagname,CFX_CSSSelector * pSel)69 bool CFX_CSSStyleSelector::MatchSelector(const WideString& tagname,
70 CFX_CSSSelector* pSel) {
71 // TODO(dsinclair): The code only supports a single level of selector at this
72 // point. None of the code using selectors required the complexity so lets
73 // just say we don't support them to simplify the code for now.
74 if (!pSel || pSel->GetNextSelector() ||
75 pSel->GetType() == CFX_CSSSelectorType::Descendant) {
76 return false;
77 }
78 return pSel->GetNameHash() == FX_HashCode_GetW(tagname.AsStringView(), true);
79 }
80
ComputeStyle(const std::vector<const CFX_CSSDeclaration * > & declArray,const WideString & styleString,const WideString & alignString,CFX_CSSComputedStyle * pDest)81 void CFX_CSSStyleSelector::ComputeStyle(
82 const std::vector<const CFX_CSSDeclaration*>& declArray,
83 const WideString& styleString,
84 const WideString& alignString,
85 CFX_CSSComputedStyle* pDest) {
86 std::unique_ptr<CFX_CSSDeclaration> pDecl;
87 if (!styleString.IsEmpty() || !alignString.IsEmpty()) {
88 pDecl = pdfium::MakeUnique<CFX_CSSDeclaration>();
89
90 if (!styleString.IsEmpty())
91 AppendInlineStyle(pDecl.get(), styleString);
92 if (!alignString.IsEmpty()) {
93 pDecl->AddProperty(
94 CFX_CSSData::GetPropertyByEnum(CFX_CSSProperty::TextAlign),
95 alignString.AsStringView());
96 }
97 }
98 ApplyDeclarations(declArray, pDecl.get(), pDest);
99 }
100
ApplyDeclarations(const std::vector<const CFX_CSSDeclaration * > & declArray,const CFX_CSSDeclaration * extraDecl,CFX_CSSComputedStyle * pComputedStyle)101 void CFX_CSSStyleSelector::ApplyDeclarations(
102 const std::vector<const CFX_CSSDeclaration*>& declArray,
103 const CFX_CSSDeclaration* extraDecl,
104 CFX_CSSComputedStyle* pComputedStyle) {
105 std::vector<const CFX_CSSPropertyHolder*> importants;
106 std::vector<const CFX_CSSPropertyHolder*> normals;
107 std::vector<const CFX_CSSCustomProperty*> customs;
108
109 for (auto* decl : declArray)
110 ExtractValues(decl, &importants, &normals, &customs);
111
112 if (extraDecl)
113 ExtractValues(extraDecl, &importants, &normals, &customs);
114
115 for (auto* prop : normals)
116 ApplyProperty(prop->eProperty, prop->pValue, pComputedStyle);
117
118 for (auto* prop : customs)
119 pComputedStyle->AddCustomStyle(*prop);
120
121 for (auto* prop : importants)
122 ApplyProperty(prop->eProperty, prop->pValue, pComputedStyle);
123 }
124
ExtractValues(const CFX_CSSDeclaration * decl,std::vector<const CFX_CSSPropertyHolder * > * importants,std::vector<const CFX_CSSPropertyHolder * > * normals,std::vector<const CFX_CSSCustomProperty * > * custom)125 void CFX_CSSStyleSelector::ExtractValues(
126 const CFX_CSSDeclaration* decl,
127 std::vector<const CFX_CSSPropertyHolder*>* importants,
128 std::vector<const CFX_CSSPropertyHolder*>* normals,
129 std::vector<const CFX_CSSCustomProperty*>* custom) {
130 for (const auto& holder : *decl) {
131 if (holder->bImportant)
132 importants->push_back(holder.get());
133 else
134 normals->push_back(holder.get());
135 }
136 for (auto it = decl->custom_begin(); it != decl->custom_end(); it++)
137 custom->push_back(it->get());
138 }
139
AppendInlineStyle(CFX_CSSDeclaration * pDecl,const WideString & style)140 void CFX_CSSStyleSelector::AppendInlineStyle(CFX_CSSDeclaration* pDecl,
141 const WideString& style) {
142 ASSERT(pDecl);
143 ASSERT(!style.IsEmpty());
144
145 auto pSyntax = pdfium::MakeUnique<CFX_CSSSyntaxParser>(
146 style.c_str(), style.GetLength(), 32, true);
147 int32_t iLen2 = 0;
148 const CFX_CSSData::Property* property = nullptr;
149 WideString wsName;
150 while (1) {
151 CFX_CSSSyntaxStatus eStatus = pSyntax->DoSyntaxParse();
152 if (eStatus == CFX_CSSSyntaxStatus::PropertyName) {
153 WideStringView strValue = pSyntax->GetCurrentString();
154 property = CFX_CSSData::GetPropertyByName(strValue);
155 if (!property)
156 wsName = WideString(strValue);
157 } else if (eStatus == CFX_CSSSyntaxStatus::PropertyValue) {
158 if (property || iLen2 > 0) {
159 WideStringView strValue = pSyntax->GetCurrentString();
160 if (!strValue.IsEmpty()) {
161 if (property)
162 pDecl->AddProperty(property, strValue);
163 else if (iLen2 > 0)
164 pDecl->AddProperty(wsName, WideString(strValue));
165 }
166 }
167 } else {
168 break;
169 }
170 }
171 }
172
ApplyProperty(CFX_CSSProperty eProperty,const RetainPtr<CFX_CSSValue> & pValue,CFX_CSSComputedStyle * pComputedStyle)173 void CFX_CSSStyleSelector::ApplyProperty(CFX_CSSProperty eProperty,
174 const RetainPtr<CFX_CSSValue>& pValue,
175 CFX_CSSComputedStyle* pComputedStyle) {
176 if (pValue->GetType() != CFX_CSSPrimitiveType::List) {
177 CFX_CSSPrimitiveType eType = pValue->GetType();
178 switch (eProperty) {
179 case CFX_CSSProperty::Display:
180 if (eType == CFX_CSSPrimitiveType::Enum) {
181 pComputedStyle->m_NonInheritedData.m_eDisplay =
182 ToDisplay(pValue.As<CFX_CSSEnumValue>()->Value());
183 }
184 break;
185 case CFX_CSSProperty::FontSize: {
186 float& fFontSize = pComputedStyle->m_InheritedData.m_fFontSize;
187 if (eType == CFX_CSSPrimitiveType::Number) {
188 fFontSize = pValue.As<CFX_CSSNumberValue>()->Apply(fFontSize);
189 } else if (eType == CFX_CSSPrimitiveType::Enum) {
190 fFontSize =
191 ToFontSize(pValue.As<CFX_CSSEnumValue>()->Value(), fFontSize);
192 }
193 } break;
194 case CFX_CSSProperty::LineHeight:
195 if (eType == CFX_CSSPrimitiveType::Number) {
196 RetainPtr<CFX_CSSNumberValue> v = pValue.As<CFX_CSSNumberValue>();
197 if (v->Kind() == CFX_CSSNumberType::Number) {
198 pComputedStyle->m_InheritedData.m_fLineHeight =
199 v->Value() * pComputedStyle->m_InheritedData.m_fFontSize;
200 } else {
201 pComputedStyle->m_InheritedData.m_fLineHeight =
202 v->Apply(pComputedStyle->m_InheritedData.m_fFontSize);
203 }
204 }
205 break;
206 case CFX_CSSProperty::TextAlign:
207 if (eType == CFX_CSSPrimitiveType::Enum) {
208 pComputedStyle->m_InheritedData.m_eTextAlign =
209 ToTextAlign(pValue.As<CFX_CSSEnumValue>()->Value());
210 }
211 break;
212 case CFX_CSSProperty::TextIndent:
213 SetLengthWithPercent(pComputedStyle->m_InheritedData.m_TextIndent,
214 eType, pValue,
215 pComputedStyle->m_InheritedData.m_fFontSize);
216 break;
217 case CFX_CSSProperty::FontWeight:
218 if (eType == CFX_CSSPrimitiveType::Enum) {
219 pComputedStyle->m_InheritedData.m_wFontWeight =
220 ToFontWeight(pValue.As<CFX_CSSEnumValue>()->Value());
221 } else if (eType == CFX_CSSPrimitiveType::Number) {
222 int32_t iValue =
223 (int32_t)pValue.As<CFX_CSSNumberValue>()->Value() / 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_CSSPrimitiveType::Enum) {
231 pComputedStyle->m_InheritedData.m_eFontStyle =
232 ToFontStyle(pValue.As<CFX_CSSEnumValue>()->Value());
233 }
234 break;
235 case CFX_CSSProperty::Color:
236 if (eType == CFX_CSSPrimitiveType::RGB) {
237 pComputedStyle->m_InheritedData.m_dwFontColor =
238 pValue.As<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_CSSPrimitiveType::Enum) {
327 pComputedStyle->m_NonInheritedData.m_eVerticalAlign =
328 ToVerticalAlign(pValue.As<CFX_CSSEnumValue>()->Value());
329 } else if (eType == CFX_CSSPrimitiveType::Number) {
330 pComputedStyle->m_NonInheritedData.m_eVerticalAlign =
331 CFX_CSSVerticalAlign::Number;
332 pComputedStyle->m_NonInheritedData.m_fVerticalAlign =
333 pValue.As<CFX_CSSNumberValue>()->Apply(
334 pComputedStyle->m_InheritedData.m_fFontSize);
335 }
336 break;
337 case CFX_CSSProperty::FontVariant:
338 if (eType == CFX_CSSPrimitiveType::Enum) {
339 pComputedStyle->m_InheritedData.m_eFontVariant =
340 ToFontVariant(pValue.As<CFX_CSSEnumValue>()->Value());
341 }
342 break;
343 case CFX_CSSProperty::LetterSpacing:
344 if (eType == CFX_CSSPrimitiveType::Enum) {
345 pComputedStyle->m_InheritedData.m_LetterSpacing.Set(
346 CFX_CSSLengthUnit::Normal);
347 } else if (eType == CFX_CSSPrimitiveType::Number) {
348 if (pValue.As<CFX_CSSNumberValue>()->Kind() ==
349 CFX_CSSNumberType::Percent) {
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_CSSPrimitiveType::Enum) {
360 pComputedStyle->m_InheritedData.m_WordSpacing.Set(
361 CFX_CSSLengthUnit::Normal);
362 } else if (eType == CFX_CSSPrimitiveType::Number) {
363 if (pValue.As<CFX_CSSNumberValue>()->Kind() ==
364 CFX_CSSNumberType::Percent) {
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_CSSPrimitiveType::List) {
396 RetainPtr<CFX_CSSValueList> pList = pValue.As<CFX_CSSValueList>();
397 int32_t iCount = pList->CountValues();
398 if (iCount > 0) {
399 switch (eProperty) {
400 case CFX_CSSProperty::FontFamily:
401 pComputedStyle->m_InheritedData.m_pFontFamily = pList;
402 break;
403 case CFX_CSSProperty::TextDecoration:
404 pComputedStyle->m_NonInheritedData.m_dwTextDecoration =
405 ToTextDecoration(pList);
406 break;
407 default:
408 break;
409 }
410 }
411 } else {
412 NOTREACHED();
413 }
414 }
415
ToDisplay(CFX_CSSPropertyValue eValue)416 CFX_CSSDisplay CFX_CSSStyleSelector::ToDisplay(CFX_CSSPropertyValue eValue) {
417 switch (eValue) {
418 case CFX_CSSPropertyValue::Block:
419 return CFX_CSSDisplay::Block;
420 case CFX_CSSPropertyValue::None:
421 return CFX_CSSDisplay::None;
422 case CFX_CSSPropertyValue::ListItem:
423 return CFX_CSSDisplay::ListItem;
424 case CFX_CSSPropertyValue::InlineTable:
425 return CFX_CSSDisplay::InlineTable;
426 case CFX_CSSPropertyValue::InlineBlock:
427 return CFX_CSSDisplay::InlineBlock;
428 case CFX_CSSPropertyValue::Inline:
429 default:
430 return CFX_CSSDisplay::Inline;
431 }
432 }
433
ToTextAlign(CFX_CSSPropertyValue eValue)434 CFX_CSSTextAlign CFX_CSSStyleSelector::ToTextAlign(
435 CFX_CSSPropertyValue eValue) {
436 switch (eValue) {
437 case CFX_CSSPropertyValue::Center:
438 return CFX_CSSTextAlign::Center;
439 case CFX_CSSPropertyValue::Right:
440 return CFX_CSSTextAlign::Right;
441 case CFX_CSSPropertyValue::Justify:
442 return CFX_CSSTextAlign::Justify;
443 case CFX_CSSPropertyValue::Left:
444 default:
445 return CFX_CSSTextAlign::Left;
446 }
447 }
448
ToFontWeight(CFX_CSSPropertyValue eValue)449 uint16_t CFX_CSSStyleSelector::ToFontWeight(CFX_CSSPropertyValue eValue) {
450 switch (eValue) {
451 case CFX_CSSPropertyValue::Bold:
452 return 700;
453 case CFX_CSSPropertyValue::Bolder:
454 return 900;
455 case CFX_CSSPropertyValue::Lighter:
456 return 200;
457 case CFX_CSSPropertyValue::Normal:
458 default:
459 return 400;
460 }
461 }
462
ToFontStyle(CFX_CSSPropertyValue eValue)463 CFX_CSSFontStyle CFX_CSSStyleSelector::ToFontStyle(
464 CFX_CSSPropertyValue eValue) {
465 switch (eValue) {
466 case CFX_CSSPropertyValue::Italic:
467 case CFX_CSSPropertyValue::Oblique:
468 return CFX_CSSFontStyle::Italic;
469 default:
470 return CFX_CSSFontStyle::Normal;
471 }
472 }
473
SetLengthWithPercent(CFX_CSSLength & width,CFX_CSSPrimitiveType eType,const RetainPtr<CFX_CSSValue> & pValue,float fFontSize)474 bool CFX_CSSStyleSelector::SetLengthWithPercent(
475 CFX_CSSLength& width,
476 CFX_CSSPrimitiveType eType,
477 const RetainPtr<CFX_CSSValue>& pValue,
478 float fFontSize) {
479 if (eType == CFX_CSSPrimitiveType::Number) {
480 RetainPtr<CFX_CSSNumberValue> v = pValue.As<CFX_CSSNumberValue>();
481 if (v->Kind() == CFX_CSSNumberType::Percent) {
482 width.Set(CFX_CSSLengthUnit::Percent,
483 pValue.As<CFX_CSSNumberValue>()->Value() / 100.0f);
484 return width.NonZero();
485 }
486
487 float fValue = v->Apply(fFontSize);
488 width.Set(CFX_CSSLengthUnit::Point, fValue);
489 return width.NonZero();
490 } else if (eType == CFX_CSSPrimitiveType::Enum) {
491 switch (pValue.As<CFX_CSSEnumValue>()->Value()) {
492 case CFX_CSSPropertyValue::Auto:
493 width.Set(CFX_CSSLengthUnit::Auto);
494 return true;
495 case CFX_CSSPropertyValue::None:
496 width.Set(CFX_CSSLengthUnit::None);
497 return true;
498 case CFX_CSSPropertyValue::Thin:
499 width.Set(CFX_CSSLengthUnit::Point, 2);
500 return true;
501 case CFX_CSSPropertyValue::Medium:
502 width.Set(CFX_CSSLengthUnit::Point, 3);
503 return true;
504 case CFX_CSSPropertyValue::Thick:
505 width.Set(CFX_CSSLengthUnit::Point, 4);
506 return true;
507 default:
508 return false;
509 }
510 }
511 return false;
512 }
513
ToFontSize(CFX_CSSPropertyValue eValue,float fCurFontSize)514 float CFX_CSSStyleSelector::ToFontSize(CFX_CSSPropertyValue eValue,
515 float fCurFontSize) {
516 switch (eValue) {
517 case CFX_CSSPropertyValue::XxSmall:
518 return m_fDefFontSize / 1.2f / 1.2f / 1.2f;
519 case CFX_CSSPropertyValue::XSmall:
520 return m_fDefFontSize / 1.2f / 1.2f;
521 case CFX_CSSPropertyValue::Small:
522 return m_fDefFontSize / 1.2f;
523 case CFX_CSSPropertyValue::Medium:
524 return m_fDefFontSize;
525 case CFX_CSSPropertyValue::Large:
526 return m_fDefFontSize * 1.2f;
527 case CFX_CSSPropertyValue::XLarge:
528 return m_fDefFontSize * 1.2f * 1.2f;
529 case CFX_CSSPropertyValue::XxLarge:
530 return m_fDefFontSize * 1.2f * 1.2f * 1.2f;
531 case CFX_CSSPropertyValue::Larger:
532 return fCurFontSize * 1.2f;
533 case CFX_CSSPropertyValue::Smaller:
534 return fCurFontSize / 1.2f;
535 default:
536 return fCurFontSize;
537 }
538 }
539
ToVerticalAlign(CFX_CSSPropertyValue eValue)540 CFX_CSSVerticalAlign CFX_CSSStyleSelector::ToVerticalAlign(
541 CFX_CSSPropertyValue eValue) {
542 switch (eValue) {
543 case CFX_CSSPropertyValue::Middle:
544 return CFX_CSSVerticalAlign::Middle;
545 case CFX_CSSPropertyValue::Bottom:
546 return CFX_CSSVerticalAlign::Bottom;
547 case CFX_CSSPropertyValue::Super:
548 return CFX_CSSVerticalAlign::Super;
549 case CFX_CSSPropertyValue::Sub:
550 return CFX_CSSVerticalAlign::Sub;
551 case CFX_CSSPropertyValue::Top:
552 return CFX_CSSVerticalAlign::Top;
553 case CFX_CSSPropertyValue::TextTop:
554 return CFX_CSSVerticalAlign::TextTop;
555 case CFX_CSSPropertyValue::TextBottom:
556 return CFX_CSSVerticalAlign::TextBottom;
557 case CFX_CSSPropertyValue::Baseline:
558 default:
559 return CFX_CSSVerticalAlign::Baseline;
560 }
561 }
562
ToTextDecoration(const RetainPtr<CFX_CSSValueList> & pValue)563 uint32_t CFX_CSSStyleSelector::ToTextDecoration(
564 const RetainPtr<CFX_CSSValueList>& pValue) {
565 uint32_t dwDecoration = 0;
566 for (int32_t i = pValue->CountValues() - 1; i >= 0; --i) {
567 const RetainPtr<CFX_CSSValue> pVal = pValue->GetValue(i);
568 if (pVal->GetType() != CFX_CSSPrimitiveType::Enum)
569 continue;
570
571 switch (pVal.As<CFX_CSSEnumValue>()->Value()) {
572 case CFX_CSSPropertyValue::Underline:
573 dwDecoration |= CFX_CSSTEXTDECORATION_Underline;
574 break;
575 case CFX_CSSPropertyValue::LineThrough:
576 dwDecoration |= CFX_CSSTEXTDECORATION_LineThrough;
577 break;
578 case CFX_CSSPropertyValue::Overline:
579 dwDecoration |= CFX_CSSTEXTDECORATION_Overline;
580 break;
581 case CFX_CSSPropertyValue::Blink:
582 dwDecoration |= CFX_CSSTEXTDECORATION_Blink;
583 break;
584 case CFX_CSSPropertyValue::Double:
585 dwDecoration |= CFX_CSSTEXTDECORATION_Double;
586 break;
587 default:
588 break;
589 }
590 }
591 return dwDecoration;
592 }
593
ToFontVariant(CFX_CSSPropertyValue eValue)594 CFX_CSSFontVariant CFX_CSSStyleSelector::ToFontVariant(
595 CFX_CSSPropertyValue eValue) {
596 return eValue == CFX_CSSPropertyValue::SmallCaps
597 ? CFX_CSSFontVariant::SmallCaps
598 : CFX_CSSFontVariant::Normal;
599 }
600