diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/css/CSSPrimitiveValue.cpp | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebCore/css/CSSPrimitiveValue.cpp')
-rw-r--r-- | Source/WebCore/css/CSSPrimitiveValue.cpp | 1046 |
1 files changed, 437 insertions, 609 deletions
diff --git a/Source/WebCore/css/CSSPrimitiveValue.cpp b/Source/WebCore/css/CSSPrimitiveValue.cpp index 1492d25a3..482fd3da8 100644 --- a/Source/WebCore/css/CSSPrimitiveValue.cpp +++ b/Source/WebCore/css/CSSPrimitiveValue.cpp @@ -23,15 +23,20 @@ #include "CSSBasicShapes.h" #include "CSSCalculationValue.h" +#include "CSSFontFamily.h" #include "CSSHelper.h" -#include "CSSParser.h" +#include "CSSMarkup.h" +#include "CSSParserSelector.h" +#include "CSSPrimitiveValueMappings.h" #include "CSSPropertyNames.h" +#include "CSSToLengthConversionData.h" #include "CSSValueKeywords.h" #include "CalculationValue.h" #include "Color.h" #include "Counter.h" +#include "DeprecatedCSSOMPrimitiveValue.h" #include "ExceptionCode.h" -#include "Font.h" +#include "FontCascade.h" #include "Node.h" #include "Pair.h" #include "RGBColor.h" @@ -40,6 +45,7 @@ #include "StyleSheetContents.h" #include <wtf/ASCIICType.h> #include <wtf/DecimalNumber.h> +#include <wtf/NeverDestroyed.h> #include <wtf/StdLibExtras.h> #include <wtf/text/StringBuffer.h> #include <wtf/text/StringBuilder.h> @@ -52,22 +58,20 @@ using namespace WTF; namespace WebCore { -static inline bool isValidCSSUnitTypeForDoubleConversion(CSSPrimitiveValue::UnitTypes unitType) +static inline bool isValidCSSUnitTypeForDoubleConversion(CSSPrimitiveValue::UnitType unitType) { switch (unitType) { case CSSPrimitiveValue::CSS_CALC: - case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_NUMBER: case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_LENGTH: + case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_NUMBER: + case CSSPrimitiveValue::CSS_CHS: case CSSPrimitiveValue::CSS_CM: case CSSPrimitiveValue::CSS_DEG: case CSSPrimitiveValue::CSS_DIMENSION: -#if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) - case CSSPrimitiveValue::CSS_DPPX: - case CSSPrimitiveValue::CSS_DPI: - case CSSPrimitiveValue::CSS_DPCM: -#endif case CSSPrimitiveValue::CSS_EMS: + case CSSPrimitiveValue::CSS_QUIRKY_EMS: case CSSPrimitiveValue::CSS_EXS: + case CSSPrimitiveValue::CSS_FR: case CSSPrimitiveValue::CSS_GRAD: case CSSPrimitiveValue::CSS_HZ: case CSSPrimitiveValue::CSS_IN: @@ -75,48 +79,111 @@ static inline bool isValidCSSUnitTypeForDoubleConversion(CSSPrimitiveValue::Unit case CSSPrimitiveValue::CSS_MM: case CSSPrimitiveValue::CSS_MS: case CSSPrimitiveValue::CSS_NUMBER: - case CSSPrimitiveValue::CSS_PERCENTAGE: case CSSPrimitiveValue::CSS_PC: + case CSSPrimitiveValue::CSS_PERCENTAGE: case CSSPrimitiveValue::CSS_PT: case CSSPrimitiveValue::CSS_PX: case CSSPrimitiveValue::CSS_RAD: case CSSPrimitiveValue::CSS_REMS: - case CSSPrimitiveValue::CSS_CHS: case CSSPrimitiveValue::CSS_S: case CSSPrimitiveValue::CSS_TURN: - case CSSPrimitiveValue::CSS_VW: case CSSPrimitiveValue::CSS_VH: - case CSSPrimitiveValue::CSS_VMIN: case CSSPrimitiveValue::CSS_VMAX: - case CSSPrimitiveValue::CSS_FR: + case CSSPrimitiveValue::CSS_VMIN: + case CSSPrimitiveValue::CSS_VW: return true; + case CSSPrimitiveValue::CSS_DPCM: + case CSSPrimitiveValue::CSS_DPI: + case CSSPrimitiveValue::CSS_DPPX: +#if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) + return true; +#else + return false; +#endif case CSSPrimitiveValue::CSS_ATTR: case CSSPrimitiveValue::CSS_COUNTER: case CSSPrimitiveValue::CSS_COUNTER_NAME: + case CSSPrimitiveValue::CSS_FONT_FAMILY: + case CSSPrimitiveValue::CSS_IDENT: + case CSSPrimitiveValue::CSS_PAIR: + case CSSPrimitiveValue::CSS_PROPERTY_ID: + case CSSPrimitiveValue::CSS_QUAD: + case CSSPrimitiveValue::CSS_RECT: + case CSSPrimitiveValue::CSS_RGBCOLOR: + case CSSPrimitiveValue::CSS_SHAPE: + case CSSPrimitiveValue::CSS_STRING: + case CSSPrimitiveValue::CSS_UNICODE_RANGE: + case CSSPrimitiveValue::CSS_UNKNOWN: + case CSSPrimitiveValue::CSS_URI: + case CSSPrimitiveValue::CSS_VALUE_ID: #if ENABLE(DASHBOARD_SUPPORT) case CSSPrimitiveValue::CSS_DASHBOARD_REGION: #endif -#if !ENABLE(CSS_IMAGE_RESOLUTION) && !ENABLE(RESOLUTION_MEDIA_QUERY) - case CSSPrimitiveValue::CSS_DPPX: - case CSSPrimitiveValue::CSS_DPI: + return false; + } + + ASSERT_NOT_REACHED(); + return false; +} + +#if !ASSERT_DISABLED + +static inline bool isStringType(CSSPrimitiveValue::UnitType type) +{ + switch (type) { + case CSSPrimitiveValue::CSS_STRING: + case CSSPrimitiveValue::CSS_URI: + case CSSPrimitiveValue::CSS_ATTR: + case CSSPrimitiveValue::CSS_COUNTER_NAME: + case CSSPrimitiveValue::CSS_DIMENSION: + return true; + case CSSPrimitiveValue::CSS_CALC: + case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_LENGTH: + case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_NUMBER: + case CSSPrimitiveValue::CSS_CHS: + case CSSPrimitiveValue::CSS_CM: + case CSSPrimitiveValue::CSS_COUNTER: + case CSSPrimitiveValue::CSS_DEG: case CSSPrimitiveValue::CSS_DPCM: -#endif + case CSSPrimitiveValue::CSS_DPI: + case CSSPrimitiveValue::CSS_DPPX: + case CSSPrimitiveValue::CSS_EMS: + case CSSPrimitiveValue::CSS_QUIRKY_EMS: + case CSSPrimitiveValue::CSS_EXS: + case CSSPrimitiveValue::CSS_FONT_FAMILY: + case CSSPrimitiveValue::CSS_FR: + case CSSPrimitiveValue::CSS_GRAD: + case CSSPrimitiveValue::CSS_HZ: case CSSPrimitiveValue::CSS_IDENT: - case CSSPrimitiveValue::CSS_PROPERTY_ID: - case CSSPrimitiveValue::CSS_VALUE_ID: + case CSSPrimitiveValue::CSS_IN: + case CSSPrimitiveValue::CSS_KHZ: + case CSSPrimitiveValue::CSS_MM: + case CSSPrimitiveValue::CSS_MS: + case CSSPrimitiveValue::CSS_NUMBER: case CSSPrimitiveValue::CSS_PAIR: - case CSSPrimitiveValue::CSS_PARSER_HEXCOLOR: - case CSSPrimitiveValue::CSS_PARSER_IDENTIFIER: - case CSSPrimitiveValue::CSS_PARSER_INTEGER: - case CSSPrimitiveValue::CSS_PARSER_OPERATOR: - case CSSPrimitiveValue::CSS_RECT: + case CSSPrimitiveValue::CSS_PC: + case CSSPrimitiveValue::CSS_PERCENTAGE: + case CSSPrimitiveValue::CSS_PROPERTY_ID: + case CSSPrimitiveValue::CSS_PT: + case CSSPrimitiveValue::CSS_PX: case CSSPrimitiveValue::CSS_QUAD: + case CSSPrimitiveValue::CSS_RAD: + case CSSPrimitiveValue::CSS_RECT: + case CSSPrimitiveValue::CSS_REMS: case CSSPrimitiveValue::CSS_RGBCOLOR: + case CSSPrimitiveValue::CSS_S: case CSSPrimitiveValue::CSS_SHAPE: - case CSSPrimitiveValue::CSS_STRING: + case CSSPrimitiveValue::CSS_TURN: case CSSPrimitiveValue::CSS_UNICODE_RANGE: case CSSPrimitiveValue::CSS_UNKNOWN: - case CSSPrimitiveValue::CSS_URI: + case CSSPrimitiveValue::CSS_VALUE_ID: + case CSSPrimitiveValue::CSS_VH: + case CSSPrimitiveValue::CSS_VMAX: + case CSSPrimitiveValue::CSS_VMIN: + case CSSPrimitiveValue::CSS_VW: +#if ENABLE(DASHBOARD_SUPPORT) + case CSSPrimitiveValue::CSS_DASHBOARD_REGION: +#endif return false; } @@ -124,7 +191,9 @@ static inline bool isValidCSSUnitTypeForDoubleConversion(CSSPrimitiveValue::Unit return false; } -CSSPrimitiveValue::UnitCategory CSSPrimitiveValue::unitCategory(CSSPrimitiveValue::UnitTypes type) +#endif // !ASSERT_DISABLED + +CSSPrimitiveValue::UnitCategory CSSPrimitiveValue::unitCategory(CSSPrimitiveValue::UnitType type) { // Here we violate the spec (http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue) and allow conversions // between CSS_PX and relative lengths (see cssPixelsPerInch comment in CSSHelper.h for the topic treatment). @@ -151,11 +220,6 @@ CSSPrimitiveValue::UnitCategory CSSPrimitiveValue::unitCategory(CSSPrimitiveValu case CSS_HZ: case CSS_KHZ: return UFrequency; - case CSS_VW: - case CSS_VH: - case CSS_VMIN: - case CSS_VMAX: - return UViewportPercentageLength; #if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) case CSS_DPPX: case CSS_DPI: @@ -170,7 +234,7 @@ CSSPrimitiveValue::UnitCategory CSSPrimitiveValue::unitCategory(CSSPrimitiveValu typedef HashMap<const CSSPrimitiveValue*, String> CSSTextCache; static CSSTextCache& cssTextCache() { - DEFINE_STATIC_LOCAL(CSSTextCache, cache, ()); + static NeverDestroyed<CSSTextCache> cache; return cache; } @@ -179,20 +243,29 @@ unsigned short CSSPrimitiveValue::primitiveType() const if (m_primitiveUnitType == CSS_PROPERTY_ID || m_primitiveUnitType == CSS_VALUE_ID) return CSS_IDENT; + // Web-exposed content expects font family values to have CSS_STRING primitive type + // so we need to map our internal CSS_FONT_FAMILY type here. + if (m_primitiveUnitType == CSS_FONT_FAMILY) + return CSS_STRING; + if (m_primitiveUnitType != CSSPrimitiveValue::CSS_CALC) return m_primitiveUnitType; switch (m_value.calc->category()) { case CalcNumber: return CSSPrimitiveValue::CSS_NUMBER; - case CalcPercent: - return CSSPrimitiveValue::CSS_PERCENTAGE; case CalcLength: return CSSPrimitiveValue::CSS_PX; + case CalcPercent: + return CSSPrimitiveValue::CSS_PERCENTAGE; case CalcPercentNumber: return CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_NUMBER; case CalcPercentLength: return CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_LENGTH; + case CalcAngle: + case CalcTime: + case CalcFrequency: + return m_value.calc->primitiveType(); case CalcOther: return CSSPrimitiveValue::CSS_UNKNOWN; } @@ -201,12 +274,8 @@ unsigned short CSSPrimitiveValue::primitiveType() const static const AtomicString& propertyName(CSSPropertyID propertyID) { - ASSERT_ARG(propertyID, propertyID >= 0); ASSERT_ARG(propertyID, (propertyID >= firstCSSProperty && propertyID < firstCSSProperty + numCSSProperties)); - if (propertyID < 0) - return nullAtom; - return getPropertyNameAtomicString(propertyID); } @@ -239,14 +308,7 @@ CSSPrimitiveValue::CSSPrimitiveValue(CSSPropertyID propertyID) m_value.propertyID = propertyID; } -CSSPrimitiveValue::CSSPrimitiveValue(int parserOperator) - : CSSValue(PrimitiveClass) -{ - m_primitiveUnitType = CSS_PARSER_OPERATOR; - m_value.parserOperator = parserOperator; -} - -CSSPrimitiveValue::CSSPrimitiveValue(double num, UnitTypes type) +CSSPrimitiveValue::CSSPrimitiveValue(double num, UnitType type) : CSSValue(PrimitiveClass) { m_primitiveUnitType = type; @@ -254,19 +316,20 @@ CSSPrimitiveValue::CSSPrimitiveValue(double num, UnitTypes type) m_value.num = num; } -CSSPrimitiveValue::CSSPrimitiveValue(const String& str, UnitTypes type) +CSSPrimitiveValue::CSSPrimitiveValue(const String& string, UnitType type) : CSSValue(PrimitiveClass) { + ASSERT(isStringType(type)); m_primitiveUnitType = type; - if ((m_value.string = str.impl())) + if ((m_value.string = string.impl())) m_value.string->ref(); } -CSSPrimitiveValue::CSSPrimitiveValue(RGBA32 color) +CSSPrimitiveValue::CSSPrimitiveValue(const Color& color) : CSSValue(PrimitiveClass) { m_primitiveUnitType = CSS_RGBCOLOR; - m_value.rgbcolor = color; + m_value.color = new Color(color); } CSSPrimitiveValue::CSSPrimitiveValue(const Length& length) @@ -275,7 +338,7 @@ CSSPrimitiveValue::CSSPrimitiveValue(const Length& length) init(length); } -CSSPrimitiveValue::CSSPrimitiveValue(const Length& length, const RenderStyle* style) +CSSPrimitiveValue::CSSPrimitiveValue(const Length& length, const RenderStyle& style) : CSSValue(PrimitiveClass) { switch (length.type()) { @@ -287,10 +350,6 @@ CSSPrimitiveValue::CSSPrimitiveValue(const Length& length, const RenderStyle* st case FillAvailable: case FitContent: case Percent: - case ViewportPercentageWidth: - case ViewportPercentageHeight: - case ViewportPercentageMin: - case ViewportPercentageMax: init(length); return; case Fixed: @@ -298,21 +357,21 @@ CSSPrimitiveValue::CSSPrimitiveValue(const Length& length, const RenderStyle* st m_value.num = adjustFloatForAbsoluteZoom(length.value(), style); return; case Calculated: { - RefPtr<CSSCalcValue> calcValue = CSSCalcValue::create(length.calculationValue().get(), style); - init(calcValue.release()); + init(CSSCalcValue::create(length.calculationValue(), style)); return; } case Relative: case Undefined: ASSERT_NOT_REACHED(); - break; + return; } + ASSERT_NOT_REACHED(); } -CSSPrimitiveValue::CSSPrimitiveValue(const LengthSize& lengthSize) +CSSPrimitiveValue::CSSPrimitiveValue(const LengthSize& lengthSize, const RenderStyle& style) : CSSValue(PrimitiveClass) { - init(lengthSize); + init(lengthSize, style); } void CSSPrimitiveValue::init(const Length& length) @@ -321,94 +380,79 @@ void CSSPrimitiveValue::init(const Length& length) case Auto: m_primitiveUnitType = CSS_VALUE_ID; m_value.valueID = CSSValueAuto; - break; + return; case WebCore::Fixed: m_primitiveUnitType = CSS_PX; m_value.num = length.value(); - break; + return; case Intrinsic: m_primitiveUnitType = CSS_VALUE_ID; m_value.valueID = CSSValueIntrinsic; - break; + return; case MinIntrinsic: m_primitiveUnitType = CSS_VALUE_ID; m_value.valueID = CSSValueMinIntrinsic; - break; + return; case MinContent: m_primitiveUnitType = CSS_VALUE_ID; m_value.valueID = CSSValueWebkitMinContent; - break; + return; case MaxContent: m_primitiveUnitType = CSS_VALUE_ID; m_value.valueID = CSSValueWebkitMaxContent; - break; + return; case FillAvailable: m_primitiveUnitType = CSS_VALUE_ID; m_value.valueID = CSSValueWebkitFillAvailable; - break; + return; case FitContent: m_primitiveUnitType = CSS_VALUE_ID; m_value.valueID = CSSValueWebkitFitContent; - break; + return; case Percent: m_primitiveUnitType = CSS_PERCENTAGE; ASSERT(std::isfinite(length.percent())); m_value.num = length.percent(); - break; - case ViewportPercentageWidth: - m_primitiveUnitType = CSS_VW; - m_value.num = length.viewportPercentageLength(); - break; - case ViewportPercentageHeight: - m_primitiveUnitType = CSS_VH; - m_value.num = length.viewportPercentageLength(); - break; - case ViewportPercentageMin: - m_primitiveUnitType = CSS_VMIN; - m_value.num = length.viewportPercentageLength(); - break; - case ViewportPercentageMax: - m_primitiveUnitType = CSS_VMAX; - m_value.num = length.viewportPercentageLength(); - break; + return; case Calculated: case Relative: case Undefined: ASSERT_NOT_REACHED(); - break; + return; } + ASSERT_NOT_REACHED(); } -void CSSPrimitiveValue::init(const LengthSize& lengthSize) +void CSSPrimitiveValue::init(const LengthSize& lengthSize, const RenderStyle& style) { m_primitiveUnitType = CSS_PAIR; m_hasCachedCSSText = false; - m_value.pair = Pair::create(create(lengthSize.width()), create(lengthSize.height())).leakRef(); + m_value.pair = &Pair::create(create(lengthSize.width, style), create(lengthSize.height, style)).leakRef(); } -void CSSPrimitiveValue::init(PassRefPtr<Counter> c) +void CSSPrimitiveValue::init(Ref<Counter>&& counter) { m_primitiveUnitType = CSS_COUNTER; m_hasCachedCSSText = false; - m_value.counter = c.leakRef(); + m_value.counter = &counter.leakRef(); } -void CSSPrimitiveValue::init(PassRefPtr<Rect> r) +void CSSPrimitiveValue::init(Ref<Rect>&& r) { m_primitiveUnitType = CSS_RECT; m_hasCachedCSSText = false; - m_value.rect = r.leakRef(); + m_value.rect = &r.leakRef(); } -void CSSPrimitiveValue::init(PassRefPtr<Quad> quad) +void CSSPrimitiveValue::init(Ref<Quad>&& quad) { m_primitiveUnitType = CSS_QUAD; m_hasCachedCSSText = false; - m_value.quad = quad.leakRef(); + m_value.quad = &quad.leakRef(); } #if ENABLE(DASHBOARD_SUPPORT) -void CSSPrimitiveValue::init(PassRefPtr<DashboardRegion> r) +void CSSPrimitiveValue::init(RefPtr<DashboardRegion>&& r) { m_primitiveUnitType = CSS_DASHBOARD_REGION; m_hasCachedCSSText = false; @@ -416,25 +460,25 @@ void CSSPrimitiveValue::init(PassRefPtr<DashboardRegion> r) } #endif -void CSSPrimitiveValue::init(PassRefPtr<Pair> p) +void CSSPrimitiveValue::init(Ref<Pair>&& p) { m_primitiveUnitType = CSS_PAIR; m_hasCachedCSSText = false; - m_value.pair = p.leakRef(); + m_value.pair = &p.leakRef(); } -void CSSPrimitiveValue::init(PassRefPtr<CSSCalcValue> c) +void CSSPrimitiveValue::init(Ref<CSSBasicShape>&& shape) { - m_primitiveUnitType = CSS_CALC; + m_primitiveUnitType = CSS_SHAPE; m_hasCachedCSSText = false; - m_value.calc = c.leakRef(); + m_value.shape = &shape.leakRef(); } -void CSSPrimitiveValue::init(PassRefPtr<CSSBasicShape> shape) +void CSSPrimitiveValue::init(RefPtr<CSSCalcValue>&& c) { - m_primitiveUnitType = CSS_SHAPE; + m_primitiveUnitType = CSS_CALC; m_hasCachedCSSText = false; - m_value.shape = shape.leakRef(); + m_value.calc = c.leakRef(); } CSSPrimitiveValue::~CSSPrimitiveValue() @@ -444,15 +488,16 @@ CSSPrimitiveValue::~CSSPrimitiveValue() void CSSPrimitiveValue::cleanup() { - switch (static_cast<UnitTypes>(m_primitiveUnitType)) { + auto type = static_cast<UnitType>(m_primitiveUnitType); + switch (type) { case CSS_STRING: case CSS_URI: case CSS_ATTR: case CSS_COUNTER_NAME: - case CSS_PARSER_HEXCOLOR: if (m_value.string) m_value.string->deref(); break; + case CSS_DIMENSION: case CSS_COUNTER: m_value.counter->deref(); break; @@ -481,10 +526,20 @@ void CSSPrimitiveValue::cleanup() case CSS_SHAPE: m_value.shape->deref(); break; + case CSS_FONT_FAMILY: + ASSERT(m_value.fontFamily); + delete m_value.fontFamily; + m_value.fontFamily = nullptr; + break; + case CSS_RGBCOLOR: + ASSERT(m_value.color); + delete m_value.color; + m_value.color = nullptr; + break; case CSS_NUMBER: - case CSS_PARSER_INTEGER: case CSS_PERCENTAGE: case CSS_EMS: + case CSS_QUIRKY_EMS: case CSS_EXS: case CSS_REMS: case CSS_CHS: @@ -511,14 +566,11 @@ void CSSPrimitiveValue::cleanup() case CSS_DPCM: case CSS_FR: case CSS_IDENT: - case CSS_RGBCOLOR: - case CSS_DIMENSION: case CSS_UNKNOWN: case CSS_UNICODE_RANGE: - case CSS_PARSER_OPERATOR: - case CSS_PARSER_IDENTIFIER: case CSS_PROPERTY_ID: case CSS_VALUE_ID: + ASSERT(!isStringType(type)); break; } m_primitiveUnitType = 0; @@ -528,91 +580,96 @@ void CSSPrimitiveValue::cleanup() } } -double CSSPrimitiveValue::computeDegrees() +double CSSPrimitiveValue::computeDegrees() const { - switch (m_primitiveUnitType) { + switch (primitiveType()) { case CSS_DEG: - return getDoubleValue(); + return doubleValue(); case CSS_RAD: - return rad2deg(getDoubleValue()); + return rad2deg(doubleValue()); case CSS_GRAD: - return grad2deg(getDoubleValue()); + return grad2deg(doubleValue()); case CSS_TURN: - return turn2deg(getDoubleValue()); + return turn2deg(doubleValue()); default: ASSERT_NOT_REACHED(); return 0; } } -template<> int CSSPrimitiveValue::computeLength(const RenderStyle* style, const RenderStyle* rootStyle, float multiplier, bool computingFontSize) const +template<> int CSSPrimitiveValue::computeLength(const CSSToLengthConversionData& conversionData) const { - return roundForImpreciseConversion<int>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize)); + return roundForImpreciseConversion<int>(computeLengthDouble(conversionData)); } -template<> unsigned CSSPrimitiveValue::computeLength(const RenderStyle* style, const RenderStyle* rootStyle, float multiplier, bool computingFontSize) const +template<> unsigned CSSPrimitiveValue::computeLength(const CSSToLengthConversionData& conversionData) const { - return roundForImpreciseConversion<unsigned>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize)); + return roundForImpreciseConversion<unsigned>(computeLengthDouble(conversionData)); } -template<> Length CSSPrimitiveValue::computeLength(const RenderStyle* style, const RenderStyle* rootStyle, float multiplier, bool computingFontSize) const +template<> Length CSSPrimitiveValue::computeLength(const CSSToLengthConversionData& conversionData) const { -#if ENABLE(SUBPIXEL_LAYOUT) - return Length(clampTo<float>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize), minValueForCssLength, maxValueForCssLength), Fixed); -#else - return Length(clampTo<float>(roundForImpreciseConversion<float>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize)), minValueForCssLength, maxValueForCssLength), Fixed); -#endif + return Length(clampTo<float>(computeLengthDouble(conversionData), minValueForCssLength, maxValueForCssLength), Fixed); } -template<> short CSSPrimitiveValue::computeLength(const RenderStyle* style, const RenderStyle* rootStyle, float multiplier, bool computingFontSize) const +template<> short CSSPrimitiveValue::computeLength(const CSSToLengthConversionData& conversionData) const { - return roundForImpreciseConversion<short>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize)); + return roundForImpreciseConversion<short>(computeLengthDouble(conversionData)); } -template<> unsigned short CSSPrimitiveValue::computeLength(const RenderStyle* style, const RenderStyle* rootStyle, float multiplier, bool computingFontSize) const +template<> unsigned short CSSPrimitiveValue::computeLength(const CSSToLengthConversionData& conversionData) const { - return roundForImpreciseConversion<unsigned short>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize)); + return roundForImpreciseConversion<unsigned short>(computeLengthDouble(conversionData)); } -template<> float CSSPrimitiveValue::computeLength(const RenderStyle* style, const RenderStyle* rootStyle, float multiplier, bool computingFontSize) const +template<> float CSSPrimitiveValue::computeLength(const CSSToLengthConversionData& conversionData) const { - return static_cast<float>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize)); + return static_cast<float>(computeLengthDouble(conversionData)); } -template<> double CSSPrimitiveValue::computeLength(const RenderStyle* style, const RenderStyle* rootStyle, float multiplier, bool computingFontSize) const +template<> double CSSPrimitiveValue::computeLength(const CSSToLengthConversionData& conversionData) const { - return computeLengthDouble(style, rootStyle, multiplier, computingFontSize); + return computeLengthDouble(conversionData); } -double CSSPrimitiveValue::computeLengthDouble(const RenderStyle* style, const RenderStyle* rootStyle, float multiplier, bool computingFontSize) const +double CSSPrimitiveValue::computeLengthDouble(const CSSToLengthConversionData& conversionData) const { if (m_primitiveUnitType == CSS_CALC) // The multiplier and factor is applied to each value in the calc expression individually - return m_value.calc->computeLengthPx(style, rootStyle, multiplier, computingFontSize); + return m_value.calc->computeLengthPx(conversionData); + + return computeNonCalcLengthDouble(conversionData, static_cast<UnitType>(primitiveType()), m_value.num); +} +double CSSPrimitiveValue::computeNonCalcLengthDouble(const CSSToLengthConversionData& conversionData, UnitType primitiveType, double value) +{ double factor; - switch (primitiveType()) { + switch (primitiveType) { case CSS_EMS: - factor = computingFontSize ? style->fontDescription().specifiedSize() : style->fontDescription().computedSize(); + case CSS_QUIRKY_EMS: + ASSERT(conversionData.style()); + factor = conversionData.computingFontSize() ? conversionData.style()->fontDescription().specifiedSize() : conversionData.style()->fontDescription().computedSize(); break; case CSS_EXS: + ASSERT(conversionData.style()); // FIXME: We have a bug right now where the zoom will be applied twice to EX units. // We really need to compute EX using fontMetrics for the original specifiedSize and not use // our actual constructed rendering font. - if (style->fontMetrics().hasXHeight()) - factor = style->fontMetrics().xHeight(); + if (conversionData.style()->fontMetrics().hasXHeight()) + factor = conversionData.style()->fontMetrics().xHeight(); else - factor = (computingFontSize ? style->fontDescription().specifiedSize() : style->fontDescription().computedSize()) / 2.0; + factor = (conversionData.computingFontSize() ? conversionData.style()->fontDescription().specifiedSize() : conversionData.style()->fontDescription().computedSize()) / 2.0; break; case CSS_REMS: - if (rootStyle) - factor = computingFontSize ? rootStyle->fontDescription().specifiedSize() : rootStyle->fontDescription().computedSize(); + if (conversionData.rootStyle()) + factor = conversionData.computingFontSize() ? conversionData.rootStyle()->fontDescription().specifiedSize() : conversionData.rootStyle()->fontDescription().computedSize(); else factor = 1.0; break; case CSS_CHS: - factor = style->fontMetrics().zeroWidth(); + ASSERT(conversionData.style()); + factor = conversionData.style()->fontMetrics().zeroWidth(); break; case CSS_PX: factor = 1.0; @@ -638,10 +695,16 @@ double CSSPrimitiveValue::computeLengthDouble(const RenderStyle* style, const Re ASSERT_NOT_REACHED(); return -1.0; case CSS_VH: + factor = conversionData.viewportHeightFactor(); + break; case CSS_VW: + factor = conversionData.viewportWidthFactor(); + break; case CSS_VMAX: + factor = conversionData.viewportMaxFactor(); + break; case CSS_VMIN: - factor = 1.0; + factor = conversionData.viewportMinFactor(); break; default: ASSERT_NOT_REACHED(); @@ -651,22 +714,22 @@ double CSSPrimitiveValue::computeLengthDouble(const RenderStyle* style, const Re // We do not apply the zoom factor when we are computing the value of the font-size property. The zooming // for font sizes is much more complicated, since we have to worry about enforcing the minimum font size preference // as well as enforcing the implicit "smart minimum." - double result = getDoubleValue() * factor; - if (computingFontSize || isFontRelativeLength()) + double result = value * factor; + if (conversionData.computingFontSize() || isFontRelativeLength(primitiveType)) return result; - return result * multiplier; + return result * conversionData.zoom(); } -void CSSPrimitiveValue::setFloatValue(unsigned short, double, ExceptionCode& ec) +ExceptionOr<void> CSSPrimitiveValue::setFloatValue(unsigned short, double) { // Keeping values immutable makes optimizations easier and allows sharing of the primitive value objects. // No other engine supports mutating style through this API. Computed style is always read-only anyway. // Supporting setter would require making primitive value copy-on-write and taking care of style invalidation. - ec = NO_MODIFICATION_ALLOWED_ERR; + return Exception { NO_MODIFICATION_ALLOWED_ERR }; } -double CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor(unsigned short unitType) +double CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor(UnitType unitType) { double factor = 1.0; // FIXME: the switch can be replaced by an array of scale factors. @@ -718,32 +781,26 @@ double CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor(unsigned short u return factor; } -double CSSPrimitiveValue::getDoubleValue(unsigned short unitType, ExceptionCode& ec) const +ExceptionOr<float> CSSPrimitiveValue::getFloatValue(unsigned short unitType) const { - double result = 0; - bool success = getDoubleValueInternal(static_cast<UnitTypes>(unitType), &result); - if (!success) { - ec = INVALID_ACCESS_ERR; - return 0.0; - } - - ec = 0; - return result; + auto result = doubleValueInternal(static_cast<UnitType>(unitType)); + if (!result) + return Exception { INVALID_ACCESS_ERR }; + return clampTo<float>(result.value()); } -double CSSPrimitiveValue::getDoubleValue(unsigned short unitType) const +double CSSPrimitiveValue::doubleValue(UnitType unitType) const { - double result = 0; - getDoubleValueInternal(static_cast<UnitTypes>(unitType), &result); - return result; + return doubleValueInternal(unitType).value_or(0); } -double CSSPrimitiveValue::getDoubleValue() const +double CSSPrimitiveValue::doubleValue() const { return m_primitiveUnitType != CSS_CALC ? m_value.num : m_value.calc->doubleValue(); } -CSSPrimitiveValue::UnitTypes CSSPrimitiveValue::canonicalUnitTypeForCategory(UnitCategory category) + +CSSPrimitiveValue::UnitType CSSPrimitiveValue::canonicalUnitTypeForCategory(UnitCategory category) { // The canonical unit type is chosen according to the way CSSParser::validUnit() chooses the default unit // in each category (based on unitflags). @@ -760,8 +817,6 @@ CSSPrimitiveValue::UnitTypes CSSPrimitiveValue::canonicalUnitTypeForCategory(Uni return CSS_DEG; case UFrequency: return CSS_HZ; - case UViewportPercentageLength: - return CSS_UNKNOWN; // Cannot convert between numbers and relative lengths. #if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) case UResolution: return CSS_DPPX; @@ -771,43 +826,41 @@ CSSPrimitiveValue::UnitTypes CSSPrimitiveValue::canonicalUnitTypeForCategory(Uni } } -bool CSSPrimitiveValue::getDoubleValueInternal(UnitTypes requestedUnitType, double* result) const +std::optional<double> CSSPrimitiveValue::doubleValueInternal(UnitType requestedUnitType) const { - if (!isValidCSSUnitTypeForDoubleConversion(static_cast<UnitTypes>(m_primitiveUnitType)) || !isValidCSSUnitTypeForDoubleConversion(requestedUnitType)) - return false; + if (!isValidCSSUnitTypeForDoubleConversion(static_cast<UnitType>(m_primitiveUnitType)) || !isValidCSSUnitTypeForDoubleConversion(requestedUnitType)) + return std::nullopt; - UnitTypes sourceUnitType = static_cast<UnitTypes>(primitiveType()); - if (requestedUnitType == sourceUnitType || requestedUnitType == CSS_DIMENSION) { - *result = getDoubleValue(); - return true; - } + UnitType sourceUnitType = static_cast<UnitType>(primitiveType()); + if (requestedUnitType == sourceUnitType || requestedUnitType == CSS_DIMENSION) + return doubleValue(); UnitCategory sourceCategory = unitCategory(sourceUnitType); ASSERT(sourceCategory != UOther); - UnitTypes targetUnitType = requestedUnitType; + UnitType targetUnitType = requestedUnitType; UnitCategory targetCategory = unitCategory(targetUnitType); ASSERT(targetCategory != UOther); // Cannot convert between unrelated unit categories if one of them is not UNumber. if (sourceCategory != targetCategory && sourceCategory != UNumber && targetCategory != UNumber) - return false; + return std::nullopt; if (targetCategory == UNumber) { // We interpret conversion to CSS_NUMBER as conversion to a canonical unit in this value's category. targetUnitType = canonicalUnitTypeForCategory(sourceCategory); if (targetUnitType == CSS_UNKNOWN) - return false; + return std::nullopt; } if (sourceUnitType == CSS_NUMBER) { // We interpret conversion from CSS_NUMBER in the same way as CSSParser::validUnit() while using non-strict mode. sourceUnitType = canonicalUnitTypeForCategory(targetCategory); if (sourceUnitType == CSS_UNKNOWN) - return false; + return std::nullopt; } - double convertedValue = getDoubleValue(); + double convertedValue = doubleValue(); // First convert the value from m_primitiveUnitType to canonical type. double factor = conversionToCanonicalUnitsScaleFactor(sourceUnitType); @@ -817,509 +870,281 @@ bool CSSPrimitiveValue::getDoubleValueInternal(UnitTypes requestedUnitType, doub factor = conversionToCanonicalUnitsScaleFactor(targetUnitType); convertedValue /= factor; - *result = convertedValue; - return true; + return convertedValue; } -void CSSPrimitiveValue::setStringValue(unsigned short, const String&, ExceptionCode& ec) +ExceptionOr<void> CSSPrimitiveValue::setStringValue(unsigned short, const String&) { // Keeping values immutable makes optimizations easier and allows sharing of the primitive value objects. // No other engine supports mutating style through this API. Computed style is always read-only anyway. // Supporting setter would require making primitive value copy-on-write and taking care of style invalidation. - ec = NO_MODIFICATION_ALLOWED_ERR; + return Exception { NO_MODIFICATION_ALLOWED_ERR }; } -String CSSPrimitiveValue::getStringValue(ExceptionCode& ec) const +ExceptionOr<String> CSSPrimitiveValue::getStringValue() const { - ec = 0; switch (m_primitiveUnitType) { case CSS_STRING: case CSS_ATTR: case CSS_URI: return m_value.string; + case CSS_FONT_FAMILY: + return String { m_value.fontFamily->familyName }; case CSS_VALUE_ID: - return valueName(m_value.valueID); + return String { valueName(m_value.valueID).string() }; case CSS_PROPERTY_ID: - return propertyName(m_value.propertyID); + return String { propertyName(m_value.propertyID).string() }; default: - ec = INVALID_ACCESS_ERR; - break; + return Exception { INVALID_ACCESS_ERR }; } - - return String(); } -String CSSPrimitiveValue::getStringValue() const +String CSSPrimitiveValue::stringValue() const { switch (m_primitiveUnitType) { case CSS_STRING: case CSS_ATTR: case CSS_URI: return m_value.string; + case CSS_FONT_FAMILY: + return m_value.fontFamily->familyName; case CSS_VALUE_ID: return valueName(m_value.valueID); case CSS_PROPERTY_ID: return propertyName(m_value.propertyID); default: - break; + return String(); } - - return String(); -} - -Counter* CSSPrimitiveValue::getCounterValue(ExceptionCode& ec) const -{ - ec = 0; - if (m_primitiveUnitType != CSS_COUNTER) { - ec = INVALID_ACCESS_ERR; - return 0; - } - - return m_value.counter; } -Rect* CSSPrimitiveValue::getRectValue(ExceptionCode& ec) const +ExceptionOr<Counter&> CSSPrimitiveValue::getCounterValue() const { - ec = 0; - if (m_primitiveUnitType != CSS_RECT) { - ec = INVALID_ACCESS_ERR; - return 0; - } - - return m_value.rect; + if (m_primitiveUnitType != CSS_COUNTER) + return Exception { INVALID_ACCESS_ERR }; + return *m_value.counter; } -Quad* CSSPrimitiveValue::getQuadValue(ExceptionCode& ec) const +ExceptionOr<Rect&> CSSPrimitiveValue::getRectValue() const { - ec = 0; - if (m_primitiveUnitType != CSS_QUAD) { - ec = INVALID_ACCESS_ERR; - return 0; - } - - return m_value.quad; + if (m_primitiveUnitType != CSS_RECT) + return Exception { INVALID_ACCESS_ERR }; + return *m_value.rect; } -PassRefPtr<RGBColor> CSSPrimitiveValue::getRGBColorValue(ExceptionCode& ec) const +ExceptionOr<Ref<RGBColor>> CSSPrimitiveValue::getRGBColorValue() const { - ec = 0; - if (m_primitiveUnitType != CSS_RGBCOLOR) { - ec = INVALID_ACCESS_ERR; - return 0; - } + if (m_primitiveUnitType != CSS_RGBCOLOR) + return Exception { INVALID_ACCESS_ERR }; - // FIMXE: This should not return a new object for each invocation. - return RGBColor::create(m_value.rgbcolor); + // FIXME: This should not return a new object for each invocation. + return RGBColor::create(m_value.color->rgb()); } -Pair* CSSPrimitiveValue::getPairValue(ExceptionCode& ec) const +NEVER_INLINE Ref<StringImpl> CSSPrimitiveValue::formatNumberValue(const char* suffix, unsigned suffixLength) const { - ec = 0; - if (m_primitiveUnitType != CSS_PAIR) { - ec = INVALID_ACCESS_ERR; - return 0; - } - - return m_value.pair; -} + DecimalNumber decimal(m_value.num); -static String formatNumber(double number, const char* suffix, unsigned suffixLength) -{ - DecimalNumber decimal(number); + unsigned bufferLength = decimal.bufferLengthForStringDecimal() + suffixLength; + LChar* buffer; + auto string = StringImpl::createUninitialized(bufferLength, buffer); - StringBuffer<LChar> buffer(decimal.bufferLengthForStringDecimal() + suffixLength); - unsigned length = decimal.toStringDecimal(buffer.characters(), buffer.length()); - ASSERT(length + suffixLength == buffer.length()); + unsigned length = decimal.toStringDecimal(buffer, bufferLength); for (unsigned i = 0; i < suffixLength; ++i) buffer[length + i] = static_cast<LChar>(suffix[i]); - return String::adopt(buffer); + return string; } template <unsigned characterCount> -ALWAYS_INLINE static String formatNumber(double number, const char (&characters)[characterCount]) -{ - return formatNumber(number, characters, characterCount - 1); -} - -String CSSPrimitiveValue::customCSSText() const -{ - // FIXME: return the original value instead of a generated one (e.g. color - // name if it was specified) - check what spec says about this - - if (m_hasCachedCSSText) { - ASSERT(cssTextCache().contains(this)); - return cssTextCache().get(this); - } - - String text; - switch (m_primitiveUnitType) { - case CSS_UNKNOWN: - // FIXME - break; - case CSS_NUMBER: - case CSS_PARSER_INTEGER: - text = formatNumber(m_value.num, ""); - break; - case CSS_PERCENTAGE: - text = formatNumber(m_value.num, "%"); - break; - case CSS_EMS: - text = formatNumber(m_value.num, "em"); - break; - case CSS_EXS: - text = formatNumber(m_value.num, "ex"); - break; - case CSS_REMS: - text = formatNumber(m_value.num, "rem"); - break; - case CSS_CHS: - text = formatNumber(m_value.num, "ch"); - break; - case CSS_PX: - text = formatNumber(m_value.num, "px"); - break; - case CSS_CM: - text = formatNumber(m_value.num, "cm"); - break; -#if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) - case CSS_DPPX: - text = formatNumber(m_value.num, "dppx"); - break; - case CSS_DPI: - text = formatNumber(m_value.num, "dpi"); - break; - case CSS_DPCM: - text = formatNumber(m_value.num, "dpcm"); - break; -#endif - case CSS_MM: - text = formatNumber(m_value.num, "mm"); - break; - case CSS_IN: - text = formatNumber(m_value.num, "in"); - break; - case CSS_PT: - text = formatNumber(m_value.num, "pt"); - break; - case CSS_PC: - text = formatNumber(m_value.num, "pc"); - break; - case CSS_DEG: - text = formatNumber(m_value.num, "deg"); - break; - case CSS_RAD: - text = formatNumber(m_value.num, "rad"); - break; - case CSS_GRAD: - text = formatNumber(m_value.num, "grad"); - break; - case CSS_MS: - text = formatNumber(m_value.num, "ms"); - break; - case CSS_S: - text = formatNumber(m_value.num, "s"); - break; - case CSS_HZ: - text = formatNumber(m_value.num, "hz"); - break; - case CSS_KHZ: - text = formatNumber(m_value.num, "khz"); - break; - case CSS_TURN: - text = formatNumber(m_value.num, "turn"); - break; - case CSS_FR: - text = formatNumber(m_value.num, "fr"); - break; - case CSS_DIMENSION: - // FIXME: We currently don't handle CSS_DIMENSION properly as we don't store - // the actual dimension, just the numeric value as a string. - break; - case CSS_STRING: - text = quoteCSSStringIfNeeded(m_value.string); - break; - case CSS_URI: - text = "url(" + quoteCSSURLIfNeeded(m_value.string) + ')'; - break; - case CSS_VALUE_ID: - text = valueName(m_value.valueID); - break; - case CSS_PROPERTY_ID: - text = propertyName(m_value.propertyID); - break; - case CSS_ATTR: { - StringBuilder result; - result.reserveCapacity(6 + m_value.string->length()); - result.appendLiteral("attr("); - result.append(m_value.string); - result.append(')'); - - text = result.toString(); - break; - } - case CSS_COUNTER_NAME: - text = "counter(" + String(m_value.string) + ')'; - break; - case CSS_COUNTER: { - StringBuilder result; - String separator = m_value.counter->separator(); - if (separator.isEmpty()) - result.appendLiteral("counter("); - else - result.appendLiteral("counters("); - - result.append(m_value.counter->identifier()); - if (!separator.isEmpty()) { - result.appendLiteral(", "); - result.append(quoteCSSStringIfNeeded(separator)); - } - String listStyle = m_value.counter->listStyle(); - if (!listStyle.isEmpty()) { - result.appendLiteral(", "); - result.append(listStyle); - } - result.append(')'); - - text = result.toString(); - break; - } - case CSS_RECT: - text = getRectValue()->cssText(); - break; - case CSS_QUAD: - text = getQuadValue()->cssText(); - break; - case CSS_RGBCOLOR: - case CSS_PARSER_HEXCOLOR: { - RGBA32 rgbColor = m_value.rgbcolor; - if (m_primitiveUnitType == CSS_PARSER_HEXCOLOR) - Color::parseHexColor(m_value.string, rgbColor); - Color color(rgbColor); - - Vector<LChar> result; - result.reserveInitialCapacity(32); - bool colorHasAlpha = color.hasAlpha(); - if (colorHasAlpha) - result.append("rgba(", 5); - else - result.append("rgb(", 4); - - appendNumber(result, static_cast<unsigned char>(color.red())); - result.append(", ", 2); - - appendNumber(result, static_cast<unsigned char>(color.green())); - result.append(", ", 2); - - appendNumber(result, static_cast<unsigned char>(color.blue())); - if (colorHasAlpha) { - result.append(", ", 2); - - NumberToStringBuffer buffer; - const char* alphaString = numberToFixedPrecisionString(color.alpha() / 255.0f, 6, buffer, true); - result.append(alphaString, strlen(alphaString)); - } - - result.append(')'); - text = String::adopt(result); - break; - } - case CSS_PAIR: - text = getPairValue()->cssText(); - break; -#if ENABLE(DASHBOARD_SUPPORT) - case CSS_DASHBOARD_REGION: { - StringBuilder result; - for (DashboardRegion* region = getDashboardRegionValue(); region; region = region->m_next.get()) { - if (!result.isEmpty()) - result.append(' '); - result.appendLiteral("dashboard-region("); - result.append(region->m_label); - if (region->m_isCircle) - result.appendLiteral(" circle"); - else if (region->m_isRectangle) - result.appendLiteral(" rectangle"); - else - break; - if (region->top()->m_primitiveUnitType == CSS_VALUE_ID && region->top()->getValueID() == CSSValueInvalid) { - ASSERT(region->right()->m_primitiveUnitType == CSS_VALUE_ID); - ASSERT(region->bottom()->m_primitiveUnitType == CSS_VALUE_ID); - ASSERT(region->left()->m_primitiveUnitType == CSS_VALUE_ID); - ASSERT(region->right()->getValueID() == CSSValueInvalid); - ASSERT(region->bottom()->getValueID() == CSSValueInvalid); - ASSERT(region->left()->getValueID() == CSSValueInvalid); - } else { - result.append(' '); - result.append(region->top()->cssText()); - result.append(' '); - result.append(region->right()->cssText()); - result.append(' '); - result.append(region->bottom()->cssText()); - result.append(' '); - result.append(region->left()->cssText()); - } - result.append(')'); - } - text = result.toString(); - break; - } -#endif - case CSS_PARSER_OPERATOR: { - char c = static_cast<char>(m_value.parserOperator); - text = String(&c, 1U); - break; - } - case CSS_PARSER_IDENTIFIER: - text = quoteCSSStringIfNeeded(m_value.string); - break; - case CSS_CALC: - text = m_value.calc->cssText(); - break; - case CSS_SHAPE: - text = m_value.shape->cssText(); - break; - case CSS_VW: - text = formatNumber(m_value.num, "vw"); - break; - case CSS_VH: - text = formatNumber(m_value.num, "vh"); - break; - case CSS_VMIN: - text = formatNumber(m_value.num, "vmin"); - break; - case CSS_VMAX: - text = formatNumber(m_value.num, "vmax"); - break; - } - - ASSERT(!cssTextCache().contains(this)); - cssTextCache().set(this, text); - m_hasCachedCSSText = true; - return text; -} - -void CSSPrimitiveValue::addSubresourceStyleURLs(ListHashSet<URL>& urls, const StyleSheetContents* styleSheet) const -{ - if (m_primitiveUnitType == CSS_URI) - addSubresourceURL(urls, styleSheet->completeURL(m_value.string)); -} - -Length CSSPrimitiveValue::viewportPercentageLength() const +ALWAYS_INLINE Ref<StringImpl> CSSPrimitiveValue::formatNumberValue(const char (&characters)[characterCount]) const { - ASSERT(isViewportPercentageLength()); - Length viewportLength; - switch (m_primitiveUnitType) { - case CSS_VW: - viewportLength = Length(getDoubleValue(), ViewportPercentageWidth); - break; - case CSS_VH: - viewportLength = Length(getDoubleValue(), ViewportPercentageHeight); - break; - case CSS_VMIN: - viewportLength = Length(getDoubleValue(), ViewportPercentageMin); - break; - case CSS_VMAX: - viewportLength = Length(getDoubleValue(), ViewportPercentageMax); - break; - default: - break; - } - return viewportLength; + return formatNumberValue(characters, characterCount - 1); } -PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::cloneForCSSOM() const +ALWAYS_INLINE String CSSPrimitiveValue::formatNumberForCustomCSSText() const { - RefPtr<CSSPrimitiveValue> result; - switch (m_primitiveUnitType) { - case CSS_STRING: - case CSS_URI: - case CSS_ATTR: - case CSS_COUNTER_NAME: - result = CSSPrimitiveValue::create(m_value.string, static_cast<UnitTypes>(m_primitiveUnitType)); - break; - case CSS_COUNTER: - result = CSSPrimitiveValue::create(m_value.counter->cloneForCSSOM()); - break; - case CSS_RECT: - result = CSSPrimitiveValue::create(m_value.rect->cloneForCSSOM()); - break; - case CSS_QUAD: - result = CSSPrimitiveValue::create(m_value.quad->cloneForCSSOM()); - break; - case CSS_PAIR: - // Pair is not exposed to the CSSOM, no need for a deep clone. - result = CSSPrimitiveValue::create(m_value.pair); - break; -#if ENABLE(DASHBOARD_SUPPORT) - case CSS_DASHBOARD_REGION: - // DashboardRegion is not exposed to the CSSOM, no need for a deep clone. - result = CSSPrimitiveValue::create(m_value.region); - break; -#endif - case CSS_CALC: - // CSSCalcValue is not exposed to the CSSOM, no need for a deep clone. - result = CSSPrimitiveValue::create(m_value.calc); - break; - case CSS_SHAPE: - // CSSShapeValue is not exposed to the CSSOM, no need for a deep clone. - result = CSSPrimitiveValue::create(m_value.shape); - break; + case CSS_UNKNOWN: + return String(); case CSS_NUMBER: - case CSS_PARSER_INTEGER: + return formatNumberValue(""); case CSS_PERCENTAGE: + return formatNumberValue("%"); case CSS_EMS: + case CSS_QUIRKY_EMS: + return formatNumberValue("em"); case CSS_EXS: + return formatNumberValue("ex"); case CSS_REMS: + return formatNumberValue("rem"); case CSS_CHS: + return formatNumberValue("ch"); case CSS_PX: + return formatNumberValue("px"); case CSS_CM: + return formatNumberValue("cm"); +#if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) + case CSS_DPPX: + return formatNumberValue("dppx"); + case CSS_DPI: + return formatNumberValue("dpi"); + case CSS_DPCM: + return formatNumberValue("dpcm"); +#endif case CSS_MM: + return formatNumberValue("mm"); case CSS_IN: + return formatNumberValue("in"); case CSS_PT: + return formatNumberValue("pt"); case CSS_PC: + return formatNumberValue("pc"); case CSS_DEG: + return formatNumberValue("deg"); case CSS_RAD: + return formatNumberValue("rad"); case CSS_GRAD: + return formatNumberValue("grad"); case CSS_MS: + return formatNumberValue("ms"); case CSS_S: + return formatNumberValue("s"); case CSS_HZ: + return formatNumberValue("hz"); case CSS_KHZ: + return formatNumberValue("khz"); case CSS_TURN: + return formatNumberValue("turn"); + case CSS_FR: + return formatNumberValue("fr"); + case CSS_DIMENSION: + // FIXME: We currently don't handle CSS_DIMENSION properly as we don't store + // the actual dimension, just the numeric value as a string. + case CSS_STRING: + // FIME-NEWPARSER: Once we have CSSCustomIdentValue hooked up, this can just be + // serializeString, since custom identifiers won't be the same value as strings + // any longer. + return serializeAsStringOrCustomIdent(m_value.string); + case CSS_FONT_FAMILY: + return serializeFontFamily(m_value.fontFamily->familyName); + case CSS_URI: + return serializeURL(m_value.string); + case CSS_VALUE_ID: + return valueName(m_value.valueID); + case CSS_PROPERTY_ID: + return propertyName(m_value.propertyID); + case CSS_ATTR: { + StringBuilder result; + result.reserveCapacity(6 + m_value.string->length()); + result.appendLiteral("attr("); + result.append(String(m_value.string)); + result.append(')'); + + return result.toString(); + } + case CSS_COUNTER_NAME: + return "counter(" + String(m_value.string) + ')'; + case CSS_COUNTER: { + StringBuilder result; + String separator = m_value.counter->separator(); + if (separator.isEmpty()) + result.appendLiteral("counter("); + else + result.appendLiteral("counters("); + + result.append(m_value.counter->identifier()); + if (!separator.isEmpty()) { + result.appendLiteral(", "); + serializeString(separator, result); + } + String listStyle = m_value.counter->listStyle(); + if (!listStyle.isEmpty()) { + result.appendLiteral(", "); + result.append(listStyle); + } + result.append(')'); + + return result.toString(); + } + case CSS_RECT: + return rectValue()->cssText(); + case CSS_QUAD: + return quadValue()->cssText(); + case CSS_RGBCOLOR: + return color().cssText(); + case CSS_PAIR: + return pairValue()->cssText(); +#if ENABLE(DASHBOARD_SUPPORT) + case CSS_DASHBOARD_REGION: { + StringBuilder result; + for (DashboardRegion* region = dashboardRegionValue(); region; region = region->m_next.get()) { + if (!result.isEmpty()) + result.append(' '); + result.appendLiteral("dashboard-region("); + result.append(region->m_label); + if (region->m_isCircle) + result.appendLiteral(" circle"); + else if (region->m_isRectangle) + result.appendLiteral(" rectangle"); + else + break; + if (region->top()->m_primitiveUnitType == CSS_VALUE_ID && region->top()->valueID() == CSSValueInvalid) { + ASSERT(region->right()->m_primitiveUnitType == CSS_VALUE_ID); + ASSERT(region->bottom()->m_primitiveUnitType == CSS_VALUE_ID); + ASSERT(region->left()->m_primitiveUnitType == CSS_VALUE_ID); + ASSERT(region->right()->valueID() == CSSValueInvalid); + ASSERT(region->bottom()->valueID() == CSSValueInvalid); + ASSERT(region->left()->valueID() == CSSValueInvalid); + } else { + result.append(' '); + result.append(region->top()->cssText()); + result.append(' '); + result.append(region->right()->cssText()); + result.append(' '); + result.append(region->bottom()->cssText()); + result.append(' '); + result.append(region->left()->cssText()); + } + result.append(')'); + } + return result.toString(); + } +#endif + case CSS_CALC: + return m_value.calc->cssText(); + case CSS_SHAPE: + return m_value.shape->cssText(); case CSS_VW: + return formatNumberValue("vw"); case CSS_VH: + return formatNumberValue("vh"); case CSS_VMIN: + return formatNumberValue("vmin"); case CSS_VMAX: -#if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) - case CSS_DPPX: - case CSS_DPI: - case CSS_DPCM: -#endif - case CSS_FR: - result = CSSPrimitiveValue::create(m_value.num, static_cast<UnitTypes>(m_primitiveUnitType)); - break; - case CSS_PROPERTY_ID: - result = CSSPrimitiveValue::createIdentifier(m_value.propertyID); - break; - case CSS_VALUE_ID: - result = CSSPrimitiveValue::createIdentifier(m_value.valueID); - break; - case CSS_RGBCOLOR: - result = CSSPrimitiveValue::createColor(m_value.rgbcolor); - break; - case CSS_DIMENSION: - case CSS_UNKNOWN: - case CSS_PARSER_OPERATOR: - case CSS_PARSER_IDENTIFIER: - case CSS_PARSER_HEXCOLOR: - ASSERT_NOT_REACHED(); - break; + return formatNumberValue("vmax"); + } + return String(); +} + +String CSSPrimitiveValue::customCSSText() const +{ + // FIXME: return the original value instead of a generated one (e.g. color + // name if it was specified) - check what spec says about this + + CSSTextCache& cssTextCache = WebCore::cssTextCache(); + + if (m_hasCachedCSSText) { + ASSERT(cssTextCache.contains(this)); + return cssTextCache.get(this); } - if (result) - result->setCSSOMSafe(); - return result; + String text = formatNumberForCustomCSSText(); + + ASSERT(!cssTextCache.contains(this)); + m_hasCachedCSSText = true; + cssTextCache.set(this, text); + return text; } bool CSSPrimitiveValue::equals(const CSSPrimitiveValue& other) const @@ -1331,9 +1156,9 @@ bool CSSPrimitiveValue::equals(const CSSPrimitiveValue& other) const case CSS_UNKNOWN: return false; case CSS_NUMBER: - case CSS_PARSER_INTEGER: case CSS_PERCENTAGE: case CSS_EMS: + case CSS_QUIRKY_EMS: case CSS_EXS: case CSS_REMS: case CSS_PX: @@ -1358,19 +1183,17 @@ bool CSSPrimitiveValue::equals(const CSSPrimitiveValue& other) const case CSS_VW: case CSS_VH: case CSS_VMIN: - case CSS_DIMENSION: case CSS_FR: return m_value.num == other.m_value.num; case CSS_PROPERTY_ID: return propertyName(m_value.propertyID) == propertyName(other.m_value.propertyID); case CSS_VALUE_ID: return valueName(m_value.valueID) == valueName(other.m_value.valueID); + case CSS_DIMENSION: case CSS_STRING: case CSS_URI: case CSS_ATTR: case CSS_COUNTER_NAME: - case CSS_PARSER_IDENTIFIER: - case CSS_PARSER_HEXCOLOR: return equal(m_value.string, other.m_value.string); case CSS_COUNTER: return m_value.counter && other.m_value.counter && m_value.counter->equals(*other.m_value.counter); @@ -1379,21 +1202,26 @@ bool CSSPrimitiveValue::equals(const CSSPrimitiveValue& other) const case CSS_QUAD: return m_value.quad && other.m_value.quad && m_value.quad->equals(*other.m_value.quad); case CSS_RGBCOLOR: - return m_value.rgbcolor == other.m_value.rgbcolor; + return color() == other.color(); case CSS_PAIR: return m_value.pair && other.m_value.pair && m_value.pair->equals(*other.m_value.pair); #if ENABLE(DASHBOARD_SUPPORT) case CSS_DASHBOARD_REGION: return m_value.region && other.m_value.region && m_value.region->equals(*other.m_value.region); #endif - case CSS_PARSER_OPERATOR: - return m_value.parserOperator == other.m_value.parserOperator; case CSS_CALC: return m_value.calc && other.m_value.calc && m_value.calc->equals(*other.m_value.calc); case CSS_SHAPE: return m_value.shape && other.m_value.shape && m_value.shape->equals(*other.m_value.shape); + case CSS_FONT_FAMILY: + return fontFamily() == other.fontFamily(); } return false; } +Ref<DeprecatedCSSOMPrimitiveValue> CSSPrimitiveValue::createDeprecatedCSSOMPrimitiveWrapper() const +{ + return DeprecatedCSSOMPrimitiveValue::create(*this); +} + } // namespace WebCore |