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