| // Copyright 2014 PDFium Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
| #include "core/fxcrt/css/cfx_cssstyleselector.h" | |
| #include <algorithm> | |
| #include <utility> | |
| #include "core/fxcrt/css/cfx_csscolorvalue.h" | |
| #include "core/fxcrt/css/cfx_csscomputedstyle.h" | |
| #include "core/fxcrt/css/cfx_csscustomproperty.h" | |
| #include "core/fxcrt/css/cfx_cssdeclaration.h" | |
| #include "core/fxcrt/css/cfx_cssenumvalue.h" | |
| #include "core/fxcrt/css/cfx_csspropertyholder.h" | |
| #include "core/fxcrt/css/cfx_cssselector.h" | |
| #include "core/fxcrt/css/cfx_cssstylesheet.h" | |
| #include "core/fxcrt/css/cfx_csssyntaxparser.h" | |
| #include "core/fxcrt/css/cfx_cssvaluelist.h" | |
| #include "third_party/base/containers/adapters.h" | |
| #include "third_party/base/logging.h" | |
| CFX_CSSStyleSelector::CFX_CSSStyleSelector() = default; | |
| CFX_CSSStyleSelector::~CFX_CSSStyleSelector() = default; | |
| void CFX_CSSStyleSelector::SetDefaultFontSize(float fFontSize) { | |
| ASSERT(fFontSize > 0); | |
| m_fDefaultFontSize = fFontSize; | |
| } | |
| RetainPtr<CFX_CSSComputedStyle> CFX_CSSStyleSelector::CreateComputedStyle( | |
| const CFX_CSSComputedStyle* pParentStyle) { | |
| auto pStyle = pdfium::MakeRetain<CFX_CSSComputedStyle>(); | |
| if (pParentStyle) | |
| pStyle->m_InheritedData = pParentStyle->m_InheritedData; | |
| return pStyle; | |
| } | |
| void CFX_CSSStyleSelector::SetUAStyleSheet( | |
| std::unique_ptr<CFX_CSSStyleSheet> pSheet) { | |
| m_UAStyles = std::move(pSheet); | |
| } | |
| void CFX_CSSStyleSelector::UpdateStyleIndex() { | |
| m_UARules.Clear(); | |
| m_UARules.AddRulesFrom(m_UAStyles.get()); | |
| } | |
| std::vector<const CFX_CSSDeclaration*> CFX_CSSStyleSelector::MatchDeclarations( | |
| const WideString& tagname) { | |
| std::vector<const CFX_CSSDeclaration*> matchedDecls; | |
| if (m_UARules.CountSelectors() == 0 || tagname.IsEmpty()) | |
| return matchedDecls; | |
| auto* rules = m_UARules.GetTagRuleData(tagname); | |
| if (!rules) | |
| return matchedDecls; | |
| for (const auto& d : *rules) { | |
| if (MatchSelector(tagname, d->pSelector)) | |
| matchedDecls.push_back(d->pDeclaration); | |
| } | |
| return matchedDecls; | |
| } | |
| bool CFX_CSSStyleSelector::MatchSelector(const WideString& tagname, | |
| CFX_CSSSelector* pSel) { | |
| // TODO(dsinclair): The code only supports a single level of selector at this | |
| // point. None of the code using selectors required the complexity so lets | |
| // just say we don't support them to simplify the code for now. | |
| if (!pSel || pSel->next_selector() || pSel->is_descendant()) | |
| return false; | |
| return pSel->name_hash() == FX_HashCode_GetW(tagname.AsStringView(), true); | |
| } | |
| void CFX_CSSStyleSelector::ComputeStyle( | |
| const std::vector<const CFX_CSSDeclaration*>& declArray, | |
| const WideString& styleString, | |
| const WideString& alignString, | |
| CFX_CSSComputedStyle* pDest) { | |
| std::unique_ptr<CFX_CSSDeclaration> pDecl; | |
| if (!styleString.IsEmpty() || !alignString.IsEmpty()) { | |
| pDecl = std::make_unique<CFX_CSSDeclaration>(); | |
| if (!styleString.IsEmpty()) | |
| AppendInlineStyle(pDecl.get(), styleString); | |
| if (!alignString.IsEmpty()) { | |
| pDecl->AddProperty( | |
| CFX_CSSData::GetPropertyByEnum(CFX_CSSProperty::TextAlign), | |
| alignString.AsStringView()); | |
| } | |
| } | |
| ApplyDeclarations(declArray, pDecl.get(), pDest); | |
| } | |
| void CFX_CSSStyleSelector::ApplyDeclarations( | |
| const std::vector<const CFX_CSSDeclaration*>& declArray, | |
| const CFX_CSSDeclaration* extraDecl, | |
| CFX_CSSComputedStyle* pComputedStyle) { | |
| std::vector<const CFX_CSSPropertyHolder*> importants; | |
| std::vector<const CFX_CSSPropertyHolder*> normals; | |
| std::vector<const CFX_CSSCustomProperty*> customs; | |
| for (auto* decl : declArray) | |
| ExtractValues(decl, &importants, &normals, &customs); | |
| if (extraDecl) | |
| ExtractValues(extraDecl, &importants, &normals, &customs); | |
| for (auto* prop : normals) | |
| ApplyProperty(prop->eProperty, prop->pValue, pComputedStyle); | |
| for (auto* prop : customs) | |
| pComputedStyle->AddCustomStyle(*prop); | |
| for (auto* prop : importants) | |
| ApplyProperty(prop->eProperty, prop->pValue, pComputedStyle); | |
| } | |
| void CFX_CSSStyleSelector::ExtractValues( | |
| const CFX_CSSDeclaration* decl, | |
| std::vector<const CFX_CSSPropertyHolder*>* importants, | |
| std::vector<const CFX_CSSPropertyHolder*>* normals, | |
| std::vector<const CFX_CSSCustomProperty*>* custom) { | |
| for (const auto& holder : *decl) { | |
| if (holder->bImportant) | |
| importants->push_back(holder.get()); | |
| else | |
| normals->push_back(holder.get()); | |
| } | |
| for (auto it = decl->custom_begin(); it != decl->custom_end(); it++) | |
| custom->push_back(it->get()); | |
| } | |
| void CFX_CSSStyleSelector::AppendInlineStyle(CFX_CSSDeclaration* pDecl, | |
| const WideString& style) { | |
| ASSERT(pDecl); | |
| ASSERT(!style.IsEmpty()); | |
| auto pSyntax = std::make_unique<CFX_CSSSyntaxParser>(style.AsStringView()); | |
| pSyntax->SetParseOnlyDeclarations(); | |
| int32_t iLen2 = 0; | |
| const CFX_CSSData::Property* property = nullptr; | |
| WideString wsName; | |
| while (1) { | |
| CFX_CSSSyntaxStatus eStatus = pSyntax->DoSyntaxParse(); | |
| if (eStatus == CFX_CSSSyntaxStatus::kPropertyName) { | |
| WideStringView strValue = pSyntax->GetCurrentString(); | |
| property = CFX_CSSData::GetPropertyByName(strValue); | |
| if (!property) | |
| wsName = WideString(strValue); | |
| } else if (eStatus == CFX_CSSSyntaxStatus::kPropertyValue) { | |
| if (property || iLen2 > 0) { | |
| WideStringView strValue = pSyntax->GetCurrentString(); | |
| if (!strValue.IsEmpty()) { | |
| if (property) | |
| pDecl->AddProperty(property, strValue); | |
| else if (iLen2 > 0) | |
| pDecl->AddProperty(wsName, WideString(strValue)); | |
| } | |
| } | |
| } else { | |
| break; | |
| } | |
| } | |
| } | |
| void CFX_CSSStyleSelector::ApplyProperty(CFX_CSSProperty eProperty, | |
| const RetainPtr<CFX_CSSValue>& pValue, | |
| CFX_CSSComputedStyle* pComputedStyle) { | |
| if (pValue->GetType() != CFX_CSSPrimitiveType::List) { | |
| CFX_CSSPrimitiveType eType = pValue->GetType(); | |
| switch (eProperty) { | |
| case CFX_CSSProperty::Display: | |
| if (eType == CFX_CSSPrimitiveType::Enum) { | |
| pComputedStyle->m_NonInheritedData.m_eDisplay = | |
| ToDisplay(pValue.As<CFX_CSSEnumValue>()->Value()); | |
| } | |
| break; | |
| case CFX_CSSProperty::FontSize: { | |
| float& fFontSize = pComputedStyle->m_InheritedData.m_fFontSize; | |
| if (eType == CFX_CSSPrimitiveType::Number) { | |
| fFontSize = pValue.As<CFX_CSSNumberValue>()->Apply(fFontSize); | |
| } else if (eType == CFX_CSSPrimitiveType::Enum) { | |
| fFontSize = | |
| ToFontSize(pValue.As<CFX_CSSEnumValue>()->Value(), fFontSize); | |
| } | |
| } break; | |
| case CFX_CSSProperty::LineHeight: | |
| if (eType == CFX_CSSPrimitiveType::Number) { | |
| RetainPtr<CFX_CSSNumberValue> v = pValue.As<CFX_CSSNumberValue>(); | |
| if (v->Kind() == CFX_CSSNumberType::Number) { | |
| pComputedStyle->m_InheritedData.m_fLineHeight = | |
| v->Value() * pComputedStyle->m_InheritedData.m_fFontSize; | |
| } else { | |
| pComputedStyle->m_InheritedData.m_fLineHeight = | |
| v->Apply(pComputedStyle->m_InheritedData.m_fFontSize); | |
| } | |
| } | |
| break; | |
| case CFX_CSSProperty::TextAlign: | |
| if (eType == CFX_CSSPrimitiveType::Enum) { | |
| pComputedStyle->m_InheritedData.m_eTextAlign = | |
| ToTextAlign(pValue.As<CFX_CSSEnumValue>()->Value()); | |
| } | |
| break; | |
| case CFX_CSSProperty::TextIndent: | |
| SetLengthWithPercent(pComputedStyle->m_InheritedData.m_TextIndent, | |
| eType, pValue, | |
| pComputedStyle->m_InheritedData.m_fFontSize); | |
| break; | |
| case CFX_CSSProperty::FontWeight: | |
| if (eType == CFX_CSSPrimitiveType::Enum) { | |
| pComputedStyle->m_InheritedData.m_wFontWeight = | |
| ToFontWeight(pValue.As<CFX_CSSEnumValue>()->Value()); | |
| } else if (eType == CFX_CSSPrimitiveType::Number) { | |
| int32_t iValue = | |
| (int32_t)pValue.As<CFX_CSSNumberValue>()->Value() / 100; | |
| if (iValue >= 1 && iValue <= 9) { | |
| pComputedStyle->m_InheritedData.m_wFontWeight = iValue * 100; | |
| } | |
| } | |
| break; | |
| case CFX_CSSProperty::FontStyle: | |
| if (eType == CFX_CSSPrimitiveType::Enum) { | |
| pComputedStyle->m_InheritedData.m_eFontStyle = | |
| ToFontStyle(pValue.As<CFX_CSSEnumValue>()->Value()); | |
| } | |
| break; | |
| case CFX_CSSProperty::Color: | |
| if (eType == CFX_CSSPrimitiveType::RGB) { | |
| pComputedStyle->m_InheritedData.m_dwFontColor = | |
| pValue.As<CFX_CSSColorValue>()->Value(); | |
| } | |
| break; | |
| case CFX_CSSProperty::MarginLeft: | |
| if (SetLengthWithPercent( | |
| pComputedStyle->m_NonInheritedData.m_MarginWidth.left, eType, | |
| pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { | |
| pComputedStyle->m_NonInheritedData.m_bHasMargin = true; | |
| } | |
| break; | |
| case CFX_CSSProperty::MarginTop: | |
| if (SetLengthWithPercent( | |
| pComputedStyle->m_NonInheritedData.m_MarginWidth.top, eType, | |
| pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { | |
| pComputedStyle->m_NonInheritedData.m_bHasMargin = true; | |
| } | |
| break; | |
| case CFX_CSSProperty::MarginRight: | |
| if (SetLengthWithPercent( | |
| pComputedStyle->m_NonInheritedData.m_MarginWidth.right, eType, | |
| pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { | |
| pComputedStyle->m_NonInheritedData.m_bHasMargin = true; | |
| } | |
| break; | |
| case CFX_CSSProperty::MarginBottom: | |
| if (SetLengthWithPercent( | |
| pComputedStyle->m_NonInheritedData.m_MarginWidth.bottom, eType, | |
| pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { | |
| pComputedStyle->m_NonInheritedData.m_bHasMargin = true; | |
| } | |
| break; | |
| case CFX_CSSProperty::PaddingLeft: | |
| if (SetLengthWithPercent( | |
| pComputedStyle->m_NonInheritedData.m_PaddingWidth.left, eType, | |
| pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { | |
| pComputedStyle->m_NonInheritedData.m_bHasPadding = true; | |
| } | |
| break; | |
| case CFX_CSSProperty::PaddingTop: | |
| if (SetLengthWithPercent( | |
| pComputedStyle->m_NonInheritedData.m_PaddingWidth.top, eType, | |
| pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { | |
| pComputedStyle->m_NonInheritedData.m_bHasPadding = true; | |
| } | |
| break; | |
| case CFX_CSSProperty::PaddingRight: | |
| if (SetLengthWithPercent( | |
| pComputedStyle->m_NonInheritedData.m_PaddingWidth.right, eType, | |
| pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { | |
| pComputedStyle->m_NonInheritedData.m_bHasPadding = true; | |
| } | |
| break; | |
| case CFX_CSSProperty::PaddingBottom: | |
| if (SetLengthWithPercent( | |
| pComputedStyle->m_NonInheritedData.m_PaddingWidth.bottom, eType, | |
| pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { | |
| pComputedStyle->m_NonInheritedData.m_bHasPadding = true; | |
| } | |
| break; | |
| case CFX_CSSProperty::BorderLeftWidth: | |
| if (SetLengthWithPercent( | |
| pComputedStyle->m_NonInheritedData.m_BorderWidth.left, eType, | |
| pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { | |
| pComputedStyle->m_NonInheritedData.m_bHasBorder = true; | |
| } | |
| break; | |
| case CFX_CSSProperty::BorderTopWidth: | |
| if (SetLengthWithPercent( | |
| pComputedStyle->m_NonInheritedData.m_BorderWidth.top, eType, | |
| pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { | |
| pComputedStyle->m_NonInheritedData.m_bHasBorder = true; | |
| } | |
| break; | |
| case CFX_CSSProperty::BorderRightWidth: | |
| if (SetLengthWithPercent( | |
| pComputedStyle->m_NonInheritedData.m_BorderWidth.right, eType, | |
| pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { | |
| pComputedStyle->m_NonInheritedData.m_bHasBorder = true; | |
| } | |
| break; | |
| case CFX_CSSProperty::BorderBottomWidth: | |
| if (SetLengthWithPercent( | |
| pComputedStyle->m_NonInheritedData.m_BorderWidth.bottom, eType, | |
| pValue, pComputedStyle->m_InheritedData.m_fFontSize)) { | |
| pComputedStyle->m_NonInheritedData.m_bHasBorder = true; | |
| } | |
| break; | |
| case CFX_CSSProperty::VerticalAlign: | |
| if (eType == CFX_CSSPrimitiveType::Enum) { | |
| pComputedStyle->m_NonInheritedData.m_eVerticalAlignType = | |
| ToVerticalAlign(pValue.As<CFX_CSSEnumValue>()->Value()); | |
| } else if (eType == CFX_CSSPrimitiveType::Number) { | |
| pComputedStyle->m_NonInheritedData.m_eVerticalAlignType = | |
| CFX_CSSVerticalAlign::Number; | |
| pComputedStyle->m_NonInheritedData.m_fVerticalAlign = | |
| pValue.As<CFX_CSSNumberValue>()->Apply( | |
| pComputedStyle->m_InheritedData.m_fFontSize); | |
| } | |
| break; | |
| case CFX_CSSProperty::FontVariant: | |
| if (eType == CFX_CSSPrimitiveType::Enum) { | |
| pComputedStyle->m_InheritedData.m_eFontVariant = | |
| ToFontVariant(pValue.As<CFX_CSSEnumValue>()->Value()); | |
| } | |
| break; | |
| case CFX_CSSProperty::LetterSpacing: | |
| if (eType == CFX_CSSPrimitiveType::Enum) { | |
| pComputedStyle->m_InheritedData.m_LetterSpacing.Set( | |
| CFX_CSSLengthUnit::Normal); | |
| } else if (eType == CFX_CSSPrimitiveType::Number) { | |
| if (pValue.As<CFX_CSSNumberValue>()->Kind() == | |
| CFX_CSSNumberType::Percent) { | |
| break; | |
| } | |
| SetLengthWithPercent(pComputedStyle->m_InheritedData.m_LetterSpacing, | |
| eType, pValue, | |
| pComputedStyle->m_InheritedData.m_fFontSize); | |
| } | |
| break; | |
| case CFX_CSSProperty::WordSpacing: | |
| if (eType == CFX_CSSPrimitiveType::Enum) { | |
| pComputedStyle->m_InheritedData.m_WordSpacing.Set( | |
| CFX_CSSLengthUnit::Normal); | |
| } else if (eType == CFX_CSSPrimitiveType::Number) { | |
| if (pValue.As<CFX_CSSNumberValue>()->Kind() == | |
| CFX_CSSNumberType::Percent) { | |
| break; | |
| } | |
| SetLengthWithPercent(pComputedStyle->m_InheritedData.m_WordSpacing, | |
| eType, pValue, | |
| pComputedStyle->m_InheritedData.m_fFontSize); | |
| } | |
| break; | |
| case CFX_CSSProperty::Top: | |
| SetLengthWithPercent(pComputedStyle->m_NonInheritedData.m_Top, eType, | |
| pValue, | |
| pComputedStyle->m_InheritedData.m_fFontSize); | |
| break; | |
| case CFX_CSSProperty::Bottom: | |
| SetLengthWithPercent(pComputedStyle->m_NonInheritedData.m_Bottom, eType, | |
| pValue, | |
| pComputedStyle->m_InheritedData.m_fFontSize); | |
| break; | |
| case CFX_CSSProperty::Left: | |
| SetLengthWithPercent(pComputedStyle->m_NonInheritedData.m_Left, eType, | |
| pValue, | |
| pComputedStyle->m_InheritedData.m_fFontSize); | |
| break; | |
| case CFX_CSSProperty::Right: | |
| SetLengthWithPercent(pComputedStyle->m_NonInheritedData.m_Right, eType, | |
| pValue, | |
| pComputedStyle->m_InheritedData.m_fFontSize); | |
| break; | |
| default: | |
| break; | |
| } | |
| } else if (pValue->GetType() == CFX_CSSPrimitiveType::List) { | |
| RetainPtr<CFX_CSSValueList> value_list = pValue.As<CFX_CSSValueList>(); | |
| if (!value_list->values().empty()) { | |
| switch (eProperty) { | |
| case CFX_CSSProperty::FontFamily: | |
| pComputedStyle->m_InheritedData.m_pFontFamily = std::move(value_list); | |
| break; | |
| case CFX_CSSProperty::TextDecoration: | |
| pComputedStyle->m_NonInheritedData.m_dwTextDecoration = | |
| ToTextDecoration(value_list); | |
| break; | |
| default: | |
| break; | |
| } | |
| } | |
| } else { | |
| NOTREACHED(); | |
| } | |
| } | |
| CFX_CSSDisplay CFX_CSSStyleSelector::ToDisplay(CFX_CSSPropertyValue eValue) { | |
| switch (eValue) { | |
| case CFX_CSSPropertyValue::Block: | |
| return CFX_CSSDisplay::Block; | |
| case CFX_CSSPropertyValue::None: | |
| return CFX_CSSDisplay::None; | |
| case CFX_CSSPropertyValue::ListItem: | |
| return CFX_CSSDisplay::ListItem; | |
| case CFX_CSSPropertyValue::InlineTable: | |
| return CFX_CSSDisplay::InlineTable; | |
| case CFX_CSSPropertyValue::InlineBlock: | |
| return CFX_CSSDisplay::InlineBlock; | |
| case CFX_CSSPropertyValue::Inline: | |
| default: | |
| return CFX_CSSDisplay::Inline; | |
| } | |
| } | |
| CFX_CSSTextAlign CFX_CSSStyleSelector::ToTextAlign( | |
| CFX_CSSPropertyValue eValue) { | |
| switch (eValue) { | |
| case CFX_CSSPropertyValue::Center: | |
| return CFX_CSSTextAlign::Center; | |
| case CFX_CSSPropertyValue::Right: | |
| return CFX_CSSTextAlign::Right; | |
| case CFX_CSSPropertyValue::Justify: | |
| return CFX_CSSTextAlign::Justify; | |
| case CFX_CSSPropertyValue::Left: | |
| default: | |
| return CFX_CSSTextAlign::Left; | |
| } | |
| } | |
| uint16_t CFX_CSSStyleSelector::ToFontWeight(CFX_CSSPropertyValue eValue) { | |
| switch (eValue) { | |
| case CFX_CSSPropertyValue::Bold: | |
| return 700; | |
| case CFX_CSSPropertyValue::Bolder: | |
| return 900; | |
| case CFX_CSSPropertyValue::Lighter: | |
| return 200; | |
| case CFX_CSSPropertyValue::Normal: | |
| default: | |
| return 400; | |
| } | |
| } | |
| CFX_CSSFontStyle CFX_CSSStyleSelector::ToFontStyle( | |
| CFX_CSSPropertyValue eValue) { | |
| switch (eValue) { | |
| case CFX_CSSPropertyValue::Italic: | |
| case CFX_CSSPropertyValue::Oblique: | |
| return CFX_CSSFontStyle::Italic; | |
| default: | |
| return CFX_CSSFontStyle::Normal; | |
| } | |
| } | |
| bool CFX_CSSStyleSelector::SetLengthWithPercent( | |
| CFX_CSSLength& width, | |
| CFX_CSSPrimitiveType eType, | |
| const RetainPtr<CFX_CSSValue>& pValue, | |
| float fFontSize) { | |
| if (eType == CFX_CSSPrimitiveType::Number) { | |
| RetainPtr<CFX_CSSNumberValue> v = pValue.As<CFX_CSSNumberValue>(); | |
| if (v->Kind() == CFX_CSSNumberType::Percent) { | |
| width.Set(CFX_CSSLengthUnit::Percent, | |
| pValue.As<CFX_CSSNumberValue>()->Value() / 100.0f); | |
| return width.NonZero(); | |
| } | |
| float fValue = v->Apply(fFontSize); | |
| width.Set(CFX_CSSLengthUnit::Point, fValue); | |
| return width.NonZero(); | |
| } else if (eType == CFX_CSSPrimitiveType::Enum) { | |
| switch (pValue.As<CFX_CSSEnumValue>()->Value()) { | |
| case CFX_CSSPropertyValue::Auto: | |
| width.Set(CFX_CSSLengthUnit::Auto); | |
| return true; | |
| case CFX_CSSPropertyValue::None: | |
| width.Set(CFX_CSSLengthUnit::None); | |
| return true; | |
| case CFX_CSSPropertyValue::Thin: | |
| width.Set(CFX_CSSLengthUnit::Point, 2); | |
| return true; | |
| case CFX_CSSPropertyValue::Medium: | |
| width.Set(CFX_CSSLengthUnit::Point, 3); | |
| return true; | |
| case CFX_CSSPropertyValue::Thick: | |
| width.Set(CFX_CSSLengthUnit::Point, 4); | |
| return true; | |
| default: | |
| return false; | |
| } | |
| } | |
| return false; | |
| } | |
| float CFX_CSSStyleSelector::ToFontSize(CFX_CSSPropertyValue eValue, | |
| float fCurFontSize) { | |
| switch (eValue) { | |
| case CFX_CSSPropertyValue::XxSmall: | |
| return m_fDefaultFontSize / 1.2f / 1.2f / 1.2f; | |
| case CFX_CSSPropertyValue::XSmall: | |
| return m_fDefaultFontSize / 1.2f / 1.2f; | |
| case CFX_CSSPropertyValue::Small: | |
| return m_fDefaultFontSize / 1.2f; | |
| case CFX_CSSPropertyValue::Medium: | |
| return m_fDefaultFontSize; | |
| case CFX_CSSPropertyValue::Large: | |
| return m_fDefaultFontSize * 1.2f; | |
| case CFX_CSSPropertyValue::XLarge: | |
| return m_fDefaultFontSize * 1.2f * 1.2f; | |
| case CFX_CSSPropertyValue::XxLarge: | |
| return m_fDefaultFontSize * 1.2f * 1.2f * 1.2f; | |
| case CFX_CSSPropertyValue::Larger: | |
| return fCurFontSize * 1.2f; | |
| case CFX_CSSPropertyValue::Smaller: | |
| return fCurFontSize / 1.2f; | |
| default: | |
| return fCurFontSize; | |
| } | |
| } | |
| CFX_CSSVerticalAlign CFX_CSSStyleSelector::ToVerticalAlign( | |
| CFX_CSSPropertyValue eValue) { | |
| switch (eValue) { | |
| case CFX_CSSPropertyValue::Middle: | |
| return CFX_CSSVerticalAlign::Middle; | |
| case CFX_CSSPropertyValue::Bottom: | |
| return CFX_CSSVerticalAlign::Bottom; | |
| case CFX_CSSPropertyValue::Super: | |
| return CFX_CSSVerticalAlign::Super; | |
| case CFX_CSSPropertyValue::Sub: | |
| return CFX_CSSVerticalAlign::Sub; | |
| case CFX_CSSPropertyValue::Top: | |
| return CFX_CSSVerticalAlign::Top; | |
| case CFX_CSSPropertyValue::TextTop: | |
| return CFX_CSSVerticalAlign::TextTop; | |
| case CFX_CSSPropertyValue::TextBottom: | |
| return CFX_CSSVerticalAlign::TextBottom; | |
| case CFX_CSSPropertyValue::Baseline: | |
| default: | |
| return CFX_CSSVerticalAlign::Baseline; | |
| } | |
| } | |
| uint32_t CFX_CSSStyleSelector::ToTextDecoration( | |
| const RetainPtr<CFX_CSSValueList>& pValue) { | |
| uint32_t dwDecoration = 0; | |
| for (const RetainPtr<CFX_CSSValue>& val : | |
| pdfium::base::Reversed(pValue->values())) { | |
| if (val->GetType() != CFX_CSSPrimitiveType::Enum) | |
| continue; | |
| switch (val.As<CFX_CSSEnumValue>()->Value()) { | |
| case CFX_CSSPropertyValue::Underline: | |
| dwDecoration |= CFX_CSSTEXTDECORATION_Underline; | |
| break; | |
| case CFX_CSSPropertyValue::LineThrough: | |
| dwDecoration |= CFX_CSSTEXTDECORATION_LineThrough; | |
| break; | |
| case CFX_CSSPropertyValue::Overline: | |
| dwDecoration |= CFX_CSSTEXTDECORATION_Overline; | |
| break; | |
| case CFX_CSSPropertyValue::Blink: | |
| dwDecoration |= CFX_CSSTEXTDECORATION_Blink; | |
| break; | |
| case CFX_CSSPropertyValue::Double: | |
| dwDecoration |= CFX_CSSTEXTDECORATION_Double; | |
| break; | |
| default: | |
| break; | |
| } | |
| } | |
| return dwDecoration; | |
| } | |
| CFX_CSSFontVariant CFX_CSSStyleSelector::ToFontVariant( | |
| CFX_CSSPropertyValue eValue) { | |
| return eValue == CFX_CSSPropertyValue::SmallCaps | |
| ? CFX_CSSFontVariant::SmallCaps | |
| : CFX_CSSFontVariant::Normal; | |
| } |