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