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