2 * (C) 1999-2003 Lars Knoll (knoll@kde.org)
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008 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 "CSSPrimitiveValue.h"
24 #include "CSSHelper.h"
25 #include "CSSParser.h"
26 #include "CSSPropertyNames.h"
27 #include "CSSStyleSheet.h"
28 #include "CSSValueKeywords.h"
31 #include "ExceptionCode.h"
36 #include "RenderStyle.h"
37 #include <wtf/ASCIICType.h>
38 #include <wtf/DecimalNumber.h>
39 #include <wtf/MathExtras.h>
40 #include <wtf/StdLibExtras.h>
41 #include <wtf/text/StringBuffer.h>
43 #if ENABLE(DASHBOARD_SUPPORT)
44 #include "DashboardRegion.h"
51 static CSSPrimitiveValue::UnitCategory unitCategory(CSSPrimitiveValue::UnitTypes type)
53 // Here we violate the spec (http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue) and allow conversions
54 // between CSS_PX and relative lengths (see cssPixelsPerInch comment in CSSHelper.h for the topic treatment).
56 case CSSPrimitiveValue::CSS_NUMBER:
57 return CSSPrimitiveValue::UNumber;
58 case CSSPrimitiveValue::CSS_PERCENTAGE:
59 return CSSPrimitiveValue::UPercent;
60 case CSSPrimitiveValue::CSS_PX:
61 case CSSPrimitiveValue::CSS_CM:
62 case CSSPrimitiveValue::CSS_MM:
63 case CSSPrimitiveValue::CSS_IN:
64 case CSSPrimitiveValue::CSS_PT:
65 case CSSPrimitiveValue::CSS_PC:
66 return CSSPrimitiveValue::ULength;
67 case CSSPrimitiveValue::CSS_MS:
68 case CSSPrimitiveValue::CSS_S:
69 return CSSPrimitiveValue::UTime;
70 case CSSPrimitiveValue::CSS_DEG:
71 case CSSPrimitiveValue::CSS_RAD:
72 case CSSPrimitiveValue::CSS_GRAD:
73 case CSSPrimitiveValue::CSS_TURN:
74 return CSSPrimitiveValue::UAngle;
75 case CSSPrimitiveValue::CSS_HZ:
76 case CSSPrimitiveValue::CSS_KHZ:
77 return CSSPrimitiveValue::UFrequency;
79 return CSSPrimitiveValue::UOther;
83 typedef HashMap<const CSSPrimitiveValue*, String> CSSTextCache;
84 static CSSTextCache& cssTextCache()
86 DEFINE_STATIC_LOCAL(CSSTextCache, cache, ());
90 // A more stylish solution than sharing would be to turn CSSPrimitiveValue (or CSSValues in general) into non-virtual,
91 // non-refcounted simple type with value semantics. In practice these sharing tricks get similar memory benefits
92 // with less need for refactoring.
94 inline PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::createUncachedIdentifier(int identifier)
96 return adoptRef(new CSSPrimitiveValue(identifier));
99 inline PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::createUncachedColor(unsigned rgbValue)
101 return adoptRef(new CSSPrimitiveValue(rgbValue));
104 inline PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::createUncached(double value, UnitTypes type)
106 return adoptRef(new CSSPrimitiveValue(value, type));
109 PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::createIdentifier(int ident)
111 static RefPtr<CSSPrimitiveValue>* identValueCache = new RefPtr<CSSPrimitiveValue>[numCSSValueKeywords];
112 if (ident >= 0 && ident < numCSSValueKeywords) {
113 RefPtr<CSSPrimitiveValue> primitiveValue = identValueCache[ident];
114 if (!primitiveValue) {
115 primitiveValue = createUncachedIdentifier(ident);
116 identValueCache[ident] = primitiveValue;
118 return primitiveValue.release();
120 return createUncachedIdentifier(ident);
123 PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::createColor(unsigned rgbValue)
125 typedef HashMap<unsigned, RefPtr<CSSPrimitiveValue> > ColorValueCache;
126 static ColorValueCache* colorValueCache = new ColorValueCache;
127 // These are the empty and deleted values of the hash table.
128 if (rgbValue == Color::transparent) {
129 static CSSPrimitiveValue* colorTransparent = createUncachedColor(Color::transparent).releaseRef();
130 #if CPU(ARM) && OS(LINUX)
131 // A workaround for gcc bug on ARM.
132 if (!colorTransparent)
135 return colorTransparent;
137 if (rgbValue == Color::white) {
138 static CSSPrimitiveValue* colorWhite = createUncachedColor(Color::white).releaseRef();
139 #if CPU(ARM) && OS(LINUX)
140 // A workaround for gcc bug on ARM.
146 RefPtr<CSSPrimitiveValue> primitiveValue = colorValueCache->get(rgbValue);
148 return primitiveValue.release();
149 primitiveValue = createUncachedColor(rgbValue);
150 // Just wipe out the cache and start rebuilding when it gets too big.
151 const int maxColorCacheSize = 512;
152 if (colorValueCache->size() >= maxColorCacheSize)
153 colorValueCache->clear();
154 colorValueCache->add(rgbValue, primitiveValue);
156 return primitiveValue.release();
159 PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::create(double value, UnitTypes type)
161 // Small integers are very common. Try to share them.
162 const int cachedIntegerCount = 128;
163 // Other common primitive types have UnitTypes smaller than this.
164 const int maxCachedUnitType = CSS_PX;
165 typedef RefPtr<CSSPrimitiveValue>(* IntegerValueCache)[maxCachedUnitType + 1];
166 static IntegerValueCache integerValueCache = new RefPtr<CSSPrimitiveValue>[cachedIntegerCount][maxCachedUnitType + 1];
167 if (type <= maxCachedUnitType && value >= 0 && value < cachedIntegerCount) {
168 int intValue = static_cast<int>(value);
169 if (value == intValue) {
170 RefPtr<CSSPrimitiveValue> primitiveValue = integerValueCache[intValue][type];
171 if (!primitiveValue) {
172 primitiveValue = createUncached(value, type);
173 integerValueCache[intValue][type] = primitiveValue;
175 return primitiveValue.release();
179 return createUncached(value, type);
182 PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::create(const String& value, UnitTypes type)
184 return adoptRef(new CSSPrimitiveValue(value, type));
187 static const AtomicString& valueOrPropertyName(int valueOrPropertyID)
189 ASSERT_ARG(valueOrPropertyID, valueOrPropertyID >= 0);
190 ASSERT_ARG(valueOrPropertyID, valueOrPropertyID < numCSSValueKeywords || (valueOrPropertyID >= firstCSSProperty && valueOrPropertyID < firstCSSProperty + numCSSProperties));
192 if (valueOrPropertyID < 0)
195 if (valueOrPropertyID < numCSSValueKeywords) {
196 static AtomicString* cssValueKeywordStrings[numCSSValueKeywords];
197 if (!cssValueKeywordStrings[valueOrPropertyID])
198 cssValueKeywordStrings[valueOrPropertyID] = new AtomicString(getValueName(valueOrPropertyID));
199 return *cssValueKeywordStrings[valueOrPropertyID];
202 if (valueOrPropertyID >= firstCSSProperty && valueOrPropertyID < firstCSSProperty + numCSSProperties) {
203 static AtomicString* cssPropertyStrings[numCSSProperties];
204 int propertyIndex = valueOrPropertyID - firstCSSProperty;
205 if (!cssPropertyStrings[propertyIndex])
206 cssPropertyStrings[propertyIndex] = new AtomicString(getPropertyName(static_cast<CSSPropertyID>(valueOrPropertyID)));
207 return *cssPropertyStrings[propertyIndex];
213 CSSPrimitiveValue::CSSPrimitiveValue()
215 , m_hasCachedCSSText(false)
219 CSSPrimitiveValue::CSSPrimitiveValue(int ident)
221 , m_hasCachedCSSText(false)
223 m_value.ident = ident;
226 CSSPrimitiveValue::CSSPrimitiveValue(double num, UnitTypes type)
228 , m_hasCachedCSSText(false)
233 CSSPrimitiveValue::CSSPrimitiveValue(const String& str, UnitTypes type)
235 , m_hasCachedCSSText(false)
237 if ((m_value.string = str.impl()))
238 m_value.string->ref();
241 CSSPrimitiveValue::CSSPrimitiveValue(RGBA32 color)
242 : m_type(CSS_RGBCOLOR)
243 , m_hasCachedCSSText(false)
245 m_value.rgbcolor = color;
248 CSSPrimitiveValue::CSSPrimitiveValue(const Length& length)
249 : m_hasCachedCSSText(false)
251 switch (length.type()) {
254 m_value.ident = CSSValueAuto;
258 m_value.num = length.value();
262 m_value.ident = CSSValueIntrinsic;
266 m_value.ident = CSSValueMinIntrinsic;
269 m_type = CSS_PERCENTAGE;
270 m_value.num = length.percent();
274 ASSERT_NOT_REACHED();
279 void CSSPrimitiveValue::init(PassRefPtr<Counter> c)
281 m_type = CSS_COUNTER;
282 m_hasCachedCSSText = false;
283 m_value.counter = c.releaseRef();
286 void CSSPrimitiveValue::init(PassRefPtr<Rect> r)
289 m_hasCachedCSSText = false;
290 m_value.rect = r.releaseRef();
293 #if ENABLE(DASHBOARD_SUPPORT)
294 void CSSPrimitiveValue::init(PassRefPtr<DashboardRegion> r)
296 m_type = CSS_DASHBOARD_REGION;
297 m_hasCachedCSSText = false;
298 m_value.region = r.releaseRef();
302 void CSSPrimitiveValue::init(PassRefPtr<Pair> p)
305 m_hasCachedCSSText = false;
306 m_value.pair = p.releaseRef();
309 CSSPrimitiveValue::~CSSPrimitiveValue()
314 void CSSPrimitiveValue::cleanup()
320 case CSS_PARSER_HEXCOLOR:
322 m_value.string->deref();
325 m_value.counter->deref();
328 m_value.rect->deref();
331 m_value.pair->deref();
333 #if ENABLE(DASHBOARD_SUPPORT)
334 case CSS_DASHBOARD_REGION:
336 m_value.region->deref();
344 if (m_hasCachedCSSText) {
345 cssTextCache().remove(this);
346 m_hasCachedCSSText = false;
350 int CSSPrimitiveValue::computeLengthInt(RenderStyle* style, RenderStyle* rootStyle)
352 return roundForImpreciseConversion<int, INT_MAX, INT_MIN>(computeLengthDouble(style, rootStyle));
355 int CSSPrimitiveValue::computeLengthInt(RenderStyle* style, RenderStyle* rootStyle, double multiplier)
357 return roundForImpreciseConversion<int, INT_MAX, INT_MIN>(computeLengthDouble(style, rootStyle, multiplier));
360 // Lengths expect an int that is only 28-bits, so we have to check for a
361 // different overflow.
362 int CSSPrimitiveValue::computeLengthIntForLength(RenderStyle* style, RenderStyle* rootStyle)
364 return roundForImpreciseConversion<int, intMaxForLength, intMinForLength>(computeLengthDouble(style, rootStyle));
367 int CSSPrimitiveValue::computeLengthIntForLength(RenderStyle* style, RenderStyle* rootStyle, double multiplier)
369 return roundForImpreciseConversion<int, intMaxForLength, intMinForLength>(computeLengthDouble(style, rootStyle, multiplier));
372 short CSSPrimitiveValue::computeLengthShort(RenderStyle* style, RenderStyle* rootStyle)
374 return roundForImpreciseConversion<short, SHRT_MAX, SHRT_MIN>(computeLengthDouble(style, rootStyle));
377 short CSSPrimitiveValue::computeLengthShort(RenderStyle* style, RenderStyle* rootStyle, double multiplier)
379 return roundForImpreciseConversion<short, SHRT_MAX, SHRT_MIN>(computeLengthDouble(style, rootStyle, multiplier));
382 float CSSPrimitiveValue::computeLengthFloat(RenderStyle* style, RenderStyle* rootStyle, bool computingFontSize)
384 return static_cast<float>(computeLengthDouble(style, rootStyle, 1.0, computingFontSize));
387 float CSSPrimitiveValue::computeLengthFloat(RenderStyle* style, RenderStyle* rootStyle, double multiplier, bool computingFontSize)
389 return static_cast<float>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize));
392 double CSSPrimitiveValue::computeLengthDouble(RenderStyle* style, RenderStyle* rootStyle, double multiplier, bool computingFontSize)
394 unsigned short type = primitiveType();
396 // We do not apply the zoom factor when we are computing the value of the font-size property. The zooming
397 // for font sizes is much more complicated, since we have to worry about enforcing the minimum font size preference
398 // as well as enforcing the implicit "smart minimum." In addition the CSS property text-size-adjust is used to
399 // prevent text from zooming at all. Therefore we will not apply the zoom here if we are computing font-size.
400 bool applyZoomMultiplier = !computingFontSize;
405 applyZoomMultiplier = false;
406 factor = computingFontSize ? style->fontDescription().specifiedSize() : style->fontDescription().computedSize();
409 // FIXME: We have a bug right now where the zoom will be applied twice to EX units.
410 // We really need to compute EX using fontMetrics for the original specifiedSize and not use
411 // our actual constructed rendering font.
412 applyZoomMultiplier = false;
413 factor = style->fontMetrics().xHeight();
416 applyZoomMultiplier = false;
417 factor = computingFontSize ? rootStyle->fontDescription().specifiedSize() : rootStyle->fontDescription().computedSize();
422 factor = cssPixelsPerInch / 2.54; // (2.54 cm/in)
425 factor = cssPixelsPerInch / 25.4;
428 factor = cssPixelsPerInch;
431 factor = cssPixelsPerInch / 72.0;
435 factor = cssPixelsPerInch * 12.0 / 72.0;
441 double result = getDoubleValue() * factor;
442 if (!applyZoomMultiplier || multiplier == 1.0)
445 // Any original result that was >= 1 should not be allowed to fall below 1. This keeps border lines from
447 double zoomedResult = result * multiplier;
449 zoomedResult = max(1.0, zoomedResult);
453 void CSSPrimitiveValue::setFloatValue(unsigned short, double, ExceptionCode& ec)
455 // Keeping values immutable makes optimizations easier and allows sharing of the primitive value objects.
456 // No other engine supports mutating style through this API. Computed style is always read-only anyway.
457 // Supporting setter would require making primitive value copy-on-write and taking care of style invalidation.
458 ec = NO_MODIFICATION_ALLOWED_ERR;
461 static double conversionToCanonicalUnitsScaleFactor(unsigned short unitType)
464 // FIXME: the switch can be replaced by an array of scale factors.
466 // These are "canonical" units in their respective categories.
467 case CSSPrimitiveValue::CSS_PX:
468 case CSSPrimitiveValue::CSS_DEG:
469 case CSSPrimitiveValue::CSS_MS:
470 case CSSPrimitiveValue::CSS_HZ:
472 case CSSPrimitiveValue::CSS_CM:
473 factor = cssPixelsPerInch / 2.54; // (2.54 cm/in)
475 case CSSPrimitiveValue::CSS_MM:
476 factor = cssPixelsPerInch / 25.4;
478 case CSSPrimitiveValue::CSS_IN:
479 factor = cssPixelsPerInch;
481 case CSSPrimitiveValue::CSS_PT:
482 factor = cssPixelsPerInch / 72.0;
484 case CSSPrimitiveValue::CSS_PC:
485 factor = cssPixelsPerInch * 12.0 / 72.0; // 1 pc == 12 pt
487 case CSSPrimitiveValue::CSS_RAD:
488 factor = 180 / piDouble;
490 case CSSPrimitiveValue::CSS_GRAD:
493 case CSSPrimitiveValue::CSS_TURN:
496 case CSSPrimitiveValue::CSS_S:
497 case CSSPrimitiveValue::CSS_KHZ:
507 double CSSPrimitiveValue::getDoubleValue(unsigned short unitType, ExceptionCode& ec) const
510 bool success = getDoubleValueInternal(static_cast<UnitTypes>(unitType), &result);
512 ec = INVALID_ACCESS_ERR;
520 double CSSPrimitiveValue::getDoubleValue(unsigned short unitType) const
523 getDoubleValueInternal(static_cast<UnitTypes>(unitType), &result);
527 CSSPrimitiveValue::UnitTypes CSSPrimitiveValue::canonicalUnitTypeForCategory(UnitCategory category)
529 // The canonical unit type is chosen according to the way CSSParser::validUnit() chooses the default unit
530 // in each category (based on unitflags).
537 return CSS_UNKNOWN; // Cannot convert between numbers and percent.
549 bool CSSPrimitiveValue::getDoubleValueInternal(UnitTypes requestedUnitType, double* result) const
551 if (m_type < CSS_NUMBER || (m_type > CSS_DIMENSION && m_type < CSS_TURN) || requestedUnitType < CSS_NUMBER || (requestedUnitType > CSS_DIMENSION && requestedUnitType < CSS_TURN))
553 if (requestedUnitType == m_type || requestedUnitType == CSS_DIMENSION) {
554 *result = m_value.num;
558 UnitTypes sourceUnitType = static_cast<UnitTypes>(m_type);
559 UnitCategory sourceCategory = unitCategory(sourceUnitType);
560 ASSERT(sourceCategory != UOther);
562 UnitTypes targetUnitType = requestedUnitType;
563 UnitCategory targetCategory = unitCategory(targetUnitType);
564 ASSERT(targetCategory != UOther);
566 // Cannot convert between unrelated unit categories if one of them is not UNumber.
567 if (sourceCategory != targetCategory && sourceCategory != UNumber && targetCategory != UNumber)
570 if (targetCategory == UNumber) {
571 // We interpret conversion to CSS_NUMBER as conversion to a canonical unit in this value's category.
572 targetUnitType = canonicalUnitTypeForCategory(sourceCategory);
573 if (targetUnitType == CSS_UNKNOWN)
577 if (sourceUnitType == CSS_NUMBER) {
578 // We interpret conversion from CSS_NUMBER in the same way as CSSParser::validUnit() while using non-strict mode.
579 sourceUnitType = canonicalUnitTypeForCategory(targetCategory);
580 if (sourceUnitType == CSS_UNKNOWN)
584 double convertedValue = m_value.num;
586 // First convert the value from m_type to canonical type.
587 double factor = conversionToCanonicalUnitsScaleFactor(sourceUnitType);
588 convertedValue *= factor;
590 // Now convert from canonical type to the target unitType.
591 factor = conversionToCanonicalUnitsScaleFactor(targetUnitType);
592 convertedValue /= factor;
594 *result = convertedValue;
598 void CSSPrimitiveValue::setStringValue(unsigned short, const String&, ExceptionCode& ec)
600 // Keeping values immutable makes optimizations easier and allows sharing of the primitive value objects.
601 // No other engine supports mutating style through this API. Computed style is always read-only anyway.
602 // Supporting setter would require making primitive value copy-on-write and taking care of style invalidation.
603 ec = NO_MODIFICATION_ALLOWED_ERR;
606 String CSSPrimitiveValue::getStringValue(ExceptionCode& ec) const
613 return m_value.string;
615 return valueOrPropertyName(m_value.ident);
617 ec = INVALID_ACCESS_ERR;
624 String CSSPrimitiveValue::getStringValue() const
630 return m_value.string;
632 return valueOrPropertyName(m_value.ident);
640 Counter* CSSPrimitiveValue::getCounterValue(ExceptionCode& ec) const
643 if (m_type != CSS_COUNTER) {
644 ec = INVALID_ACCESS_ERR;
648 return m_value.counter;
651 Rect* CSSPrimitiveValue::getRectValue(ExceptionCode& ec) const
654 if (m_type != CSS_RECT) {
655 ec = INVALID_ACCESS_ERR;
662 PassRefPtr<RGBColor> CSSPrimitiveValue::getRGBColorValue(ExceptionCode& ec) const
665 if (m_type != CSS_RGBCOLOR) {
666 ec = INVALID_ACCESS_ERR;
670 // FIMXE: This should not return a new object for each invocation.
671 return RGBColor::create(m_value.rgbcolor);
674 Pair* CSSPrimitiveValue::getPairValue(ExceptionCode& ec) const
677 if (m_type != CSS_PAIR) {
678 ec = INVALID_ACCESS_ERR;
685 unsigned short CSSPrimitiveValue::cssValueType() const
687 return CSS_PRIMITIVE_VALUE;
690 bool CSSPrimitiveValue::parseString(const String& /*string*/, bool /*strict*/)
696 int CSSPrimitiveValue::getIdent() const
698 if (m_type != CSS_IDENT)
700 return m_value.ident;
703 static String formatNumber(double number)
705 DecimalNumber decimal(number);
707 StringBuffer buffer(decimal.bufferLengthForStringDecimal());
708 unsigned length = decimal.toStringDecimal(buffer.characters(), buffer.length());
709 ASSERT_UNUSED(length, length == buffer.length());
711 return String::adopt(buffer);
714 String CSSPrimitiveValue::cssText() const
716 // FIXME: return the original value instead of a generated one (e.g. color
717 // name if it was specified) - check what spec says about this
719 if (m_hasCachedCSSText) {
720 ASSERT(cssTextCache().contains(this));
721 return cssTextCache().get(this);
730 case CSS_PARSER_INTEGER:
731 text = formatNumber(m_value.num);
734 text = formatNumber(m_value.num) + "%";
737 text = formatNumber(m_value.num) + "em";
740 text = formatNumber(m_value.num) + "ex";
743 text = formatNumber(m_value.num) + "rem";
746 text = formatNumber(m_value.num) + "px";
749 text = formatNumber(m_value.num) + "cm";
752 text = formatNumber(m_value.num) + "mm";
755 text = formatNumber(m_value.num) + "in";
758 text = formatNumber(m_value.num) + "pt";
761 text = formatNumber(m_value.num) + "pc";
764 text = formatNumber(m_value.num) + "deg";
767 text = formatNumber(m_value.num) + "rad";
770 text = formatNumber(m_value.num) + "grad";
773 text = formatNumber(m_value.num) + "ms";
776 text = formatNumber(m_value.num) + "s";
779 text = formatNumber(m_value.num) + "hz";
782 text = formatNumber(m_value.num) + "khz";
785 text = formatNumber(m_value.num) + "turn";
791 text = quoteCSSStringIfNeeded(m_value.string);
794 text = "url(" + quoteCSSURLIfNeeded(m_value.string) + ")";
797 text = valueOrPropertyName(m_value.ident);
800 DEFINE_STATIC_LOCAL(const String, attrParen, ("attr("));
802 Vector<UChar> result;
803 result.reserveInitialCapacity(6 + m_value.string->length());
805 append(result, attrParen);
806 append(result, m_value.string);
807 result.uncheckedAppend(')');
809 text = String::adopt(result);
814 text += String::number(m_value.num);
816 // FIXME: Add list-style and separator
819 DEFINE_STATIC_LOCAL(const String, rectParen, ("rect("));
821 Rect* rectVal = getRectValue();
822 Vector<UChar> result;
823 result.reserveInitialCapacity(32);
824 append(result, rectParen);
826 append(result, rectVal->top()->cssText());
829 append(result, rectVal->right()->cssText());
832 append(result, rectVal->bottom()->cssText());
835 append(result, rectVal->left()->cssText());
838 text = String::adopt(result);
842 case CSS_PARSER_HEXCOLOR: {
843 DEFINE_STATIC_LOCAL(const String, commaSpace, (", "));
844 DEFINE_STATIC_LOCAL(const String, rgbParen, ("rgb("));
845 DEFINE_STATIC_LOCAL(const String, rgbaParen, ("rgba("));
847 RGBA32 rgbColor = m_value.rgbcolor;
848 if (m_type == CSS_PARSER_HEXCOLOR)
849 Color::parseHexColor(m_value.string, rgbColor);
850 Color color(rgbColor);
852 Vector<UChar> result;
853 result.reserveInitialCapacity(32);
854 if (color.hasAlpha())
855 append(result, rgbaParen);
857 append(result, rgbParen);
859 appendNumber(result, static_cast<unsigned char>(color.red()));
860 append(result, commaSpace);
862 appendNumber(result, static_cast<unsigned char>(color.green()));
863 append(result, commaSpace);
865 appendNumber(result, static_cast<unsigned char>(color.blue()));
866 if (color.hasAlpha()) {
867 append(result, commaSpace);
868 append(result, String::number(color.alpha() / 256.0f));
872 text = String::adopt(result);
876 text = m_value.pair->first()->cssText();
878 text += m_value.pair->second()->cssText();
880 #if ENABLE(DASHBOARD_SUPPORT)
881 case CSS_DASHBOARD_REGION:
882 for (DashboardRegion* region = getDashboardRegionValue(); region; region = region->m_next.get()) {
885 text += "dashboard-region(";
886 text += region->m_label;
887 if (region->m_isCircle)
889 else if (region->m_isRectangle)
890 text += " rectangle";
893 if (region->top()->m_type == CSS_IDENT && region->top()->getIdent() == CSSValueInvalid) {
894 ASSERT(region->right()->m_type == CSS_IDENT);
895 ASSERT(region->bottom()->m_type == CSS_IDENT);
896 ASSERT(region->left()->m_type == CSS_IDENT);
897 ASSERT(region->right()->getIdent() == CSSValueInvalid);
898 ASSERT(region->bottom()->getIdent() == CSSValueInvalid);
899 ASSERT(region->left()->getIdent() == CSSValueInvalid);
902 text += region->top()->cssText() + " ";
903 text += region->right()->cssText() + " ";
904 text += region->bottom()->cssText() + " ";
905 text += region->left()->cssText();
911 case CSS_PARSER_OPERATOR: {
912 char c = static_cast<char>(m_value.ident);
913 text = String(&c, 1U);
916 case CSS_PARSER_IDENTIFIER:
917 text = quoteCSSStringIfNeeded(m_value.string);
921 ASSERT(!cssTextCache().contains(this));
922 cssTextCache().set(this, text);
923 m_hasCachedCSSText = true;
927 void CSSPrimitiveValue::addSubresourceStyleURLs(ListHashSet<KURL>& urls, const CSSStyleSheet* styleSheet)
929 if (m_type == CSS_URI)
930 addSubresourceURL(urls, styleSheet->completeURL(m_value.string));
933 } // namespace WebCore