2 * (C) 1999-2003 Lars Knoll (knoll@kde.org)
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2012 Apple Inc. All rights reserved.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
22 #include "core/css/CSSPrimitiveValue.h"
24 #include "core/css/CSSBasicShapes.h"
25 #include "core/css/CSSCalculationValue.h"
26 #include "core/css/CSSHelper.h"
27 #include "core/css/CSSMarkup.h"
28 #include "core/css/CSSToLengthConversionData.h"
29 #include "core/css/Counter.h"
30 #include "core/css/Pair.h"
31 #include "core/css/Rect.h"
32 #include "core/css/StyleSheetContents.h"
33 #include "core/dom/Node.h"
34 #include "core/style/ComputedStyle.h"
35 #include "platform/LayoutUnit.h"
36 #include "platform/fonts/FontMetrics.h"
37 #include "wtf/StdLibExtras.h"
38 #include "wtf/ThreadSpecific.h"
39 #include "wtf/Threading.h"
40 #include "wtf/text/StringBuffer.h"
41 #include "wtf/text/StringBuilder.h"
49 // Max/min values for CSS, needs to slightly smaller/larger than the true max/min values to allow for rounding without overflowing.
50 // Subtract two (rather than one) to allow for values to be converted to float and back without exceeding the LayoutUnit::max.
51 const int maxValueForCssLength
= INT_MAX
/ kFixedPointDenominator
- 2;
52 const int minValueForCssLength
= INT_MIN
/ kFixedPointDenominator
+ 2;
54 typedef HashMap
<String
, CSSPrimitiveValue::UnitType
> StringToUnitTable
;
56 StringToUnitTable
createStringToUnitTable()
58 StringToUnitTable table
;
59 table
.set(String("em"), CSSPrimitiveValue::CSS_EMS
);
60 table
.set(String("ex"), CSSPrimitiveValue::CSS_EXS
);
61 table
.set(String("px"), CSSPrimitiveValue::CSS_PX
);
62 table
.set(String("cm"), CSSPrimitiveValue::CSS_CM
);
63 table
.set(String("mm"), CSSPrimitiveValue::CSS_MM
);
64 table
.set(String("in"), CSSPrimitiveValue::CSS_IN
);
65 table
.set(String("pt"), CSSPrimitiveValue::CSS_PT
);
66 table
.set(String("pc"), CSSPrimitiveValue::CSS_PC
);
67 table
.set(String("deg"), CSSPrimitiveValue::CSS_DEG
);
68 table
.set(String("rad"), CSSPrimitiveValue::CSS_RAD
);
69 table
.set(String("grad"), CSSPrimitiveValue::CSS_GRAD
);
70 table
.set(String("ms"), CSSPrimitiveValue::CSS_MS
);
71 table
.set(String("s"), CSSPrimitiveValue::CSS_S
);
72 table
.set(String("hz"), CSSPrimitiveValue::CSS_HZ
);
73 table
.set(String("khz"), CSSPrimitiveValue::CSS_KHZ
);
74 table
.set(String("dpi"), CSSPrimitiveValue::CSS_DPI
);
75 table
.set(String("dpcm"), CSSPrimitiveValue::CSS_DPCM
);
76 table
.set(String("dppx"), CSSPrimitiveValue::CSS_DPPX
);
77 table
.set(String("vw"), CSSPrimitiveValue::CSS_VW
);
78 table
.set(String("vh"), CSSPrimitiveValue::CSS_VH
);
79 table
.set(String("vmin"), CSSPrimitiveValue::CSS_VMIN
);
80 table
.set(String("vmax"), CSSPrimitiveValue::CSS_VMAX
);
81 table
.set(String("rem"), CSSPrimitiveValue::CSS_REMS
);
82 table
.set(String("fr"), CSSPrimitiveValue::CSS_FR
);
83 table
.set(String("turn"), CSSPrimitiveValue::CSS_TURN
);
84 table
.set(String("ch"), CSSPrimitiveValue::CSS_CHS
);
85 table
.set(String("__qem"), CSSPrimitiveValue::CSS_QEM
);
89 StringToUnitTable
& unitTable()
91 DEFINE_STATIC_LOCAL(StringToUnitTable
, unitTable
, (createStringToUnitTable()));
97 float CSSPrimitiveValue::clampToCSSLengthRange(double value
)
99 return clampTo
<float>(value
, minValueForCssLength
, maxValueForCssLength
);
102 void CSSPrimitiveValue::initUnitTable()
104 // Make sure we initialize this during blink initialization
105 // to avoid racy static local initialization.
109 CSSPrimitiveValue::UnitType
CSSPrimitiveValue::fromName(const String
& unit
)
111 return unitTable().get(unit
.lower());
114 CSSPrimitiveValue::UnitCategory
CSSPrimitiveValue::unitCategory(UnitType type
)
118 return CSSPrimitiveValue::UNumber
;
120 return CSSPrimitiveValue::UPercent
;
127 return CSSPrimitiveValue::ULength
;
130 return CSSPrimitiveValue::UTime
;
135 return CSSPrimitiveValue::UAngle
;
138 return CSSPrimitiveValue::UFrequency
;
142 return CSSPrimitiveValue::UResolution
;
144 return CSSPrimitiveValue::UOther
;
148 bool CSSPrimitiveValue::colorIsDerivedFromElement() const
150 int valueID
= getValueID();
152 case CSSValueWebkitText
:
153 case CSSValueWebkitLink
:
154 case CSSValueWebkitActivelink
:
155 case CSSValueCurrentcolor
:
162 typedef HashMap
<const CSSPrimitiveValue
*, String
> CSSTextCache
;
163 static CSSTextCache
& cssTextCache()
165 AtomicallyInitializedStaticReference(ThreadSpecific
<CSSTextCache
>, cache
, new ThreadSpecific
<CSSTextCache
>());
169 CSSPrimitiveValue::UnitType
CSSPrimitiveValue::primitiveType() const
171 if (m_primitiveUnitType
== CSS_PROPERTY_ID
|| m_primitiveUnitType
== CSS_VALUE_ID
)
174 if (m_primitiveUnitType
!= CSS_CALC
)
175 return static_cast<UnitType
>(m_primitiveUnitType
);
177 switch (m_value
.calc
->category()) {
185 return CSS_PERCENTAGE
;
188 case CalcPercentNumber
:
189 return CSS_CALC_PERCENTAGE_WITH_NUMBER
;
190 case CalcPercentLength
:
191 return CSS_CALC_PERCENTAGE_WITH_LENGTH
;
200 static const AtomicString
& propertyName(CSSPropertyID propertyID
)
202 return getPropertyNameAtomicString(propertyID
);
205 static const AtomicString
& valueName(CSSValueID valueID
)
207 ASSERT_ARG(valueID
, valueID
>= 0);
208 ASSERT_ARG(valueID
, valueID
< numCSSValueKeywords
);
213 static AtomicString
* keywordStrings
= new AtomicString
[numCSSValueKeywords
]; // Leaked intentionally.
214 AtomicString
& keywordString
= keywordStrings
[valueID
];
215 if (keywordString
.isNull())
216 keywordString
= getValueName(valueID
);
217 return keywordString
;
220 CSSPrimitiveValue::CSSPrimitiveValue(CSSValueID valueID
)
221 : CSSValue(PrimitiveClass
)
223 m_primitiveUnitType
= CSS_VALUE_ID
;
224 m_value
.valueID
= valueID
;
227 CSSPrimitiveValue::CSSPrimitiveValue(CSSPropertyID propertyID
)
228 : CSSValue(PrimitiveClass
)
230 m_primitiveUnitType
= CSS_PROPERTY_ID
;
231 m_value
.propertyID
= propertyID
;
234 CSSPrimitiveValue::CSSPrimitiveValue(double num
, UnitType type
)
235 : CSSValue(PrimitiveClass
)
237 m_primitiveUnitType
= type
;
238 ASSERT(std::isfinite(num
));
242 CSSPrimitiveValue::CSSPrimitiveValue(const String
& str
, UnitType type
)
243 : CSSValue(PrimitiveClass
)
245 m_primitiveUnitType
= type
;
246 m_value
.string
= str
.impl();
248 m_value
.string
->ref();
251 CSSPrimitiveValue::CSSPrimitiveValue(const LengthSize
& lengthSize
, const ComputedStyle
& style
)
252 : CSSValue(PrimitiveClass
)
254 init(lengthSize
, style
);
257 CSSPrimitiveValue::CSSPrimitiveValue(RGBA32 color
)
258 : CSSValue(PrimitiveClass
)
260 m_primitiveUnitType
= CSS_RGBCOLOR
;
261 m_value
.rgbcolor
= color
;
264 CSSPrimitiveValue::CSSPrimitiveValue(const Length
& length
, float zoom
)
265 : CSSValue(PrimitiveClass
)
267 switch (length
.type()) {
269 m_primitiveUnitType
= CSS_VALUE_ID
;
270 m_value
.valueID
= CSSValueAuto
;
273 m_primitiveUnitType
= CSS_VALUE_ID
;
274 m_value
.valueID
= CSSValueIntrinsic
;
277 m_primitiveUnitType
= CSS_VALUE_ID
;
278 m_value
.valueID
= CSSValueMinIntrinsic
;
281 m_primitiveUnitType
= CSS_VALUE_ID
;
282 m_value
.valueID
= CSSValueMinContent
;
285 m_primitiveUnitType
= CSS_VALUE_ID
;
286 m_value
.valueID
= CSSValueMaxContent
;
289 m_primitiveUnitType
= CSS_VALUE_ID
;
290 m_value
.valueID
= CSSValueWebkitFillAvailable
;
293 m_primitiveUnitType
= CSS_VALUE_ID
;
294 m_value
.valueID
= CSSValueWebkitFitContent
;
297 m_primitiveUnitType
= CSS_VALUE_ID
;
298 m_value
.valueID
= CSSValueInternalExtendToZoom
;
301 m_primitiveUnitType
= CSS_PERCENTAGE
;
302 ASSERT(std::isfinite(length
.percent()));
303 m_value
.num
= length
.percent();
306 m_primitiveUnitType
= CSS_PX
;
307 m_value
.num
= length
.value() / zoom
;
310 const CalculationValue
& calc
= length
.calculationValue();
311 if (calc
.pixels() && calc
.percent()) {
312 init(CSSCalcValue::create(
313 CSSCalcValue::createExpressionNode(calc
.pixels() / zoom
, calc
.percent()),
314 calc
.isNonNegative() ? ValueRangeNonNegative
: ValueRangeAll
));
317 if (calc
.percent()) {
318 m_primitiveUnitType
= CSS_PERCENTAGE
;
319 m_value
.num
= calc
.percent();
321 m_primitiveUnitType
= CSS_PX
;
322 m_value
.num
= calc
.pixels() / zoom
;
324 if (m_value
.num
< 0 && calc
.isNonNegative())
331 ASSERT_NOT_REACHED();
336 void CSSPrimitiveValue::init(const LengthSize
& lengthSize
, const ComputedStyle
& style
)
338 m_primitiveUnitType
= CSS_PAIR
;
339 m_hasCachedCSSText
= false;
340 m_value
.pair
= Pair::create(create(lengthSize
.width(), style
.effectiveZoom()), create(lengthSize
.height(), style
.effectiveZoom()), Pair::KeepIdenticalValues
).leakRef();
343 void CSSPrimitiveValue::init(PassRefPtrWillBeRawPtr
<Counter
> c
)
345 m_primitiveUnitType
= CSS_COUNTER
;
346 m_hasCachedCSSText
= false;
347 m_value
.counter
= c
.leakRef();
350 void CSSPrimitiveValue::init(PassRefPtrWillBeRawPtr
<Rect
> r
)
352 m_primitiveUnitType
= CSS_RECT
;
353 m_hasCachedCSSText
= false;
354 m_value
.rect
= r
.leakRef();
357 void CSSPrimitiveValue::init(PassRefPtrWillBeRawPtr
<Quad
> quad
)
359 m_primitiveUnitType
= CSS_QUAD
;
360 m_hasCachedCSSText
= false;
361 m_value
.quad
= quad
.leakRef();
364 void CSSPrimitiveValue::init(PassRefPtrWillBeRawPtr
<Pair
> p
)
366 m_primitiveUnitType
= CSS_PAIR
;
367 m_hasCachedCSSText
= false;
368 m_value
.pair
= p
.leakRef();
371 void CSSPrimitiveValue::init(PassRefPtrWillBeRawPtr
<CSSCalcValue
> c
)
373 m_primitiveUnitType
= CSS_CALC
;
374 m_hasCachedCSSText
= false;
375 m_value
.calc
= c
.leakRef();
378 void CSSPrimitiveValue::init(PassRefPtrWillBeRawPtr
<CSSBasicShape
> shape
)
380 m_primitiveUnitType
= CSS_SHAPE
;
381 m_hasCachedCSSText
= false;
382 m_value
.shape
= shape
.leakRef();
385 CSSPrimitiveValue::~CSSPrimitiveValue()
390 void CSSPrimitiveValue::cleanup()
392 switch (static_cast<UnitType
>(m_primitiveUnitType
)) {
393 case CSS_CUSTOM_IDENT
:
398 m_value
.string
->deref();
401 // We must not call deref() when oilpan is enabled because m_value.counter is traced.
403 m_value
.counter
->deref();
407 // We must not call deref() when oilpan is enabled because m_value.rect is traced.
409 m_value
.rect
->deref();
413 // We must not call deref() when oilpan is enabled because m_value.quad is traced.
415 m_value
.quad
->deref();
419 // We must not call deref() when oilpan is enabled because m_value.pair is traced.
421 m_value
.pair
->deref();
425 // We must not call deref() when oilpan is enabled because m_value.calc is traced.
427 m_value
.calc
->deref();
430 case CSS_CALC_PERCENTAGE_WITH_NUMBER
:
431 case CSS_CALC_PERCENTAGE_WITH_LENGTH
:
432 ASSERT_NOT_REACHED();
435 // We must not call deref() when oilpan is enabled because m_value.shape is traced.
437 m_value
.shape
->deref();
473 case CSS_PROPERTY_ID
:
477 m_primitiveUnitType
= 0;
478 if (m_hasCachedCSSText
) {
479 cssTextCache().remove(this);
480 m_hasCachedCSSText
= false;
484 double CSSPrimitiveValue::computeSeconds()
486 ASSERT(isTime() || (isCalculated() && cssCalcValue()->category() == CalcTime
));
487 UnitType currentType
= isCalculated() ? cssCalcValue()->expressionNode()->primitiveType() : static_cast<UnitType
>(m_primitiveUnitType
);
488 if (currentType
== CSS_S
)
489 return getDoubleValue();
490 if (currentType
== CSS_MS
)
491 return getDoubleValue() / 1000;
492 ASSERT_NOT_REACHED();
496 double CSSPrimitiveValue::computeDegrees() const
498 ASSERT(isAngle() || (isCalculated() && cssCalcValue()->category() == CalcAngle
));
499 UnitType currentType
= isCalculated() ? cssCalcValue()->expressionNode()->primitiveType() : static_cast<UnitType
>(m_primitiveUnitType
);
500 switch (currentType
) {
502 return getDoubleValue();
504 return rad2deg(getDoubleValue());
506 return grad2deg(getDoubleValue());
508 return turn2deg(getDoubleValue());
510 ASSERT_NOT_REACHED();
515 template<> int CSSPrimitiveValue::computeLength(const CSSToLengthConversionData
& conversionData
)
517 return roundForImpreciseConversion
<int>(computeLengthDouble(conversionData
));
520 template<> unsigned CSSPrimitiveValue::computeLength(const CSSToLengthConversionData
& conversionData
)
522 return roundForImpreciseConversion
<unsigned>(computeLengthDouble(conversionData
));
525 template<> Length
CSSPrimitiveValue::computeLength(const CSSToLengthConversionData
& conversionData
)
527 return Length(clampToCSSLengthRange(computeLengthDouble(conversionData
)), Fixed
);
530 template<> short CSSPrimitiveValue::computeLength(const CSSToLengthConversionData
& conversionData
)
532 return roundForImpreciseConversion
<short>(computeLengthDouble(conversionData
));
535 template<> unsigned short CSSPrimitiveValue::computeLength(const CSSToLengthConversionData
& conversionData
)
537 return roundForImpreciseConversion
<unsigned short>(computeLengthDouble(conversionData
));
540 template<> float CSSPrimitiveValue::computeLength(const CSSToLengthConversionData
& conversionData
)
542 return static_cast<float>(computeLengthDouble(conversionData
));
545 template<> double CSSPrimitiveValue::computeLength(const CSSToLengthConversionData
& conversionData
)
547 return computeLengthDouble(conversionData
);
550 double CSSPrimitiveValue::computeLengthDouble(const CSSToLengthConversionData
& conversionData
)
552 // The logic in this function is duplicated in MediaValues::computeLength
553 // because MediaValues::computeLength needs nearly identical logic, but we haven't found a way to make
554 // CSSPrimitiveValue::computeLengthDouble more generic (to solve both cases) without hurting performance.
555 if (m_primitiveUnitType
== CSS_CALC
)
556 return m_value
.calc
->computeLengthPx(conversionData
);
560 switch (primitiveType()) {
562 factor
= conversionData
.emFontSize();
565 factor
= conversionData
.exFontSize();
568 factor
= conversionData
.remFontSize();
571 factor
= conversionData
.chFontSize();
577 factor
= cssPixelsPerCentimeter
;
580 factor
= cssPixelsPerMillimeter
;
583 factor
= cssPixelsPerInch
;
586 factor
= cssPixelsPerPoint
;
589 factor
= cssPixelsPerPica
;
592 factor
= conversionData
.viewportWidthPercent();
595 factor
= conversionData
.viewportHeightPercent();
598 factor
= conversionData
.viewportMinPercent();
601 factor
= conversionData
.viewportMaxPercent();
603 case CSS_CALC_PERCENTAGE_WITH_LENGTH
:
604 case CSS_CALC_PERCENTAGE_WITH_NUMBER
:
605 ASSERT_NOT_REACHED();
608 ASSERT_NOT_REACHED();
612 // We do not apply the zoom factor when we are computing the value of the font-size property. The zooming
613 // for font sizes is much more complicated, since we have to worry about enforcing the minimum font size preference
614 // as well as enforcing the implicit "smart minimum."
615 double result
= getDoubleValue() * factor
;
616 if (isFontRelativeLength())
619 return result
* conversionData
.zoom();
622 void CSSPrimitiveValue::accumulateLengthArray(CSSLengthArray
& lengthArray
, CSSLengthTypeArray
& lengthTypeArray
, double multiplier
) const
624 ASSERT(lengthArray
.size() == LengthUnitTypeCount
);
626 if (m_primitiveUnitType
== CSS_CALC
) {
627 cssCalcValue()->accumulateLengthArray(lengthArray
, lengthTypeArray
, multiplier
);
631 LengthUnitType lengthType
;
632 if (unitTypeToLengthUnitType(static_cast<UnitType
>(m_primitiveUnitType
), lengthType
)) {
633 lengthArray
.at(lengthType
) += m_value
.num
* conversionToCanonicalUnitsScaleFactor(static_cast<UnitType
>(m_primitiveUnitType
)) * multiplier
;
634 lengthTypeArray
.set(lengthType
);
638 void CSSPrimitiveValue::accumulateLengthArray(CSSLengthArray
& lengthArray
, double multiplier
) const
640 CSSLengthTypeArray lengthTypeArray
;
641 lengthTypeArray
.resize(CSSPrimitiveValue::LengthUnitTypeCount
);
642 for (size_t i
= 0; i
< CSSPrimitiveValue::LengthUnitTypeCount
; ++i
)
643 lengthTypeArray
.clear(i
);
644 return CSSPrimitiveValue::accumulateLengthArray(lengthArray
, lengthTypeArray
, multiplier
);
647 double CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor(UnitType unitType
)
650 // FIXME: the switch can be replaced by an array of scale factors.
652 // These are "canonical" units in their respective categories.
659 factor
= cssPixelsPerCentimeter
;
662 factor
= 1 / cssPixelsPerCentimeter
;
665 factor
= cssPixelsPerMillimeter
;
668 factor
= cssPixelsPerInch
;
671 factor
= 1 / cssPixelsPerInch
;
674 factor
= cssPixelsPerPoint
;
677 factor
= cssPixelsPerPica
;
680 factor
= 180 / piDouble
;
699 Length
CSSPrimitiveValue::convertToLength(const CSSToLengthConversionData
& conversionData
)
702 return computeLength
<Length
>(conversionData
);
704 return Length(getDoubleValue(), Percent
);
705 ASSERT(isCalculated());
706 return Length(cssCalcValue()->toCalcValue(conversionData
));
709 double CSSPrimitiveValue::getDoubleValue() const
711 return m_primitiveUnitType
!= CSS_CALC
? m_value
.num
: m_value
.calc
->doubleValue();
714 CSSPrimitiveValue::UnitType
CSSPrimitiveValue::canonicalUnitTypeForCategory(UnitCategory category
)
716 // The canonical unit type is chosen according to the way CSSPropertyParser::validUnit() chooses the default unit
717 // in each category (based on unitflags).
724 return CSS_UNKNOWN
; // Cannot convert between numbers and percent.
738 bool CSSPrimitiveValue::unitTypeToLengthUnitType(UnitType unitType
, LengthUnitType
& lengthType
)
741 case CSSPrimitiveValue::CSS_PX
:
742 case CSSPrimitiveValue::CSS_CM
:
743 case CSSPrimitiveValue::CSS_MM
:
744 case CSSPrimitiveValue::CSS_IN
:
745 case CSSPrimitiveValue::CSS_PT
:
746 case CSSPrimitiveValue::CSS_PC
:
747 lengthType
= UnitTypePixels
;
749 case CSSPrimitiveValue::CSS_EMS
:
750 lengthType
= UnitTypeFontSize
;
752 case CSSPrimitiveValue::CSS_EXS
:
753 lengthType
= UnitTypeFontXSize
;
755 case CSSPrimitiveValue::CSS_REMS
:
756 lengthType
= UnitTypeRootFontSize
;
758 case CSSPrimitiveValue::CSS_CHS
:
759 lengthType
= UnitTypeZeroCharacterWidth
;
761 case CSSPrimitiveValue::CSS_PERCENTAGE
:
762 lengthType
= UnitTypePercentage
;
764 case CSSPrimitiveValue::CSS_VW
:
765 lengthType
= UnitTypeViewportWidth
;
767 case CSSPrimitiveValue::CSS_VH
:
768 lengthType
= UnitTypeViewportHeight
;
770 case CSSPrimitiveValue::CSS_VMIN
:
771 lengthType
= UnitTypeViewportMin
;
773 case CSSPrimitiveValue::CSS_VMAX
:
774 lengthType
= UnitTypeViewportMax
;
781 CSSPrimitiveValue::UnitType
CSSPrimitiveValue::lengthUnitTypeToUnitType(LengthUnitType type
)
785 return CSSPrimitiveValue::CSS_PX
;
786 case UnitTypeFontSize
:
787 return CSSPrimitiveValue::CSS_EMS
;
788 case UnitTypeFontXSize
:
789 return CSSPrimitiveValue::CSS_EXS
;
790 case UnitTypeRootFontSize
:
791 return CSSPrimitiveValue::CSS_REMS
;
792 case UnitTypeZeroCharacterWidth
:
793 return CSSPrimitiveValue::CSS_CHS
;
794 case UnitTypePercentage
:
795 return CSSPrimitiveValue::CSS_PERCENTAGE
;
796 case UnitTypeViewportWidth
:
797 return CSSPrimitiveValue::CSS_VW
;
798 case UnitTypeViewportHeight
:
799 return CSSPrimitiveValue::CSS_VH
;
800 case UnitTypeViewportMin
:
801 return CSSPrimitiveValue::CSS_VMIN
;
802 case UnitTypeViewportMax
:
803 return CSSPrimitiveValue::CSS_VMAX
;
804 case LengthUnitTypeCount
:
807 ASSERT_NOT_REACHED();
808 return CSSPrimitiveValue::CSS_UNKNOWN
;
811 String
CSSPrimitiveValue::getStringValue() const
813 switch (m_primitiveUnitType
) {
814 case CSS_CUSTOM_IDENT
:
818 return m_value
.string
;
820 return valueName(m_value
.valueID
);
821 case CSS_PROPERTY_ID
:
822 return propertyName(m_value
.propertyID
);
830 static String
formatNumber(double number
, const char* suffix
, unsigned suffixLength
)
832 #if OS(WIN) && _MSC_VER < 1900
833 unsigned oldFormat
= _set_output_format(_TWO_DIGIT_EXPONENT
);
835 String result
= String::format("%.6g", number
);
836 #if OS(WIN) && _MSC_VER < 1900
837 _set_output_format(oldFormat
);
839 result
.append(suffix
, suffixLength
);
843 template <unsigned characterCount
>
844 ALWAYS_INLINE
static String
formatNumber(double number
, const char (&characters
)[characterCount
])
846 return formatNumber(number
, characters
, characterCount
- 1);
849 static String
formatNumber(double number
, const char* characters
)
851 return formatNumber(number
, characters
, strlen(characters
));
854 const char* CSSPrimitiveValue::unitTypeToString(UnitType type
)
915 case CSS_CUSTOM_IDENT
:
919 case CSS_PROPERTY_ID
:
929 case CSS_CALC_PERCENTAGE_WITH_NUMBER
:
930 case CSS_CALC_PERCENTAGE_WITH_LENGTH
:
934 ASSERT_NOT_REACHED();
938 String
CSSPrimitiveValue::customCSSText() const
940 if (m_hasCachedCSSText
) {
941 ASSERT(cssTextCache().contains(this));
942 return cssTextCache().get(this);
946 switch (m_primitiveUnitType
) {
951 text
= String::format("%d", getIntValue());
981 text
= formatNumber(m_value
.num
, unitTypeToString((UnitType
)m_primitiveUnitType
));
983 case CSS_CUSTOM_IDENT
:
984 text
= quoteCSSStringIfNeeded(m_value
.string
);
987 text
= serializeString(m_value
.string
);
991 text
= "url(" + quoteCSSURLIfNeeded(m_value
.string
) + ")";
994 text
= valueName(m_value
.valueID
);
996 case CSS_PROPERTY_ID
:
997 text
= propertyName(m_value
.propertyID
);
1000 StringBuilder result
;
1001 result
.reserveCapacity(6 + m_value
.string
->length());
1002 result
.appendLiteral("attr(");
1003 result
.append(m_value
.string
);
1006 text
= result
.toString();
1010 StringBuilder result
;
1011 String separator
= m_value
.counter
->separator();
1012 if (separator
.isEmpty())
1013 result
.appendLiteral("counter(");
1015 result
.appendLiteral("counters(");
1017 result
.append(m_value
.counter
->identifier());
1018 if (!separator
.isEmpty()) {
1019 result
.appendLiteral(", ");
1020 result
.append(serializeString(separator
));
1022 String listStyle
= m_value
.counter
->listStyle();
1023 bool isDefaultListStyle
= m_value
.counter
->listStyleIdent() == CSSValueDecimal
;
1024 if (!listStyle
.isEmpty() && !isDefaultListStyle
) {
1025 result
.appendLiteral(", ");
1026 result
.append(listStyle
);
1030 text
= result
.toString();
1034 text
= getRectValue()->cssText();
1037 text
= getQuadValue()->cssText();
1039 case CSS_RGBCOLOR
: {
1040 text
= Color(m_value
.rgbcolor
).serializedAsCSSComponentValue();
1044 text
= getPairValue()->cssText();
1047 text
= m_value
.calc
->cssText();
1050 text
= m_value
.shape
->cssText();
1054 ASSERT(!cssTextCache().contains(this));
1055 cssTextCache().set(this, text
);
1056 m_hasCachedCSSText
= true;
1060 bool CSSPrimitiveValue::equals(const CSSPrimitiveValue
& other
) const
1062 if (m_primitiveUnitType
!= other
.m_primitiveUnitType
)
1065 switch (m_primitiveUnitType
) {
1069 case CSS_PERCENTAGE
:
1095 return m_value
.num
== other
.m_value
.num
;
1096 case CSS_PROPERTY_ID
:
1097 return m_value
.propertyID
== other
.m_value
.propertyID
;
1099 return m_value
.valueID
== other
.m_value
.valueID
;
1100 case CSS_CUSTOM_IDENT
:
1104 return equal(m_value
.string
, other
.m_value
.string
);
1106 return m_value
.counter
&& other
.m_value
.counter
&& m_value
.counter
->equals(*other
.m_value
.counter
);
1108 return m_value
.rect
&& other
.m_value
.rect
&& m_value
.rect
->equals(*other
.m_value
.rect
);
1110 return m_value
.quad
&& other
.m_value
.quad
&& m_value
.quad
->equals(*other
.m_value
.quad
);
1112 return m_value
.rgbcolor
== other
.m_value
.rgbcolor
;
1114 return m_value
.pair
&& other
.m_value
.pair
&& m_value
.pair
->equals(*other
.m_value
.pair
);
1116 return m_value
.calc
&& other
.m_value
.calc
&& m_value
.calc
->equals(*other
.m_value
.calc
);
1118 return m_value
.shape
&& other
.m_value
.shape
&& m_value
.shape
->equals(*other
.m_value
.shape
);
1123 DEFINE_TRACE_AFTER_DISPATCH(CSSPrimitiveValue
)
1126 switch (m_primitiveUnitType
) {
1128 visitor
->trace(m_value
.counter
);
1131 visitor
->trace(m_value
.rect
);
1134 visitor
->trace(m_value
.quad
);
1137 visitor
->trace(m_value
.pair
);
1140 visitor
->trace(m_value
.calc
);
1143 visitor
->trace(m_value
.shape
);
1149 CSSValue::traceAfterDispatch(visitor
);
1152 } // namespace blink