PageRenderTime 80ms CodeModel.GetById 16ms app.highlight 57ms RepoModel.GetById 2ms app.codeStats 0ms

/platform/external/webkit/WebCore/css/CSSPrimitiveValue.cpp

https://github.com/aharish/totoro-gb-opensource-update2
C++ | 971 lines | 916 code | 22 blank | 33 comment | 40 complexity | 960793e56dbb64de173ebf74eceb120b MD5 | raw file
  1/*
  2 * (C) 1999-2003 Lars Knoll (knoll@kde.org)
  3 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
  4 *
  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.
  9 *
 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.
 14 *
 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.
 19 */
 20
 21#include "config.h"
 22#include "CSSPrimitiveValue.h"
 23
 24#include "CSSHelper.h"
 25#include "CSSPropertyNames.h"
 26#include "CSSStyleSheet.h"
 27#include "CSSValueKeywords.h"
 28#include "Color.h"
 29#include "Counter.h"
 30#include "ExceptionCode.h"
 31#include "Node.h"
 32#include "Pair.h"
 33#include "RGBColor.h"
 34#include "Rect.h"
 35#include "RenderStyle.h"
 36#include <wtf/ASCIICType.h>
 37#include <wtf/StdLibExtras.h>
 38
 39#if ENABLE(DASHBOARD_SUPPORT)
 40#include "DashboardRegion.h"
 41#endif
 42
 43using namespace WTF;
 44
 45namespace WebCore {
 46
 47// A more stylish solution than sharing would be to turn CSSPrimitiveValue (or CSSValues in general) into non-virtual,
 48// non-refcounted simple type with value semantics. In practice these sharing tricks get similar memory benefits 
 49// with less need for refactoring.
 50
 51PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::createIdentifier(int ident)
 52{
 53    static RefPtr<CSSPrimitiveValue>* identValueCache = new RefPtr<CSSPrimitiveValue>[numCSSValueKeywords];
 54    if (ident >= 0 && ident < numCSSValueKeywords) {
 55        RefPtr<CSSPrimitiveValue> primitiveValue = identValueCache[ident];
 56        if (!primitiveValue) {
 57            primitiveValue = adoptRef(new CSSPrimitiveValue(ident));
 58            identValueCache[ident] = primitiveValue;
 59        }
 60        return primitiveValue.release();
 61    } 
 62    return adoptRef(new CSSPrimitiveValue(ident));
 63}
 64
 65PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::createColor(unsigned rgbValue)
 66{
 67    typedef HashMap<unsigned, RefPtr<CSSPrimitiveValue> > ColorValueCache;
 68    static ColorValueCache* colorValueCache = new ColorValueCache;
 69    // These are the empty and deleted values of the hash table.
 70    if (rgbValue == Color::transparent) {
 71        static CSSPrimitiveValue* colorTransparent = new CSSPrimitiveValue(Color::transparent);
 72        return colorTransparent;
 73    }
 74    if (rgbValue == Color::white) {
 75        static CSSPrimitiveValue* colorWhite = new CSSPrimitiveValue(Color::white);
 76        return colorWhite;
 77    }
 78    RefPtr<CSSPrimitiveValue> primitiveValue = colorValueCache->get(rgbValue);
 79    if (primitiveValue)
 80        return primitiveValue.release();
 81    primitiveValue = adoptRef(new CSSPrimitiveValue(rgbValue));
 82    // Just wipe out the cache and start rebuilding when it gets too big.
 83    const int maxColorCacheSize = 512;
 84    if (colorValueCache->size() >= maxColorCacheSize)
 85        colorValueCache->clear();
 86    colorValueCache->add(rgbValue, primitiveValue);
 87    
 88    return primitiveValue.release();
 89}
 90
 91PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::create(double value, UnitTypes type)
 92{
 93    // Small integers are very common. Try to share them.
 94    const int cachedIntegerCount = 128;
 95    // Other common primitive types have UnitTypes smaller than this.
 96    const int maxCachedUnitType = CSS_PX;
 97    typedef RefPtr<CSSPrimitiveValue>(* IntegerValueCache)[maxCachedUnitType + 1];
 98    static IntegerValueCache integerValueCache = new RefPtr<CSSPrimitiveValue>[cachedIntegerCount][maxCachedUnitType + 1];
 99    if (type <= maxCachedUnitType && value >= 0 && value < cachedIntegerCount) {
100        int intValue = static_cast<int>(value);
101        if (value == intValue) {
102            RefPtr<CSSPrimitiveValue> primitiveValue = integerValueCache[intValue][type];
103            if (!primitiveValue) {
104                primitiveValue = adoptRef(new CSSPrimitiveValue(value, type));
105                integerValueCache[intValue][type] = primitiveValue;
106            }
107            return primitiveValue.release();
108        }
109    }
110
111    return adoptRef(new CSSPrimitiveValue(value, type));
112}
113
114PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::create(const String& value, UnitTypes type)
115{
116    return adoptRef(new CSSPrimitiveValue(value, type));
117}
118
119static const char* valueOrPropertyName(int valueOrPropertyID)
120{
121    if (const char* valueName = getValueName(valueOrPropertyID))
122        return valueName;
123    return getPropertyName(static_cast<CSSPropertyID>(valueOrPropertyID));
124}
125
126// "ident" from the CSS tokenizer, minus backslash-escape sequences
127static bool isCSSTokenizerIdentifier(const String& string)
128{
129    const UChar* p = string.characters();
130    const UChar* end = p + string.length();
131
132    // -?
133    if (p != end && p[0] == '-')
134        ++p;
135
136    // {nmstart}
137    if (p == end || !(p[0] == '_' || p[0] >= 128 || isASCIIAlpha(p[0])))
138        return false;
139    ++p;
140
141    // {nmchar}*
142    for (; p != end; ++p) {
143        if (!(p[0] == '_' || p[0] == '-' || p[0] >= 128 || isASCIIAlphanumeric(p[0])))
144            return false;
145    }
146
147    return true;
148}
149
150// "url" from the CSS tokenizer, minus backslash-escape sequences
151static bool isCSSTokenizerURL(const String& string)
152{
153    const UChar* p = string.characters();
154    const UChar* end = p + string.length();
155
156    for (; p != end; ++p) {
157        UChar c = p[0];
158        switch (c) {
159            case '!':
160            case '#':
161            case '$':
162            case '%':
163            case '&':
164                break;
165            default:
166                if (c < '*')
167                    return false;
168                if (c <= '~')
169                    break;
170                if (c < 128)
171                    return false;
172        }
173    }
174
175    return true;
176}
177
178// We use single quotes for now because markup.cpp uses double quotes.
179static String quoteString(const String& string)
180{
181    // FIXME: Also need to escape characters like '\n'.
182    String s = string;
183    s.replace('\\', "\\\\");
184    s.replace('\'', "\\'");
185    return "'" + s + "'";
186}
187
188static String quoteStringIfNeeded(const String& string)
189{
190    return isCSSTokenizerIdentifier(string) ? string : quoteString(string);
191}
192
193static String quoteURLIfNeeded(const String& string)
194{
195    return isCSSTokenizerURL(string) ? string : quoteString(string);
196}
197
198CSSPrimitiveValue::CSSPrimitiveValue()
199    : m_type(0)
200{
201}
202
203CSSPrimitiveValue::CSSPrimitiveValue(int ident)
204    : m_type(CSS_IDENT)
205{
206    m_value.ident = ident;
207}
208
209CSSPrimitiveValue::CSSPrimitiveValue(double num, UnitTypes type)
210    : m_type(type)
211{
212    m_value.num = num;
213}
214
215CSSPrimitiveValue::CSSPrimitiveValue(const String& str, UnitTypes type)
216    : m_type(type)
217{
218    if ((m_value.string = str.impl()))
219        m_value.string->ref();
220}
221
222CSSPrimitiveValue::CSSPrimitiveValue(RGBA32 color)
223    : m_type(CSS_RGBCOLOR)
224{
225    m_value.rgbcolor = color;
226}
227
228CSSPrimitiveValue::CSSPrimitiveValue(const Length& length)
229{
230    switch (length.type()) {
231        case Auto:
232            m_type = CSS_IDENT;
233            m_value.ident = CSSValueAuto;
234            break;
235        case WebCore::Fixed:
236            m_type = CSS_PX;
237            m_value.num = length.value();
238            break;
239        case Intrinsic:
240            m_type = CSS_IDENT;
241            m_value.ident = CSSValueIntrinsic;
242            break;
243        case MinIntrinsic:
244            m_type = CSS_IDENT;
245            m_value.ident = CSSValueMinIntrinsic;
246            break;
247        case Percent:
248            m_type = CSS_PERCENTAGE;
249            m_value.num = length.percent();
250            break;
251        case Relative:
252        case Static:
253            ASSERT_NOT_REACHED();
254            break;
255    }
256}
257
258void CSSPrimitiveValue::init(PassRefPtr<Counter> c)
259{
260    m_type = CSS_COUNTER;
261    m_value.counter = c.releaseRef();
262}
263
264void CSSPrimitiveValue::init(PassRefPtr<Rect> r)
265{
266    m_type = CSS_RECT;
267    m_value.rect = r.releaseRef();
268}
269
270#if ENABLE(DASHBOARD_SUPPORT)
271void CSSPrimitiveValue::init(PassRefPtr<DashboardRegion> r)
272{
273    m_type = CSS_DASHBOARD_REGION;
274    m_value.region = r.releaseRef();
275}
276#endif
277
278void CSSPrimitiveValue::init(PassRefPtr<Pair> p)
279{
280    m_type = CSS_PAIR;
281    m_value.pair = p.releaseRef();
282}
283
284CSSPrimitiveValue::~CSSPrimitiveValue()
285{
286    cleanup();
287}
288
289void CSSPrimitiveValue::cleanup()
290{
291    switch (m_type) {
292        case CSS_STRING:
293        case CSS_URI:
294        case CSS_ATTR:
295        case CSS_PARSER_VARIABLE_FUNCTION_SYNTAX:
296        case CSS_PARSER_HEXCOLOR:
297            if (m_value.string)
298                m_value.string->deref();
299            break;
300        case CSS_COUNTER:
301            m_value.counter->deref();
302            break;
303        case CSS_RECT:
304            m_value.rect->deref();
305            break;
306        case CSS_PAIR:
307            m_value.pair->deref();
308            break;
309#if ENABLE(DASHBOARD_SUPPORT)
310        case CSS_DASHBOARD_REGION:
311            if (m_value.region)
312                m_value.region->deref();
313            break;
314#endif
315        default:
316            break;
317    }
318
319    m_type = 0;
320}
321
322int CSSPrimitiveValue::computeLengthInt(RenderStyle* style, RenderStyle* rootStyle)
323{
324    double result = computeLengthDouble(style, rootStyle);
325
326    // This conversion is imprecise, often resulting in values of, e.g., 44.99998.  We
327    // need to go ahead and round if we're really close to the next integer value.
328    result += result < 0 ? -0.01 : +0.01;
329
330    if (result > INT_MAX || result < INT_MIN)
331        return 0;
332    return static_cast<int>(result);
333}
334
335int CSSPrimitiveValue::computeLengthInt(RenderStyle* style, RenderStyle* rootStyle, double multiplier)
336{
337    double result = computeLengthDouble(style, rootStyle, multiplier);
338
339    // This conversion is imprecise, often resulting in values of, e.g., 44.99998.  We
340    // need to go ahead and round if we're really close to the next integer value.
341    result += result < 0 ? -0.01 : +0.01;
342
343    if (result > INT_MAX || result < INT_MIN)
344        return 0;
345    return static_cast<int>(result);
346}
347
348const int intMaxForLength = 0x7ffffff; // max value for a 28-bit int
349const int intMinForLength = (-0x7ffffff - 1); // min value for a 28-bit int
350
351// Lengths expect an int that is only 28-bits, so we have to check for a different overflow.
352int CSSPrimitiveValue::computeLengthIntForLength(RenderStyle* style, RenderStyle* rootStyle)
353{
354    double result = computeLengthDouble(style, rootStyle);
355
356    // This conversion is imprecise, often resulting in values of, e.g., 44.99998.  We
357    // need to go ahead and round if we're really close to the next integer value.
358    result += result < 0 ? -0.01 : +0.01;
359
360    if (result > intMaxForLength || result < intMinForLength)
361        return 0;
362    return static_cast<int>(result);
363}
364
365// Lengths expect an int that is only 28-bits, so we have to check for a different overflow.
366int CSSPrimitiveValue::computeLengthIntForLength(RenderStyle* style, RenderStyle* rootStyle, double multiplier)
367{
368    double result = computeLengthDouble(style, rootStyle, multiplier);
369
370    // This conversion is imprecise, often resulting in values of, e.g., 44.99998.  We
371    // need to go ahead and round if we're really close to the next integer value.
372    result += result < 0 ? -0.01 : +0.01;
373
374    if (result > intMaxForLength || result < intMinForLength)
375        return 0;
376    return static_cast<int>(result);
377}
378
379short CSSPrimitiveValue::computeLengthShort(RenderStyle* style, RenderStyle* rootStyle)
380{
381    double result = computeLengthDouble(style, rootStyle);
382
383    // This conversion is imprecise, often resulting in values of, e.g., 44.99998.  We
384    // need to go ahead and round if we're really close to the next integer value.
385    result += result < 0 ? -0.01 : +0.01;
386
387    if (result > SHRT_MAX || result < SHRT_MIN)
388        return 0;
389    return static_cast<short>(result);
390}
391
392short CSSPrimitiveValue::computeLengthShort(RenderStyle* style, RenderStyle* rootStyle, double multiplier)
393{
394    double result = computeLengthDouble(style, rootStyle, multiplier);
395
396    // This conversion is imprecise, often resulting in values of, e.g., 44.99998.  We
397    // need to go ahead and round if we're really close to the next integer value.
398    result += result < 0 ? -0.01 : +0.01;
399
400    if (result > SHRT_MAX || result < SHRT_MIN)
401        return 0;
402    return static_cast<short>(result);
403}
404
405float CSSPrimitiveValue::computeLengthFloat(RenderStyle* style, RenderStyle* rootStyle, bool computingFontSize)
406{
407    return static_cast<float>(computeLengthDouble(style, rootStyle, 1.0, computingFontSize));
408}
409
410float CSSPrimitiveValue::computeLengthFloat(RenderStyle* style, RenderStyle* rootStyle, double multiplier, bool computingFontSize)
411{
412    return static_cast<float>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize));
413}
414
415double CSSPrimitiveValue::computeLengthDouble(RenderStyle* style, RenderStyle* rootStyle, double multiplier, bool computingFontSize)
416{
417    unsigned short type = primitiveType();
418
419    // We do not apply the zoom factor when we are computing the value of the font-size property.  The zooming
420    // for font sizes is much more complicated, since we have to worry about enforcing the minimum font size preference
421    // as well as enforcing the implicit "smart minimum."  In addition the CSS property text-size-adjust is used to
422    // prevent text from zooming at all.  Therefore we will not apply the zoom here if we are computing font-size.
423    bool applyZoomMultiplier = !computingFontSize;
424
425    double factor = 1.0;
426    switch (type) {
427        case CSS_EMS:
428            applyZoomMultiplier = false;
429            factor = computingFontSize ? style->fontDescription().specifiedSize() : style->fontDescription().computedSize();
430            break;
431        case CSS_EXS:
432            // FIXME: We have a bug right now where the zoom will be applied twice to EX units.
433            // We really need to compute EX using fontMetrics for the original specifiedSize and not use
434            // our actual constructed rendering font.
435            applyZoomMultiplier = false;
436            factor = style->font().xHeight();
437            break;
438        case CSS_REMS:
439            applyZoomMultiplier = false;
440            factor = computingFontSize ? rootStyle->fontDescription().specifiedSize() : rootStyle->fontDescription().computedSize();
441            break;
442        case CSS_PX:
443            break;
444        case CSS_CM:
445            factor = cssPixelsPerInch / 2.54; // (2.54 cm/in)
446            break;
447        case CSS_MM:
448            factor = cssPixelsPerInch / 25.4;
449            break;
450        case CSS_IN:
451            factor = cssPixelsPerInch;
452            break;
453        case CSS_PT:
454            factor = cssPixelsPerInch / 72.0;
455            break;
456        case CSS_PC:
457            // 1 pc == 12 pt
458            factor = cssPixelsPerInch * 12.0 / 72.0;
459            break;
460        default:
461            return -1.0;
462    }
463
464    double result = getDoubleValue() * factor;
465    if (!applyZoomMultiplier || multiplier == 1.0)
466        return result;
467     
468    // Any original result that was >= 1 should not be allowed to fall below 1.  This keeps border lines from
469    // vanishing.
470    double zoomedResult = result * multiplier;
471    if (result >= 1.0)
472        zoomedResult = max(1.0, zoomedResult);
473    return zoomedResult;
474}
475
476void CSSPrimitiveValue::setFloatValue(unsigned short unitType, double floatValue, ExceptionCode& ec)
477{
478    ec = 0;
479
480    if (m_type < CSS_NUMBER || m_type > CSS_DIMENSION || unitType < CSS_NUMBER || unitType > CSS_DIMENSION) {
481        ec = INVALID_ACCESS_ERR;
482        return;
483    }
484
485    cleanup();
486
487    //if(m_type > CSS_DIMENSION) throw DOMException(INVALID_ACCESS_ERR);
488    m_value.num = floatValue;
489    m_type = unitType;
490}
491
492static double scaleFactorForConversion(unsigned short unitType)
493{
494    double factor = 1.0;
495    switch (unitType) {
496        case CSSPrimitiveValue::CSS_PX:
497            break;
498        case CSSPrimitiveValue::CSS_CM:
499            factor = cssPixelsPerInch / 2.54; // (2.54 cm/in)
500            break;
501        case CSSPrimitiveValue::CSS_MM:
502            factor = cssPixelsPerInch / 25.4;
503            break;
504        case CSSPrimitiveValue::CSS_IN:
505            factor = cssPixelsPerInch;
506            break;
507        case CSSPrimitiveValue::CSS_PT:
508            factor = cssPixelsPerInch / 72.0;
509            break;
510        case CSSPrimitiveValue::CSS_PC:
511            factor = cssPixelsPerInch * 12.0 / 72.0; // 1 pc == 12 pt
512            break;
513        default:
514            break;
515    }
516
517    return factor;
518}
519
520double CSSPrimitiveValue::getDoubleValue(unsigned short unitType, ExceptionCode& ec)
521{
522    ec = 0;
523    if (m_type < CSS_NUMBER || m_type > CSS_DIMENSION || unitType < CSS_NUMBER || unitType > CSS_DIMENSION) {
524        ec = INVALID_ACCESS_ERR;
525        return 0.0;
526    }
527
528    if (unitType == m_type || unitType < CSS_PX || unitType > CSS_PC)
529        return m_value.num;
530
531    double convertedValue = m_value.num;
532
533    // First convert the value from m_type into CSSPixels
534    double factor = scaleFactorForConversion(m_type);
535    convertedValue *= factor;
536
537    // Now convert from CSSPixels to the specified unitType
538    factor = scaleFactorForConversion(unitType);
539    convertedValue /= factor;
540
541    return convertedValue;
542}
543
544double CSSPrimitiveValue::getDoubleValue(unsigned short unitType)
545{
546    if (m_type < CSS_NUMBER || m_type > CSS_DIMENSION || unitType < CSS_NUMBER || unitType > CSS_DIMENSION)
547        return 0;
548
549    if (unitType == m_type || unitType < CSS_PX || unitType > CSS_PC)
550        return m_value.num;
551
552    double convertedValue = m_value.num;
553
554    // First convert the value from m_type into CSSPixels
555    double factor = scaleFactorForConversion(m_type);
556    convertedValue *= factor;
557
558    // Now convert from CSSPixels to the specified unitType
559    factor = scaleFactorForConversion(unitType);
560    convertedValue /= factor;
561
562    return convertedValue;
563}
564
565
566void CSSPrimitiveValue::setStringValue(unsigned short stringType, const String& stringValue, ExceptionCode& ec)
567{
568    ec = 0;
569
570    if (m_type < CSS_STRING || m_type > CSS_ATTR || stringType < CSS_STRING || stringType > CSS_ATTR) {
571        ec = INVALID_ACCESS_ERR;
572        return;
573    }
574
575    cleanup();
576
577    if (stringType != CSS_IDENT) {
578        m_value.string = stringValue.impl();
579        m_value.string->ref();
580        m_type = stringType;
581    }
582    // FIXME: parse ident
583}
584
585String CSSPrimitiveValue::getStringValue(ExceptionCode& ec) const
586{
587    ec = 0;
588    switch (m_type) {
589        case CSS_STRING:
590        case CSS_ATTR:
591        case CSS_URI:
592        case CSS_PARSER_VARIABLE_FUNCTION_SYNTAX:
593            return m_value.string;
594        case CSS_IDENT:
595            return valueOrPropertyName(m_value.ident);
596        default:
597            ec = INVALID_ACCESS_ERR;
598            break;
599    }
600
601    return String();
602}
603
604String CSSPrimitiveValue::getStringValue() const
605{
606    switch (m_type) {
607        case CSS_STRING:
608        case CSS_ATTR:
609        case CSS_URI:
610        case CSS_PARSER_VARIABLE_FUNCTION_SYNTAX:
611             return m_value.string;
612        case CSS_IDENT:
613            return valueOrPropertyName(m_value.ident);
614        default:
615            break;
616    }
617
618    return String();
619}
620
621Counter* CSSPrimitiveValue::getCounterValue(ExceptionCode& ec) const
622{
623    ec = 0;
624    if (m_type != CSS_COUNTER) {
625        ec = INVALID_ACCESS_ERR;
626        return 0;
627    }
628
629    return m_value.counter;
630}
631
632Rect* CSSPrimitiveValue::getRectValue(ExceptionCode& ec) const
633{
634    ec = 0;
635    if (m_type != CSS_RECT) {
636        ec = INVALID_ACCESS_ERR;
637        return 0;
638    }
639
640    return m_value.rect;
641}
642
643PassRefPtr<RGBColor> CSSPrimitiveValue::getRGBColorValue(ExceptionCode& ec) const
644{
645    ec = 0;
646    if (m_type != CSS_RGBCOLOR) {
647        ec = INVALID_ACCESS_ERR;
648        return 0;
649    }
650
651    // FIMXE: This should not return a new object for each invocation.
652    return RGBColor::create(m_value.rgbcolor);
653}
654
655Pair* CSSPrimitiveValue::getPairValue(ExceptionCode& ec) const
656{
657    ec = 0;
658    if (m_type != CSS_PAIR) {
659        ec = INVALID_ACCESS_ERR;
660        return 0;
661    }
662
663    return m_value.pair;
664}
665
666unsigned short CSSPrimitiveValue::cssValueType() const
667{
668    return CSS_PRIMITIVE_VALUE;
669}
670
671bool CSSPrimitiveValue::parseString(const String& /*string*/, bool /*strict*/)
672{
673    // FIXME
674    return false;
675}
676
677int CSSPrimitiveValue::getIdent()
678{
679    if (m_type != CSS_IDENT)
680        return 0;
681    return m_value.ident;
682}
683
684String CSSPrimitiveValue::cssText() const
685{
686    // FIXME: return the original value instead of a generated one (e.g. color
687    // name if it was specified) - check what spec says about this
688    String text;
689    switch (m_type) {
690        case CSS_UNKNOWN:
691            // FIXME
692            break;
693        case CSS_NUMBER:
694        case CSS_PARSER_INTEGER:
695            text = String::number(m_value.num);
696            break;
697        case CSS_PERCENTAGE:
698            text = String::format("%.6lg%%", m_value.num);
699            break;
700        case CSS_EMS:
701            text = String::format("%.6lgem", m_value.num);
702            break;
703        case CSS_EXS:
704            text = String::format("%.6lgex", m_value.num);
705            break;
706        case CSS_REMS:
707            text = String::format("%.6lgrem", m_value.num);
708            break;
709        case CSS_PX:
710            text = String::format("%.6lgpx", m_value.num);
711            break;
712        case CSS_CM:
713            text = String::format("%.6lgcm", m_value.num);
714            break;
715        case CSS_MM:
716            text = String::format("%.6lgmm", m_value.num);
717            break;
718        case CSS_IN:
719            text = String::format("%.6lgin", m_value.num);
720            break;
721        case CSS_PT:
722            text = String::format("%.6lgpt", m_value.num);
723            break;
724        case CSS_PC:
725            text = String::format("%.6lgpc", m_value.num);
726            break;
727        case CSS_DEG:
728            text = String::format("%.6lgdeg", m_value.num);
729            break;
730        case CSS_RAD:
731            text = String::format("%.6lgrad", m_value.num);
732            break;
733        case CSS_GRAD:
734            text = String::format("%.6lggrad", m_value.num);
735            break;
736        case CSS_MS:
737            text = String::format("%.6lgms", m_value.num);
738            break;
739        case CSS_S:
740            text = String::format("%.6lgs", m_value.num);
741            break;
742        case CSS_HZ:
743            text = String::format("%.6lghz", m_value.num);
744            break;
745        case CSS_KHZ:
746            text = String::format("%.6lgkhz", m_value.num);
747            break;
748        case CSS_TURN:
749            text = String::format("%.6lgturn", m_value.num);
750            break;
751        case CSS_DIMENSION:
752            // FIXME
753            break;
754        case CSS_STRING:
755            text = quoteStringIfNeeded(m_value.string);
756            break;
757        case CSS_URI:
758            text = "url(" + quoteURLIfNeeded(m_value.string) + ")";
759            break;
760        case CSS_IDENT:
761            text = valueOrPropertyName(m_value.ident);
762            break;
763        case CSS_ATTR: {
764            DEFINE_STATIC_LOCAL(const String, attrParen, ("attr("));
765
766            Vector<UChar> result;
767            result.reserveInitialCapacity(6 + m_value.string->length());
768
769            append(result, attrParen);
770            append(result, m_value.string);
771            result.uncheckedAppend(')');
772
773            return String::adopt(result);
774        }
775        case CSS_COUNTER:
776            text = "counter(";
777            text += String::number(m_value.num);
778            text += ")";
779            // FIXME: Add list-style and separator
780            break;
781        case CSS_RECT: {
782            DEFINE_STATIC_LOCAL(const String, rectParen, ("rect("));
783
784            Rect* rectVal = getRectValue();
785            Vector<UChar> result;
786            result.reserveInitialCapacity(32);
787            append(result, rectParen);
788
789            append(result, rectVal->top()->cssText());
790            result.append(' ');
791
792            append(result, rectVal->right()->cssText());
793            result.append(' ');
794
795            append(result, rectVal->bottom()->cssText());
796            result.append(' ');
797
798            append(result, rectVal->left()->cssText());
799            result.append(')');
800
801            return String::adopt(result);
802        }
803        case CSS_RGBCOLOR:
804        case CSS_PARSER_HEXCOLOR: {
805            DEFINE_STATIC_LOCAL(const String, commaSpace, (", "));
806            DEFINE_STATIC_LOCAL(const String, rgbParen, ("rgb("));
807            DEFINE_STATIC_LOCAL(const String, rgbaParen, ("rgba("));
808
809            RGBA32 rgbColor = m_value.rgbcolor;
810            if (m_type == CSS_PARSER_HEXCOLOR)
811                Color::parseHexColor(m_value.string, rgbColor);
812            Color color(rgbColor);
813
814            Vector<UChar> result;
815            result.reserveInitialCapacity(32);
816            if (color.hasAlpha())
817                append(result, rgbaParen);
818            else
819                append(result, rgbParen);
820
821            appendNumber(result, static_cast<unsigned char>(color.red()));
822            append(result, commaSpace);
823
824            appendNumber(result, static_cast<unsigned char>(color.green()));
825            append(result, commaSpace);
826
827            appendNumber(result, static_cast<unsigned char>(color.blue()));
828            if (color.hasAlpha()) {
829                append(result, commaSpace);
830                append(result, String::number(static_cast<float>(color.alpha()) / 256.0f));
831            }
832
833            result.append(')');
834            return String::adopt(result);
835        }
836        case CSS_PAIR:
837            text = m_value.pair->first()->cssText();
838            text += " ";
839            text += m_value.pair->second()->cssText();
840            break;
841#if ENABLE(DASHBOARD_SUPPORT)
842        case CSS_DASHBOARD_REGION:
843            for (DashboardRegion* region = getDashboardRegionValue(); region; region = region->m_next.get()) {
844                if (!text.isEmpty())
845                    text.append(' ');
846                text += "dashboard-region(";
847                text += region->m_label;
848                if (region->m_isCircle)
849                    text += " circle";
850                else if (region->m_isRectangle)
851                    text += " rectangle";
852                else
853                    break;
854                if (region->top()->m_type == CSS_IDENT && region->top()->getIdent() == CSSValueInvalid) {
855                    ASSERT(region->right()->m_type == CSS_IDENT);
856                    ASSERT(region->bottom()->m_type == CSS_IDENT);
857                    ASSERT(region->left()->m_type == CSS_IDENT);
858                    ASSERT(region->right()->getIdent() == CSSValueInvalid);
859                    ASSERT(region->bottom()->getIdent() == CSSValueInvalid);
860                    ASSERT(region->left()->getIdent() == CSSValueInvalid);
861                } else {
862                    text.append(' ');
863                    text += region->top()->cssText() + " ";
864                    text += region->right()->cssText() + " ";
865                    text += region->bottom()->cssText() + " ";
866                    text += region->left()->cssText();
867                }
868                text += ")";
869            }
870            break;
871#endif
872        case CSS_PARSER_VARIABLE_FUNCTION_SYNTAX:
873            text = "-webkit-var(";
874            text += m_value.string;
875            text += ")";
876            break;
877        case CSS_PARSER_OPERATOR: {
878            char c = static_cast<char>(m_value.ident);
879            text = String(&c, 1U);
880            break;
881        }
882        case CSS_PARSER_IDENTIFIER:
883            text = quoteStringIfNeeded(m_value.string);
884            break;
885    }
886    return text;
887}
888
889CSSParserValue CSSPrimitiveValue::parserValue() const
890{
891    // We only have to handle a subset of types.
892    CSSParserValue value;
893    value.id = 0;
894    value.isInt = false;
895    value.unit = CSSPrimitiveValue::CSS_IDENT;
896    switch (m_type) {
897        case CSS_NUMBER:
898        case CSS_PERCENTAGE:
899        case CSS_EMS:
900        case CSS_EXS:
901        case CSS_REMS:
902        case CSS_PX:
903        case CSS_CM:
904        case CSS_MM:
905        case CSS_IN:
906        case CSS_PT:
907        case CSS_PC:
908        case CSS_DEG:
909        case CSS_RAD:
910        case CSS_GRAD:
911        case CSS_MS:
912        case CSS_S:
913        case CSS_HZ:
914        case CSS_KHZ:
915        case CSS_DIMENSION:
916        case CSS_TURN:
917            value.fValue = m_value.num;
918            value.unit = m_type;
919            break;
920        case CSS_STRING:
921        case CSS_URI:
922        case CSS_PARSER_VARIABLE_FUNCTION_SYNTAX:
923        case CSS_PARSER_HEXCOLOR:
924            value.string.characters = const_cast<UChar*>(m_value.string->characters());
925            value.string.length = m_value.string->length();
926            value.unit = m_type;
927            break;
928        case CSS_IDENT: {
929            value.id = m_value.ident;
930            String name = valueOrPropertyName(m_value.ident);
931            value.string.characters = const_cast<UChar*>(name.characters());
932            value.string.length = name.length();
933            break;
934        }
935        case CSS_PARSER_OPERATOR:
936            value.iValue = m_value.ident;
937            value.unit = CSSParserValue::Operator;
938            break;
939        case CSS_PARSER_INTEGER:
940            value.fValue = m_value.num;
941            value.unit = CSSPrimitiveValue::CSS_NUMBER;
942            value.isInt = true;
943            break;
944        case CSS_PARSER_IDENTIFIER:
945            value.string.characters = const_cast<UChar*>(m_value.string->characters());
946            value.string.length = m_value.string->length();
947            value.unit = CSSPrimitiveValue::CSS_IDENT;
948            break;
949        case CSS_UNKNOWN:
950        case CSS_ATTR:
951        case CSS_COUNTER:
952        case CSS_RECT:
953        case CSS_RGBCOLOR:
954        case CSS_PAIR:
955#if ENABLE(DASHBOARD_SUPPORT)
956        case CSS_DASHBOARD_REGION:
957#endif
958            ASSERT_NOT_REACHED();
959            break;
960    }
961    
962    return value;
963}
964
965void CSSPrimitiveValue::addSubresourceStyleURLs(ListHashSet<KURL>& urls, const CSSStyleSheet* styleSheet)
966{
967    if (m_type == CSS_URI)
968        addSubresourceURL(urls, styleSheet->completeURL(m_value.string));
969}
970
971} // namespace WebCore