1 /* 2 * This file is part of the DOM implementation for KDE. 3 * 4 * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org) 5 * (C) 2004, 2005, 2006 Apple Computer, Inc. 6 * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Library General Public 10 * License as published by the Free Software Foundation; either 11 * version 2 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Library General Public License for more details. 17 * 18 * You should have received a copy of the GNU Library General Public License 19 * along with this library; see the file COPYING.LIB. If not, write to 20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 21 * Boston, MA 02110-1301, USA. 22 * 23 */ 24 #ifndef _CSS_css_valueimpl_h_ 25 #define _CSS_css_valueimpl_h_ 26 27 #include "dom/css_value.h" 28 #include "dom/dom_string.h" 29 #include "css/css_base.h" 30 #include "misc/loader_client.h" 31 #include "misc/shared.h" 32 #include "misc/enum.h" 33 34 namespace khtml 35 { 36 class RenderStyle; 37 class CachedImage; 38 } 39 40 namespace DOM 41 { 42 43 class CSSRuleImpl; 44 class CSSValueImpl; 45 class NodeImpl; 46 class CounterImpl; 47 class PairImpl; 48 49 class CSSStyleDeclarationImpl : public StyleBaseImpl 50 { 51 public: 52 CSSStyleDeclarationImpl(CSSRuleImpl *parentRule); 53 CSSStyleDeclarationImpl(CSSRuleImpl *parentRule, QList<CSSProperty *> *lstValues); 54 virtual ~CSSStyleDeclarationImpl(); 55 56 CSSStyleDeclarationImpl &operator=(const CSSStyleDeclarationImpl &); 57 58 virtual unsigned long length() const; 59 CSSRuleImpl *parentRule() const; 60 virtual void removeProperty(int propertyID, DOM::DOMString *old = nullptr); 61 virtual bool removePropertiesInSet(const int *set, unsigned length); 62 virtual bool setProperty(int propertyId, const DOM::DOMString &value, bool important, int &ec); 63 virtual bool setProperty(int propertyId, const DOM::DOMString &value, bool important = false); 64 virtual void setProperty(int propertyId, int value, bool important = false); 65 virtual void clear(); 66 // this treats integers as pixels! 67 // needed for conversion of html attributes 68 virtual void setLengthProperty(int id, const DOM::DOMString &value, bool important, bool multiLength = false); 69 70 void setProperty(const DOMString &propertyName, const DOMString &value, const DOMString &priority); 71 DOMString removeProperty(const DOMString &propertyName); 72 73 // add a whole, unparsed property 74 virtual void setProperty(const DOMString &propertyString); 75 virtual DOM::DOMString item(unsigned long index) const; 76 77 DOM::DOMString cssText() const; 78 void setCssText(const DOM::DOMString &str); 79 isStyleDeclaration()80 bool isStyleDeclaration() const override 81 { 82 return true; 83 } 84 virtual bool isPropertyImplicit(int propertyID) const; 85 bool parseString(const DOMString &string, bool = false) override; 86 87 CSSValueImpl *getPropertyCSSValue(const DOMString &propertyName) const; 88 DOMString getPropertyValue(const DOMString &propertyName) const; 89 DOMString getPropertyPriority(const DOMString &propertyName) const; 90 91 virtual CSSValueImpl *getPropertyCSSValue(int propertyID) const; 92 virtual DOMString getPropertyValue(int propertyID) const; 93 virtual bool getPropertyPriority(int propertyID) const; 94 values()95 QList<CSSProperty *> *values() const 96 { 97 return m_lstValues; 98 } setNode(NodeImpl * _node)99 void setNode(NodeImpl *_node) 100 { 101 m_node = _node; 102 } 103 104 virtual void setChanged(); 105 106 protected: 107 DOMString getShortHandValue(const int *properties, int number) const; 108 DOMString getCommonValue(const int *properties, int number) const; 109 DOMString getLayeredShortHandValue(const int *properties, unsigned number) const; 110 DOMString get4Values(const int *properties) const; 111 112 QList<CSSProperty *> *m_lstValues; 113 NodeImpl *m_node; 114 115 private: 116 // currently not needed - make sure it is not used 117 CSSStyleDeclarationImpl(const CSSStyleDeclarationImpl &o); 118 }; 119 120 class CSSInlineStyleDeclarationImpl : public CSSStyleDeclarationImpl 121 { 122 public: CSSInlineStyleDeclarationImpl(CSSRuleImpl * parentRule)123 CSSInlineStyleDeclarationImpl(CSSRuleImpl *parentRule): CSSStyleDeclarationImpl(parentRule) {} 124 void setChanged() override; 125 void updateFromAttribute(const DOMString &value); 126 }; 127 128 class CSSValueImpl : public StyleBaseImpl 129 { 130 public: CSSValueImpl()131 CSSValueImpl() : StyleBaseImpl() {} 132 133 virtual unsigned short cssValueType() const = 0; 134 135 virtual DOM::DOMString cssText() const = 0; setCssText(const DOM::DOMString &)136 void setCssText(const DOM::DOMString &) { } // FIXME: Not implemented. 137 isValue()138 bool isValue() const override 139 { 140 return true; 141 } isFontValue()142 virtual bool isFontValue() const 143 { 144 return false; 145 } isImplicitInitialValue()146 virtual bool isImplicitInitialValue() const 147 { 148 return false; 149 } 150 }; 151 152 class CSSInheritedValueImpl : public CSSValueImpl 153 { 154 public: CSSInheritedValueImpl()155 CSSInheritedValueImpl() : CSSValueImpl() {} ~CSSInheritedValueImpl()156 virtual ~CSSInheritedValueImpl() {} 157 158 unsigned short cssValueType() const override; 159 DOM::DOMString cssText() const override; 160 }; 161 162 class CSSInitialValueImpl : public CSSValueImpl 163 { 164 public: CSSInitialValueImpl(bool implicit)165 CSSInitialValueImpl(bool implicit) 166 : m_implicit(implicit) 167 {} 168 unsigned short cssValueType() const override; 169 DOM::DOMString cssText() const override; 170 isImplicitInitialValue()171 bool isImplicitInitialValue() const override 172 { 173 return m_implicit; 174 } 175 private: 176 bool m_implicit; // whether this property has been created implicitly to fill undeclared properties 177 // of a shorthand (e.g. 'border-top-width: medium' set from the 'border: solid red' declaration) 178 }; 179 180 class CSSValueListImpl : public CSSValueImpl 181 { 182 public: 183 enum Separator { 184 Space, 185 Comma 186 }; 187 CSSValueListImpl()188 CSSValueListImpl() : CSSValueImpl(), m_separator(Space) {} CSSValueListImpl(Separator sep)189 CSSValueListImpl(Separator sep) : CSSValueImpl(), m_separator(sep) {} 190 191 virtual ~CSSValueListImpl(); 192 length()193 unsigned long length() const 194 { 195 return m_values.count(); 196 } item(unsigned long index)197 CSSValueImpl *item(unsigned long index) 198 { 199 return index < length() ? m_values.at(index) : nullptr; 200 } 201 isValueList()202 bool isValueList() const override 203 { 204 return true; 205 } 206 207 unsigned short cssValueType() const override; 208 209 void append(CSSValueImpl *val); 210 DOM::DOMString cssText() const override; 211 212 protected: 213 KDE_BF_ENUM(Separator) m_separator: 1; 214 QList<CSSValueImpl *> m_values; 215 }; 216 217 class Counter; 218 class RGBColor; 219 class Rect; 220 221 class CSSPrimitiveValueImpl : public CSSValueImpl 222 { 223 public: 224 CSSPrimitiveValueImpl(); 225 CSSPrimitiveValueImpl(int ident); 226 CSSPrimitiveValueImpl(double num, CSSPrimitiveValue::UnitTypes type); 227 CSSPrimitiveValueImpl(const DOMString &str, CSSPrimitiveValue::UnitTypes type); 228 CSSPrimitiveValueImpl(CounterImpl *c); 229 CSSPrimitiveValueImpl(RectImpl *r); 230 CSSPrimitiveValueImpl(QRgb color); 231 CSSPrimitiveValueImpl(PairImpl *p); 232 233 virtual ~CSSPrimitiveValueImpl(); 234 235 void cleanup(); 236 primitiveType()237 unsigned short primitiveType() const 238 { 239 return m_type; 240 } 241 242 /* 243 * computes a length in pixels out of the given CSSValue. Need the RenderStyle to get 244 * the fontinfo in case val is defined in em or ex. 245 * 246 * The metrics have to be a bit different for screen and printer output. 247 * For screen output we assume 1 inch == 72 px, for printer we assume 300 dpi 248 * 249 * this is screen/printer dependent, so we probably need a config option for this, 250 * and some tool to calibrate. 251 */ 252 int computeLength(khtml::RenderStyle *style, khtml::RenderStyle *rootStyle, int logicalDpiY); 253 254 double computeLengthFloat(khtml::RenderStyle *style, khtml::RenderStyle *rootStyle, int logicalDpiY); 255 256 /* 257 * rounds a computer value into integer as appropriate. This takes 258 * care of the various 4.9999999999 type cases 259 */ snapValue(double result)260 static int snapValue(double result) 261 { 262 // Conversions are imprecise, often resulting in values of, e.g., 44.99998. We 263 // need to go ahead and round if we're really close to the next integer value. 264 return (int)(result + (result < 0 ? -0.01 : +0.01)); 265 } 266 267 // Retrieves an explicit resolution from the CSSValue if it contains one. 268 // This is specific to the CSS3 Media Queries module's resolution feature. 269 int getDPIResolution() const; 270 271 // use with care!!! setPrimitiveType(unsigned short type)272 void setPrimitiveType(unsigned short type) 273 { 274 m_type = type; 275 } 276 void setFloatValue(unsigned short unitType, double floatValue, int &exceptioncode); 277 double floatValue(unsigned short unitType = CSSPrimitiveValue::CSS_UNKNOWN) const 278 { 279 (void)unitType; 280 return m_value.num; 281 } 282 283 void setStringValue(unsigned short stringType, const DOM::DOMString &stringValue, int &exceptioncode); getStringValue()284 DOM::DOMStringImpl *getStringValue() const 285 { 286 return ((m_type < CSSPrimitiveValue::CSS_STRING || 287 m_type > CSSPrimitiveValue::CSS_ATTR || 288 m_type == CSSPrimitiveValue::CSS_IDENT) ? // fix IDENT 289 nullptr : m_value.string); 290 } getCounterValue()291 CounterImpl *getCounterValue() const 292 { 293 return (m_type != CSSPrimitiveValue::CSS_COUNTER ? nullptr : m_value.counter); 294 } 295 getRectValue()296 RectImpl *getRectValue() const 297 { 298 return (m_type != CSSPrimitiveValue::CSS_RECT ? nullptr : m_value.rect); 299 } 300 getRGBColorValue()301 QRgb getRGBColorValue() const 302 { 303 return (m_type != CSSPrimitiveValue::CSS_RGBCOLOR ? 0 : m_value.rgbcolor); 304 } 305 getPairValue()306 PairImpl *getPairValue() const 307 { 308 return (m_type != CSSPrimitiveValue::CSS_PAIR ? nullptr : m_value.pair); 309 } 310 isPrimitiveValue()311 bool isPrimitiveValue() const override 312 { 313 return true; 314 } 315 unsigned short cssValueType() const override; 316 317 int getIdent(); 318 319 bool parseString(const DOMString &string, bool = false) override; 320 DOM::DOMString cssText() const override; 321 isQuirkValue()322 virtual bool isQuirkValue() const 323 { 324 return false; 325 } 326 327 protected: 328 int m_type; 329 union { 330 int ident; 331 double num; 332 DOM::DOMStringImpl *string; 333 CounterImpl *counter; 334 RectImpl *rect; 335 QRgb rgbcolor; 336 PairImpl *pair; 337 } m_value; 338 }; 339 340 // This value is used to handle quirky margins in reflow roots (body, td, and th) like WinIE. 341 // The basic idea is that a stylesheet can use the value __qem (for quirky em) instead of em 342 // in a stylesheet. When the quirky value is used, if you're in quirks mode, the margin will 343 // collapse away inside a table cell. 344 class CSSQuirkPrimitiveValueImpl : public CSSPrimitiveValueImpl 345 { 346 public: CSSQuirkPrimitiveValueImpl(double num,CSSPrimitiveValue::UnitTypes type)347 CSSQuirkPrimitiveValueImpl(double num, CSSPrimitiveValue::UnitTypes type) 348 : CSSPrimitiveValueImpl(num, type) {} 349 ~CSSQuirkPrimitiveValueImpl()350 virtual ~CSSQuirkPrimitiveValueImpl() {} 351 isQuirkValue()352 bool isQuirkValue() const override 353 { 354 return true; 355 } 356 }; 357 358 class CounterImpl : public khtml::Shared<CounterImpl> 359 { 360 public: CounterImpl()361 CounterImpl() : m_listStyle(0) { } identifier()362 DOMString identifier() const 363 { 364 return m_identifier; 365 } listStyle()366 unsigned int listStyle() const 367 { 368 return m_listStyle; 369 } separator()370 DOMString separator() const 371 { 372 return m_separator; 373 } 374 375 DOMString m_identifier; 376 unsigned int m_listStyle; 377 DOMString m_separator; 378 }; 379 380 class RectImpl : public khtml::Shared<RectImpl> 381 { 382 public: 383 RectImpl(); 384 ~RectImpl(); 385 top()386 CSSPrimitiveValueImpl *top() const 387 { 388 return m_top; 389 } right()390 CSSPrimitiveValueImpl *right() const 391 { 392 return m_right; 393 } bottom()394 CSSPrimitiveValueImpl *bottom() const 395 { 396 return m_bottom; 397 } left()398 CSSPrimitiveValueImpl *left() const 399 { 400 return m_left; 401 } 402 403 void setTop(CSSPrimitiveValueImpl *top); 404 void setRight(CSSPrimitiveValueImpl *right); 405 void setBottom(CSSPrimitiveValueImpl *bottom); 406 void setLeft(CSSPrimitiveValueImpl *left); 407 protected: 408 CSSPrimitiveValueImpl *m_top; 409 CSSPrimitiveValueImpl *m_right; 410 CSSPrimitiveValueImpl *m_bottom; 411 CSSPrimitiveValueImpl *m_left; 412 }; 413 414 // A primitive value representing a pair. This is useful for properties like border-radius, background-size/position, 415 // and border-spacing (all of which are space-separated sets of two values). At the moment we are only using it for 416 // border-radius and background-size, but (FIXME) border-spacing and background-position could be converted over to use 417 // it (eliminating some extra -webkit- internal properties). 418 class PairImpl : public khtml::Shared<PairImpl> 419 { 420 public: PairImpl()421 PairImpl() : m_first(nullptr), m_second(nullptr) { } PairImpl(CSSPrimitiveValueImpl * first,CSSPrimitiveValueImpl * second)422 PairImpl(CSSPrimitiveValueImpl *first, CSSPrimitiveValueImpl *second) 423 : m_first(first), m_second(second) 424 { 425 if (first) { 426 first->ref(); 427 } if (second) { 428 second->ref(); 429 } 430 } 431 virtual ~PairImpl(); 432 first()433 CSSPrimitiveValueImpl *first() const 434 { 435 return m_first; 436 } second()437 CSSPrimitiveValueImpl *second() const 438 { 439 return m_second; 440 } 441 442 void setFirst(CSSPrimitiveValueImpl *first); 443 void setSecond(CSSPrimitiveValueImpl *second); 444 445 protected: 446 CSSPrimitiveValueImpl *m_first; 447 CSSPrimitiveValueImpl *m_second; 448 }; 449 450 class CSSImageValueImpl : public CSSPrimitiveValueImpl, public khtml::CachedObjectClient 451 { 452 public: 453 CSSImageValueImpl(const DOMString &url, StyleBaseImpl *style); 454 CSSImageValueImpl(); 455 virtual ~CSSImageValueImpl(); 456 457 khtml::CachedImage *requestCssImage(DocumentImpl *doc); 458 protected: 459 khtml::CachedImage *m_image; 460 QString m_fullImageUrl; 461 }; 462 463 class FontFamilyValueImpl : public CSSPrimitiveValueImpl 464 { 465 public: 466 FontFamilyValueImpl(const QString &string); fontName()467 const QString &fontName() const 468 { 469 return parsedFontName; 470 } genericFamilyType()471 int genericFamilyType() const 472 { 473 return _genericFamilyType; 474 } 475 protected: 476 QString parsedFontName; 477 private: 478 int _genericFamilyType; 479 }; 480 481 class FontValueImpl : public CSSValueImpl 482 { 483 public: 484 FontValueImpl(); 485 virtual ~FontValueImpl(); 486 cssValueType()487 unsigned short cssValueType() const override 488 { 489 return CSSValue::CSS_CUSTOM; 490 } 491 492 DOM::DOMString cssText() const override; 493 isFontValue()494 bool isFontValue() const override 495 { 496 return true; 497 } 498 499 CSSPrimitiveValueImpl *style; 500 CSSPrimitiveValueImpl *variant; 501 CSSPrimitiveValueImpl *weight; 502 CSSPrimitiveValueImpl *size; 503 CSSPrimitiveValueImpl *lineHeight; 504 CSSValueListImpl *family; 505 }; 506 507 // Used for quotes 508 class QuotesValueImpl : public CSSValueImpl 509 { 510 public: 511 QuotesValueImpl(); 512 // virtual ~QuotesValueImpl(); 513 cssValueType()514 unsigned short cssValueType() const override 515 { 516 return CSSValue::CSS_CUSTOM; 517 } 518 DOM::DOMString cssText() const override; 519 520 void addLevel(const QString &open, const QString &close); 521 QString openQuote(int level) const; 522 QString closeQuote(int level) const; 523 524 unsigned int levels; 525 QStringList data; 526 }; 527 528 // Used for text-shadow and box-shadow 529 class ShadowValueImpl : public CSSValueImpl 530 { 531 public: 532 ShadowValueImpl(CSSPrimitiveValueImpl *_x, CSSPrimitiveValueImpl *_y, 533 CSSPrimitiveValueImpl *_blur, CSSPrimitiveValueImpl *_color); 534 virtual ~ShadowValueImpl(); 535 cssValueType()536 unsigned short cssValueType() const override 537 { 538 return CSSValue::CSS_CUSTOM; 539 } 540 541 DOM::DOMString cssText() const override; 542 543 CSSPrimitiveValueImpl *x; 544 CSSPrimitiveValueImpl *y; 545 CSSPrimitiveValueImpl *blur; 546 CSSPrimitiveValueImpl *color; 547 }; 548 549 // Used for counter-reset and counter-increment 550 class CounterActImpl : public CSSValueImpl 551 { 552 public: CounterActImpl(const DOMString & c,short v)553 CounterActImpl(const DOMString &c, short v) : m_counter(c), m_value(v) { } ~CounterActImpl()554 virtual ~CounterActImpl() {} 555 cssValueType()556 unsigned short cssValueType() const override 557 { 558 return CSSValue::CSS_CUSTOM; 559 } 560 DOM::DOMString cssText() const override; 561 counter()562 const DOMString &counter() const 563 { 564 return m_counter; 565 } value()566 short value() const 567 { 568 return m_value; 569 } setValue(const short v)570 void setValue(const short v) 571 { 572 m_value = v; 573 } 574 575 DOM::DOMString m_counter; 576 short m_value; 577 }; 578 579 class CSSFontFaceSrcValueImpl : public CSSValueImpl 580 { 581 public: CSSFontFaceSrcValueImpl(const DOMString & resource,bool local)582 CSSFontFaceSrcValueImpl(const DOMString &resource, bool local) 583 : m_resource(resource) 584 , m_isLocal(local) 585 #if 0 586 //ENABLE(SVG_FONTS) 587 , m_svgFontFaceElement(0) 588 #endif 589 { 590 } ~CSSFontFaceSrcValueImpl()591 virtual ~CSSFontFaceSrcValueImpl() { } 592 cssValueType()593 unsigned short cssValueType() const override 594 { 595 return CSSValue::CSS_CUSTOM; 596 } 597 resource()598 const DOMString &resource() const 599 { 600 return m_resource; 601 } format()602 const DOMString &format() const 603 { 604 return m_format; 605 } isLocal()606 bool isLocal() const 607 { 608 return m_isLocal; 609 } 610 setFormat(const DOMString & format)611 void setFormat(const DOMString &format) 612 { 613 m_format = format; 614 } 615 616 bool isSupportedFormat() const; 617 618 #if 0 619 //ENABLE(SVG_FONTS) 620 bool isSVGFontFaceSrc() const; 621 622 SVGFontFaceElement *svgFontFaceElement() const 623 { 624 return m_svgFontFaceElement; 625 } 626 void setSVGFontFaceElement(SVGFontFaceElement *element) 627 { 628 m_svgFontFaceElement = element; 629 } 630 #endif 631 632 DOMString cssText() const override; 633 634 private: 635 636 DOMString m_resource; 637 DOMString m_format; 638 bool m_isLocal; 639 640 #if 0 641 //ENABLE(SVG_FONTS) 642 SVGFontFaceElement *m_svgFontFaceElement; 643 #endif 644 }; 645 646 // ------------------------------------------------------------------------------ 647 648 // another helper class 649 class CSSProperty 650 { 651 public: CSSProperty()652 CSSProperty() 653 { 654 m_id = -1; 655 m_important = false; 656 m_value = nullptr; 657 } CSSProperty(const CSSProperty & o)658 CSSProperty(const CSSProperty &o) 659 { 660 m_id = o.m_id; 661 m_important = o.m_important; 662 m_value = o.m_value; 663 if (m_value) { 664 m_value->ref(); 665 } 666 } ~CSSProperty()667 ~CSSProperty() 668 { 669 if (m_value) { 670 m_value->deref(); 671 } 672 } 673 setValue(CSSValueImpl * val)674 void setValue(CSSValueImpl *val) 675 { 676 if (val != m_value) { 677 if (m_value) { 678 m_value->deref(); 679 } 680 m_value = val; 681 if (m_value) { 682 m_value->ref(); 683 } 684 } 685 } 686 id()687 int id() const 688 { 689 return m_id; 690 } 691 isImportant()692 bool isImportant() const 693 { 694 return m_important; 695 } isImplicit()696 bool isImplicit() const 697 { 698 return m_implicit; 699 } 700 value()701 CSSValueImpl *value() const 702 { 703 return m_value; 704 } 705 706 DOM::DOMString cssText() const; 707 708 // make sure the following fits in 4 bytes. 709 signed int m_id : 28; 710 bool m_important : 1; 711 bool m_implicit : 1; // whether this property has been set implicitly as part of a shorthand 712 // (e.g. 'margin-left: 10px' set from the 'margin: 10px' declaration) 713 protected: 714 CSSValueImpl *m_value; 715 }; 716 717 } // namespace 718 719 #endif 720