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