1 /*
2  * This file is part of the DOM implementation for KDE.
3  *
4  * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
5  * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
6  * Copyright (C) 2002-2003 Dirk Mueller (mueller@kde.org)
7  * Copyright (C) 2002-2005 Apple Computer, Inc.
8  * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public License
21  * along with this library; see the file COPYING.LIB.  If not, write to
22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23  * Boston, MA 02110-1301, USA.
24  *
25  */
26 
27 #include "render_style.h"
28 
29 #include <xml/dom_stringimpl.h>
30 #include <css/cssstyleselector.h>
31 #include <css/css_valueimpl.h>
32 
33 using namespace khtml;
34 using namespace DOM;
35 
36 /* CSS says Fixed for the default padding value, but we treat variable as 0 padding anyways, and like
37  * this is works fine for table paddings aswell
38  */
StyleSurroundData()39 StyleSurroundData::StyleSurroundData()
40     : margin(Fixed), padding(Auto)
41 {
42 }
43 
StyleSurroundData(const StyleSurroundData & o)44 StyleSurroundData::StyleSurroundData(const StyleSurroundData &o)
45     : Shared<StyleSurroundData>(),
46       offset(o.offset), margin(o.margin), padding(o.padding),
47       border(o.border)
48 {
49 }
50 
operator ==(const StyleSurroundData & o) const51 bool StyleSurroundData::operator==(const StyleSurroundData &o) const
52 {
53     return offset == o.offset && margin == o.margin &&
54            padding == o.padding && border == o.border;
55 }
56 
StyleBoxData()57 StyleBoxData::StyleBoxData()
58     : z_index(0), z_auto(true)
59 {
60     min_width = min_height = RenderStyle::initialMinSize();
61     max_width = max_height = RenderStyle::initialMaxSize();
62     box_sizing = RenderStyle::initialBoxSizing();
63 }
64 
StyleBoxData(const StyleBoxData & o)65 StyleBoxData::StyleBoxData(const StyleBoxData &o)
66     : Shared<StyleBoxData>(),
67       width(o.width), height(o.height),
68       min_width(o.min_width), max_width(o.max_width),
69       min_height(o.min_height), max_height(o.max_height),
70       box_sizing(o.box_sizing),
71       z_index(o.z_index), z_auto(o.z_auto)
72 {
73 }
74 
operator ==(const StyleBoxData & o) const75 bool StyleBoxData::operator==(const StyleBoxData &o) const
76 {
77     return
78         width == o.width &&
79         height == o.height &&
80         min_width == o.min_width &&
81         max_width == o.max_width &&
82         min_height == o.min_height &&
83         max_height == o.max_height &&
84         box_sizing == o.box_sizing &&
85         vertical_align == o.vertical_align &&
86         z_index == o.z_index &&
87         z_auto == o.z_auto;
88 }
89 
StyleVisualData()90 StyleVisualData::StyleVisualData()
91     : textDecoration(RenderStyle::initialTextDecoration()),
92       palette(QApplication::palette())
93 {
94 }
95 
~StyleVisualData()96 StyleVisualData::~StyleVisualData()
97 {
98 }
99 
StyleVisualData(const StyleVisualData & o)100 StyleVisualData::StyleVisualData(const StyleVisualData &o)
101     : Shared<StyleVisualData>(),
102       clip(o.clip), textDecoration(o.textDecoration),
103       palette(o.palette)
104 {
105 }
106 
BackgroundLayer()107 BackgroundLayer::BackgroundLayer()
108     : m_image(RenderStyle::initialBackgroundImage()),
109       m_xPosition(RenderStyle::initialBackgroundXPosition()),
110       m_yPosition(RenderStyle::initialBackgroundYPosition()),
111       m_bgAttachment(RenderStyle::initialBackgroundAttachment()),
112       m_bgClip(RenderStyle::initialBackgroundClip()),
113       m_bgOrigin(RenderStyle::initialBackgroundOrigin()),
114       m_bgRepeat(RenderStyle::initialBackgroundRepeat()),
115       m_backgroundSize(RenderStyle::initialBackgroundSize()),
116       m_next(nullptr)
117 {
118     m_imageSet = m_attachmentSet = m_clipSet = m_originSet =
119                                        m_repeatSet = m_xPosSet = m_yPosSet = m_backgroundSizeSet = false;
120 }
121 
BackgroundLayer(const BackgroundLayer & o)122 BackgroundLayer::BackgroundLayer(const BackgroundLayer &o)
123 {
124     m_next = o.m_next ? new BackgroundLayer(*o.m_next) : nullptr;
125     m_image = o.m_image;
126     m_xPosition = o.m_xPosition;
127     m_yPosition = o.m_yPosition;
128     m_bgAttachment = o.m_bgAttachment;
129     m_bgClip = o.m_bgClip;
130     m_bgOrigin = o.m_bgOrigin;
131     m_bgRepeat = o.m_bgRepeat;
132     m_backgroundSize = o.m_backgroundSize;
133     m_imageSet = o.m_imageSet;
134     m_attachmentSet = o.m_attachmentSet;
135     m_clipSet = o.m_clipSet;
136     m_originSet = o.m_originSet;
137     m_repeatSet = o.m_repeatSet;
138     m_xPosSet = o.m_xPosSet;
139     m_yPosSet = o.m_yPosSet;
140     m_backgroundSizeSet = o.m_backgroundSizeSet;
141 }
142 
~BackgroundLayer()143 BackgroundLayer::~BackgroundLayer()
144 {
145     delete m_next;
146 }
147 
operator =(const BackgroundLayer & o)148 BackgroundLayer &BackgroundLayer::operator=(const BackgroundLayer &o)
149 {
150     if (m_next != o.m_next) {
151         delete m_next;
152         m_next = o.m_next ? new BackgroundLayer(*o.m_next) : nullptr;
153     }
154 
155     m_image = o.m_image;
156     m_xPosition = o.m_xPosition;
157     m_yPosition = o.m_yPosition;
158     m_bgAttachment = o.m_bgAttachment;
159     m_bgClip = o.m_bgClip;
160     m_bgOrigin = o.m_bgOrigin;
161     m_bgRepeat = o.m_bgRepeat;
162     m_backgroundSize = o.m_backgroundSize;
163 
164     m_imageSet = o.m_imageSet;
165     m_attachmentSet = o.m_attachmentSet;
166     m_originSet = o.m_originSet;
167     m_repeatSet = o.m_repeatSet;
168     m_xPosSet = o.m_xPosSet;
169     m_yPosSet = o.m_yPosSet;
170     m_backgroundSizeSet = o.m_backgroundSizeSet;
171 
172     return *this;
173 }
174 
operator ==(const BackgroundLayer & o) const175 bool BackgroundLayer::operator==(const BackgroundLayer &o) const
176 {
177     return m_image == o.m_image && m_xPosition == o.m_xPosition && m_yPosition == o.m_yPosition &&
178            m_bgAttachment == o.m_bgAttachment && m_bgClip == o.m_bgClip && m_bgOrigin == o.m_bgOrigin &&
179            m_bgRepeat == o.m_bgRepeat && m_backgroundSize == o.m_backgroundSize &&
180            m_imageSet == o.m_imageSet && m_attachmentSet == o.m_attachmentSet && m_repeatSet == o.m_repeatSet &&
181            m_xPosSet == o.m_xPosSet && m_yPosSet == o.m_yPosSet && m_backgroundSizeSet == o.m_backgroundSizeSet &&
182            ((m_next && o.m_next) ? *m_next == *o.m_next : m_next == o.m_next);
183 }
184 
fillUnsetProperties()185 void BackgroundLayer::fillUnsetProperties()
186 {
187     BackgroundLayer *curr;
188 
189     for (curr = this; curr && curr->isBackgroundXPositionSet(); curr = curr->next()) {};
190     if (curr && curr != this) {
191         // We need to fill in the remaining values with the pattern specified.
192         for (BackgroundLayer *pattern = this; curr; curr = curr->next()) {
193             curr->setBackgroundXPosition(pattern->backgroundXPosition());
194             pattern = pattern->next();
195             if (pattern == curr || !pattern) {
196                 pattern = this;
197             }
198         }
199     }
200 
201     for (curr = this; curr && curr->isBackgroundYPositionSet(); curr = curr->next()) {};
202     if (curr && curr != this) {
203         // We need to fill in the remaining values with the pattern specified.
204         for (BackgroundLayer *pattern = this; curr; curr = curr->next()) {
205             curr->setBackgroundYPosition(pattern->backgroundYPosition());
206             pattern = pattern->next();
207             if (pattern == curr || !pattern) {
208                 pattern = this;
209             }
210         }
211     }
212 
213     for (curr = this; curr && curr->isBackgroundAttachmentSet(); curr = curr->next()) {};
214     if (curr && curr != this) {
215         // We need to fill in the remaining values with the pattern specified.
216         for (BackgroundLayer *pattern = this; curr; curr = curr->next()) {
217             curr->setBackgroundAttachment(pattern->backgroundAttachment());
218             pattern = pattern->next();
219             if (pattern == curr || !pattern) {
220                 pattern = this;
221             }
222         }
223     }
224 
225     for (curr = this; curr && curr->isBackgroundClipSet(); curr = curr->next()) {};
226     if (curr && curr != this) {
227         // We need to fill in the remaining values with the pattern specified.
228         for (BackgroundLayer *pattern = this; curr; curr = curr->next()) {
229             curr->setBackgroundClip(pattern->backgroundClip());
230             pattern = pattern->next();
231             if (pattern == curr || !pattern) {
232                 pattern = this;
233             }
234         }
235     }
236 
237     for (curr = this; curr && curr->isBackgroundOriginSet(); curr = curr->next()) {};
238     if (curr && curr != this) {
239         // We need to fill in the remaining values with the pattern specified.
240         for (BackgroundLayer *pattern = this; curr; curr = curr->next()) {
241             curr->setBackgroundOrigin(pattern->backgroundOrigin());
242             pattern = pattern->next();
243             if (pattern == curr || !pattern) {
244                 pattern = this;
245             }
246         }
247     }
248 
249     for (curr = this; curr && curr->isBackgroundRepeatSet(); curr = curr->next()) {};
250     if (curr && curr != this) {
251         // We need to fill in the remaining values with the pattern specified.
252         for (BackgroundLayer *pattern = this; curr; curr = curr->next()) {
253             curr->setBackgroundRepeat(pattern->backgroundRepeat());
254             pattern = pattern->next();
255             if (pattern == curr || !pattern) {
256                 pattern = this;
257             }
258         }
259     }
260 
261     for (curr = this; curr && curr->isBackgroundSizeSet(); curr = curr->next()) {};
262     if (curr && curr != this) {
263         // We need to fill in the remaining values with the pattern specified.
264         for (BackgroundLayer *pattern = this; curr; curr = curr->next()) {
265             curr->setBackgroundSize(pattern->backgroundSize());
266             pattern = pattern->next();
267             if (pattern == curr || !pattern) {
268                 pattern = this;
269             }
270         }
271     }
272 }
273 
cullEmptyLayers()274 void BackgroundLayer::cullEmptyLayers()
275 {
276     BackgroundLayer *next;
277     for (BackgroundLayer *p = this; p; p = next) {
278         next = p->m_next;
279         if (next && !next->isBackgroundImageSet()) {
280             delete next;
281             p->m_next = nullptr;
282             break;
283         }
284     }
285 }
286 
StyleBackgroundData()287 StyleBackgroundData::StyleBackgroundData()
288 {}
289 
StyleBackgroundData(const StyleBackgroundData & o)290 StyleBackgroundData::StyleBackgroundData(const StyleBackgroundData &o)
291     : Shared<StyleBackgroundData>(), m_background(o.m_background), m_outline(o.m_outline)
292 {}
293 
operator ==(const StyleBackgroundData & o) const294 bool StyleBackgroundData::operator==(const StyleBackgroundData &o) const
295 {
296     return m_background == o.m_background && m_color == o.m_color && m_outline == o.m_outline;
297 }
298 
StyleGeneratedData()299 StyleGeneratedData::StyleGeneratedData() : Shared<StyleGeneratedData>(), content(nullptr), counter_reset(nullptr), counter_increment(nullptr) {}
300 
~StyleGeneratedData()301 StyleGeneratedData::~StyleGeneratedData()
302 {
303     if (counter_reset) {
304         counter_reset->deref();
305     }
306     if (counter_increment) {
307         counter_increment->deref();
308     }
309     delete content;
310 }
311 
StyleGeneratedData(const StyleGeneratedData & o)312 StyleGeneratedData::StyleGeneratedData(const StyleGeneratedData &o)
313     : Shared<StyleGeneratedData>(), content(nullptr),
314       counter_reset(o.counter_reset), counter_increment(o.counter_increment)
315 {
316     if (o.content) {
317         content = new ContentData(*o.content);
318     }
319     if (counter_reset) {
320         counter_reset->ref();
321     }
322     if (counter_increment) {
323         counter_increment->ref();
324     }
325 }
326 
contentDataEquivalent(const StyleGeneratedData * otherStyle) const327 bool StyleGeneratedData::contentDataEquivalent(const StyleGeneratedData *otherStyle) const
328 {
329     ContentData *c1 = content;
330     ContentData *c2 = otherStyle->content;
331 
332     while (c1 && c2) {
333         if (c1->_contentType != c2->_contentType) {
334             return false;
335         }
336         if (c1->_contentType == CONTENT_TEXT) {
337             DOM::DOMString c1Str(c1->_content.text);
338             DOM::DOMString c2Str(c2->_content.text);
339             if (c1Str != c2Str) {
340                 return false;
341             }
342         } else if (c1->_contentType == CONTENT_OBJECT) {
343             if (c1->_content.object != c2->_content.object) {
344                 return false;
345             }
346         } else if (c1->_contentType == CONTENT_COUNTER) {
347             if (c1->_content.counter != c2->_content.counter) {
348                 return false;
349             }
350         } else if (c1->_contentType == CONTENT_QUOTE) {
351             if (c1->_content.quote != c2->_content.quote) {
352                 return false;
353             }
354         }
355 
356         c1 = c1->_nextContent;
357         c2 = c2->_nextContent;
358     }
359 
360     return !c1 && !c2;
361 }
362 
compareCounterActList(const CSSValueListImpl * ca,const CSSValueListImpl * cb)363 static bool compareCounterActList(const CSSValueListImpl *ca, const CSSValueListImpl *cb)
364 {
365     // weeee....
366     CSSValueListImpl *a = const_cast<CSSValueListImpl *>(ca);
367     CSSValueListImpl *b = const_cast<CSSValueListImpl *>(cb);
368 
369     if (!a && !b) {
370         return true;
371     }
372     if (!a || !b) {
373         return false;
374     }
375     if (a->length() != b->length()) {
376         return false;
377     }
378     for (uint i = 0; i < a->length(); i++) {
379         CSSValueImpl *ai =  a->item(i);
380         CSSValueImpl *bi =  b->item(i);
381         assert(ai && ai->cssValueType() == CSSValue::CSS_CUSTOM);
382         assert(bi && bi->cssValueType() == CSSValue::CSS_CUSTOM);
383         CounterActImpl *caa = static_cast<CounterActImpl *>(ai);
384         CounterActImpl *cab = static_cast<CounterActImpl *>(bi);
385         if (caa->value() != cab->value()) {
386             return false;
387         }
388         if (caa->counter() != cab->counter()) {
389             return false;
390         }
391     }
392     return true;
393 }
394 
counterDataEquivalent(const StyleGeneratedData * otherStyle) const395 bool StyleGeneratedData::counterDataEquivalent(const StyleGeneratedData *otherStyle) const
396 {
397     return compareCounterActList(counter_reset, otherStyle->counter_reset) &&
398            compareCounterActList(counter_increment, otherStyle->counter_increment);
399 }
400 
operator ==(const StyleGeneratedData & o) const401 bool StyleGeneratedData::operator==(const StyleGeneratedData &o) const
402 {
403     return contentDataEquivalent(&o) && counterDataEquivalent(&o);
404 }
405 
StyleMarqueeData()406 StyleMarqueeData::StyleMarqueeData()
407 {
408     increment = RenderStyle::initialMarqueeIncrement();
409     speed = RenderStyle::initialMarqueeSpeed();
410     direction = RenderStyle::initialMarqueeDirection();
411     behavior = RenderStyle::initialMarqueeBehavior();
412     loops = RenderStyle::initialMarqueeLoopCount();
413 }
414 
StyleMarqueeData(const StyleMarqueeData & o)415 StyleMarqueeData::StyleMarqueeData(const StyleMarqueeData &o)
416     : Shared<StyleMarqueeData>(), increment(o.increment), speed(o.speed), loops(o.loops),
417       behavior(o.behavior), direction(o.direction)
418 {}
419 
operator ==(const StyleMarqueeData & o) const420 bool StyleMarqueeData::operator==(const StyleMarqueeData &o) const
421 {
422     return (increment == o.increment && speed == o.speed && direction == o.direction &&
423             behavior == o.behavior && loops == o.loops);
424 }
425 
operator ==(const BorderRadii & o) const426 bool BorderRadii::operator==(const BorderRadii &o) const
427 {
428     return horizontal == o.horizontal &&
429            vertical   == o.vertical;
430 }
431 
BorderRadiusData()432 BorderRadiusData::BorderRadiusData()
433     :Shared<BorderRadiusData>()
434 {
435     topRight = RenderStyle::initialBorderRadius();
436     bottomRight = RenderStyle::initialBorderRadius();
437     bottomLeft = RenderStyle::initialBorderRadius();
438     topLeft = RenderStyle::initialBorderRadius();
439 }
440 
operator ==(const BorderRadiusData & o) const441 bool BorderRadiusData::operator==(const BorderRadiusData &o) const
442 {
443     return topRight == o.topRight && bottomRight == o.bottomRight
444            && bottomLeft == o.bottomLeft && topLeft == o.topLeft;
445 }
446 
hasBorderRadius() const447 bool BorderRadiusData::hasBorderRadius() const
448 {
449     return topRight.hasBorderRadius()   || bottomRight.hasBorderRadius() ||
450            bottomLeft.hasBorderRadius() || topLeft.hasBorderRadius();
451 }
452 
StyleCSS3NonInheritedData()453 StyleCSS3NonInheritedData::StyleCSS3NonInheritedData()
454     : Shared<StyleCSS3NonInheritedData>()
455     , opacity(RenderStyle::initialOpacity())
456 {
457 }
458 
StyleCSS3NonInheritedData(const StyleCSS3NonInheritedData & o)459 StyleCSS3NonInheritedData::StyleCSS3NonInheritedData(const StyleCSS3NonInheritedData &o)
460     : Shared<StyleCSS3NonInheritedData>(),
461       opacity(o.opacity),
462 #ifdef APPLE_CHANGES
463       flexibleBox(o.flexibleBox),
464 #endif
465       marquee(o.marquee),
466       borderRadius(o.borderRadius)
467 {
468 }
469 
operator ==(const StyleCSS3NonInheritedData & o) const470 bool StyleCSS3NonInheritedData::operator==(const StyleCSS3NonInheritedData &o) const
471 {
472     return
473         opacity == o.opacity &&
474 #ifdef APPLE_CHANGES
475         flexibleBox == o.flexibleBox &&
476 #endif
477         marquee == o.marquee &&
478         borderRadius == o.borderRadius;
479 }
480 
StyleCSS3InheritedData()481 StyleCSS3InheritedData::StyleCSS3InheritedData()
482     : Shared<StyleCSS3InheritedData>(), textShadow(nullptr), wordWrap(RenderStyle::initialWordWrap())
483 #ifdef APPLE_CHANGES
484     , userModify(READ_ONLY), textSizeAdjust(RenderStyle::initialTextSizeAdjust())
485 #endif
486 {
487 
488 }
489 
StyleCSS3InheritedData(const StyleCSS3InheritedData & o)490 StyleCSS3InheritedData::StyleCSS3InheritedData(const StyleCSS3InheritedData &o)
491     : Shared<StyleCSS3InheritedData>()
492 {
493     textShadow = o.textShadow ? new ShadowData(*o.textShadow) : nullptr;
494     wordWrap = o.wordWrap;
495 #ifdef APPLE_CHANGES
496     userModify = o.userModify;
497     textSizeAdjust = o.textSizeAdjust;
498 #endif
499 }
500 
~StyleCSS3InheritedData()501 StyleCSS3InheritedData::~StyleCSS3InheritedData()
502 {
503     delete textShadow;
504 }
505 
operator ==(const StyleCSS3InheritedData & o) const506 bool StyleCSS3InheritedData::operator==(const StyleCSS3InheritedData &o) const
507 {
508     return shadowDataEquivalent(o) && (wordWrap == o.wordWrap)
509 #ifdef APPLE_CHANGES
510            && (userModify == o.userModify) && (textSizeAdjust == o.textSizeAdjust)
511 #endif
512            ;
513 }
514 
shadowDataEquivalent(const StyleCSS3InheritedData & o) const515 bool StyleCSS3InheritedData::shadowDataEquivalent(const StyleCSS3InheritedData &o) const
516 {
517     if ((!textShadow && o.textShadow) || (textShadow && !o.textShadow)) {
518         return false;
519     }
520     if ((textShadow && o.textShadow) && (*textShadow != *o.textShadow)) {
521         return false;
522     }
523     return true;
524 }
525 
StyleInheritedData()526 StyleInheritedData::StyleInheritedData()
527     : indent(RenderStyle::initialTextIndent()), line_height(RenderStyle::initialLineHeight()),
528       style_image(RenderStyle::initialListStyleImage()),
529       font(), color(RenderStyle::initialColor()),
530       border_hspacing(RenderStyle::initialBorderHorizontalSpacing()),
531       border_vspacing(RenderStyle::initialBorderVerticalSpacing()),
532       widows(RenderStyle::initialWidows()), orphans(RenderStyle::initialOrphans()),
533       quotes(nullptr)
534 {
535 }
536 
~StyleInheritedData()537 StyleInheritedData::~StyleInheritedData()
538 {
539     if (quotes) {
540         quotes->deref();
541     }
542 }
543 
StyleInheritedData(const StyleInheritedData & o)544 StyleInheritedData::StyleInheritedData(const StyleInheritedData &o)
545     : Shared<StyleInheritedData>(),
546       indent(o.indent), line_height(o.line_height), style_image(o.style_image),
547       font(o.font), color(o.color),
548       border_hspacing(o.border_hspacing),
549       border_vspacing(o.border_vspacing),
550       widows(o.widows), orphans(o.orphans)
551 {
552     quotes = o.quotes;
553     if (quotes) {
554         quotes->ref();
555     }
556 }
557 
operator ==(const StyleInheritedData & o) const558 bool StyleInheritedData::operator==(const StyleInheritedData &o) const
559 {
560     return
561         indent == o.indent &&
562         line_height == o.line_height &&
563         border_hspacing == o.border_hspacing &&
564         border_vspacing == o.border_vspacing &&
565         style_image == o.style_image &&
566         font == o.font &&
567         color == o.color &&
568         border_hspacing == o.border_hspacing &&
569         border_vspacing == o.border_vspacing &&
570         quotes == o.quotes &&
571         widows == o.widows &&
572         orphans == o.orphans;
573 
574     // doesn't work because structs are not packed
575     //return memcmp(this, &o, sizeof(*this))==0;
576 }
577 
RenderStyle()578 RenderStyle::RenderStyle()
579 {
580 //    counter++;
581     if (!_default) {
582         _default = new RenderStyle(true);
583     }
584 
585     box = _default->box;
586     visual = _default->visual;
587     background = _default->background;
588     surround = _default->surround;
589     generated = _default->generated;
590     css3NonInheritedData = _default->css3NonInheritedData;
591     css3InheritedData = _default->css3InheritedData;
592 
593     inherited = _default->inherited;
594 
595     m_svgStyle = _default->m_svgStyle;
596 
597     setBitDefaults();
598 
599     pseudoStyle = nullptr;
600 }
601 
RenderStyle(bool)602 RenderStyle::RenderStyle(bool)
603 {
604     // Let the font cache create its initial value.
605     // We need this because attach can call styleForElement
606     // for things with display:none parents, and then we need to be
607     // able to provide some sort of fallback font data to operate on.
608     Font::initDefault();
609 
610     setBitDefaults();
611 
612     box.init();
613     visual.init();
614     background.init();
615     surround.init();
616     generated.init();
617     css3NonInheritedData.init();
618 #ifdef APPLE_CHANGES    // ### yet to be merged
619     css3NonInheritedData.access()->flexibleBox.init();
620 #endif
621     css3NonInheritedData.access()->marquee.init();
622     css3NonInheritedData.access()->borderRadius.init();
623     css3InheritedData.init();
624     inherited.init();
625 
626     m_svgStyle.init();
627 
628     pseudoStyle = nullptr;
629 }
630 
RenderStyle(const RenderStyle & o)631 RenderStyle::RenderStyle(const RenderStyle &o)
632     : Shared<RenderStyle>(),
633       inherited_flags(o.inherited_flags), noninherited_flags(o.noninherited_flags),
634       box(o.box), visual(o.visual), background(o.background), surround(o.surround), generated(o.generated),
635       css3NonInheritedData(o.css3NonInheritedData), css3InheritedData(o.css3InheritedData),
636       inherited(o.inherited), pseudoStyle(nullptr), m_svgStyle(o.m_svgStyle)
637 {}
638 
inheritFrom(const RenderStyle * inheritParent)639 void RenderStyle::inheritFrom(const RenderStyle *inheritParent)
640 {
641     css3InheritedData = inheritParent->css3InheritedData;
642     inherited = inheritParent->inherited;
643     inherited_flags = inheritParent->inherited_flags;
644 
645     // SVG
646     if (m_svgStyle != inheritParent->m_svgStyle) {
647         m_svgStyle.access()->inheritFrom(inheritParent->m_svgStyle.get());
648     }
649 
650     // Simulate ":after,:before { white-space: pre-line }"
651     if (styleType() == AFTER || styleType() == BEFORE) {
652         setWhiteSpace(PRE_LINE);
653     }
654 }
655 
compactWith(const RenderStyle * similarStyle)656 void RenderStyle::compactWith(const RenderStyle *similarStyle)
657 {
658     if (this == similarStyle) {
659         return;
660     }
661 
662     if (box.get() != similarStyle->box.get() && box == similarStyle->box) {
663         box = similarStyle->box;
664     }
665     if (visual.get() != similarStyle->visual.get() && visual == similarStyle->visual) {
666         visual = similarStyle->visual;
667     }
668     if (background.get() != similarStyle->background.get() && background == similarStyle->background) {
669         background = similarStyle->background;
670     }
671     if (surround.get() != similarStyle->surround.get() && surround == similarStyle->surround) {
672         surround = similarStyle->surround;
673     }
674     if (generated.get() != similarStyle->generated.get() && generated == similarStyle->generated) {
675         generated = similarStyle->generated;
676     }
677     if (css3NonInheritedData.get() != similarStyle->css3NonInheritedData.get() && css3NonInheritedData == similarStyle->css3NonInheritedData) {
678         css3NonInheritedData = similarStyle->css3NonInheritedData;
679     }
680     if (css3InheritedData.get() != similarStyle->css3InheritedData.get() && css3InheritedData == similarStyle->css3InheritedData) {
681         css3InheritedData = similarStyle->css3InheritedData;
682     }
683     if (inherited.get() != similarStyle->inherited.get() && inherited == similarStyle->inherited) {
684         inherited = similarStyle->inherited;
685     }
686 }
687 
~RenderStyle()688 RenderStyle::~RenderStyle()
689 {
690     RenderStyle *ps = pseudoStyle;
691     RenderStyle *prev = nullptr;
692 
693     while (ps) {
694         prev = ps;
695         ps = ps->pseudoStyle;
696         // to prevent a double deletion.
697         // this works only because the styles below aren't really shared
698         // Dirk said we need another construct as soon as these are shared
699         prev->pseudoStyle = nullptr;
700         prev->deref();
701     }
702 }
703 
operator ==(const RenderStyle & o) const704 bool RenderStyle::operator==(const RenderStyle &o) const
705 {
706 // compare everything except the pseudoStyle pointer
707     return (inherited_flags == o.inherited_flags &&
708             noninherited_flags == o.noninherited_flags &&
709             box == o.box &&
710             visual == o.visual &&
711             background == o.background &&
712             surround == o.surround &&
713             generated == o.generated &&
714             css3NonInheritedData == o.css3NonInheritedData &&
715             css3InheritedData == o.css3InheritedData &&
716             inherited == o.inherited &&
717             m_svgStyle == o.m_svgStyle); // SVG
718 }
719 
720 enum EPseudoBit { NO_BIT = 0x0,
721                   FIRST_LINE_BIT = 0x1, FIRST_LETTER_BIT = 0x2, SELECTION_BIT = 0x4,
722                   BEFORE_BIT = 0x8, AFTER_BIT = 0x10, MARKER_BIT = 0x20,
723                   REPLACED_BIT = 0x40
724                 };
725 
pseudoBit(RenderStyle::PseudoId pseudo)726 static int pseudoBit(RenderStyle::PseudoId pseudo)
727 {
728     switch (pseudo) {
729     case RenderStyle::BEFORE:
730         return BEFORE_BIT;
731     case RenderStyle::AFTER:
732         return AFTER_BIT;
733     case RenderStyle::MARKER:
734         return MARKER_BIT;
735     case RenderStyle::REPLACED:
736         return REPLACED_BIT;
737     case RenderStyle::FIRST_LINE:
738         return FIRST_LINE_BIT;
739     case RenderStyle::FIRST_LETTER:
740         return FIRST_LETTER_BIT;
741     case RenderStyle::SELECTION:
742         return SELECTION_BIT;
743     default:
744         return NO_BIT;
745     }
746 }
747 
hasPseudoStyle(PseudoId pseudo) const748 bool RenderStyle::hasPseudoStyle(PseudoId pseudo) const
749 {
750     return (pseudoBit(pseudo) & noninherited_flags.f._pseudoBits) != 0;
751 }
752 
setHasPseudoStyle(PseudoId pseudo,bool b)753 void RenderStyle::setHasPseudoStyle(PseudoId pseudo, bool b)
754 {
755     if (b) {
756         noninherited_flags.f._pseudoBits |= pseudoBit(pseudo);
757     } else {
758         noninherited_flags.f._pseudoBits &= ~(pseudoBit(pseudo));
759     }
760 }
761 
getPseudoStyle(PseudoId pid) const762 RenderStyle *RenderStyle::getPseudoStyle(PseudoId pid) const
763 {
764     if (!hasPseudoStyle(pid)) {
765         return nullptr;
766     }
767 
768     RenderStyle *ps = nullptr;
769     if (noninherited_flags.f._styleType == NOPSEUDO)
770         for (ps = pseudoStyle; ps; ps = ps->pseudoStyle)
771             if (ps->noninherited_flags.f._styleType == pid) {
772                 break;
773             }
774     return ps;
775 }
776 
addPseudoStyle(PseudoId pid)777 RenderStyle *RenderStyle::addPseudoStyle(PseudoId pid)
778 {
779     if (hasPseudoStyle(pid)) {
780         return getPseudoStyle(pid);
781     }
782 
783     RenderStyle *ps = nullptr;
784 
785     switch (pid) {
786     case FIRST_LETTER:             // pseudo-elements (FIRST_LINE has a special handling)
787     case SELECTION:
788     case BEFORE:
789     case AFTER:
790         ps = new RenderStyle();
791         break;
792     default:
793         ps = new RenderStyle(*this); // use the real copy constructor to get an identical copy
794     }
795     ps->ref();
796     ps->noninherited_flags.f._styleType = pid;
797     ps->pseudoStyle = pseudoStyle;
798 
799     pseudoStyle = ps;
800 
801     setHasPseudoStyle(pid, true);
802 
803     return ps;
804 }
805 
removePseudoStyle(PseudoId pid)806 void RenderStyle::removePseudoStyle(PseudoId pid)
807 {
808     RenderStyle *ps = pseudoStyle;
809     RenderStyle *prev = this;
810 
811     while (ps) {
812         if (ps->noninherited_flags.f._styleType == pid) {
813             prev->pseudoStyle = ps->pseudoStyle;
814             ps->deref();
815             return;
816         }
817         prev = ps;
818         ps = ps->pseudoStyle;
819     }
820 
821     setHasPseudoStyle(pid, false);
822 }
823 
inheritedNotEqual(RenderStyle * other) const824 bool RenderStyle::inheritedNotEqual(RenderStyle *other) const
825 {
826     return
827         (
828             inherited_flags != other->inherited_flags ||
829             inherited != other->inherited ||
830             css3InheritedData != other->css3InheritedData ||
831             m_svgStyle->inheritedNotEqual(other->m_svgStyle.get())
832         );
833 }
834 
835 /*
836   compares two styles. The result gives an idea of the action that
837   needs to be taken when replacing the old style with a new one.
838 
839   CbLayout: The containing block of the object needs a relayout.
840   Layout: the RenderObject needs a relayout after the style change
841   Visible: The change is visible, but no relayout is needed
842   NonVisible: The object does need neither repaint nor relayout after
843        the change.
844 
845   ### TODO:
846   A lot can be optimised here based on the display type, lots of
847   optimizations are unimplemented, and currently result in the
848   worst case result causing a relayout of the containing block.
849 */
diff(const RenderStyle * other) const850 RenderStyle::Diff RenderStyle::diff(const RenderStyle *other) const
851 {
852     if (m_svgStyle != other->m_svgStyle) {
853         return Layout;
854     }
855     // we anyway assume they are the same
856 //  EDisplay _display : 5;
857 
858     // NonVisible:
859 //  ECursor _cursor_style : 4;
860 //  EUserInput _user_input : 2; as long as :enabled is not impl'd
861 
862 // ### this needs work to know more exactly if we need a relayout
863 //     or just a repaint
864 
865 // non-inherited attributes
866 //     DataRef<StyleBoxData> box;
867 //     DataRef<StyleVisualData> visual;
868 //     DataRef<StyleSurroundData> surround;
869 
870 // inherited attributes
871 //     DataRef<StyleInheritedData> inherited;
872 
873     if (*box.get() != *other->box.get() ||
874             *visual.get() != *other->visual.get() ||
875             (*surround.get() != *other->surround.get()
876              && (other->position() == PSTATIC || other->position() != position())) ||
877             !(inherited->indent == other->inherited->indent) ||
878             !(inherited->line_height == other->inherited->line_height) ||
879             !(inherited->style_image == other->inherited->style_image) ||
880             !(inherited->font == other->inherited->font) ||
881             !(inherited->border_hspacing == other->inherited->border_hspacing) ||
882             !(inherited->border_vspacing == other->inherited->border_vspacing) ||
883             !(inherited_flags.f._visuallyOrdered == other->inherited_flags.f._visuallyOrdered) ||
884             !(inherited_flags.f._htmlHacks == other->inherited_flags.f._htmlHacks) ||
885             !(noninherited_flags.f._textOverflow == other->noninherited_flags.f._textOverflow)) {
886         return CbLayout;
887     }
888 
889     // changes causing Layout changes:
890 
891 // only for tables:
892 //  _border_collapse
893 //  EEmptyCell _empty_cells : 2 ;
894 //  ECaptionSide _caption_side : 2;
895 //     ETableLayout _table_layout : 1;
896 //     EPosition _position : 2;
897 //     EFloat _floating : 2;
898     if (((int)noninherited_flags.f._display) >= TABLE) {
899         if (!(inherited_flags.f._empty_cells == other->inherited_flags.f._empty_cells) ||
900                 !(inherited_flags.f._caption_side == other->inherited_flags.f._caption_side) ||
901                 !(inherited_flags.f._border_collapse == other->inherited_flags.f._border_collapse) ||
902                 !(noninherited_flags.f._table_layout == other->noninherited_flags.f._table_layout) ||
903                 !(noninherited_flags.f._position == other->noninherited_flags.f._position) ||
904                 !(noninherited_flags.f._floating == other->noninherited_flags.f._floating) ||
905                 !(noninherited_flags.f._flowAroundFloats == other->noninherited_flags.f._flowAroundFloats) ||
906                 !(noninherited_flags.f._unicodeBidi == other->noninherited_flags.f._unicodeBidi)) {
907             return CbLayout;
908         }
909     }
910 
911 // only for lists:
912 //  EListStyleType _list_style_type : 5 ;
913 //  EListStylePosition _list_style_position :1;
914     if (noninherited_flags.f._display == LIST_ITEM) {
915         if (!(inherited_flags.f._list_style_type == other->inherited_flags.f._list_style_type) ||
916                 !(inherited_flags.f._list_style_position == other->inherited_flags.f._list_style_position)) {
917             return Layout;
918         }
919     }
920 
921 // ### These could be better optimised
922 //  ETextAlign _text_align : 3;
923 //  ETextTransform _text_transform : 4;
924 //  EDirection _direction : 1;
925 //  EWhiteSpace _white_space : 2;
926 //     EClear _clear : 2;
927     if (!(inherited_flags.f._text_align == other->inherited_flags.f._text_align) ||
928             !(inherited_flags.f._text_transform == other->inherited_flags.f._text_transform) ||
929             !(inherited_flags.f._direction == other->inherited_flags.f._direction) ||
930             !(inherited_flags.f._white_space == other->inherited_flags.f._white_space) ||
931             !(noninherited_flags.f._clear == other->noninherited_flags.f._clear)
932        ) {
933         return Layout;
934     }
935 
936     // Overflow returns a layout hint.
937     if (noninherited_flags.f._overflowX != other->noninherited_flags.f._overflowX ||
938             noninherited_flags.f._overflowY != other->noninherited_flags.f._overflowY) {
939         return Layout;
940     }
941 
942 // only for inline:
943 //     EVerticalAlign _vertical_align : 4;
944 
945     if (!(noninherited_flags.f._display == INLINE) &&
946             !(noninherited_flags.f._vertical_align == other->noninherited_flags.f._vertical_align)) {
947         return Layout;
948     }
949 
950     if (*surround.get() != *other->surround.get()) {
951         assert(other->position() != PSTATIC);                        // this style is positioned or relatively positioned
952         if (surround->hasSamePBMData(*other->surround.get()) &&     // padding/border/margin are identical
953                 (other->position() == PRELATIVE ||
954                  (!(other->left().isAuto() && other->right().isAuto()) &&  // X isn't static
955                   !(other->top().isAuto() && other->bottom().isAuto()))))    // neither is Y
956             // therefore only the offset is different
957         {
958             return Position;
959         }
960         return Layout;
961     }
962 
963     // Visible:
964 //  EVisibility _visibility : 2;
965 //  int _text_decorations : 4;
966 //     DataRef<StyleBackgroundData> background;
967     if (inherited->color != other->inherited->color ||
968             !(inherited_flags.f._visibility == other->inherited_flags.f._visibility) ||
969             !(inherited_flags.f._text_decorations == other->inherited_flags.f._text_decorations) ||
970             !(noninherited_flags.f._hasClip == other->noninherited_flags.f._hasClip) ||
971             visual->textDecoration != other->visual->textDecoration ||
972             *background.get() != *other->background.get() ||
973             css3NonInheritedData->opacity != other->css3NonInheritedData->opacity ||
974             !css3InheritedData->shadowDataEquivalent(*other->css3InheritedData.get())
975        ) {
976         return Visible;
977     }
978 
979     RenderStyle::Diff ch = Equal;
980     // Check for visible pseudo-changes:
981     if (hasPseudoStyle(FIRST_LINE) != other->hasPseudoStyle(FIRST_LINE)) {
982         ch = Visible;
983     } else if (hasPseudoStyle(FIRST_LINE) && other->hasPseudoStyle(FIRST_LINE)) {
984         ch = getPseudoStyle(FIRST_LINE)->diff(other->getPseudoStyle(FIRST_LINE));
985     }
986 
987     if (ch != Equal) {
988         return ch;
989     }
990 
991     // Check for visible pseudo-changes:
992     if (hasPseudoStyle(SELECTION) != other->hasPseudoStyle(SELECTION)) {
993         ch = Visible;
994     } else if (hasPseudoStyle(SELECTION) && other->hasPseudoStyle(SELECTION)) {
995         ch = getPseudoStyle(SELECTION)->diff(other->getPseudoStyle(SELECTION));
996     }
997 
998     return ch;
999 }
1000 
1001 RenderStyle *RenderStyle::_default = nullptr;
1002 
cleanup()1003 void RenderStyle::cleanup()
1004 {
1005     delete _default;
1006     _default = nullptr;
1007 }
1008 
setPaletteColor(QPalette::ColorGroup g,QPalette::ColorRole r,const QColor & c)1009 void RenderStyle::setPaletteColor(QPalette::ColorGroup g, QPalette::ColorRole r, const QColor &c)
1010 {
1011     visual.access()->palette.setColor(g, r, c);
1012 }
1013 
adjustBackgroundLayers()1014 void RenderStyle::adjustBackgroundLayers()
1015 {
1016     // https://www.w3.org/TR/css3-background/#layering
1017     if (backgroundLayers()->next()) {
1018         // First we cull out backgroundLayers that have no image property set.
1019         accessBackgroundLayers()->cullEmptyLayers();
1020 
1021         // Next we repeat patterns into layers that don't have some properties set.
1022         accessBackgroundLayers()->fillUnsetProperties();
1023     }
1024 }
1025 
setClip(Length top,Length right,Length bottom,Length left)1026 void RenderStyle::setClip(Length top, Length right, Length bottom, Length left)
1027 {
1028     StyleVisualData *data = visual.access();
1029     data->clip.top = top;
1030     data->clip.right = right;
1031     data->clip.bottom = bottom;
1032     data->clip.left = left;
1033 }
1034 
setQuotes(DOM::QuotesValueImpl * q)1035 void RenderStyle::setQuotes(DOM::QuotesValueImpl *q)
1036 {
1037     DOM::QuotesValueImpl *t = inherited->quotes;
1038     inherited.access()->quotes = q;
1039     if (q) {
1040         q->ref();
1041     }
1042     if (t) {
1043         t->deref();
1044     }
1045 }
1046 
openQuote(int level) const1047 QString RenderStyle::openQuote(int level) const
1048 {
1049     if (inherited->quotes) {
1050         return inherited->quotes->openQuote(level);
1051     } else if (level > 1) {
1052         return "'";
1053     } else {
1054         return "\"";    // 0 is default quotes
1055     }
1056 }
1057 
closeQuote(int level) const1058 QString RenderStyle::closeQuote(int level) const
1059 {
1060     if (inherited->quotes) {
1061         return inherited->quotes->closeQuote(level);
1062     } else if (level) {
1063         return "'";
1064     } else {
1065         return "\"";    // 0 is default quotes
1066     }
1067 }
1068 
addContent(CachedObject * o)1069 void RenderStyle::addContent(CachedObject *o)
1070 {
1071     if (!o) {
1072         return;    // The object is null. Nothing to do. Just bail.
1073     }
1074 
1075     StyleGeneratedData *t_generated = generated.access();
1076 
1077     ContentData *lastContent = t_generated->content;
1078     while (lastContent && lastContent->_nextContent) {
1079         lastContent = lastContent->_nextContent;
1080     }
1081 
1082     ContentData *newContentData = new ContentData;
1083 
1084     if (lastContent) {
1085         lastContent->_nextContent = newContentData;
1086     } else {
1087         t_generated->content = newContentData;
1088     }
1089 
1090     //    o->ref();
1091     newContentData->_content.object = o;
1092     newContentData->_contentType = CONTENT_OBJECT;
1093 }
1094 
addContent(DOM::DOMStringImpl * s)1095 void RenderStyle::addContent(DOM::DOMStringImpl *s)
1096 {
1097     if (!s) {
1098         return;    // The string is null. Nothing to do. Just bail.
1099     }
1100 
1101     StyleGeneratedData *t_generated = generated.access();
1102 
1103     ContentData *lastContent = t_generated->content;
1104     while (lastContent && lastContent->_nextContent) {
1105         lastContent = lastContent->_nextContent;
1106     }
1107 
1108     if (lastContent) {
1109         if (lastContent->_contentType == CONTENT_TEXT) {
1110             // We can augment the existing string and share this ContentData node.
1111             DOMStringImpl *oldStr = lastContent->_content.text;
1112             DOMStringImpl *newStr = oldStr->copy();
1113             newStr->ref();
1114             oldStr->deref();
1115             newStr->append(s);
1116             lastContent->_content.text = newStr;
1117             return;
1118         }
1119     }
1120 
1121     ContentData *newContentData = new ContentData;
1122 
1123     if (lastContent) {
1124         lastContent->_nextContent = newContentData;
1125     } else {
1126         t_generated->content = newContentData;
1127     }
1128 
1129     newContentData->_content.text = s;
1130     newContentData->_content.text->ref();
1131     newContentData->_contentType = CONTENT_TEXT;
1132 
1133 }
1134 
addContent(DOM::CounterImpl * c)1135 void RenderStyle::addContent(DOM::CounterImpl *c)
1136 {
1137     if (!c) {
1138         return;
1139     }
1140 
1141     StyleGeneratedData *t_generated = generated.access();
1142 
1143     ContentData *lastContent = t_generated->content;
1144     while (lastContent && lastContent->_nextContent) {
1145         lastContent = lastContent->_nextContent;
1146     }
1147 
1148     ContentData *newContentData = new ContentData;
1149 
1150     if (lastContent) {
1151         lastContent->_nextContent = newContentData;
1152     } else {
1153         t_generated->content = newContentData;
1154     }
1155 
1156     c->ref();
1157     newContentData->_content.counter = c;
1158     newContentData->_contentType = CONTENT_COUNTER;
1159 }
1160 
addContent(EQuoteContent q)1161 void RenderStyle::addContent(EQuoteContent q)
1162 {
1163     if (q == NO_QUOTE) {
1164         return;
1165     }
1166 
1167     StyleGeneratedData *t_generated = generated.access();
1168 
1169     ContentData *lastContent = t_generated->content;
1170     while (lastContent && lastContent->_nextContent) {
1171         lastContent = lastContent->_nextContent;
1172     }
1173 
1174     ContentData *newContentData = new ContentData;
1175 
1176     if (lastContent) {
1177         lastContent->_nextContent = newContentData;
1178     } else {
1179         t_generated->content = newContentData;
1180     }
1181 
1182     newContentData->_content.quote = q;
1183     newContentData->_contentType = CONTENT_QUOTE;
1184 }
1185 
1186 // content: normal is the same as having no content at all
setContentNormal()1187 void RenderStyle::setContentNormal()
1188 {
1189     if (generated->content != nullptr) {
1190         delete generated->content;
1191         generated.access()->content = nullptr;
1192     }
1193 }
1194 
1195 // content: none, add an empty content node
setContentNone()1196 void RenderStyle::setContentNone()
1197 {
1198     setContentNormal();
1199     generated.access()->content = new ContentData;
1200 }
1201 
setContentData(ContentData * data)1202 void RenderStyle::setContentData(ContentData *data)
1203 {
1204     if (data != generated->content) {
1205         if (data) {
1206             generated.access()->content = new ContentData(*data);
1207         } else {
1208             generated.access()->content = nullptr;
1209         }
1210     }
1211 }
1212 
ContentData(const ContentData & o)1213 ContentData::ContentData(const ContentData &o) : _contentType(o._contentType)
1214 {
1215     switch (_contentType) {
1216     case CONTENT_OBJECT:
1217         _content.object = o._content.object;
1218         break;
1219     case CONTENT_TEXT:
1220         _content.text = o._content.text;
1221         _content.text->ref();
1222         break;
1223     case CONTENT_COUNTER:
1224         _content.counter = o._content.counter;
1225         _content.counter->ref();
1226         break;
1227     case CONTENT_QUOTE:
1228         _content.quote = o._content.quote;
1229         break;
1230     case CONTENT_NONE:
1231     default:
1232         break;
1233     }
1234 
1235     _nextContent = o._nextContent ? new ContentData(*o._nextContent) : nullptr;
1236 }
1237 
~ContentData()1238 ContentData::~ContentData()
1239 {
1240     clearContent();
1241 }
1242 
clearContent()1243 void ContentData::clearContent()
1244 {
1245     delete _nextContent;
1246     _nextContent = nullptr;
1247 
1248     switch (_contentType) {
1249     case CONTENT_OBJECT:
1250         _content.object = nullptr;
1251         break;
1252     case CONTENT_TEXT:
1253         _content.text->deref();
1254         _content.text = nullptr;
1255         break;
1256     case CONTENT_COUNTER:
1257         _content.counter->deref();
1258         _content.counter = nullptr;
1259         break;
1260     case CONTENT_QUOTE:
1261         _content.quote = NO_QUOTE;
1262         break;
1263     default:
1264         ;
1265     }
1266 }
1267 
setTextShadow(ShadowData * val,bool add)1268 void RenderStyle::setTextShadow(ShadowData *val, bool add)
1269 {
1270     StyleCSS3InheritedData *css3Data = css3InheritedData.access();
1271     if (!add) {
1272         delete css3Data->textShadow;
1273         css3Data->textShadow = val;
1274         return;
1275     }
1276 
1277     ShadowData *last = css3Data->textShadow;
1278     while (last->next) {
1279         last = last->next;
1280     }
1281     last->next = val;
1282 }
1283 
ShadowData(const ShadowData & o)1284 ShadowData::ShadowData(const ShadowData &o)
1285     : x(o.x), y(o.y), blur(o.blur), color(o.color)
1286 {
1287     next = o.next ? new ShadowData(*o.next) : nullptr;
1288 }
1289 
operator ==(const ShadowData & o) const1290 bool ShadowData::operator==(const ShadowData &o) const
1291 {
1292     if ((next && !o.next) || (!next && o.next) ||
1293             (next && o.next && *next != *o.next)) {
1294         return false;
1295     }
1296 
1297     return x == o.x && y == o.y && blur == o.blur && color == o.color;
1298 }
1299 
hasCounter(const DOM::DOMString & c,CSSValueListImpl * l)1300 static bool hasCounter(const DOM::DOMString &c, CSSValueListImpl *l)
1301 {
1302     int len = l->length();
1303     for (int i = 0; i < len; i++) {
1304         CounterActImpl *ca = static_cast<CounterActImpl *>(l->item(i));
1305         Q_ASSERT(ca != nullptr);
1306         if (ca->m_counter == c) {
1307             return true;
1308         }
1309     }
1310     return false;
1311 }
1312 
hasCounterReset(const DOM::DOMString & c) const1313 bool RenderStyle::hasCounterReset(const DOM::DOMString &c) const
1314 {
1315     if (generated->counter_reset) {
1316         return hasCounter(c, generated->counter_reset);
1317     } else {
1318         return false;
1319     }
1320 }
1321 
hasCounterIncrement(const DOM::DOMString & c) const1322 bool RenderStyle::hasCounterIncrement(const DOM::DOMString &c) const
1323 {
1324     if (generated->counter_increment) {
1325         return hasCounter(c, generated->counter_increment);
1326     } else {
1327         return false;
1328     }
1329 }
1330 
counterReset(const DOM::DOMString & c) const1331 short RenderStyle::counterReset(const DOM::DOMString &c) const
1332 {
1333     if (generated->counter_reset) {
1334         int len = generated->counter_reset->length();
1335         int value = 0;
1336         // Return the last matching counter-reset
1337         for (int i = 0; i < len; i++) {
1338             CounterActImpl *ca = static_cast<CounterActImpl *>(generated->counter_reset->item(i));
1339             Q_ASSERT(ca != nullptr);
1340             if (ca->m_counter == c) {
1341                 value = ca->m_value;
1342             }
1343         }
1344         return value;
1345     } else {
1346         return 0;
1347     }
1348 }
1349 
counterIncrement(const DOM::DOMString & c) const1350 short RenderStyle::counterIncrement(const DOM::DOMString &c) const
1351 {
1352     if (generated->counter_increment) {
1353         int len = generated->counter_increment->length();
1354         int value = 0;
1355         // Return the sum of matching counter-increments
1356         for (int i = 0; i < len; i++) {
1357             CounterActImpl *ca = static_cast<CounterActImpl *>(generated->counter_increment->item(i));
1358             Q_ASSERT(ca != nullptr);
1359             if (ca->m_counter == c) {
1360                 value += ca->m_value;
1361             }
1362         }
1363         return value;
1364     } else {
1365         return 0;
1366     }
1367 }
1368 
setCounterReset(CSSValueListImpl * l)1369 void RenderStyle::setCounterReset(CSSValueListImpl *l)
1370 {
1371     CSSValueListImpl *t = generated->counter_reset;
1372     generated.access()->counter_reset = l;
1373     if (l) {
1374         l->ref();
1375     }
1376     if (t) {
1377         t->deref();
1378     }
1379 }
1380 
setCounterIncrement(CSSValueListImpl * l)1381 void RenderStyle::setCounterIncrement(CSSValueListImpl *l)
1382 {
1383     CSSValueListImpl *t = generated->counter_increment;
1384     generated.access()->counter_increment = l;
1385     if (l) {
1386         l->ref();
1387     }
1388     if (t) {
1389         t->deref();
1390     }
1391 }
1392 
1393 #ifdef ENABLE_DUMP
1394 
describeFont(const QFont & f)1395 static QString describeFont(const QFont &f)
1396 {
1397     QString res = '\'' + f.family() + "' ";
1398 
1399     if (f.pointSize() > 0) {
1400         res += QString::number(f.pointSize()) + "pt";
1401     } else {
1402         res += QString::number(f.pixelSize()) + "px";
1403     }
1404 
1405     if (f.bold()) {
1406         res += " bold";
1407     }
1408     if (f.italic()) {
1409         res += " italic";
1410     }
1411     if (f.underline()) {
1412         res += " underline";
1413     }
1414     if (f.overline()) {
1415         res += " overline";
1416     }
1417     if (f.strikeOut()) {
1418         res += " strikeout";
1419     }
1420     return res;
1421 }
1422 
createDiff(const RenderStyle & parent) const1423 QString RenderStyle::createDiff(const RenderStyle &parent) const
1424 {
1425     QString res;
1426     if (color().isValid() && parent.color() != color()) {
1427         res += " [color=" + color().name() + ']';
1428     }
1429     if (backgroundColor().isValid() && parent.backgroundColor() != backgroundColor()) {
1430         res += " [bgcolor=" + backgroundColor().name() + ']';
1431     }
1432     if (parent.font() != font()) {
1433         res += " [font=" + describeFont(font()) + ']';
1434     }
1435 
1436     return res;
1437 }
1438 #endif
1439 
RenderPageStyle()1440 RenderPageStyle::RenderPageStyle() : next(nullptr), m_pageType(ANY_PAGE)
1441 {
1442 }
1443 
~RenderPageStyle()1444 RenderPageStyle::~RenderPageStyle()
1445 {
1446     delete next;
1447 }
1448 
getPageStyle(PageType type)1449 RenderPageStyle *RenderPageStyle::getPageStyle(PageType type)
1450 {
1451     RenderPageStyle *ps = nullptr;
1452     for (ps = this; ps; ps = ps->next)
1453         if (ps->m_pageType == type) {
1454             break;
1455         }
1456     return ps;
1457 }
1458 
addPageStyle(PageType type)1459 RenderPageStyle *RenderPageStyle::addPageStyle(PageType type)
1460 {
1461     RenderPageStyle *ps = getPageStyle(type);
1462 
1463     if (!ps) {
1464         ps = new RenderPageStyle(*this); // use the real copy constructor to get an identical copy
1465         ps->m_pageType = type;
1466 
1467         ps->next = next;
1468         next = ps;
1469     }
1470 
1471     return ps;
1472 }
1473 
removePageStyle(PageType type)1474 void RenderPageStyle::removePageStyle(PageType type)
1475 {
1476     RenderPageStyle *ps = next;
1477     RenderPageStyle *prev = this;
1478 
1479     while (ps) {
1480         if (ps->m_pageType == type) {
1481             prev->next = ps->next;
1482             delete ps;
1483             return;
1484         }
1485         prev = ps;
1486         ps = ps->next;
1487     }
1488 }
1489