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 "xfa/fde/css/cfde_cssstyleselector.h"
8
9 #include <algorithm>
10 #include <utility>
11
12 #include "third_party/base/ptr_util.h"
13 #include "xfa/fde/css/cfde_csscolorvalue.h"
14 #include "xfa/fde/css/cfde_csscomputedstyle.h"
15 #include "xfa/fde/css/cfde_csscustomproperty.h"
16 #include "xfa/fde/css/cfde_cssdeclaration.h"
17 #include "xfa/fde/css/cfde_cssenumvalue.h"
18 #include "xfa/fde/css/cfde_csspropertyholder.h"
19 #include "xfa/fde/css/cfde_cssselector.h"
20 #include "xfa/fde/css/cfde_cssstylesheet.h"
21 #include "xfa/fde/css/cfde_csssyntaxparser.h"
22 #include "xfa/fde/css/cfde_cssvaluelist.h"
23 #include "xfa/fxfa/app/cxfa_csstagprovider.h"
24
CFDE_CSSStyleSelector(CFGAS_FontMgr * pFontMgr)25 CFDE_CSSStyleSelector::CFDE_CSSStyleSelector(CFGAS_FontMgr* pFontMgr)
26 : m_pFontMgr(pFontMgr), m_fDefFontSize(12.0f) {}
27
~CFDE_CSSStyleSelector()28 CFDE_CSSStyleSelector::~CFDE_CSSStyleSelector() {}
29
SetDefFontSize(FX_FLOAT fFontSize)30 void CFDE_CSSStyleSelector::SetDefFontSize(FX_FLOAT fFontSize) {
31 ASSERT(fFontSize > 0);
32 m_fDefFontSize = fFontSize;
33 }
34
CreateComputedStyle(CFDE_CSSComputedStyle * pParentStyle)35 CFX_RetainPtr<CFDE_CSSComputedStyle> CFDE_CSSStyleSelector::CreateComputedStyle(
36 CFDE_CSSComputedStyle* pParentStyle) {
37 auto pStyle = pdfium::MakeRetain<CFDE_CSSComputedStyle>();
38 if (pParentStyle)
39 pStyle->m_InheritedData = pParentStyle->m_InheritedData;
40 return pStyle;
41 }
42
SetUAStyleSheet(std::unique_ptr<CFDE_CSSStyleSheet> pSheet)43 void CFDE_CSSStyleSelector::SetUAStyleSheet(
44 std::unique_ptr<CFDE_CSSStyleSheet> pSheet) {
45 m_UAStyles = std::move(pSheet);
46 }
47
UpdateStyleIndex()48 void CFDE_CSSStyleSelector::UpdateStyleIndex() {
49 m_UARules.Clear();
50 m_UARules.AddRulesFrom(m_UAStyles.get(), m_pFontMgr);
51 }
52
53 std::vector<const CFDE_CSSDeclaration*>
MatchDeclarations(const CFX_WideString & tagname)54 CFDE_CSSStyleSelector::MatchDeclarations(const CFX_WideString& tagname) {
55 std::vector<const CFDE_CSSDeclaration*> matchedDecls;
56 if (m_UARules.CountSelectors() == 0 || tagname.IsEmpty())
57 return matchedDecls;
58
59 auto rules = m_UARules.GetTagRuleData(tagname);
60 if (!rules)
61 return matchedDecls;
62
63 for (const auto& d : *rules) {
64 if (MatchSelector(tagname, d->pSelector))
65 matchedDecls.push_back(d->pDeclaration);
66 }
67 return matchedDecls;
68 }
69
MatchSelector(const CFX_WideString & tagname,CFDE_CSSSelector * pSel)70 bool CFDE_CSSStyleSelector::MatchSelector(const CFX_WideString& tagname,
71 CFDE_CSSSelector* pSel) {
72 // TODO(dsinclair): The code only supports a single level of selector at this
73 // point. None of the code using selectors required the complexity so lets
74 // just say we don't support them to simplify the code for now.
75 if (!pSel || pSel->GetNextSelector() ||
76 pSel->GetType() == FDE_CSSSelectorType::Descendant) {
77 return false;
78 }
79 return pSel->GetNameHash() == FX_HashCode_GetW(tagname.c_str(), true);
80 }
81
ComputeStyle(const std::vector<const CFDE_CSSDeclaration * > & declArray,const CFX_WideString & styleString,const CFX_WideString & alignString,CFDE_CSSComputedStyle * pDest)82 void CFDE_CSSStyleSelector::ComputeStyle(
83 const std::vector<const CFDE_CSSDeclaration*>& declArray,
84 const CFX_WideString& styleString,
85 const CFX_WideString& alignString,
86 CFDE_CSSComputedStyle* pDest) {
87 std::unique_ptr<CFDE_CSSDeclaration> pDecl;
88 if (!styleString.IsEmpty() || !alignString.IsEmpty()) {
89 pDecl = pdfium::MakeUnique<CFDE_CSSDeclaration>();
90
91 if (!styleString.IsEmpty())
92 AppendInlineStyle(pDecl.get(), styleString);
93 if (!alignString.IsEmpty()) {
94 pDecl->AddProperty(FDE_GetCSSPropertyByEnum(FDE_CSSProperty::TextAlign),
95 alignString.AsStringC());
96 }
97 }
98 ApplyDeclarations(declArray, pDecl.get(), pDest);
99 }
100
ApplyDeclarations(const std::vector<const CFDE_CSSDeclaration * > & declArray,const CFDE_CSSDeclaration * extraDecl,CFDE_CSSComputedStyle * pComputedStyle)101 void CFDE_CSSStyleSelector::ApplyDeclarations(
102 const std::vector<const CFDE_CSSDeclaration*>& declArray,
103 const CFDE_CSSDeclaration* extraDecl,
104 CFDE_CSSComputedStyle* pComputedStyle) {
105 std::vector<const CFDE_CSSPropertyHolder*> importants;
106 std::vector<const CFDE_CSSPropertyHolder*> normals;
107 std::vector<const CFDE_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 CFDE_CSSDeclaration * decl,std::vector<const CFDE_CSSPropertyHolder * > * importants,std::vector<const CFDE_CSSPropertyHolder * > * normals,std::vector<const CFDE_CSSCustomProperty * > * custom)125 void CFDE_CSSStyleSelector::ExtractValues(
126 const CFDE_CSSDeclaration* decl,
127 std::vector<const CFDE_CSSPropertyHolder*>* importants,
128 std::vector<const CFDE_CSSPropertyHolder*>* normals,
129 std::vector<const CFDE_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(CFDE_CSSDeclaration * pDecl,const CFX_WideString & style)140 void CFDE_CSSStyleSelector::AppendInlineStyle(CFDE_CSSDeclaration* pDecl,
141 const CFX_WideString& style) {
142 ASSERT(pDecl && !style.IsEmpty());
143
144 auto pSyntax = pdfium::MakeUnique<CFDE_CSSSyntaxParser>();
145 if (!pSyntax->Init(style.c_str(), style.GetLength(), 32, true))
146 return;
147
148 int32_t iLen2 = 0;
149 const FDE_CSSPropertyTable* table = nullptr;
150 CFX_WideString wsName;
151 while (1) {
152 FDE_CSSSyntaxStatus eStatus = pSyntax->DoSyntaxParse();
153 if (eStatus == FDE_CSSSyntaxStatus::PropertyName) {
154 CFX_WideStringC strValue = pSyntax->GetCurrentString();
155 table = FDE_GetCSSPropertyByName(strValue);
156 if (!table)
157 wsName = CFX_WideString(strValue);
158 } else if (eStatus == FDE_CSSSyntaxStatus::PropertyValue) {
159 if (table || iLen2 > 0) {
160 CFX_WideStringC strValue = pSyntax->GetCurrentString();
161 if (!strValue.IsEmpty()) {
162 if (table)
163 pDecl->AddProperty(table, strValue);
164 else if (iLen2 > 0)
165 pDecl->AddProperty(wsName, CFX_WideString(strValue));
166 }
167 }
168 } else {
169 break;
170 }
171 }
172 }
173
ApplyProperty(FDE_CSSProperty eProperty,const CFX_RetainPtr<CFDE_CSSValue> & pValue,CFDE_CSSComputedStyle * pComputedStyle)174 void CFDE_CSSStyleSelector::ApplyProperty(
175 FDE_CSSProperty eProperty,
176 const CFX_RetainPtr<CFDE_CSSValue>& pValue,
177 CFDE_CSSComputedStyle* pComputedStyle) {
178 if (pValue->GetType() != FDE_CSSPrimitiveType::List) {
179 FDE_CSSPrimitiveType eType = pValue->GetType();
180 switch (eProperty) {
181 case FDE_CSSProperty::Display:
182 if (eType == FDE_CSSPrimitiveType::Enum) {
183 pComputedStyle->m_NonInheritedData.m_eDisplay =
184 ToDisplay(pValue.As<CFDE_CSSEnumValue>()->Value());
185 }
186 break;
187 case FDE_CSSProperty::FontSize: {
188 FX_FLOAT& fFontSize = pComputedStyle->m_InheritedData.m_fFontSize;
189 if (eType == FDE_CSSPrimitiveType::Number) {
190 fFontSize = pValue.As<CFDE_CSSNumberValue>()->Apply(fFontSize);
191 } else if (eType == FDE_CSSPrimitiveType::Enum) {
192 fFontSize =
193 ToFontSize(pValue.As<CFDE_CSSEnumValue>()->Value(), fFontSize);
194 }
195 } break;
196 case FDE_CSSProperty::LineHeight:
197 if (eType == FDE_CSSPrimitiveType::Number) {
198 CFX_RetainPtr<CFDE_CSSNumberValue> v =
199 pValue.As<CFDE_CSSNumberValue>();
200 if (v->Kind() == FDE_CSSNumberType::Number) {
201 pComputedStyle->m_InheritedData.m_fLineHeight =
202 v->Value() * pComputedStyle->m_InheritedData.m_fFontSize;
203 } else {
204 pComputedStyle->m_InheritedData.m_fLineHeight =
205 v->Apply(pComputedStyle->m_InheritedData.m_fFontSize);
206 }
207 }
208 break;
209 case FDE_CSSProperty::TextAlign:
210 if (eType == FDE_CSSPrimitiveType::Enum) {
211 pComputedStyle->m_InheritedData.m_eTextAlign =
212 ToTextAlign(pValue.As<CFDE_CSSEnumValue>()->Value());
213 }
214 break;
215 case FDE_CSSProperty::TextIndent:
216 SetLengthWithPercent(pComputedStyle->m_InheritedData.m_TextIndent,
217 eType, pValue,
218 pComputedStyle->m_InheritedData.m_fFontSize);
219 break;
220 case FDE_CSSProperty::FontWeight:
221 if (eType == FDE_CSSPrimitiveType::Enum) {
222 pComputedStyle->m_InheritedData.m_wFontWeight =
223 ToFontWeight(pValue.As<CFDE_CSSEnumValue>()->Value());
224 } else if (eType == FDE_CSSPrimitiveType::Number) {
225 int32_t iValue =
226 (int32_t)pValue.As<CFDE_CSSNumberValue>()->Value() / 100;
227 if (iValue >= 1 && iValue <= 9) {
228 pComputedStyle->m_InheritedData.m_wFontWeight = iValue * 100;
229 }
230 }
231 break;
232 case FDE_CSSProperty::FontStyle:
233 if (eType == FDE_CSSPrimitiveType::Enum) {
234 pComputedStyle->m_InheritedData.m_eFontStyle =
235 ToFontStyle(pValue.As<CFDE_CSSEnumValue>()->Value());
236 }
237 break;
238 case FDE_CSSProperty::Color:
239 if (eType == FDE_CSSPrimitiveType::RGB) {
240 pComputedStyle->m_InheritedData.m_dwFontColor =
241 pValue.As<CFDE_CSSColorValue>()->Value();
242 }
243 break;
244 case FDE_CSSProperty::MarginLeft:
245 if (SetLengthWithPercent(
246 pComputedStyle->m_NonInheritedData.m_MarginWidth.left, eType,
247 pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
248 pComputedStyle->m_NonInheritedData.m_bHasMargin = true;
249 }
250 break;
251 case FDE_CSSProperty::MarginTop:
252 if (SetLengthWithPercent(
253 pComputedStyle->m_NonInheritedData.m_MarginWidth.top, eType,
254 pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
255 pComputedStyle->m_NonInheritedData.m_bHasMargin = true;
256 }
257 break;
258 case FDE_CSSProperty::MarginRight:
259 if (SetLengthWithPercent(
260 pComputedStyle->m_NonInheritedData.m_MarginWidth.right, eType,
261 pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
262 pComputedStyle->m_NonInheritedData.m_bHasMargin = true;
263 }
264 break;
265 case FDE_CSSProperty::MarginBottom:
266 if (SetLengthWithPercent(
267 pComputedStyle->m_NonInheritedData.m_MarginWidth.bottom, eType,
268 pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
269 pComputedStyle->m_NonInheritedData.m_bHasMargin = true;
270 }
271 break;
272 case FDE_CSSProperty::PaddingLeft:
273 if (SetLengthWithPercent(
274 pComputedStyle->m_NonInheritedData.m_PaddingWidth.left, eType,
275 pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
276 pComputedStyle->m_NonInheritedData.m_bHasPadding = true;
277 }
278 break;
279 case FDE_CSSProperty::PaddingTop:
280 if (SetLengthWithPercent(
281 pComputedStyle->m_NonInheritedData.m_PaddingWidth.top, eType,
282 pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
283 pComputedStyle->m_NonInheritedData.m_bHasPadding = true;
284 }
285 break;
286 case FDE_CSSProperty::PaddingRight:
287 if (SetLengthWithPercent(
288 pComputedStyle->m_NonInheritedData.m_PaddingWidth.right, eType,
289 pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
290 pComputedStyle->m_NonInheritedData.m_bHasPadding = true;
291 }
292 break;
293 case FDE_CSSProperty::PaddingBottom:
294 if (SetLengthWithPercent(
295 pComputedStyle->m_NonInheritedData.m_PaddingWidth.bottom, eType,
296 pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
297 pComputedStyle->m_NonInheritedData.m_bHasPadding = true;
298 }
299 break;
300 case FDE_CSSProperty::BorderLeftWidth:
301 if (SetLengthWithPercent(
302 pComputedStyle->m_NonInheritedData.m_BorderWidth.left, eType,
303 pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
304 pComputedStyle->m_NonInheritedData.m_bHasBorder = true;
305 }
306 break;
307 case FDE_CSSProperty::BorderTopWidth:
308 if (SetLengthWithPercent(
309 pComputedStyle->m_NonInheritedData.m_BorderWidth.top, eType,
310 pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
311 pComputedStyle->m_NonInheritedData.m_bHasBorder = true;
312 }
313 break;
314 case FDE_CSSProperty::BorderRightWidth:
315 if (SetLengthWithPercent(
316 pComputedStyle->m_NonInheritedData.m_BorderWidth.right, eType,
317 pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
318 pComputedStyle->m_NonInheritedData.m_bHasBorder = true;
319 }
320 break;
321 case FDE_CSSProperty::BorderBottomWidth:
322 if (SetLengthWithPercent(
323 pComputedStyle->m_NonInheritedData.m_BorderWidth.bottom, eType,
324 pValue, pComputedStyle->m_InheritedData.m_fFontSize)) {
325 pComputedStyle->m_NonInheritedData.m_bHasBorder = true;
326 }
327 break;
328 case FDE_CSSProperty::VerticalAlign:
329 if (eType == FDE_CSSPrimitiveType::Enum) {
330 pComputedStyle->m_NonInheritedData.m_eVerticalAlign =
331 ToVerticalAlign(pValue.As<CFDE_CSSEnumValue>()->Value());
332 } else if (eType == FDE_CSSPrimitiveType::Number) {
333 pComputedStyle->m_NonInheritedData.m_eVerticalAlign =
334 FDE_CSSVerticalAlign::Number;
335 pComputedStyle->m_NonInheritedData.m_fVerticalAlign =
336 pValue.As<CFDE_CSSNumberValue>()->Apply(
337 pComputedStyle->m_InheritedData.m_fFontSize);
338 }
339 break;
340 case FDE_CSSProperty::FontVariant:
341 if (eType == FDE_CSSPrimitiveType::Enum) {
342 pComputedStyle->m_InheritedData.m_eFontVariant =
343 ToFontVariant(pValue.As<CFDE_CSSEnumValue>()->Value());
344 }
345 break;
346 case FDE_CSSProperty::LetterSpacing:
347 if (eType == FDE_CSSPrimitiveType::Enum) {
348 pComputedStyle->m_InheritedData.m_LetterSpacing.Set(
349 FDE_CSSLengthUnit::Normal);
350 } else if (eType == FDE_CSSPrimitiveType::Number) {
351 if (pValue.As<CFDE_CSSNumberValue>()->Kind() ==
352 FDE_CSSNumberType::Percent) {
353 break;
354 }
355
356 SetLengthWithPercent(pComputedStyle->m_InheritedData.m_LetterSpacing,
357 eType, pValue,
358 pComputedStyle->m_InheritedData.m_fFontSize);
359 }
360 break;
361 case FDE_CSSProperty::WordSpacing:
362 if (eType == FDE_CSSPrimitiveType::Enum) {
363 pComputedStyle->m_InheritedData.m_WordSpacing.Set(
364 FDE_CSSLengthUnit::Normal);
365 } else if (eType == FDE_CSSPrimitiveType::Number) {
366 if (pValue.As<CFDE_CSSNumberValue>()->Kind() ==
367 FDE_CSSNumberType::Percent) {
368 break;
369 }
370 SetLengthWithPercent(pComputedStyle->m_InheritedData.m_WordSpacing,
371 eType, pValue,
372 pComputedStyle->m_InheritedData.m_fFontSize);
373 }
374 break;
375 case FDE_CSSProperty::Top:
376 SetLengthWithPercent(pComputedStyle->m_NonInheritedData.m_Top, eType,
377 pValue,
378 pComputedStyle->m_InheritedData.m_fFontSize);
379 break;
380 case FDE_CSSProperty::Bottom:
381 SetLengthWithPercent(pComputedStyle->m_NonInheritedData.m_Bottom, eType,
382 pValue,
383 pComputedStyle->m_InheritedData.m_fFontSize);
384 break;
385 case FDE_CSSProperty::Left:
386 SetLengthWithPercent(pComputedStyle->m_NonInheritedData.m_Left, eType,
387 pValue,
388 pComputedStyle->m_InheritedData.m_fFontSize);
389 break;
390 case FDE_CSSProperty::Right:
391 SetLengthWithPercent(pComputedStyle->m_NonInheritedData.m_Right, eType,
392 pValue,
393 pComputedStyle->m_InheritedData.m_fFontSize);
394 break;
395 default:
396 break;
397 }
398 } else if (pValue->GetType() == FDE_CSSPrimitiveType::List) {
399 CFX_RetainPtr<CFDE_CSSValueList> pList = pValue.As<CFDE_CSSValueList>();
400 int32_t iCount = pList->CountValues();
401 if (iCount > 0) {
402 switch (eProperty) {
403 case FDE_CSSProperty::FontFamily:
404 pComputedStyle->m_InheritedData.m_pFontFamily = pList;
405 break;
406 case FDE_CSSProperty::TextDecoration:
407 pComputedStyle->m_NonInheritedData.m_dwTextDecoration =
408 ToTextDecoration(pList);
409 break;
410 default:
411 break;
412 }
413 }
414 } else {
415 ASSERT(false);
416 }
417 }
418
ToDisplay(FDE_CSSPropertyValue eValue)419 FDE_CSSDisplay CFDE_CSSStyleSelector::ToDisplay(FDE_CSSPropertyValue eValue) {
420 switch (eValue) {
421 case FDE_CSSPropertyValue::Block:
422 return FDE_CSSDisplay::Block;
423 case FDE_CSSPropertyValue::None:
424 return FDE_CSSDisplay::None;
425 case FDE_CSSPropertyValue::ListItem:
426 return FDE_CSSDisplay::ListItem;
427 case FDE_CSSPropertyValue::InlineTable:
428 return FDE_CSSDisplay::InlineTable;
429 case FDE_CSSPropertyValue::InlineBlock:
430 return FDE_CSSDisplay::InlineBlock;
431 case FDE_CSSPropertyValue::Inline:
432 default:
433 return FDE_CSSDisplay::Inline;
434 }
435 }
436
ToTextAlign(FDE_CSSPropertyValue eValue)437 FDE_CSSTextAlign CFDE_CSSStyleSelector::ToTextAlign(
438 FDE_CSSPropertyValue eValue) {
439 switch (eValue) {
440 case FDE_CSSPropertyValue::Center:
441 return FDE_CSSTextAlign::Center;
442 case FDE_CSSPropertyValue::Right:
443 return FDE_CSSTextAlign::Right;
444 case FDE_CSSPropertyValue::Justify:
445 return FDE_CSSTextAlign::Justify;
446 case FDE_CSSPropertyValue::Left:
447 default:
448 return FDE_CSSTextAlign::Left;
449 }
450 }
451
ToFontWeight(FDE_CSSPropertyValue eValue)452 uint16_t CFDE_CSSStyleSelector::ToFontWeight(FDE_CSSPropertyValue eValue) {
453 switch (eValue) {
454 case FDE_CSSPropertyValue::Bold:
455 return 700;
456 case FDE_CSSPropertyValue::Bolder:
457 return 900;
458 case FDE_CSSPropertyValue::Lighter:
459 return 200;
460 case FDE_CSSPropertyValue::Normal:
461 default:
462 return 400;
463 }
464 }
465
ToFontStyle(FDE_CSSPropertyValue eValue)466 FDE_CSSFontStyle CFDE_CSSStyleSelector::ToFontStyle(
467 FDE_CSSPropertyValue eValue) {
468 switch (eValue) {
469 case FDE_CSSPropertyValue::Italic:
470 case FDE_CSSPropertyValue::Oblique:
471 return FDE_CSSFontStyle::Italic;
472 default:
473 return FDE_CSSFontStyle::Normal;
474 }
475 }
476
SetLengthWithPercent(FDE_CSSLength & width,FDE_CSSPrimitiveType eType,const CFX_RetainPtr<CFDE_CSSValue> & pValue,FX_FLOAT fFontSize)477 bool CFDE_CSSStyleSelector::SetLengthWithPercent(
478 FDE_CSSLength& width,
479 FDE_CSSPrimitiveType eType,
480 const CFX_RetainPtr<CFDE_CSSValue>& pValue,
481 FX_FLOAT fFontSize) {
482 if (eType == FDE_CSSPrimitiveType::Number) {
483 CFX_RetainPtr<CFDE_CSSNumberValue> v = pValue.As<CFDE_CSSNumberValue>();
484 if (v->Kind() == FDE_CSSNumberType::Percent) {
485 width.Set(FDE_CSSLengthUnit::Percent,
486 pValue.As<CFDE_CSSNumberValue>()->Value() / 100.0f);
487 return width.NonZero();
488 }
489
490 FX_FLOAT fValue = v->Apply(fFontSize);
491 width.Set(FDE_CSSLengthUnit::Point, fValue);
492 return width.NonZero();
493 } else if (eType == FDE_CSSPrimitiveType::Enum) {
494 switch (pValue.As<CFDE_CSSEnumValue>()->Value()) {
495 case FDE_CSSPropertyValue::Auto:
496 width.Set(FDE_CSSLengthUnit::Auto);
497 return true;
498 case FDE_CSSPropertyValue::None:
499 width.Set(FDE_CSSLengthUnit::None);
500 return true;
501 case FDE_CSSPropertyValue::Thin:
502 width.Set(FDE_CSSLengthUnit::Point, 2);
503 return true;
504 case FDE_CSSPropertyValue::Medium:
505 width.Set(FDE_CSSLengthUnit::Point, 3);
506 return true;
507 case FDE_CSSPropertyValue::Thick:
508 width.Set(FDE_CSSLengthUnit::Point, 4);
509 return true;
510 default:
511 return false;
512 }
513 }
514 return false;
515 }
516
ToFontSize(FDE_CSSPropertyValue eValue,FX_FLOAT fCurFontSize)517 FX_FLOAT CFDE_CSSStyleSelector::ToFontSize(FDE_CSSPropertyValue eValue,
518 FX_FLOAT fCurFontSize) {
519 switch (eValue) {
520 case FDE_CSSPropertyValue::XxSmall:
521 return m_fDefFontSize / 1.2f / 1.2f / 1.2f;
522 case FDE_CSSPropertyValue::XSmall:
523 return m_fDefFontSize / 1.2f / 1.2f;
524 case FDE_CSSPropertyValue::Small:
525 return m_fDefFontSize / 1.2f;
526 case FDE_CSSPropertyValue::Medium:
527 return m_fDefFontSize;
528 case FDE_CSSPropertyValue::Large:
529 return m_fDefFontSize * 1.2f;
530 case FDE_CSSPropertyValue::XLarge:
531 return m_fDefFontSize * 1.2f * 1.2f;
532 case FDE_CSSPropertyValue::XxLarge:
533 return m_fDefFontSize * 1.2f * 1.2f * 1.2f;
534 case FDE_CSSPropertyValue::Larger:
535 return fCurFontSize * 1.2f;
536 case FDE_CSSPropertyValue::Smaller:
537 return fCurFontSize / 1.2f;
538 default:
539 return fCurFontSize;
540 }
541 }
542
ToVerticalAlign(FDE_CSSPropertyValue eValue)543 FDE_CSSVerticalAlign CFDE_CSSStyleSelector::ToVerticalAlign(
544 FDE_CSSPropertyValue eValue) {
545 switch (eValue) {
546 case FDE_CSSPropertyValue::Middle:
547 return FDE_CSSVerticalAlign::Middle;
548 case FDE_CSSPropertyValue::Bottom:
549 return FDE_CSSVerticalAlign::Bottom;
550 case FDE_CSSPropertyValue::Super:
551 return FDE_CSSVerticalAlign::Super;
552 case FDE_CSSPropertyValue::Sub:
553 return FDE_CSSVerticalAlign::Sub;
554 case FDE_CSSPropertyValue::Top:
555 return FDE_CSSVerticalAlign::Top;
556 case FDE_CSSPropertyValue::TextTop:
557 return FDE_CSSVerticalAlign::TextTop;
558 case FDE_CSSPropertyValue::TextBottom:
559 return FDE_CSSVerticalAlign::TextBottom;
560 case FDE_CSSPropertyValue::Baseline:
561 default:
562 return FDE_CSSVerticalAlign::Baseline;
563 }
564 }
565
ToTextDecoration(const CFX_RetainPtr<CFDE_CSSValueList> & pValue)566 uint32_t CFDE_CSSStyleSelector::ToTextDecoration(
567 const CFX_RetainPtr<CFDE_CSSValueList>& pValue) {
568 uint32_t dwDecoration = 0;
569 for (int32_t i = pValue->CountValues() - 1; i >= 0; --i) {
570 const CFX_RetainPtr<CFDE_CSSValue> pVal = pValue->GetValue(i);
571 if (pVal->GetType() != FDE_CSSPrimitiveType::Enum)
572 continue;
573
574 switch (pVal.As<CFDE_CSSEnumValue>()->Value()) {
575 case FDE_CSSPropertyValue::Underline:
576 dwDecoration |= FDE_CSSTEXTDECORATION_Underline;
577 break;
578 case FDE_CSSPropertyValue::LineThrough:
579 dwDecoration |= FDE_CSSTEXTDECORATION_LineThrough;
580 break;
581 case FDE_CSSPropertyValue::Overline:
582 dwDecoration |= FDE_CSSTEXTDECORATION_Overline;
583 break;
584 case FDE_CSSPropertyValue::Blink:
585 dwDecoration |= FDE_CSSTEXTDECORATION_Blink;
586 break;
587 case FDE_CSSPropertyValue::Double:
588 dwDecoration |= FDE_CSSTEXTDECORATION_Double;
589 break;
590 default:
591 break;
592 }
593 }
594 return dwDecoration;
595 }
596
ToFontVariant(FDE_CSSPropertyValue eValue)597 FDE_CSSFontVariant CFDE_CSSStyleSelector::ToFontVariant(
598 FDE_CSSPropertyValue eValue) {
599 return eValue == FDE_CSSPropertyValue::SmallCaps
600 ? FDE_CSSFontVariant::SmallCaps
601 : FDE_CSSFontVariant::Normal;
602 }
603