1/* 2 * (C) 1999-2003 Lars Knoll (knoll@kde.org) 3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2012, 2013 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 "CSSBasicShapes.h" 25#include "CSSCalculationValue.h" 26#include "CSSHelper.h" 27#include "CSSParser.h" 28#include "CSSPropertyNames.h" 29#include "CSSValueKeywords.h" 30#include "CalculationValue.h" 31#include "Color.h" 32#include "Counter.h" 33#include "ExceptionCode.h" 34#include "Font.h" 35#include "LayoutUnit.h" 36#include "Node.h" 37#include "Pair.h" 38#include "RGBColor.h" 39#include "Rect.h" 40#include "RenderStyle.h" 41#include "StyleSheetContents.h" 42#include <wtf/ASCIICType.h> 43#include <wtf/DecimalNumber.h> 44#include <wtf/StdLibExtras.h> 45#include <wtf/text/StringBuffer.h> 46#include <wtf/text/StringBuilder.h> 47 48#if ENABLE(DASHBOARD_SUPPORT) 49#include "DashboardRegion.h" 50#endif 51 52using namespace WTF; 53 54namespace WebCore { 55 56// Max/min values for CSS, needs to slightly smaller/larger than the true max/min values to allow for rounding without overflowing. 57// Subtract two (rather than one) to allow for values to be converted to float and back without exceeding the LayoutUnit::max. 58const int maxValueForCssLength = INT_MAX / kFixedPointDenominator - 2; 59const int minValueForCssLength = INT_MIN / kFixedPointDenominator + 2; 60 61static inline bool isValidCSSUnitTypeForDoubleConversion(CSSPrimitiveValue::UnitTypes unitType) 62{ 63 switch (unitType) { 64 case CSSPrimitiveValue::CSS_CALC: 65 case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_NUMBER: 66 case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_LENGTH: 67 case CSSPrimitiveValue::CSS_CM: 68 case CSSPrimitiveValue::CSS_DEG: 69 case CSSPrimitiveValue::CSS_DIMENSION: 70#if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) 71 case CSSPrimitiveValue::CSS_DPPX: 72 case CSSPrimitiveValue::CSS_DPI: 73 case CSSPrimitiveValue::CSS_DPCM: 74#endif 75 case CSSPrimitiveValue::CSS_EMS: 76 case CSSPrimitiveValue::CSS_EXS: 77 case CSSPrimitiveValue::CSS_GRAD: 78 case CSSPrimitiveValue::CSS_HZ: 79 case CSSPrimitiveValue::CSS_IN: 80 case CSSPrimitiveValue::CSS_KHZ: 81 case CSSPrimitiveValue::CSS_MM: 82 case CSSPrimitiveValue::CSS_MS: 83 case CSSPrimitiveValue::CSS_NUMBER: 84 case CSSPrimitiveValue::CSS_PERCENTAGE: 85 case CSSPrimitiveValue::CSS_PC: 86 case CSSPrimitiveValue::CSS_PT: 87 case CSSPrimitiveValue::CSS_PX: 88 case CSSPrimitiveValue::CSS_RAD: 89 case CSSPrimitiveValue::CSS_REMS: 90 case CSSPrimitiveValue::CSS_CHS: 91 case CSSPrimitiveValue::CSS_S: 92 case CSSPrimitiveValue::CSS_TURN: 93 case CSSPrimitiveValue::CSS_VW: 94 case CSSPrimitiveValue::CSS_VH: 95 case CSSPrimitiveValue::CSS_VMIN: 96 case CSSPrimitiveValue::CSS_VMAX: 97 return true; 98 case CSSPrimitiveValue::CSS_ATTR: 99 case CSSPrimitiveValue::CSS_COUNTER: 100 case CSSPrimitiveValue::CSS_COUNTER_NAME: 101#if ENABLE(DASHBOARD_SUPPORT) 102 case CSSPrimitiveValue::CSS_DASHBOARD_REGION: 103#endif 104#if !ENABLE(CSS_IMAGE_RESOLUTION) && !ENABLE(RESOLUTION_MEDIA_QUERY) 105 case CSSPrimitiveValue::CSS_DPPX: 106 case CSSPrimitiveValue::CSS_DPI: 107 case CSSPrimitiveValue::CSS_DPCM: 108#endif 109 case CSSPrimitiveValue::CSS_IDENT: 110 case CSSPrimitiveValue::CSS_PAIR: 111 case CSSPrimitiveValue::CSS_PARSER_HEXCOLOR: 112 case CSSPrimitiveValue::CSS_PARSER_IDENTIFIER: 113 case CSSPrimitiveValue::CSS_PARSER_INTEGER: 114 case CSSPrimitiveValue::CSS_PARSER_OPERATOR: 115 case CSSPrimitiveValue::CSS_RECT: 116 case CSSPrimitiveValue::CSS_QUAD: 117 case CSSPrimitiveValue::CSS_RGBCOLOR: 118 case CSSPrimitiveValue::CSS_SHAPE: 119 case CSSPrimitiveValue::CSS_STRING: 120 case CSSPrimitiveValue::CSS_UNICODE_RANGE: 121 case CSSPrimitiveValue::CSS_UNKNOWN: 122 case CSSPrimitiveValue::CSS_URI: 123#if ENABLE(CSS_VARIABLES) 124 case CSSPrimitiveValue::CSS_VARIABLE_NAME: 125#endif 126 return false; 127 } 128 129 ASSERT_NOT_REACHED(); 130 return false; 131} 132 133static CSSPrimitiveValue::UnitCategory unitCategory(CSSPrimitiveValue::UnitTypes type) 134{ 135 // Here we violate the spec (http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue) and allow conversions 136 // between CSS_PX and relative lengths (see cssPixelsPerInch comment in CSSHelper.h for the topic treatment). 137 switch (type) { 138 case CSSPrimitiveValue::CSS_NUMBER: 139 return CSSPrimitiveValue::UNumber; 140 case CSSPrimitiveValue::CSS_PERCENTAGE: 141 return CSSPrimitiveValue::UPercent; 142 case CSSPrimitiveValue::CSS_PX: 143 case CSSPrimitiveValue::CSS_CM: 144 case CSSPrimitiveValue::CSS_MM: 145 case CSSPrimitiveValue::CSS_IN: 146 case CSSPrimitiveValue::CSS_PT: 147 case CSSPrimitiveValue::CSS_PC: 148 return CSSPrimitiveValue::ULength; 149 case CSSPrimitiveValue::CSS_MS: 150 case CSSPrimitiveValue::CSS_S: 151 return CSSPrimitiveValue::UTime; 152 case CSSPrimitiveValue::CSS_DEG: 153 case CSSPrimitiveValue::CSS_RAD: 154 case CSSPrimitiveValue::CSS_GRAD: 155 case CSSPrimitiveValue::CSS_TURN: 156 return CSSPrimitiveValue::UAngle; 157 case CSSPrimitiveValue::CSS_HZ: 158 case CSSPrimitiveValue::CSS_KHZ: 159 return CSSPrimitiveValue::UFrequency; 160 case CSSPrimitiveValue::CSS_VW: 161 case CSSPrimitiveValue::CSS_VH: 162 case CSSPrimitiveValue::CSS_VMIN: 163 case CSSPrimitiveValue::CSS_VMAX: 164 return CSSPrimitiveValue::UViewportPercentageLength; 165#if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) 166 case CSSPrimitiveValue::CSS_DPPX: 167 case CSSPrimitiveValue::CSS_DPI: 168 case CSSPrimitiveValue::CSS_DPCM: 169 return CSSPrimitiveValue::UResolution; 170#endif 171 default: 172 return CSSPrimitiveValue::UOther; 173 } 174} 175 176typedef HashMap<const CSSPrimitiveValue*, String> CSSTextCache; 177static CSSTextCache& cssTextCache() 178{ 179 DEFINE_STATIC_LOCAL(CSSTextCache, cache, ()); 180 return cache; 181} 182 183unsigned short CSSPrimitiveValue::primitiveType() const 184{ 185 if (m_primitiveUnitType != CSSPrimitiveValue::CSS_CALC) 186 return m_primitiveUnitType; 187 188 switch (m_value.calc->category()) { 189 case CalcNumber: 190 return CSSPrimitiveValue::CSS_NUMBER; 191 case CalcPercent: 192 return CSSPrimitiveValue::CSS_PERCENTAGE; 193 case CalcLength: 194 return CSSPrimitiveValue::CSS_PX; 195 case CalcPercentNumber: 196 return CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_NUMBER; 197 case CalcPercentLength: 198 return CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_LENGTH; 199#if ENABLE(CSS_VARIABLES) 200 case CalcVariable: 201 return CSSPrimitiveValue::CSS_UNKNOWN; // The type of a calculation containing a variable cannot be known until the value of the variable is determined. 202#endif 203 case CalcOther: 204 return CSSPrimitiveValue::CSS_UNKNOWN; 205 } 206 return CSSPrimitiveValue::CSS_UNKNOWN; 207} 208 209static const AtomicString& valueOrPropertyName(int valueOrPropertyID) 210{ 211 ASSERT_ARG(valueOrPropertyID, valueOrPropertyID >= 0); 212 ASSERT_ARG(valueOrPropertyID, valueOrPropertyID < numCSSValueKeywords || (valueOrPropertyID >= firstCSSProperty && valueOrPropertyID < firstCSSProperty + numCSSProperties)); 213 214 if (valueOrPropertyID < 0) 215 return nullAtom; 216 217 if (valueOrPropertyID < numCSSValueKeywords) { 218 static AtomicString* keywordStrings = new AtomicString[numCSSValueKeywords]; // Leaked intentionally. 219 AtomicString& keywordString = keywordStrings[valueOrPropertyID]; 220 if (keywordString.isNull()) 221 keywordString = getValueName(valueOrPropertyID); 222 return keywordString; 223 } 224 225 return getPropertyNameAtomicString(static_cast<CSSPropertyID>(valueOrPropertyID)); 226} 227 228CSSPrimitiveValue::CSSPrimitiveValue(int ident) 229 : CSSValue(PrimitiveClass) 230{ 231 m_primitiveUnitType = CSS_IDENT; 232 m_value.ident = ident; 233} 234 235CSSPrimitiveValue::CSSPrimitiveValue(double num, UnitTypes type) 236 : CSSValue(PrimitiveClass) 237{ 238 m_primitiveUnitType = type; 239 ASSERT(std::isfinite(num)); 240 m_value.num = num; 241} 242 243CSSPrimitiveValue::CSSPrimitiveValue(const String& str, UnitTypes type) 244 : CSSValue(PrimitiveClass) 245{ 246 m_primitiveUnitType = type; 247 if ((m_value.string = str.impl())) 248 m_value.string->ref(); 249} 250 251 252CSSPrimitiveValue::CSSPrimitiveValue(RGBA32 color) 253 : CSSValue(PrimitiveClass) 254{ 255 m_primitiveUnitType = CSS_RGBCOLOR; 256 m_value.rgbcolor = color; 257} 258 259CSSPrimitiveValue::CSSPrimitiveValue(const Length& length) 260 : CSSValue(PrimitiveClass) 261{ 262 switch (length.type()) { 263 case Auto: 264 m_primitiveUnitType = CSS_IDENT; 265 m_value.ident = CSSValueAuto; 266 break; 267 case WebCore::Fixed: 268 m_primitiveUnitType = CSS_PX; 269 m_value.num = length.value(); 270 break; 271 case Intrinsic: 272 m_primitiveUnitType = CSS_IDENT; 273 m_value.ident = CSSValueIntrinsic; 274 break; 275 case MinIntrinsic: 276 m_primitiveUnitType = CSS_IDENT; 277 m_value.ident = CSSValueMinIntrinsic; 278 break; 279 case MinContent: 280 m_primitiveUnitType = CSS_IDENT; 281 m_value.ident = CSSValueWebkitMinContent; 282 break; 283 case MaxContent: 284 m_primitiveUnitType = CSS_IDENT; 285 m_value.ident = CSSValueWebkitMaxContent; 286 break; 287 case FillAvailable: 288 m_primitiveUnitType = CSS_IDENT; 289 m_value.ident = CSSValueWebkitFillAvailable; 290 break; 291 case FitContent: 292 m_primitiveUnitType = CSS_IDENT; 293 m_value.ident = CSSValueWebkitFitContent; 294 break; 295 case Percent: 296 m_primitiveUnitType = CSS_PERCENTAGE; 297 ASSERT(std::isfinite(length.percent())); 298 m_value.num = length.percent(); 299 break; 300 case ViewportPercentageWidth: 301 m_primitiveUnitType = CSS_VW; 302 m_value.num = length.viewportPercentageLength(); 303 break; 304 case ViewportPercentageHeight: 305 m_primitiveUnitType = CSS_VH; 306 m_value.num = length.viewportPercentageLength(); 307 break; 308 case ViewportPercentageMin: 309 m_primitiveUnitType = CSS_VMIN; 310 m_value.num = length.viewportPercentageLength(); 311 break; 312 case ViewportPercentageMax: 313 m_primitiveUnitType = CSS_VMAX; 314 m_value.num = length.viewportPercentageLength(); 315 break; 316 case Calculated: 317 case Relative: 318 case Undefined: 319 ASSERT_NOT_REACHED(); 320 break; 321 } 322} 323 324void CSSPrimitiveValue::init(PassRefPtr<Counter> c) 325{ 326 m_primitiveUnitType = CSS_COUNTER; 327 m_hasCachedCSSText = false; 328 m_value.counter = c.leakRef(); 329} 330 331void CSSPrimitiveValue::init(PassRefPtr<Rect> r) 332{ 333 m_primitiveUnitType = CSS_RECT; 334 m_hasCachedCSSText = false; 335 m_value.rect = r.leakRef(); 336} 337 338void CSSPrimitiveValue::init(PassRefPtr<Quad> quad) 339{ 340 m_primitiveUnitType = CSS_QUAD; 341 m_hasCachedCSSText = false; 342 m_value.quad = quad.leakRef(); 343} 344 345#if ENABLE(DASHBOARD_SUPPORT) 346void CSSPrimitiveValue::init(PassRefPtr<DashboardRegion> r) 347{ 348 m_primitiveUnitType = CSS_DASHBOARD_REGION; 349 m_hasCachedCSSText = false; 350 m_value.region = r.leakRef(); 351} 352#endif 353 354void CSSPrimitiveValue::init(PassRefPtr<Pair> p) 355{ 356 m_primitiveUnitType = CSS_PAIR; 357 m_hasCachedCSSText = false; 358 m_value.pair = p.leakRef(); 359} 360 361void CSSPrimitiveValue::init(PassRefPtr<CSSCalcValue> c) 362{ 363 m_primitiveUnitType = CSS_CALC; 364 m_hasCachedCSSText = false; 365 m_value.calc = c.leakRef(); 366} 367 368void CSSPrimitiveValue::init(PassRefPtr<CSSBasicShape> shape) 369{ 370 m_primitiveUnitType = CSS_SHAPE; 371 m_hasCachedCSSText = false; 372 m_value.shape = shape.leakRef(); 373} 374 375CSSPrimitiveValue::~CSSPrimitiveValue() 376{ 377 cleanup(); 378} 379 380void CSSPrimitiveValue::cleanup() 381{ 382 switch (static_cast<UnitTypes>(m_primitiveUnitType)) { 383 case CSS_STRING: 384 case CSS_URI: 385 case CSS_ATTR: 386 case CSS_COUNTER_NAME: 387#if ENABLE(CSS_VARIABLES) 388 case CSS_VARIABLE_NAME: 389#endif 390 case CSS_PARSER_HEXCOLOR: 391 if (m_value.string) 392 m_value.string->deref(); 393 break; 394 case CSS_COUNTER: 395 m_value.counter->deref(); 396 break; 397 case CSS_RECT: 398 m_value.rect->deref(); 399 break; 400 case CSS_QUAD: 401 m_value.quad->deref(); 402 break; 403 case CSS_PAIR: 404 m_value.pair->deref(); 405 break; 406#if ENABLE(DASHBOARD_SUPPORT) 407 case CSS_DASHBOARD_REGION: 408 if (m_value.region) 409 m_value.region->deref(); 410 break; 411#endif 412 case CSS_CALC: 413 m_value.calc->deref(); 414 break; 415 case CSS_CALC_PERCENTAGE_WITH_NUMBER: 416 case CSS_CALC_PERCENTAGE_WITH_LENGTH: 417 ASSERT_NOT_REACHED(); 418 break; 419 case CSS_SHAPE: 420 m_value.shape->deref(); 421 break; 422 case CSS_NUMBER: 423 case CSS_PARSER_INTEGER: 424 case CSS_PERCENTAGE: 425 case CSS_EMS: 426 case CSS_EXS: 427 case CSS_REMS: 428 case CSS_CHS: 429 case CSS_PX: 430 case CSS_CM: 431 case CSS_MM: 432 case CSS_IN: 433 case CSS_PT: 434 case CSS_PC: 435 case CSS_DEG: 436 case CSS_RAD: 437 case CSS_GRAD: 438 case CSS_MS: 439 case CSS_S: 440 case CSS_HZ: 441 case CSS_KHZ: 442 case CSS_TURN: 443 case CSS_VW: 444 case CSS_VH: 445 case CSS_VMIN: 446 case CSS_VMAX: 447 case CSS_DPPX: 448 case CSS_DPI: 449 case CSS_DPCM: 450 case CSS_IDENT: 451 case CSS_RGBCOLOR: 452 case CSS_DIMENSION: 453 case CSS_UNKNOWN: 454 case CSS_UNICODE_RANGE: 455 case CSS_PARSER_OPERATOR: 456 case CSS_PARSER_IDENTIFIER: 457 break; 458 } 459 m_primitiveUnitType = 0; 460 if (m_hasCachedCSSText) { 461 cssTextCache().remove(this); 462 m_hasCachedCSSText = false; 463 } 464} 465 466double CSSPrimitiveValue::computeDegrees() 467{ 468 switch (m_primitiveUnitType) { 469 case CSS_DEG: 470 return getDoubleValue(); 471 case CSS_RAD: 472 return rad2deg(getDoubleValue()); 473 case CSS_GRAD: 474 return grad2deg(getDoubleValue()); 475 case CSS_TURN: 476 return turn2deg(getDoubleValue()); 477 default: 478 ASSERT_NOT_REACHED(); 479 return 0; 480 } 481} 482 483template<> int CSSPrimitiveValue::computeLength(const RenderStyle* style, const RenderStyle* rootStyle, float multiplier, bool computingFontSize) const 484{ 485 return roundForImpreciseConversion<int>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize)); 486} 487 488template<> unsigned CSSPrimitiveValue::computeLength(const RenderStyle* style, const RenderStyle* rootStyle, float multiplier, bool computingFontSize) const 489{ 490 return roundForImpreciseConversion<unsigned>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize)); 491} 492 493template<> Length CSSPrimitiveValue::computeLength(const RenderStyle* style, const RenderStyle* rootStyle, float multiplier, bool computingFontSize) const 494{ 495#if ENABLE(SUBPIXEL_LAYOUT) 496 return Length(clampTo<float>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize), minValueForCssLength, maxValueForCssLength), Fixed); 497#else 498 return Length(clampTo<float>(roundForImpreciseConversion<float>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize)), minValueForCssLength, maxValueForCssLength), Fixed); 499#endif 500} 501 502template<> short CSSPrimitiveValue::computeLength(const RenderStyle* style, const RenderStyle* rootStyle, float multiplier, bool computingFontSize) const 503{ 504 return roundForImpreciseConversion<short>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize)); 505} 506 507template<> unsigned short CSSPrimitiveValue::computeLength(const RenderStyle* style, const RenderStyle* rootStyle, float multiplier, bool computingFontSize) const 508{ 509 return roundForImpreciseConversion<unsigned short>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize)); 510} 511 512template<> float CSSPrimitiveValue::computeLength(const RenderStyle* style, const RenderStyle* rootStyle, float multiplier, bool computingFontSize) const 513{ 514 return static_cast<float>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize)); 515} 516 517template<> double CSSPrimitiveValue::computeLength(const RenderStyle* style, const RenderStyle* rootStyle, float multiplier, bool computingFontSize) const 518{ 519 return computeLengthDouble(style, rootStyle, multiplier, computingFontSize); 520} 521 522double CSSPrimitiveValue::computeLengthDouble(const RenderStyle* style, const RenderStyle* rootStyle, float multiplier, bool computingFontSize) const 523{ 524 if (m_primitiveUnitType == CSS_CALC) 525 // The multiplier and factor is applied to each value in the calc expression individually 526 return m_value.calc->computeLengthPx(style, rootStyle, multiplier, computingFontSize); 527 528 double factor; 529 530 switch (primitiveType()) { 531 case CSS_EMS: 532 factor = computingFontSize ? style->fontDescription().specifiedSize() : style->fontDescription().computedSize(); 533 break; 534 case CSS_EXS: 535 // FIXME: We have a bug right now where the zoom will be applied twice to EX units. 536 // We really need to compute EX using fontMetrics for the original specifiedSize and not use 537 // our actual constructed rendering font. 538 if (style->fontMetrics().hasXHeight()) 539 factor = style->fontMetrics().xHeight(); 540 else 541 factor = (computingFontSize ? style->fontDescription().specifiedSize() : style->fontDescription().computedSize()) / 2.0; 542 break; 543 case CSS_REMS: 544 if (rootStyle) 545 factor = computingFontSize ? rootStyle->fontDescription().specifiedSize() : rootStyle->fontDescription().computedSize(); 546 else 547 factor = 1.0; 548 break; 549 case CSS_CHS: 550 factor = style->fontMetrics().zeroWidth(); 551 break; 552 case CSS_PX: 553 factor = 1.0; 554 break; 555 case CSS_CM: 556 factor = cssPixelsPerInch / 2.54; // (2.54 cm/in) 557 break; 558 case CSS_MM: 559 factor = cssPixelsPerInch / 25.4; 560 break; 561 case CSS_IN: 562 factor = cssPixelsPerInch; 563 break; 564 case CSS_PT: 565 factor = cssPixelsPerInch / 72.0; 566 break; 567 case CSS_PC: 568 // 1 pc == 12 pt 569 factor = cssPixelsPerInch * 12.0 / 72.0; 570 break; 571 case CSS_CALC_PERCENTAGE_WITH_LENGTH: 572 case CSS_CALC_PERCENTAGE_WITH_NUMBER: 573 ASSERT_NOT_REACHED(); 574 return -1.0; 575 default: 576 ASSERT_NOT_REACHED(); 577 return -1.0; 578 } 579 580 // We do not apply the zoom factor when we are computing the value of the font-size property. The zooming 581 // for font sizes is much more complicated, since we have to worry about enforcing the minimum font size preference 582 // as well as enforcing the implicit "smart minimum." 583 double result = getDoubleValue() * factor; 584 if (computingFontSize || isFontRelativeLength()) 585 return result; 586 587 return result * multiplier; 588} 589 590void CSSPrimitiveValue::setFloatValue(unsigned short, double, ExceptionCode& ec) 591{ 592 // Keeping values immutable makes optimizations easier and allows sharing of the primitive value objects. 593 // No other engine supports mutating style through this API. Computed style is always read-only anyway. 594 // Supporting setter would require making primitive value copy-on-write and taking care of style invalidation. 595 ec = NO_MODIFICATION_ALLOWED_ERR; 596} 597 598static double conversionToCanonicalUnitsScaleFactor(unsigned short unitType) 599{ 600 double factor = 1.0; 601 // FIXME: the switch can be replaced by an array of scale factors. 602 switch (unitType) { 603 // These are "canonical" units in their respective categories. 604 case CSSPrimitiveValue::CSS_PX: 605 case CSSPrimitiveValue::CSS_DEG: 606 case CSSPrimitiveValue::CSS_MS: 607 case CSSPrimitiveValue::CSS_HZ: 608 break; 609 case CSSPrimitiveValue::CSS_CM: 610 factor = cssPixelsPerInch / 2.54; // (2.54 cm/in) 611 break; 612 case CSSPrimitiveValue::CSS_DPCM: 613 factor = 2.54 / cssPixelsPerInch; // (2.54 cm/in) 614 break; 615 case CSSPrimitiveValue::CSS_MM: 616 factor = cssPixelsPerInch / 25.4; 617 break; 618 case CSSPrimitiveValue::CSS_IN: 619 factor = cssPixelsPerInch; 620 break; 621 case CSSPrimitiveValue::CSS_DPI: 622 factor = 1 / cssPixelsPerInch; 623 break; 624 case CSSPrimitiveValue::CSS_PT: 625 factor = cssPixelsPerInch / 72.0; 626 break; 627 case CSSPrimitiveValue::CSS_PC: 628 factor = cssPixelsPerInch * 12.0 / 72.0; // 1 pc == 12 pt 629 break; 630 case CSSPrimitiveValue::CSS_RAD: 631 factor = 180 / piDouble; 632 break; 633 case CSSPrimitiveValue::CSS_GRAD: 634 factor = 0.9; 635 break; 636 case CSSPrimitiveValue::CSS_TURN: 637 factor = 360; 638 break; 639 case CSSPrimitiveValue::CSS_S: 640 case CSSPrimitiveValue::CSS_KHZ: 641 factor = 1000; 642 break; 643 default: 644 break; 645 } 646 647 return factor; 648} 649 650double CSSPrimitiveValue::getDoubleValue(unsigned short unitType, ExceptionCode& ec) const 651{ 652 double result = 0; 653 bool success = getDoubleValueInternal(static_cast<UnitTypes>(unitType), &result); 654 if (!success) { 655 ec = INVALID_ACCESS_ERR; 656 return 0.0; 657 } 658 659 ec = 0; 660 return result; 661} 662 663double CSSPrimitiveValue::getDoubleValue(unsigned short unitType) const 664{ 665 double result = 0; 666 getDoubleValueInternal(static_cast<UnitTypes>(unitType), &result); 667 return result; 668} 669 670double CSSPrimitiveValue::getDoubleValue() const 671{ 672 return m_primitiveUnitType != CSS_CALC ? m_value.num : m_value.calc->doubleValue(); 673} 674 675CSSPrimitiveValue::UnitTypes CSSPrimitiveValue::canonicalUnitTypeForCategory(UnitCategory category) 676{ 677 // The canonical unit type is chosen according to the way CSSParser::validUnit() chooses the default unit 678 // in each category (based on unitflags). 679 switch (category) { 680 case UNumber: 681 return CSS_NUMBER; 682 case ULength: 683 return CSS_PX; 684 case UPercent: 685 return CSS_UNKNOWN; // Cannot convert between numbers and percent. 686 case UTime: 687 return CSS_MS; 688 case UAngle: 689 return CSS_DEG; 690 case UFrequency: 691 return CSS_HZ; 692 case UViewportPercentageLength: 693 return CSS_UNKNOWN; // Cannot convert between numbers and relative lengths. 694#if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) 695 case UResolution: 696 return CSS_DPPX; 697#endif 698 default: 699 return CSS_UNKNOWN; 700 } 701} 702 703bool CSSPrimitiveValue::getDoubleValueInternal(UnitTypes requestedUnitType, double* result) const 704{ 705 if (!isValidCSSUnitTypeForDoubleConversion(static_cast<UnitTypes>(m_primitiveUnitType)) || !isValidCSSUnitTypeForDoubleConversion(requestedUnitType)) 706 return false; 707 708 UnitTypes sourceUnitType = static_cast<UnitTypes>(primitiveType()); 709 if (requestedUnitType == sourceUnitType || requestedUnitType == CSS_DIMENSION) { 710 *result = getDoubleValue(); 711 return true; 712 } 713 714 UnitCategory sourceCategory = unitCategory(sourceUnitType); 715 ASSERT(sourceCategory != UOther); 716 717 UnitTypes targetUnitType = requestedUnitType; 718 UnitCategory targetCategory = unitCategory(targetUnitType); 719 ASSERT(targetCategory != UOther); 720 721 // Cannot convert between unrelated unit categories if one of them is not UNumber. 722 if (sourceCategory != targetCategory && sourceCategory != UNumber && targetCategory != UNumber) 723 return false; 724 725 if (targetCategory == UNumber) { 726 // We interpret conversion to CSS_NUMBER as conversion to a canonical unit in this value's category. 727 targetUnitType = canonicalUnitTypeForCategory(sourceCategory); 728 if (targetUnitType == CSS_UNKNOWN) 729 return false; 730 } 731 732 if (sourceUnitType == CSS_NUMBER) { 733 // We interpret conversion from CSS_NUMBER in the same way as CSSParser::validUnit() while using non-strict mode. 734 sourceUnitType = canonicalUnitTypeForCategory(targetCategory); 735 if (sourceUnitType == CSS_UNKNOWN) 736 return false; 737 } 738 739 double convertedValue = getDoubleValue(); 740 741 // First convert the value from m_primitiveUnitType to canonical type. 742 double factor = conversionToCanonicalUnitsScaleFactor(sourceUnitType); 743 convertedValue *= factor; 744 745 // Now convert from canonical type to the target unitType. 746 factor = conversionToCanonicalUnitsScaleFactor(targetUnitType); 747 convertedValue /= factor; 748 749 *result = convertedValue; 750 return true; 751} 752 753void CSSPrimitiveValue::setStringValue(unsigned short, const String&, ExceptionCode& ec) 754{ 755 // Keeping values immutable makes optimizations easier and allows sharing of the primitive value objects. 756 // No other engine supports mutating style through this API. Computed style is always read-only anyway. 757 // Supporting setter would require making primitive value copy-on-write and taking care of style invalidation. 758 ec = NO_MODIFICATION_ALLOWED_ERR; 759} 760 761String CSSPrimitiveValue::getStringValue(ExceptionCode& ec) const 762{ 763 ec = 0; 764 switch (m_primitiveUnitType) { 765 case CSS_STRING: 766 case CSS_ATTR: 767 case CSS_URI: 768#if ENABLE(CSS_VARIABLES) 769 case CSS_VARIABLE_NAME: 770#endif 771 return m_value.string; 772 case CSS_IDENT: 773 return valueOrPropertyName(m_value.ident); 774 default: 775 ec = INVALID_ACCESS_ERR; 776 break; 777 } 778 779 return String(); 780} 781 782String CSSPrimitiveValue::getStringValue() const 783{ 784 switch (m_primitiveUnitType) { 785 case CSS_STRING: 786 case CSS_ATTR: 787 case CSS_URI: 788#if ENABLE(CSS_VARIABLES) 789 case CSS_VARIABLE_NAME: 790#endif 791 return m_value.string; 792 case CSS_IDENT: 793 return valueOrPropertyName(m_value.ident); 794 default: 795 break; 796 } 797 798 return String(); 799} 800 801Counter* CSSPrimitiveValue::getCounterValue(ExceptionCode& ec) const 802{ 803 ec = 0; 804 if (m_primitiveUnitType != CSS_COUNTER) { 805 ec = INVALID_ACCESS_ERR; 806 return 0; 807 } 808 809 return m_value.counter; 810} 811 812Rect* CSSPrimitiveValue::getRectValue(ExceptionCode& ec) const 813{ 814 ec = 0; 815 if (m_primitiveUnitType != CSS_RECT) { 816 ec = INVALID_ACCESS_ERR; 817 return 0; 818 } 819 820 return m_value.rect; 821} 822 823Quad* CSSPrimitiveValue::getQuadValue(ExceptionCode& ec) const 824{ 825 ec = 0; 826 if (m_primitiveUnitType != CSS_QUAD) { 827 ec = INVALID_ACCESS_ERR; 828 return 0; 829 } 830 831 return m_value.quad; 832} 833 834PassRefPtr<RGBColor> CSSPrimitiveValue::getRGBColorValue(ExceptionCode& ec) const 835{ 836 ec = 0; 837 if (m_primitiveUnitType != CSS_RGBCOLOR) { 838 ec = INVALID_ACCESS_ERR; 839 return 0; 840 } 841 842 // FIMXE: This should not return a new object for each invocation. 843 return RGBColor::create(m_value.rgbcolor); 844} 845 846Pair* CSSPrimitiveValue::getPairValue(ExceptionCode& ec) const 847{ 848 ec = 0; 849 if (m_primitiveUnitType != CSS_PAIR) { 850 ec = INVALID_ACCESS_ERR; 851 return 0; 852 } 853 854 return m_value.pair; 855} 856 857static String formatNumber(double number, const char* suffix, unsigned suffixLength) 858{ 859 DecimalNumber decimal(number); 860 861 StringBuffer<LChar> buffer(decimal.bufferLengthForStringDecimal() + suffixLength); 862 unsigned length = decimal.toStringDecimal(buffer.characters(), buffer.length()); 863 ASSERT(length + suffixLength == buffer.length()); 864 865 for (unsigned i = 0; i < suffixLength; ++i) 866 buffer[length + i] = static_cast<LChar>(suffix[i]); 867 868 return String::adopt(buffer); 869} 870 871template <unsigned characterCount> 872ALWAYS_INLINE static String formatNumber(double number, const char (&characters)[characterCount]) 873{ 874 return formatNumber(number, characters, characterCount - 1); 875} 876 877String CSSPrimitiveValue::customCssText() const 878{ 879 // FIXME: return the original value instead of a generated one (e.g. color 880 // name if it was specified) - check what spec says about this 881 882 if (m_hasCachedCSSText) { 883 ASSERT(cssTextCache().contains(this)); 884 return cssTextCache().get(this); 885 } 886 887 String text; 888 switch (m_primitiveUnitType) { 889 case CSS_UNKNOWN: 890 // FIXME 891 break; 892 case CSS_NUMBER: 893 case CSS_PARSER_INTEGER: 894 text = formatNumber(m_value.num, ""); 895 break; 896 case CSS_PERCENTAGE: 897 text = formatNumber(m_value.num, "%"); 898 break; 899 case CSS_EMS: 900 text = formatNumber(m_value.num, "em"); 901 break; 902 case CSS_EXS: 903 text = formatNumber(m_value.num, "ex"); 904 break; 905 case CSS_REMS: 906 text = formatNumber(m_value.num, "rem"); 907 break; 908 case CSS_CHS: 909 text = formatNumber(m_value.num, "ch"); 910 break; 911 case CSS_PX: 912 text = formatNumber(m_value.num, "px"); 913 break; 914 case CSS_CM: 915 text = formatNumber(m_value.num, "cm"); 916 break; 917#if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) 918 case CSS_DPPX: 919 text = formatNumber(m_value.num, "dppx"); 920 break; 921 case CSS_DPI: 922 text = formatNumber(m_value.num, "dpi"); 923 break; 924 case CSS_DPCM: 925 text = formatNumber(m_value.num, "dpcm"); 926 break; 927#endif 928 case CSS_MM: 929 text = formatNumber(m_value.num, "mm"); 930 break; 931 case CSS_IN: 932 text = formatNumber(m_value.num, "in"); 933 break; 934 case CSS_PT: 935 text = formatNumber(m_value.num, "pt"); 936 break; 937 case CSS_PC: 938 text = formatNumber(m_value.num, "pc"); 939 break; 940 case CSS_DEG: 941 text = formatNumber(m_value.num, "deg"); 942 break; 943 case CSS_RAD: 944 text = formatNumber(m_value.num, "rad"); 945 break; 946 case CSS_GRAD: 947 text = formatNumber(m_value.num, "grad"); 948 break; 949 case CSS_MS: 950 text = formatNumber(m_value.num, "ms"); 951 break; 952 case CSS_S: 953 text = formatNumber(m_value.num, "s"); 954 break; 955 case CSS_HZ: 956 text = formatNumber(m_value.num, "hz"); 957 break; 958 case CSS_KHZ: 959 text = formatNumber(m_value.num, "khz"); 960 break; 961 case CSS_TURN: 962 text = formatNumber(m_value.num, "turn"); 963 break; 964 case CSS_DIMENSION: 965 // FIXME 966 break; 967 case CSS_STRING: 968 text = quoteCSSStringIfNeeded(m_value.string); 969 break; 970 case CSS_URI: 971 text = "url(" + quoteCSSURLIfNeeded(m_value.string) + ")"; 972 break; 973 case CSS_IDENT: 974 text = valueOrPropertyName(m_value.ident); 975 break; 976 case CSS_ATTR: { 977 StringBuilder result; 978 result.reserveCapacity(6 + m_value.string->length()); 979 result.appendLiteral("attr("); 980 result.append(m_value.string); 981 result.append(')'); 982 983 text = result.toString(); 984 break; 985 } 986 case CSS_COUNTER_NAME: 987 text = "counter(" + String(m_value.string) + ')'; 988 break; 989 case CSS_COUNTER: { 990 StringBuilder result; 991 String separator = m_value.counter->separator(); 992 if (separator.isEmpty()) 993 result.appendLiteral("counter("); 994 else 995 result.appendLiteral("counters("); 996 997 result.append(m_value.counter->identifier()); 998 if (!separator.isEmpty()) { 999 result.appendLiteral(", "); 1000 result.append(quoteCSSStringIfNeeded(separator)); 1001 } 1002 String listStyle = m_value.counter->listStyle(); 1003 if (!listStyle.isEmpty()) { 1004 result.appendLiteral(", "); 1005 result.append(listStyle); 1006 } 1007 result.append(')'); 1008 1009 text = result.toString(); 1010 break; 1011 } 1012 case CSS_RECT: 1013 text = getRectValue()->cssText(); 1014 break; 1015 case CSS_QUAD: 1016 text = getQuadValue()->cssText(); 1017 break; 1018 case CSS_RGBCOLOR: 1019 case CSS_PARSER_HEXCOLOR: { 1020 RGBA32 rgbColor = m_value.rgbcolor; 1021 if (m_primitiveUnitType == CSS_PARSER_HEXCOLOR) 1022 Color::parseHexColor(m_value.string, rgbColor); 1023 Color color(rgbColor); 1024 1025 Vector<LChar> result; 1026 result.reserveInitialCapacity(32); 1027 bool colorHasAlpha = color.hasAlpha(); 1028 if (colorHasAlpha) 1029 result.append("rgba(", 5); 1030 else 1031 result.append("rgb(", 4); 1032 1033 appendNumber(result, static_cast<unsigned char>(color.red())); 1034 result.append(", ", 2); 1035 1036 appendNumber(result, static_cast<unsigned char>(color.green())); 1037 result.append(", ", 2); 1038 1039 appendNumber(result, static_cast<unsigned char>(color.blue())); 1040 if (colorHasAlpha) { 1041 result.append(", ", 2); 1042 1043 NumberToStringBuffer buffer; 1044 const char* alphaString = numberToFixedPrecisionString(color.alpha() / 255.0f, 6, buffer, true); 1045 result.append(alphaString, strlen(alphaString)); 1046 } 1047 1048 result.append(')'); 1049 text = String::adopt(result); 1050 break; 1051 } 1052 case CSS_PAIR: 1053 text = getPairValue()->cssText(); 1054 break; 1055#if ENABLE(DASHBOARD_SUPPORT) 1056 case CSS_DASHBOARD_REGION: { 1057 StringBuilder result; 1058 for (DashboardRegion* region = getDashboardRegionValue(); region; region = region->m_next.get()) { 1059 if (!result.isEmpty()) 1060 result.append(' '); 1061 result.appendLiteral("dashboard-region("); 1062 result.append(region->m_label); 1063 if (region->m_isCircle) 1064 result.appendLiteral(" circle"); 1065 else if (region->m_isRectangle) 1066 result.appendLiteral(" rectangle"); 1067 else 1068 break; 1069 if (region->top()->m_primitiveUnitType == CSS_IDENT && region->top()->getIdent() == CSSValueInvalid) { 1070 ASSERT(region->right()->m_primitiveUnitType == CSS_IDENT); 1071 ASSERT(region->bottom()->m_primitiveUnitType == CSS_IDENT); 1072 ASSERT(region->left()->m_primitiveUnitType == CSS_IDENT); 1073 ASSERT(region->right()->getIdent() == CSSValueInvalid); 1074 ASSERT(region->bottom()->getIdent() == CSSValueInvalid); 1075 ASSERT(region->left()->getIdent() == CSSValueInvalid); 1076 } else { 1077 result.append(' '); 1078 result.append(region->top()->cssText()); 1079 result.append(' '); 1080 result.append(region->right()->cssText()); 1081 result.append(' '); 1082 result.append(region->bottom()->cssText()); 1083 result.append(' '); 1084 result.append(region->left()->cssText()); 1085 } 1086 result.append(')'); 1087 } 1088 text = result.toString(); 1089 break; 1090 } 1091#endif 1092 case CSS_PARSER_OPERATOR: { 1093 char c = static_cast<char>(m_value.ident); 1094 text = String(&c, 1U); 1095 break; 1096 } 1097 case CSS_PARSER_IDENTIFIER: 1098 text = quoteCSSStringIfNeeded(m_value.string); 1099 break; 1100 case CSS_CALC: 1101 text = m_value.calc->cssText(); 1102 break; 1103 case CSS_SHAPE: 1104 text = m_value.shape->cssText(); 1105 break; 1106 case CSS_VW: 1107 text = formatNumber(m_value.num, "vw"); 1108 break; 1109 case CSS_VH: 1110 text = formatNumber(m_value.num, "vh"); 1111 break; 1112 case CSS_VMIN: 1113 text = formatNumber(m_value.num, "vmin"); 1114 break; 1115 case CSS_VMAX: 1116 text = formatNumber(m_value.num, "vmax"); 1117 break; 1118#if ENABLE(CSS_VARIABLES) 1119 case CSS_VARIABLE_NAME: 1120 text = "-webkit-var(" + String(m_value.string) + ')'; 1121 break; 1122#endif 1123 } 1124 1125 ASSERT(!cssTextCache().contains(this)); 1126 cssTextCache().set(this, text); 1127 m_hasCachedCSSText = true; 1128 return text; 1129} 1130 1131#if ENABLE(CSS_VARIABLES) 1132String CSSPrimitiveValue::customSerializeResolvingVariables(const HashMap<AtomicString, String>& variables) const 1133{ 1134 if (isVariableName() && variables.contains(m_value.string)) 1135 return variables.get(m_value.string); 1136 if (CSSCalcValue* calcValue = cssCalcValue()) 1137 return calcValue->customSerializeResolvingVariables(variables); 1138 if (Pair* pairValue = getPairValue()) 1139 return pairValue->serializeResolvingVariables(variables); 1140 if (Rect* rectVal = getRectValue()) 1141 return rectVal->serializeResolvingVariables(variables); 1142 if (Quad* quadVal = getQuadValue()) 1143 return quadVal->serializeResolvingVariables(variables); 1144 if (CSSBasicShape* shapeValue = getShapeValue()) 1145 return shapeValue->serializeResolvingVariables(variables); 1146 return customCssText(); 1147} 1148 1149bool CSSPrimitiveValue::hasVariableReference() const 1150{ 1151 if (CSSCalcValue* calcValue = cssCalcValue()) 1152 return calcValue->hasVariableReference(); 1153 if (Pair* pairValue = getPairValue()) 1154 return pairValue->hasVariableReference(); 1155 if (Quad* quadValue = getQuadValue()) 1156 return quadValue->hasVariableReference(); 1157 if (Rect* rectValue = getRectValue()) 1158 return rectValue->hasVariableReference(); 1159 if (CSSBasicShape* shapeValue = getShapeValue()) 1160 return shapeValue->hasVariableReference(); 1161 return isVariableName(); 1162} 1163#endif 1164 1165void CSSPrimitiveValue::addSubresourceStyleURLs(ListHashSet<KURL>& urls, const StyleSheetContents* styleSheet) const 1166{ 1167 if (m_primitiveUnitType == CSS_URI) 1168 addSubresourceURL(urls, styleSheet->completeURL(m_value.string)); 1169} 1170 1171Length CSSPrimitiveValue::viewportPercentageLength() const 1172{ 1173 ASSERT(isViewportPercentageLength()); 1174 Length viewportLength; 1175 switch (m_primitiveUnitType) { 1176 case CSS_VW: 1177 viewportLength = Length(getDoubleValue(), ViewportPercentageWidth); 1178 break; 1179 case CSS_VH: 1180 viewportLength = Length(getDoubleValue(), ViewportPercentageHeight); 1181 break; 1182 case CSS_VMIN: 1183 viewportLength = Length(getDoubleValue(), ViewportPercentageMin); 1184 break; 1185 case CSS_VMAX: 1186 viewportLength = Length(getDoubleValue(), ViewportPercentageMax); 1187 break; 1188 default: 1189 break; 1190 } 1191 return viewportLength; 1192} 1193 1194PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::cloneForCSSOM() const 1195{ 1196 RefPtr<CSSPrimitiveValue> result; 1197 1198 switch (m_primitiveUnitType) { 1199 case CSS_STRING: 1200 case CSS_URI: 1201 case CSS_ATTR: 1202 case CSS_COUNTER_NAME: 1203 result = CSSPrimitiveValue::create(m_value.string, static_cast<UnitTypes>(m_primitiveUnitType)); 1204 break; 1205 case CSS_COUNTER: 1206 result = CSSPrimitiveValue::create(m_value.counter->cloneForCSSOM()); 1207 break; 1208 case CSS_RECT: 1209 result = CSSPrimitiveValue::create(m_value.rect->cloneForCSSOM()); 1210 break; 1211 case CSS_QUAD: 1212 result = CSSPrimitiveValue::create(m_value.quad->cloneForCSSOM()); 1213 break; 1214 case CSS_PAIR: 1215 // Pair is not exposed to the CSSOM, no need for a deep clone. 1216 result = CSSPrimitiveValue::create(m_value.pair); 1217 break; 1218#if ENABLE(DASHBOARD_SUPPORT) 1219 case CSS_DASHBOARD_REGION: 1220 // DashboardRegion is not exposed to the CSSOM, no need for a deep clone. 1221 result = CSSPrimitiveValue::create(m_value.region); 1222 break; 1223#endif 1224 case CSS_CALC: 1225 // CSSCalcValue is not exposed to the CSSOM, no need for a deep clone. 1226 result = CSSPrimitiveValue::create(m_value.calc); 1227 break; 1228 case CSS_SHAPE: 1229 // CSSShapeValue is not exposed to the CSSOM, no need for a deep clone. 1230 result = CSSPrimitiveValue::create(m_value.shape); 1231 break; 1232 case CSS_NUMBER: 1233 case CSS_PARSER_INTEGER: 1234 case CSS_PERCENTAGE: 1235 case CSS_EMS: 1236 case CSS_EXS: 1237 case CSS_REMS: 1238 case CSS_CHS: 1239 case CSS_PX: 1240 case CSS_CM: 1241 case CSS_MM: 1242 case CSS_IN: 1243 case CSS_PT: 1244 case CSS_PC: 1245 case CSS_DEG: 1246 case CSS_RAD: 1247 case CSS_GRAD: 1248 case CSS_MS: 1249 case CSS_S: 1250 case CSS_HZ: 1251 case CSS_KHZ: 1252 case CSS_TURN: 1253 case CSS_VW: 1254 case CSS_VH: 1255 case CSS_VMIN: 1256 case CSS_VMAX: 1257#if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) 1258 case CSS_DPPX: 1259 case CSS_DPI: 1260 case CSS_DPCM: 1261#endif 1262 result = CSSPrimitiveValue::create(m_value.num, static_cast<UnitTypes>(m_primitiveUnitType)); 1263 break; 1264 case CSS_IDENT: 1265 result = CSSPrimitiveValue::createIdentifier(m_value.ident); 1266 break; 1267 case CSS_RGBCOLOR: 1268 result = CSSPrimitiveValue::createColor(m_value.rgbcolor); 1269 break; 1270 case CSS_DIMENSION: 1271 case CSS_UNKNOWN: 1272 case CSS_PARSER_OPERATOR: 1273 case CSS_PARSER_IDENTIFIER: 1274 case CSS_PARSER_HEXCOLOR: 1275 ASSERT_NOT_REACHED(); 1276 break; 1277 } 1278 if (result) 1279 result->setCSSOMSafe(); 1280 1281 return result; 1282} 1283 1284bool CSSPrimitiveValue::equals(const CSSPrimitiveValue& other) const 1285{ 1286 if (m_primitiveUnitType != other.m_primitiveUnitType) 1287 return false; 1288 1289 switch (m_primitiveUnitType) { 1290 case CSS_UNKNOWN: 1291 return false; 1292 case CSS_NUMBER: 1293 case CSS_PARSER_INTEGER: 1294 case CSS_PERCENTAGE: 1295 case CSS_EMS: 1296 case CSS_EXS: 1297 case CSS_REMS: 1298 case CSS_PX: 1299 case CSS_CM: 1300#if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) 1301 case CSS_DPPX: 1302 case CSS_DPI: 1303 case CSS_DPCM: 1304#endif 1305 case CSS_MM: 1306 case CSS_IN: 1307 case CSS_PT: 1308 case CSS_PC: 1309 case CSS_DEG: 1310 case CSS_RAD: 1311 case CSS_GRAD: 1312 case CSS_MS: 1313 case CSS_S: 1314 case CSS_HZ: 1315 case CSS_KHZ: 1316 case CSS_TURN: 1317 case CSS_VW: 1318 case CSS_VH: 1319 case CSS_VMIN: 1320 case CSS_DIMENSION: 1321 return m_value.num == other.m_value.num; 1322 case CSS_IDENT: 1323 return valueOrPropertyName(m_value.ident) == valueOrPropertyName(other.m_value.ident); 1324 case CSS_STRING: 1325 case CSS_URI: 1326 case CSS_ATTR: 1327 case CSS_COUNTER_NAME: 1328 case CSS_PARSER_IDENTIFIER: 1329 case CSS_PARSER_HEXCOLOR: 1330#if ENABLE(CSS_VARIABLES) 1331 case CSS_VARIABLE_NAME: 1332#endif 1333 return equal(m_value.string, other.m_value.string); 1334 case CSS_COUNTER: 1335 return m_value.counter && other.m_value.counter && m_value.counter->equals(*other.m_value.counter); 1336 case CSS_RECT: 1337 return m_value.rect && other.m_value.rect && m_value.rect->equals(*other.m_value.rect); 1338 case CSS_QUAD: 1339 return m_value.quad && other.m_value.quad && m_value.quad->equals(*other.m_value.quad); 1340 case CSS_RGBCOLOR: 1341 return m_value.rgbcolor == other.m_value.rgbcolor; 1342 case CSS_PAIR: 1343 return m_value.pair && other.m_value.pair && m_value.pair->equals(*other.m_value.pair); 1344#if ENABLE(DASHBOARD_SUPPORT) 1345 case CSS_DASHBOARD_REGION: { 1346 DashboardRegion* region = getDashboardRegionValue(); 1347 DashboardRegion* otherRegion = other.getDashboardRegionValue(); 1348 return region ? otherRegion && region->equals(*otherRegion) : !otherRegion; 1349 } 1350#endif 1351 case CSS_PARSER_OPERATOR: 1352 return m_value.ident == other.m_value.ident; 1353 case CSS_CALC: 1354 return m_value.calc && other.m_value.calc && m_value.calc->equals(*other.m_value.calc); 1355 case CSS_SHAPE: 1356 return m_value.shape && other.m_value.shape && m_value.shape->equals(*other.m_value.shape); 1357 } 1358 return false; 1359} 1360 1361} // namespace WebCore 1362