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