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/StyleSheetContents.h"
30 #include "core/dom/Node.h"
31 #include "core/style/ComputedStyle.h"
32 #include "platform/LayoutUnit.h"
33 #include "platform/fonts/FontMetrics.h"
34 #include "wtf/StdLibExtras.h"
35 #include "wtf/ThreadSpecific.h"
36 #include "wtf/Threading.h"
37 #include "wtf/text/StringBuffer.h"
38 #include "wtf/text/StringBuilder.h"
46 // Max/min values for CSS, needs to slightly smaller/larger than the true max/min values to allow for rounding without overflowing.
47 // Subtract two (rather than one) to allow for values to be converted to float and back without exceeding the LayoutUnit::max.
48 const int maxValueForCssLength
= INT_MAX
/ kFixedPointDenominator
- 2;
49 const int minValueForCssLength
= INT_MIN
/ kFixedPointDenominator
+ 2;
51 using StringToUnitTable
= HashMap
<String
, CSSPrimitiveValue::UnitType
>;
53 StringToUnitTable
createStringToUnitTable()
55 StringToUnitTable table
;
56 table
.set(String("em"), CSSPrimitiveValue::UnitType::Ems
);
57 table
.set(String("ex"), CSSPrimitiveValue::UnitType::Exs
);
58 table
.set(String("px"), CSSPrimitiveValue::UnitType::Pixels
);
59 table
.set(String("cm"), CSSPrimitiveValue::UnitType::Centimeters
);
60 table
.set(String("mm"), CSSPrimitiveValue::UnitType::Millimeters
);
61 table
.set(String("in"), CSSPrimitiveValue::UnitType::Inches
);
62 table
.set(String("pt"), CSSPrimitiveValue::UnitType::Points
);
63 table
.set(String("pc"), CSSPrimitiveValue::UnitType::Picas
);
64 table
.set(String("deg"), CSSPrimitiveValue::UnitType::Degrees
);
65 table
.set(String("rad"), CSSPrimitiveValue::UnitType::Radians
);
66 table
.set(String("grad"), CSSPrimitiveValue::UnitType::Gradians
);
67 table
.set(String("ms"), CSSPrimitiveValue::UnitType::Milliseconds
);
68 table
.set(String("s"), CSSPrimitiveValue::UnitType::Seconds
);
69 table
.set(String("hz"), CSSPrimitiveValue::UnitType::Hertz
);
70 table
.set(String("khz"), CSSPrimitiveValue::UnitType::Kilohertz
);
71 table
.set(String("dpi"), CSSPrimitiveValue::UnitType::DotsPerInch
);
72 table
.set(String("dpcm"), CSSPrimitiveValue::UnitType::DotsPerCentimeter
);
73 table
.set(String("dppx"), CSSPrimitiveValue::UnitType::DotsPerPixel
);
74 table
.set(String("vw"), CSSPrimitiveValue::UnitType::ViewportWidth
);
75 table
.set(String("vh"), CSSPrimitiveValue::UnitType::ViewportHeight
);
76 table
.set(String("vmin"), CSSPrimitiveValue::UnitType::ViewportMin
);
77 table
.set(String("vmax"), CSSPrimitiveValue::UnitType::ViewportMax
);
78 table
.set(String("rem"), CSSPrimitiveValue::UnitType::Rems
);
79 table
.set(String("fr"), CSSPrimitiveValue::UnitType::Fraction
);
80 table
.set(String("turn"), CSSPrimitiveValue::UnitType::Turns
);
81 table
.set(String("ch"), CSSPrimitiveValue::UnitType::Chs
);
82 table
.set(String("__qem"), CSSPrimitiveValue::UnitType::QuirkyEms
);
86 StringToUnitTable
& unitTable()
88 DEFINE_STATIC_LOCAL(StringToUnitTable
, unitTable
, (createStringToUnitTable()));
94 float CSSPrimitiveValue::clampToCSSLengthRange(double value
)
96 return clampTo
<float>(value
, minValueForCssLength
, maxValueForCssLength
);
99 void CSSPrimitiveValue::initUnitTable()
101 // Make sure we initialize this during blink initialization
102 // to avoid racy static local initialization.
106 CSSPrimitiveValue::UnitType
CSSPrimitiveValue::fromName(const String
& unit
)
108 return unitTable().get(unit
.lower());
111 CSSPrimitiveValue::UnitCategory
CSSPrimitiveValue::unitCategory(UnitType type
)
114 case UnitType::Number
:
115 return CSSPrimitiveValue::UNumber
;
116 case UnitType::Percentage
:
117 return CSSPrimitiveValue::UPercent
;
118 case UnitType::Pixels
:
119 case UnitType::Centimeters
:
120 case UnitType::Millimeters
:
121 case UnitType::Inches
:
122 case UnitType::Points
:
123 case UnitType::Picas
:
124 return CSSPrimitiveValue::ULength
;
125 case UnitType::Milliseconds
:
126 case UnitType::Seconds
:
127 return CSSPrimitiveValue::UTime
;
128 case UnitType::Degrees
:
129 case UnitType::Radians
:
130 case UnitType::Gradians
:
131 case UnitType::Turns
:
132 return CSSPrimitiveValue::UAngle
;
133 case UnitType::Hertz
:
134 case UnitType::Kilohertz
:
135 return CSSPrimitiveValue::UFrequency
;
136 case UnitType::DotsPerPixel
:
137 case UnitType::DotsPerInch
:
138 case UnitType::DotsPerCentimeter
:
139 return CSSPrimitiveValue::UResolution
;
141 return CSSPrimitiveValue::UOther
;
145 bool CSSPrimitiveValue::colorIsDerivedFromElement() const
147 int valueID
= getValueID();
149 case CSSValueWebkitText
:
150 case CSSValueWebkitLink
:
151 case CSSValueWebkitActivelink
:
152 case CSSValueCurrentcolor
:
159 using CSSTextCache
= HashMap
<const CSSPrimitiveValue
*, String
>;
160 static CSSTextCache
& cssTextCache()
162 AtomicallyInitializedStaticReference(ThreadSpecific
<CSSTextCache
>, cache
, new ThreadSpecific
<CSSTextCache
>());
166 CSSPrimitiveValue::UnitType
CSSPrimitiveValue::typeWithCalcResolved() const
168 if (type() != UnitType::Calc
)
171 switch (m_value
.calc
->category()) {
173 return UnitType::Degrees
;
175 return UnitType::Hertz
;
177 return UnitType::Number
;
179 return UnitType::Percentage
;
181 return UnitType::Pixels
;
182 case CalcPercentNumber
:
183 return UnitType::CalcPercentageWithNumber
;
184 case CalcPercentLength
:
185 return UnitType::CalcPercentageWithLength
;
187 return UnitType::Milliseconds
;
189 return UnitType::Unknown
;
191 return UnitType::Unknown
;
194 static const AtomicString
& propertyName(CSSPropertyID propertyID
)
196 return getPropertyNameAtomicString(propertyID
);
199 static const AtomicString
& valueName(CSSValueID valueID
)
201 ASSERT_ARG(valueID
, valueID
>= 0);
202 ASSERT_ARG(valueID
, valueID
< numCSSValueKeywords
);
207 static AtomicString
* keywordStrings
= new AtomicString
[numCSSValueKeywords
]; // Leaked intentionally.
208 AtomicString
& keywordString
= keywordStrings
[valueID
];
209 if (keywordString
.isNull())
210 keywordString
= getValueName(valueID
);
211 return keywordString
;
214 CSSPrimitiveValue::CSSPrimitiveValue(CSSValueID valueID
)
215 : CSSValue(PrimitiveClass
)
217 init(UnitType::ValueID
);
218 m_value
.valueID
= valueID
;
221 CSSPrimitiveValue::CSSPrimitiveValue(CSSPropertyID propertyID
)
222 : CSSValue(PrimitiveClass
)
224 init(UnitType::PropertyID
);
225 m_value
.propertyID
= propertyID
;
228 CSSPrimitiveValue::CSSPrimitiveValue(double num
, UnitType type
)
229 : CSSValue(PrimitiveClass
)
232 ASSERT(std::isfinite(num
));
236 CSSPrimitiveValue::CSSPrimitiveValue(const String
& str
, UnitType type
)
237 : CSSValue(PrimitiveClass
)
240 m_value
.string
= str
.impl();
242 m_value
.string
->ref();
245 CSSPrimitiveValue::CSSPrimitiveValue(RGBA32 color
)
246 : CSSValue(PrimitiveClass
)
248 init(UnitType::RGBColor
);
249 m_value
.rgbcolor
= color
;
252 CSSPrimitiveValue::CSSPrimitiveValue(const Length
& length
, float zoom
)
253 : CSSValue(PrimitiveClass
)
255 switch (length
.type()) {
257 init(UnitType::ValueID
);
258 m_value
.valueID
= CSSValueAuto
;
261 init(UnitType::ValueID
);
262 m_value
.valueID
= CSSValueIntrinsic
;
265 init(UnitType::ValueID
);
266 m_value
.valueID
= CSSValueMinIntrinsic
;
269 init(UnitType::ValueID
);
270 m_value
.valueID
= CSSValueMinContent
;
273 init(UnitType::ValueID
);
274 m_value
.valueID
= CSSValueMaxContent
;
277 init(UnitType::ValueID
);
278 m_value
.valueID
= CSSValueWebkitFillAvailable
;
281 init(UnitType::ValueID
);
282 m_value
.valueID
= CSSValueFitContent
;
285 init(UnitType::ValueID
);
286 m_value
.valueID
= CSSValueInternalExtendToZoom
;
289 init(UnitType::Percentage
);
290 ASSERT(std::isfinite(length
.percent()));
291 m_value
.num
= length
.percent();
294 init(UnitType::Pixels
);
295 m_value
.num
= length
.value() / zoom
;
298 const CalculationValue
& calc
= length
.calculationValue();
299 if (calc
.pixels() && calc
.percent()) {
300 init(CSSCalcValue::create(
301 CSSCalcValue::createExpressionNode(calc
.pixels() / zoom
, calc
.percent()),
305 if (calc
.percent()) {
306 init(UnitType::Percentage
);
307 m_value
.num
= calc
.percent();
309 init(UnitType::Pixels
);
310 m_value
.num
= calc
.pixels() / zoom
;
312 if (m_value
.num
< 0 && calc
.isNonNegative())
319 ASSERT_NOT_REACHED();
324 void CSSPrimitiveValue::init(UnitType type
)
326 m_primitiveUnitType
= static_cast<unsigned>(type
);
329 void CSSPrimitiveValue::init(PassRefPtrWillBeRawPtr
<CSSCalcValue
> c
)
331 init(UnitType::Calc
);
332 m_hasCachedCSSText
= false;
333 m_value
.calc
= c
.leakRef();
336 void CSSPrimitiveValue::init(PassRefPtrWillBeRawPtr
<CSSBasicShape
> shape
)
338 init(UnitType::Shape
);
339 m_hasCachedCSSText
= false;
340 m_value
.shape
= shape
.leakRef();
343 CSSPrimitiveValue::~CSSPrimitiveValue()
348 void CSSPrimitiveValue::cleanup()
351 case UnitType::CustomIdentifier
:
352 case UnitType::String
:
355 m_value
.string
->deref();
358 // We must not call deref() when oilpan is enabled because m_value.calc is traced.
360 m_value
.calc
->deref();
363 case UnitType::CalcPercentageWithNumber
:
364 case UnitType::CalcPercentageWithLength
:
365 ASSERT_NOT_REACHED();
367 case UnitType::Shape
:
368 // We must not call deref() when oilpan is enabled because m_value.shape is traced.
370 m_value
.shape
->deref();
373 case UnitType::Number
:
374 case UnitType::Integer
:
375 case UnitType::Percentage
:
377 case UnitType::QuirkyEms
:
381 case UnitType::Pixels
:
382 case UnitType::Centimeters
:
383 case UnitType::Millimeters
:
384 case UnitType::Inches
:
385 case UnitType::Points
:
386 case UnitType::Picas
:
387 case UnitType::Degrees
:
388 case UnitType::Radians
:
389 case UnitType::Gradians
:
390 case UnitType::Milliseconds
:
391 case UnitType::Seconds
:
392 case UnitType::Hertz
:
393 case UnitType::Kilohertz
:
394 case UnitType::Turns
:
395 case UnitType::ViewportWidth
:
396 case UnitType::ViewportHeight
:
397 case UnitType::ViewportMin
:
398 case UnitType::ViewportMax
:
399 case UnitType::DotsPerPixel
:
400 case UnitType::DotsPerInch
:
401 case UnitType::DotsPerCentimeter
:
402 case UnitType::Fraction
:
403 case UnitType::RGBColor
:
404 case UnitType::Unknown
:
405 case UnitType::PropertyID
:
406 case UnitType::ValueID
:
409 if (m_hasCachedCSSText
) {
410 cssTextCache().remove(this);
411 m_hasCachedCSSText
= false;
415 double CSSPrimitiveValue::computeSeconds() const
417 ASSERT(isTime() || (isCalculated() && cssCalcValue()->category() == CalcTime
));
418 UnitType currentType
= isCalculated() ? cssCalcValue()->expressionNode()->typeWithCalcResolved() : type();
419 if (currentType
== UnitType::Seconds
)
420 return getDoubleValue();
421 if (currentType
== UnitType::Milliseconds
)
422 return getDoubleValue() / 1000;
423 ASSERT_NOT_REACHED();
427 double CSSPrimitiveValue::computeDegrees() const
429 ASSERT(isAngle() || (isCalculated() && cssCalcValue()->category() == CalcAngle
));
430 UnitType currentType
= isCalculated() ? cssCalcValue()->expressionNode()->typeWithCalcResolved() : type();
431 switch (currentType
) {
432 case UnitType::Degrees
:
433 return getDoubleValue();
434 case UnitType::Radians
:
435 return rad2deg(getDoubleValue());
436 case UnitType::Gradians
:
437 return grad2deg(getDoubleValue());
438 case UnitType::Turns
:
439 return turn2deg(getDoubleValue());
441 ASSERT_NOT_REACHED();
446 template<> int CSSPrimitiveValue::computeLength(const CSSToLengthConversionData
& conversionData
) const
448 return roundForImpreciseConversion
<int>(computeLengthDouble(conversionData
));
451 template<> unsigned CSSPrimitiveValue::computeLength(const CSSToLengthConversionData
& conversionData
) const
453 return roundForImpreciseConversion
<unsigned>(computeLengthDouble(conversionData
));
456 template<> Length
CSSPrimitiveValue::computeLength(const CSSToLengthConversionData
& conversionData
) const
458 return Length(clampToCSSLengthRange(computeLengthDouble(conversionData
)), Fixed
);
461 template<> short CSSPrimitiveValue::computeLength(const CSSToLengthConversionData
& conversionData
) const
463 return roundForImpreciseConversion
<short>(computeLengthDouble(conversionData
));
466 template<> unsigned short CSSPrimitiveValue::computeLength(const CSSToLengthConversionData
& conversionData
) const
468 return roundForImpreciseConversion
<unsigned short>(computeLengthDouble(conversionData
));
471 template<> float CSSPrimitiveValue::computeLength(const CSSToLengthConversionData
& conversionData
) const
473 return static_cast<float>(computeLengthDouble(conversionData
));
476 template<> double CSSPrimitiveValue::computeLength(const CSSToLengthConversionData
& conversionData
) const
478 return computeLengthDouble(conversionData
);
481 double CSSPrimitiveValue::computeLengthDouble(const CSSToLengthConversionData
& conversionData
) const
483 // The logic in this function is duplicated in MediaValues::computeLength
484 // because MediaValues::computeLength needs nearly identical logic, but we haven't found a way to make
485 // CSSPrimitiveValue::computeLengthDouble more generic (to solve both cases) without hurting performance.
486 if (type() == UnitType::Calc
)
487 return m_value
.calc
->computeLengthPx(conversionData
);
493 case UnitType::QuirkyEms
:
494 factor
= conversionData
.emFontSize();
497 factor
= conversionData
.exFontSize();
500 factor
= conversionData
.remFontSize();
503 factor
= conversionData
.chFontSize();
505 case UnitType::Pixels
:
508 case UnitType::Centimeters
:
509 factor
= cssPixelsPerCentimeter
;
511 case UnitType::Millimeters
:
512 factor
= cssPixelsPerMillimeter
;
514 case UnitType::Inches
:
515 factor
= cssPixelsPerInch
;
517 case UnitType::Points
:
518 factor
= cssPixelsPerPoint
;
520 case UnitType::Picas
:
521 factor
= cssPixelsPerPica
;
523 case UnitType::ViewportWidth
:
524 factor
= conversionData
.viewportWidthPercent();
526 case UnitType::ViewportHeight
:
527 factor
= conversionData
.viewportHeightPercent();
529 case UnitType::ViewportMin
:
530 factor
= conversionData
.viewportMinPercent();
532 case UnitType::ViewportMax
:
533 factor
= conversionData
.viewportMaxPercent();
535 case UnitType::CalcPercentageWithLength
:
536 case UnitType::CalcPercentageWithNumber
:
537 ASSERT_NOT_REACHED();
540 ASSERT_NOT_REACHED();
544 // We do not apply the zoom factor when we are computing the value of the font-size property. The zooming
545 // for font sizes is much more complicated, since we have to worry about enforcing the minimum font size preference
546 // as well as enforcing the implicit "smart minimum."
547 double result
= getDoubleValue() * factor
;
548 if (isFontRelativeLength())
551 return result
* conversionData
.zoom();
554 void CSSPrimitiveValue::accumulateLengthArray(CSSLengthArray
& lengthArray
, CSSLengthTypeArray
& lengthTypeArray
, double multiplier
) const
556 ASSERT(lengthArray
.size() == LengthUnitTypeCount
);
558 if (type() == UnitType::Calc
) {
559 cssCalcValue()->accumulateLengthArray(lengthArray
, lengthTypeArray
, multiplier
);
563 LengthUnitType lengthType
;
564 if (unitTypeToLengthUnitType(type(), lengthType
)) {
565 lengthArray
.at(lengthType
) += m_value
.num
* conversionToCanonicalUnitsScaleFactor(type()) * multiplier
;
566 lengthTypeArray
.set(lengthType
);
570 void CSSPrimitiveValue::accumulateLengthArray(CSSLengthArray
& lengthArray
, double multiplier
) const
572 CSSLengthTypeArray lengthTypeArray
;
573 lengthTypeArray
.resize(CSSPrimitiveValue::LengthUnitTypeCount
);
574 for (size_t i
= 0; i
< CSSPrimitiveValue::LengthUnitTypeCount
; ++i
)
575 lengthTypeArray
.clear(i
);
576 return CSSPrimitiveValue::accumulateLengthArray(lengthArray
, lengthTypeArray
, multiplier
);
579 double CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor(UnitType unitType
)
582 // FIXME: the switch can be replaced by an array of scale factors.
584 // These are "canonical" units in their respective categories.
585 case UnitType::Pixels
:
586 case UnitType::Degrees
:
587 case UnitType::Milliseconds
:
588 case UnitType::Hertz
:
590 case UnitType::Centimeters
:
591 factor
= cssPixelsPerCentimeter
;
593 case UnitType::DotsPerCentimeter
:
594 factor
= 1 / cssPixelsPerCentimeter
;
596 case UnitType::Millimeters
:
597 factor
= cssPixelsPerMillimeter
;
599 case UnitType::Inches
:
600 factor
= cssPixelsPerInch
;
602 case UnitType::DotsPerInch
:
603 factor
= 1 / cssPixelsPerInch
;
605 case UnitType::Points
:
606 factor
= cssPixelsPerPoint
;
608 case UnitType::Picas
:
609 factor
= cssPixelsPerPica
;
611 case UnitType::Radians
:
612 factor
= 180 / piDouble
;
614 case UnitType::Gradians
:
617 case UnitType::Turns
:
620 case UnitType::Seconds
:
621 case UnitType::Kilohertz
:
631 Length
CSSPrimitiveValue::convertToLength(const CSSToLengthConversionData
& conversionData
) const
634 return computeLength
<Length
>(conversionData
);
636 return Length(getDoubleValue(), Percent
);
637 ASSERT(isCalculated());
638 return Length(cssCalcValue()->toCalcValue(conversionData
));
641 double CSSPrimitiveValue::getDoubleValue() const
643 return type() != UnitType::Calc
? m_value
.num
: m_value
.calc
->doubleValue();
646 CSSPrimitiveValue::UnitType
CSSPrimitiveValue::canonicalUnitTypeForCategory(UnitCategory category
)
648 // The canonical unit type is chosen according to the way CSSPropertyParser::validUnit() chooses the default unit
649 // in each category (based on unitflags).
652 return UnitType::Number
;
654 return UnitType::Pixels
;
656 return UnitType::Unknown
; // Cannot convert between numbers and percent.
658 return UnitType::Milliseconds
;
660 return UnitType::Degrees
;
662 return UnitType::Hertz
;
664 return UnitType::DotsPerPixel
;
666 return UnitType::Unknown
;
670 bool CSSPrimitiveValue::unitTypeToLengthUnitType(UnitType unitType
, LengthUnitType
& lengthType
)
673 case CSSPrimitiveValue::UnitType::Pixels
:
674 case CSSPrimitiveValue::UnitType::Centimeters
:
675 case CSSPrimitiveValue::UnitType::Millimeters
:
676 case CSSPrimitiveValue::UnitType::Inches
:
677 case CSSPrimitiveValue::UnitType::Points
:
678 case CSSPrimitiveValue::UnitType::Picas
:
679 lengthType
= UnitTypePixels
;
681 case CSSPrimitiveValue::UnitType::Ems
:
682 case CSSPrimitiveValue::UnitType::QuirkyEms
:
683 lengthType
= UnitTypeFontSize
;
685 case CSSPrimitiveValue::UnitType::Exs
:
686 lengthType
= UnitTypeFontXSize
;
688 case CSSPrimitiveValue::UnitType::Rems
:
689 lengthType
= UnitTypeRootFontSize
;
691 case CSSPrimitiveValue::UnitType::Chs
:
692 lengthType
= UnitTypeZeroCharacterWidth
;
694 case CSSPrimitiveValue::UnitType::Percentage
:
695 lengthType
= UnitTypePercentage
;
697 case CSSPrimitiveValue::UnitType::ViewportWidth
:
698 lengthType
= UnitTypeViewportWidth
;
700 case CSSPrimitiveValue::UnitType::ViewportHeight
:
701 lengthType
= UnitTypeViewportHeight
;
703 case CSSPrimitiveValue::UnitType::ViewportMin
:
704 lengthType
= UnitTypeViewportMin
;
706 case CSSPrimitiveValue::UnitType::ViewportMax
:
707 lengthType
= UnitTypeViewportMax
;
714 CSSPrimitiveValue::UnitType
CSSPrimitiveValue::lengthUnitTypeToUnitType(LengthUnitType type
)
718 return CSSPrimitiveValue::UnitType::Pixels
;
719 case UnitTypeFontSize
:
720 return CSSPrimitiveValue::UnitType::Ems
;
721 case UnitTypeFontXSize
:
722 return CSSPrimitiveValue::UnitType::Exs
;
723 case UnitTypeRootFontSize
:
724 return CSSPrimitiveValue::UnitType::Rems
;
725 case UnitTypeZeroCharacterWidth
:
726 return CSSPrimitiveValue::UnitType::Chs
;
727 case UnitTypePercentage
:
728 return CSSPrimitiveValue::UnitType::Percentage
;
729 case UnitTypeViewportWidth
:
730 return CSSPrimitiveValue::UnitType::ViewportWidth
;
731 case UnitTypeViewportHeight
:
732 return CSSPrimitiveValue::UnitType::ViewportHeight
;
733 case UnitTypeViewportMin
:
734 return CSSPrimitiveValue::UnitType::ViewportMin
;
735 case UnitTypeViewportMax
:
736 return CSSPrimitiveValue::UnitType::ViewportMax
;
737 case LengthUnitTypeCount
:
740 ASSERT_NOT_REACHED();
741 return CSSPrimitiveValue::UnitType::Unknown
;
744 String
CSSPrimitiveValue::getStringValue() const
747 case UnitType::CustomIdentifier
:
748 case UnitType::String
:
750 return m_value
.string
;
755 ASSERT_NOT_REACHED();
759 static String
formatNumber(double number
, const char* suffix
, unsigned suffixLength
)
761 #if OS(WIN) && _MSC_VER < 1900
762 unsigned oldFormat
= _set_output_format(_TWO_DIGIT_EXPONENT
);
764 String result
= String::format("%.6g", number
);
765 #if OS(WIN) && _MSC_VER < 1900
766 _set_output_format(oldFormat
);
768 result
.append(suffix
, suffixLength
);
772 template <unsigned characterCount
>
773 ALWAYS_INLINE
static String
formatNumber(double number
, const char (&characters
)[characterCount
])
775 return formatNumber(number
, characters
, characterCount
- 1);
778 static String
formatNumber(double number
, const char* characters
)
780 return formatNumber(number
, characters
, strlen(characters
));
783 const char* CSSPrimitiveValue::unitTypeToString(UnitType type
)
786 case UnitType::Number
:
787 case UnitType::Integer
:
789 case UnitType::Percentage
:
792 case UnitType::QuirkyEms
:
800 case UnitType::Pixels
:
802 case UnitType::Centimeters
:
804 case UnitType::DotsPerPixel
:
806 case UnitType::DotsPerInch
:
808 case UnitType::DotsPerCentimeter
:
810 case UnitType::Millimeters
:
812 case UnitType::Inches
:
814 case UnitType::Points
:
816 case UnitType::Picas
:
818 case UnitType::Degrees
:
820 case UnitType::Radians
:
822 case UnitType::Gradians
:
824 case UnitType::Milliseconds
:
826 case UnitType::Seconds
:
828 case UnitType::Hertz
:
830 case UnitType::Kilohertz
:
832 case UnitType::Turns
:
834 case UnitType::Fraction
:
836 case UnitType::ViewportWidth
:
838 case UnitType::ViewportHeight
:
840 case UnitType::ViewportMin
:
842 case UnitType::ViewportMax
:
844 case UnitType::Unknown
:
845 case UnitType::CustomIdentifier
:
846 case UnitType::String
:
848 case UnitType::ValueID
:
849 case UnitType::PropertyID
:
850 case UnitType::RGBColor
:
852 case UnitType::Shape
:
853 case UnitType::CalcPercentageWithNumber
:
854 case UnitType::CalcPercentageWithLength
:
857 ASSERT_NOT_REACHED();
861 String
CSSPrimitiveValue::customCSSText() const
863 if (m_hasCachedCSSText
) {
864 ASSERT(cssTextCache().contains(this));
865 return cssTextCache().get(this);
870 case UnitType::Unknown
:
873 case UnitType::Integer
:
874 text
= String::format("%d", getIntValue());
876 case UnitType::Number
:
877 case UnitType::Percentage
:
879 case UnitType::QuirkyEms
:
883 case UnitType::Pixels
:
884 case UnitType::Centimeters
:
885 case UnitType::DotsPerPixel
:
886 case UnitType::DotsPerInch
:
887 case UnitType::DotsPerCentimeter
:
888 case UnitType::Millimeters
:
889 case UnitType::Inches
:
890 case UnitType::Points
:
891 case UnitType::Picas
:
892 case UnitType::Degrees
:
893 case UnitType::Radians
:
894 case UnitType::Gradians
:
895 case UnitType::Milliseconds
:
896 case UnitType::Seconds
:
897 case UnitType::Hertz
:
898 case UnitType::Kilohertz
:
899 case UnitType::Turns
:
900 case UnitType::Fraction
:
901 case UnitType::ViewportWidth
:
902 case UnitType::ViewportHeight
:
903 case UnitType::ViewportMin
:
904 case UnitType::ViewportMax
:
905 text
= formatNumber(m_value
.num
, unitTypeToString(type()));
907 case UnitType::CustomIdentifier
:
908 text
= quoteCSSStringIfNeeded(m_value
.string
);
910 case UnitType::String
: {
911 text
= serializeString(m_value
.string
);
915 text
= "url(" + quoteCSSURLIfNeeded(m_value
.string
) + ")";
917 case UnitType::ValueID
:
918 text
= valueName(m_value
.valueID
);
920 case UnitType::PropertyID
:
921 text
= propertyName(m_value
.propertyID
);
923 case UnitType::RGBColor
: {
924 text
= Color(m_value
.rgbcolor
).serializedAsCSSComponentValue();
928 text
= m_value
.calc
->customCSSText();
930 case UnitType::Shape
:
931 text
= m_value
.shape
->cssText();
933 case UnitType::CalcPercentageWithNumber
:
934 case UnitType::CalcPercentageWithLength
:
935 ASSERT_NOT_REACHED();
939 ASSERT(!cssTextCache().contains(this));
940 cssTextCache().set(this, text
);
941 m_hasCachedCSSText
= true;
945 bool CSSPrimitiveValue::equals(const CSSPrimitiveValue
& other
) const
947 if (type() != other
.type())
951 case UnitType::Unknown
:
953 case UnitType::Number
:
954 case UnitType::Percentage
:
958 case UnitType::Pixels
:
959 case UnitType::Centimeters
:
960 case UnitType::DotsPerPixel
:
961 case UnitType::DotsPerInch
:
962 case UnitType::DotsPerCentimeter
:
963 case UnitType::Millimeters
:
964 case UnitType::Inches
:
965 case UnitType::Points
:
966 case UnitType::Picas
:
967 case UnitType::Degrees
:
968 case UnitType::Radians
:
969 case UnitType::Gradians
:
970 case UnitType::Milliseconds
:
971 case UnitType::Seconds
:
972 case UnitType::Hertz
:
973 case UnitType::Kilohertz
:
974 case UnitType::Turns
:
975 case UnitType::ViewportWidth
:
976 case UnitType::ViewportHeight
:
977 case UnitType::ViewportMin
:
978 case UnitType::ViewportMax
:
979 case UnitType::Fraction
:
980 return m_value
.num
== other
.m_value
.num
;
981 case UnitType::PropertyID
:
982 return m_value
.propertyID
== other
.m_value
.propertyID
;
983 case UnitType::ValueID
:
984 return m_value
.valueID
== other
.m_value
.valueID
;
985 case UnitType::CustomIdentifier
:
986 case UnitType::String
:
988 return equal(m_value
.string
, other
.m_value
.string
);
989 case UnitType::RGBColor
:
990 return m_value
.rgbcolor
== other
.m_value
.rgbcolor
;
992 return m_value
.calc
&& other
.m_value
.calc
&& m_value
.calc
->equals(*other
.m_value
.calc
);
993 case UnitType::Shape
:
994 return m_value
.shape
&& other
.m_value
.shape
&& m_value
.shape
->equals(*other
.m_value
.shape
);
995 case UnitType::Integer
:
997 case UnitType::CalcPercentageWithNumber
:
998 case UnitType::CalcPercentageWithLength
:
999 case UnitType::QuirkyEms
:
1005 DEFINE_TRACE_AFTER_DISPATCH(CSSPrimitiveValue
)
1009 case UnitType::Calc
:
1010 visitor
->trace(m_value
.calc
);
1012 case UnitType::Shape
:
1013 visitor
->trace(m_value
.shape
);
1019 CSSValue::traceAfterDispatch(visitor
);
1022 } // namespace blink