File indexing completed on 2024-04-28 15:24:11

0001 /*
0002  * This file is part of the DOM implementation for KDE.
0003  *
0004  * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
0005  * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
0006  * Copyright (C) 2002-2003 Dirk Mueller (mueller@kde.org)
0007  * Copyright (C) 2002-2005 Apple Computer, Inc.
0008  * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
0009  *
0010  * This library is free software; you can redistribute it and/or
0011  * modify it under the terms of the GNU Library General Public
0012  * License as published by the Free Software Foundation; either
0013  * version 2 of the License, or (at your option) any later version.
0014  *
0015  * This library is distributed in the hope that it will be useful,
0016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0018  * Library General Public License for more details.
0019  *
0020  * You should have received a copy of the GNU Library General Public License
0021  * along with this library; see the file COPYING.LIB.  If not, write to
0022  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0023  * Boston, MA 02110-1301, USA.
0024  *
0025  */
0026 
0027 #include "render_style.h"
0028 
0029 #include <xml/dom_stringimpl.h>
0030 #include <css/cssstyleselector.h>
0031 #include <css/css_valueimpl.h>
0032 
0033 using namespace khtml;
0034 using namespace DOM;
0035 
0036 /* CSS says Fixed for the default padding value, but we treat variable as 0 padding anyways, and like
0037  * this is works fine for table paddings aswell
0038  */
0039 StyleSurroundData::StyleSurroundData()
0040     : margin(Fixed), padding(Auto)
0041 {
0042 }
0043 
0044 StyleSurroundData::StyleSurroundData(const StyleSurroundData &o)
0045     : Shared<StyleSurroundData>(),
0046       offset(o.offset), margin(o.margin), padding(o.padding),
0047       border(o.border)
0048 {
0049 }
0050 
0051 bool StyleSurroundData::operator==(const StyleSurroundData &o) const
0052 {
0053     return offset == o.offset && margin == o.margin &&
0054            padding == o.padding && border == o.border;
0055 }
0056 
0057 StyleBoxData::StyleBoxData()
0058     : z_index(0), z_auto(true)
0059 {
0060     min_width = min_height = RenderStyle::initialMinSize();
0061     max_width = max_height = RenderStyle::initialMaxSize();
0062     box_sizing = RenderStyle::initialBoxSizing();
0063 }
0064 
0065 StyleBoxData::StyleBoxData(const StyleBoxData &o)
0066     : Shared<StyleBoxData>(),
0067       width(o.width), height(o.height),
0068       min_width(o.min_width), max_width(o.max_width),
0069       min_height(o.min_height), max_height(o.max_height),
0070       box_sizing(o.box_sizing),
0071       z_index(o.z_index), z_auto(o.z_auto)
0072 {
0073 }
0074 
0075 bool StyleBoxData::operator==(const StyleBoxData &o) const
0076 {
0077     return
0078         width == o.width &&
0079         height == o.height &&
0080         min_width == o.min_width &&
0081         max_width == o.max_width &&
0082         min_height == o.min_height &&
0083         max_height == o.max_height &&
0084         box_sizing == o.box_sizing &&
0085         vertical_align == o.vertical_align &&
0086         z_index == o.z_index &&
0087         z_auto == o.z_auto;
0088 }
0089 
0090 StyleVisualData::StyleVisualData()
0091     : textDecoration(RenderStyle::initialTextDecoration()),
0092       palette(QApplication::palette())
0093 {
0094 }
0095 
0096 StyleVisualData::~StyleVisualData()
0097 {
0098 }
0099 
0100 StyleVisualData::StyleVisualData(const StyleVisualData &o)
0101     : Shared<StyleVisualData>(),
0102       clip(o.clip), textDecoration(o.textDecoration),
0103       palette(o.palette)
0104 {
0105 }
0106 
0107 BackgroundLayer::BackgroundLayer()
0108     : m_image(RenderStyle::initialBackgroundImage()),
0109       m_xPosition(RenderStyle::initialBackgroundXPosition()),
0110       m_yPosition(RenderStyle::initialBackgroundYPosition()),
0111       m_bgAttachment(RenderStyle::initialBackgroundAttachment()),
0112       m_bgClip(RenderStyle::initialBackgroundClip()),
0113       m_bgOrigin(RenderStyle::initialBackgroundOrigin()),
0114       m_bgRepeat(RenderStyle::initialBackgroundRepeat()),
0115       m_backgroundSize(RenderStyle::initialBackgroundSize()),
0116       m_next(nullptr)
0117 {
0118     m_imageSet = m_attachmentSet = m_clipSet = m_originSet =
0119                                        m_repeatSet = m_xPosSet = m_yPosSet = m_backgroundSizeSet = false;
0120 }
0121 
0122 BackgroundLayer::BackgroundLayer(const BackgroundLayer &o)
0123 {
0124     m_next = o.m_next ? new BackgroundLayer(*o.m_next) : nullptr;
0125     m_image = o.m_image;
0126     m_xPosition = o.m_xPosition;
0127     m_yPosition = o.m_yPosition;
0128     m_bgAttachment = o.m_bgAttachment;
0129     m_bgClip = o.m_bgClip;
0130     m_bgOrigin = o.m_bgOrigin;
0131     m_bgRepeat = o.m_bgRepeat;
0132     m_backgroundSize = o.m_backgroundSize;
0133     m_imageSet = o.m_imageSet;
0134     m_attachmentSet = o.m_attachmentSet;
0135     m_clipSet = o.m_clipSet;
0136     m_originSet = o.m_originSet;
0137     m_repeatSet = o.m_repeatSet;
0138     m_xPosSet = o.m_xPosSet;
0139     m_yPosSet = o.m_yPosSet;
0140     m_backgroundSizeSet = o.m_backgroundSizeSet;
0141 }
0142 
0143 BackgroundLayer::~BackgroundLayer()
0144 {
0145     delete m_next;
0146 }
0147 
0148 BackgroundLayer &BackgroundLayer::operator=(const BackgroundLayer &o)
0149 {
0150     if (m_next != o.m_next) {
0151         delete m_next;
0152         m_next = o.m_next ? new BackgroundLayer(*o.m_next) : nullptr;
0153     }
0154 
0155     m_image = o.m_image;
0156     m_xPosition = o.m_xPosition;
0157     m_yPosition = o.m_yPosition;
0158     m_bgAttachment = o.m_bgAttachment;
0159     m_bgClip = o.m_bgClip;
0160     m_bgOrigin = o.m_bgOrigin;
0161     m_bgRepeat = o.m_bgRepeat;
0162     m_backgroundSize = o.m_backgroundSize;
0163 
0164     m_imageSet = o.m_imageSet;
0165     m_attachmentSet = o.m_attachmentSet;
0166     m_originSet = o.m_originSet;
0167     m_repeatSet = o.m_repeatSet;
0168     m_xPosSet = o.m_xPosSet;
0169     m_yPosSet = o.m_yPosSet;
0170     m_backgroundSizeSet = o.m_backgroundSizeSet;
0171 
0172     return *this;
0173 }
0174 
0175 bool BackgroundLayer::operator==(const BackgroundLayer &o) const
0176 {
0177     return m_image == o.m_image && m_xPosition == o.m_xPosition && m_yPosition == o.m_yPosition &&
0178            m_bgAttachment == o.m_bgAttachment && m_bgClip == o.m_bgClip && m_bgOrigin == o.m_bgOrigin &&
0179            m_bgRepeat == o.m_bgRepeat && m_backgroundSize == o.m_backgroundSize &&
0180            m_imageSet == o.m_imageSet && m_attachmentSet == o.m_attachmentSet && m_repeatSet == o.m_repeatSet &&
0181            m_xPosSet == o.m_xPosSet && m_yPosSet == o.m_yPosSet && m_backgroundSizeSet == o.m_backgroundSizeSet &&
0182            ((m_next && o.m_next) ? *m_next == *o.m_next : m_next == o.m_next);
0183 }
0184 
0185 void BackgroundLayer::fillUnsetProperties()
0186 {
0187     BackgroundLayer *curr;
0188 
0189     for (curr = this; curr && curr->isBackgroundXPositionSet(); curr = curr->next()) {};
0190     if (curr && curr != this) {
0191         // We need to fill in the remaining values with the pattern specified.
0192         for (BackgroundLayer *pattern = this; curr; curr = curr->next()) {
0193             curr->setBackgroundXPosition(pattern->backgroundXPosition());
0194             pattern = pattern->next();
0195             if (pattern == curr || !pattern) {
0196                 pattern = this;
0197             }
0198         }
0199     }
0200 
0201     for (curr = this; curr && curr->isBackgroundYPositionSet(); curr = curr->next()) {};
0202     if (curr && curr != this) {
0203         // We need to fill in the remaining values with the pattern specified.
0204         for (BackgroundLayer *pattern = this; curr; curr = curr->next()) {
0205             curr->setBackgroundYPosition(pattern->backgroundYPosition());
0206             pattern = pattern->next();
0207             if (pattern == curr || !pattern) {
0208                 pattern = this;
0209             }
0210         }
0211     }
0212 
0213     for (curr = this; curr && curr->isBackgroundAttachmentSet(); curr = curr->next()) {};
0214     if (curr && curr != this) {
0215         // We need to fill in the remaining values with the pattern specified.
0216         for (BackgroundLayer *pattern = this; curr; curr = curr->next()) {
0217             curr->setBackgroundAttachment(pattern->backgroundAttachment());
0218             pattern = pattern->next();
0219             if (pattern == curr || !pattern) {
0220                 pattern = this;
0221             }
0222         }
0223     }
0224 
0225     for (curr = this; curr && curr->isBackgroundClipSet(); curr = curr->next()) {};
0226     if (curr && curr != this) {
0227         // We need to fill in the remaining values with the pattern specified.
0228         for (BackgroundLayer *pattern = this; curr; curr = curr->next()) {
0229             curr->setBackgroundClip(pattern->backgroundClip());
0230             pattern = pattern->next();
0231             if (pattern == curr || !pattern) {
0232                 pattern = this;
0233             }
0234         }
0235     }
0236 
0237     for (curr = this; curr && curr->isBackgroundOriginSet(); curr = curr->next()) {};
0238     if (curr && curr != this) {
0239         // We need to fill in the remaining values with the pattern specified.
0240         for (BackgroundLayer *pattern = this; curr; curr = curr->next()) {
0241             curr->setBackgroundOrigin(pattern->backgroundOrigin());
0242             pattern = pattern->next();
0243             if (pattern == curr || !pattern) {
0244                 pattern = this;
0245             }
0246         }
0247     }
0248 
0249     for (curr = this; curr && curr->isBackgroundRepeatSet(); curr = curr->next()) {};
0250     if (curr && curr != this) {
0251         // We need to fill in the remaining values with the pattern specified.
0252         for (BackgroundLayer *pattern = this; curr; curr = curr->next()) {
0253             curr->setBackgroundRepeat(pattern->backgroundRepeat());
0254             pattern = pattern->next();
0255             if (pattern == curr || !pattern) {
0256                 pattern = this;
0257             }
0258         }
0259     }
0260 
0261     for (curr = this; curr && curr->isBackgroundSizeSet(); curr = curr->next()) {};
0262     if (curr && curr != this) {
0263         // We need to fill in the remaining values with the pattern specified.
0264         for (BackgroundLayer *pattern = this; curr; curr = curr->next()) {
0265             curr->setBackgroundSize(pattern->backgroundSize());
0266             pattern = pattern->next();
0267             if (pattern == curr || !pattern) {
0268                 pattern = this;
0269             }
0270         }
0271     }
0272 }
0273 
0274 void BackgroundLayer::cullEmptyLayers()
0275 {
0276     BackgroundLayer *next;
0277     for (BackgroundLayer *p = this; p; p = next) {
0278         next = p->m_next;
0279         if (next && !next->isBackgroundImageSet()) {
0280             delete next;
0281             p->m_next = nullptr;
0282             break;
0283         }
0284     }
0285 }
0286 
0287 StyleBackgroundData::StyleBackgroundData()
0288 {}
0289 
0290 StyleBackgroundData::StyleBackgroundData(const StyleBackgroundData &o)
0291     : Shared<StyleBackgroundData>(), m_background(o.m_background), m_outline(o.m_outline)
0292 {}
0293 
0294 bool StyleBackgroundData::operator==(const StyleBackgroundData &o) const
0295 {
0296     return m_background == o.m_background && m_color == o.m_color && m_outline == o.m_outline;
0297 }
0298 
0299 StyleGeneratedData::StyleGeneratedData() : Shared<StyleGeneratedData>(), content(nullptr), counter_reset(nullptr), counter_increment(nullptr) {}
0300 
0301 StyleGeneratedData::~StyleGeneratedData()
0302 {
0303     if (counter_reset) {
0304         counter_reset->deref();
0305     }
0306     if (counter_increment) {
0307         counter_increment->deref();
0308     }
0309     delete content;
0310 }
0311 
0312 StyleGeneratedData::StyleGeneratedData(const StyleGeneratedData &o)
0313     : Shared<StyleGeneratedData>(), content(nullptr),
0314       counter_reset(o.counter_reset), counter_increment(o.counter_increment)
0315 {
0316     if (o.content) {
0317         content = new ContentData(*o.content);
0318     }
0319     if (counter_reset) {
0320         counter_reset->ref();
0321     }
0322     if (counter_increment) {
0323         counter_increment->ref();
0324     }
0325 }
0326 
0327 bool StyleGeneratedData::contentDataEquivalent(const StyleGeneratedData *otherStyle) const
0328 {
0329     ContentData *c1 = content;
0330     ContentData *c2 = otherStyle->content;
0331 
0332     while (c1 && c2) {
0333         if (c1->_contentType != c2->_contentType) {
0334             return false;
0335         }
0336         if (c1->_contentType == CONTENT_TEXT) {
0337             DOM::DOMString c1Str(c1->_content.text);
0338             DOM::DOMString c2Str(c2->_content.text);
0339             if (c1Str != c2Str) {
0340                 return false;
0341             }
0342         } else if (c1->_contentType == CONTENT_OBJECT) {
0343             if (c1->_content.object != c2->_content.object) {
0344                 return false;
0345             }
0346         } else if (c1->_contentType == CONTENT_COUNTER) {
0347             if (c1->_content.counter != c2->_content.counter) {
0348                 return false;
0349             }
0350         } else if (c1->_contentType == CONTENT_QUOTE) {
0351             if (c1->_content.quote != c2->_content.quote) {
0352                 return false;
0353             }
0354         }
0355 
0356         c1 = c1->_nextContent;
0357         c2 = c2->_nextContent;
0358     }
0359 
0360     return !c1 && !c2;
0361 }
0362 
0363 static bool compareCounterActList(const CSSValueListImpl *ca, const CSSValueListImpl *cb)
0364 {
0365     // weeee....
0366     CSSValueListImpl *a = const_cast<CSSValueListImpl *>(ca);
0367     CSSValueListImpl *b = const_cast<CSSValueListImpl *>(cb);
0368 
0369     if (!a && !b) {
0370         return true;
0371     }
0372     if (!a || !b) {
0373         return false;
0374     }
0375     if (a->length() != b->length()) {
0376         return false;
0377     }
0378     for (uint i = 0; i < a->length(); i++) {
0379         CSSValueImpl *ai =  a->item(i);
0380         CSSValueImpl *bi =  b->item(i);
0381         assert(ai && ai->cssValueType() == CSSValue::CSS_CUSTOM);
0382         assert(bi && bi->cssValueType() == CSSValue::CSS_CUSTOM);
0383         CounterActImpl *caa = static_cast<CounterActImpl *>(ai);
0384         CounterActImpl *cab = static_cast<CounterActImpl *>(bi);
0385         if (caa->value() != cab->value()) {
0386             return false;
0387         }
0388         if (caa->counter() != cab->counter()) {
0389             return false;
0390         }
0391     }
0392     return true;
0393 }
0394 
0395 bool StyleGeneratedData::counterDataEquivalent(const StyleGeneratedData *otherStyle) const
0396 {
0397     return compareCounterActList(counter_reset, otherStyle->counter_reset) &&
0398            compareCounterActList(counter_increment, otherStyle->counter_increment);
0399 }
0400 
0401 bool StyleGeneratedData::operator==(const StyleGeneratedData &o) const
0402 {
0403     return contentDataEquivalent(&o) && counterDataEquivalent(&o);
0404 }
0405 
0406 StyleMarqueeData::StyleMarqueeData()
0407 {
0408     increment = RenderStyle::initialMarqueeIncrement();
0409     speed = RenderStyle::initialMarqueeSpeed();
0410     direction = RenderStyle::initialMarqueeDirection();
0411     behavior = RenderStyle::initialMarqueeBehavior();
0412     loops = RenderStyle::initialMarqueeLoopCount();
0413 }
0414 
0415 StyleMarqueeData::StyleMarqueeData(const StyleMarqueeData &o)
0416     : Shared<StyleMarqueeData>(), increment(o.increment), speed(o.speed), loops(o.loops),
0417       behavior(o.behavior), direction(o.direction)
0418 {}
0419 
0420 bool StyleMarqueeData::operator==(const StyleMarqueeData &o) const
0421 {
0422     return (increment == o.increment && speed == o.speed && direction == o.direction &&
0423             behavior == o.behavior && loops == o.loops);
0424 }
0425 
0426 bool BorderRadii::operator==(const BorderRadii &o) const
0427 {
0428     return horizontal == o.horizontal &&
0429            vertical   == o.vertical;
0430 }
0431 
0432 BorderRadiusData::BorderRadiusData()
0433     :Shared<BorderRadiusData>()
0434 {
0435     topRight = RenderStyle::initialBorderRadius();
0436     bottomRight = RenderStyle::initialBorderRadius();
0437     bottomLeft = RenderStyle::initialBorderRadius();
0438     topLeft = RenderStyle::initialBorderRadius();
0439 }
0440 
0441 bool BorderRadiusData::operator==(const BorderRadiusData &o) const
0442 {
0443     return topRight == o.topRight && bottomRight == o.bottomRight
0444            && bottomLeft == o.bottomLeft && topLeft == o.topLeft;
0445 }
0446 
0447 bool BorderRadiusData::hasBorderRadius() const
0448 {
0449     return topRight.hasBorderRadius()   || bottomRight.hasBorderRadius() ||
0450            bottomLeft.hasBorderRadius() || topLeft.hasBorderRadius();
0451 }
0452 
0453 StyleCSS3NonInheritedData::StyleCSS3NonInheritedData()
0454     : Shared<StyleCSS3NonInheritedData>()
0455     , opacity(RenderStyle::initialOpacity())
0456 {
0457 }
0458 
0459 StyleCSS3NonInheritedData::StyleCSS3NonInheritedData(const StyleCSS3NonInheritedData &o)
0460     : Shared<StyleCSS3NonInheritedData>(),
0461       opacity(o.opacity),
0462 #ifdef APPLE_CHANGES
0463       flexibleBox(o.flexibleBox),
0464 #endif
0465       marquee(o.marquee),
0466       borderRadius(o.borderRadius)
0467 {
0468 }
0469 
0470 bool StyleCSS3NonInheritedData::operator==(const StyleCSS3NonInheritedData &o) const
0471 {
0472     return
0473         opacity == o.opacity &&
0474 #ifdef APPLE_CHANGES
0475         flexibleBox == o.flexibleBox &&
0476 #endif
0477         marquee == o.marquee &&
0478         borderRadius == o.borderRadius;
0479 }
0480 
0481 StyleCSS3InheritedData::StyleCSS3InheritedData()
0482     : Shared<StyleCSS3InheritedData>(), textShadow(nullptr), wordWrap(RenderStyle::initialWordWrap())
0483 #ifdef APPLE_CHANGES
0484     , userModify(READ_ONLY), textSizeAdjust(RenderStyle::initialTextSizeAdjust())
0485 #endif
0486 {
0487 
0488 }
0489 
0490 StyleCSS3InheritedData::StyleCSS3InheritedData(const StyleCSS3InheritedData &o)
0491     : Shared<StyleCSS3InheritedData>()
0492 {
0493     textShadow = o.textShadow ? new ShadowData(*o.textShadow) : nullptr;
0494     wordWrap = o.wordWrap;
0495 #ifdef APPLE_CHANGES
0496     userModify = o.userModify;
0497     textSizeAdjust = o.textSizeAdjust;
0498 #endif
0499 }
0500 
0501 StyleCSS3InheritedData::~StyleCSS3InheritedData()
0502 {
0503     delete textShadow;
0504 }
0505 
0506 bool StyleCSS3InheritedData::operator==(const StyleCSS3InheritedData &o) const
0507 {
0508     return shadowDataEquivalent(o) && (wordWrap == o.wordWrap)
0509 #ifdef APPLE_CHANGES
0510            && (userModify == o.userModify) && (textSizeAdjust == o.textSizeAdjust)
0511 #endif
0512            ;
0513 }
0514 
0515 bool StyleCSS3InheritedData::shadowDataEquivalent(const StyleCSS3InheritedData &o) const
0516 {
0517     if ((!textShadow && o.textShadow) || (textShadow && !o.textShadow)) {
0518         return false;
0519     }
0520     if ((textShadow && o.textShadow) && (*textShadow != *o.textShadow)) {
0521         return false;
0522     }
0523     return true;
0524 }
0525 
0526 StyleInheritedData::StyleInheritedData()
0527     : indent(RenderStyle::initialTextIndent()), line_height(RenderStyle::initialLineHeight()),
0528       style_image(RenderStyle::initialListStyleImage()),
0529       font(), color(RenderStyle::initialColor()),
0530       border_hspacing(RenderStyle::initialBorderHorizontalSpacing()),
0531       border_vspacing(RenderStyle::initialBorderVerticalSpacing()),
0532       widows(RenderStyle::initialWidows()), orphans(RenderStyle::initialOrphans()),
0533       quotes(nullptr)
0534 {
0535 }
0536 
0537 StyleInheritedData::~StyleInheritedData()
0538 {
0539     if (quotes) {
0540         quotes->deref();
0541     }
0542 }
0543 
0544 StyleInheritedData::StyleInheritedData(const StyleInheritedData &o)
0545     : Shared<StyleInheritedData>(),
0546       indent(o.indent), line_height(o.line_height), style_image(o.style_image),
0547       font(o.font), color(o.color),
0548       border_hspacing(o.border_hspacing),
0549       border_vspacing(o.border_vspacing),
0550       widows(o.widows), orphans(o.orphans)
0551 {
0552     quotes = o.quotes;
0553     if (quotes) {
0554         quotes->ref();
0555     }
0556 }
0557 
0558 bool StyleInheritedData::operator==(const StyleInheritedData &o) const
0559 {
0560     return
0561         indent == o.indent &&
0562         line_height == o.line_height &&
0563         border_hspacing == o.border_hspacing &&
0564         border_vspacing == o.border_vspacing &&
0565         style_image == o.style_image &&
0566         font == o.font &&
0567         color == o.color &&
0568         border_hspacing == o.border_hspacing &&
0569         border_vspacing == o.border_vspacing &&
0570         quotes == o.quotes &&
0571         widows == o.widows &&
0572         orphans == o.orphans;
0573 
0574     // doesn't work because structs are not packed
0575     //return memcmp(this, &o, sizeof(*this))==0;
0576 }
0577 
0578 RenderStyle::RenderStyle()
0579 {
0580 //    counter++;
0581     if (!_default) {
0582         _default = new RenderStyle(true);
0583     }
0584 
0585     box = _default->box;
0586     visual = _default->visual;
0587     background = _default->background;
0588     surround = _default->surround;
0589     generated = _default->generated;
0590     css3NonInheritedData = _default->css3NonInheritedData;
0591     css3InheritedData = _default->css3InheritedData;
0592 
0593     inherited = _default->inherited;
0594 
0595     m_svgStyle = _default->m_svgStyle;
0596 
0597     setBitDefaults();
0598 
0599     pseudoStyle = nullptr;
0600 }
0601 
0602 RenderStyle::RenderStyle(bool)
0603 {
0604     // Let the font cache create its initial value.
0605     // We need this because attach can call styleForElement
0606     // for things with display:none parents, and then we need to be
0607     // able to provide some sort of fallback font data to operate on.
0608     Font::initDefault();
0609 
0610     setBitDefaults();
0611 
0612     box.init();
0613     visual.init();
0614     background.init();
0615     surround.init();
0616     generated.init();
0617     css3NonInheritedData.init();
0618 #ifdef APPLE_CHANGES    // ### yet to be merged
0619     css3NonInheritedData.access()->flexibleBox.init();
0620 #endif
0621     css3NonInheritedData.access()->marquee.init();
0622     css3NonInheritedData.access()->borderRadius.init();
0623     css3InheritedData.init();
0624     inherited.init();
0625 
0626     m_svgStyle.init();
0627 
0628     pseudoStyle = nullptr;
0629 }
0630 
0631 RenderStyle::RenderStyle(const RenderStyle &o)
0632     : Shared<RenderStyle>(),
0633       inherited_flags(o.inherited_flags), noninherited_flags(o.noninherited_flags),
0634       box(o.box), visual(o.visual), background(o.background), surround(o.surround), generated(o.generated),
0635       css3NonInheritedData(o.css3NonInheritedData), css3InheritedData(o.css3InheritedData),
0636       inherited(o.inherited), pseudoStyle(nullptr), m_svgStyle(o.m_svgStyle)
0637 {}
0638 
0639 void RenderStyle::inheritFrom(const RenderStyle *inheritParent)
0640 {
0641     css3InheritedData = inheritParent->css3InheritedData;
0642     inherited = inheritParent->inherited;
0643     inherited_flags = inheritParent->inherited_flags;
0644 
0645     // SVG
0646     if (m_svgStyle != inheritParent->m_svgStyle) {
0647         m_svgStyle.access()->inheritFrom(inheritParent->m_svgStyle.get());
0648     }
0649 
0650     // Simulate ":after,:before { white-space: pre-line }"
0651     if (styleType() == AFTER || styleType() == BEFORE) {
0652         setWhiteSpace(PRE_LINE);
0653     }
0654 }
0655 
0656 void RenderStyle::compactWith(const RenderStyle *similarStyle)
0657 {
0658     if (this == similarStyle) {
0659         return;
0660     }
0661 
0662     if (box.get() != similarStyle->box.get() && box == similarStyle->box) {
0663         box = similarStyle->box;
0664     }
0665     if (visual.get() != similarStyle->visual.get() && visual == similarStyle->visual) {
0666         visual = similarStyle->visual;
0667     }
0668     if (background.get() != similarStyle->background.get() && background == similarStyle->background) {
0669         background = similarStyle->background;
0670     }
0671     if (surround.get() != similarStyle->surround.get() && surround == similarStyle->surround) {
0672         surround = similarStyle->surround;
0673     }
0674     if (generated.get() != similarStyle->generated.get() && generated == similarStyle->generated) {
0675         generated = similarStyle->generated;
0676     }
0677     if (css3NonInheritedData.get() != similarStyle->css3NonInheritedData.get() && css3NonInheritedData == similarStyle->css3NonInheritedData) {
0678         css3NonInheritedData = similarStyle->css3NonInheritedData;
0679     }
0680     if (css3InheritedData.get() != similarStyle->css3InheritedData.get() && css3InheritedData == similarStyle->css3InheritedData) {
0681         css3InheritedData = similarStyle->css3InheritedData;
0682     }
0683     if (inherited.get() != similarStyle->inherited.get() && inherited == similarStyle->inherited) {
0684         inherited = similarStyle->inherited;
0685     }
0686 }
0687 
0688 RenderStyle::~RenderStyle()
0689 {
0690     RenderStyle *ps = pseudoStyle;
0691     RenderStyle *prev = nullptr;
0692 
0693     while (ps) {
0694         prev = ps;
0695         ps = ps->pseudoStyle;
0696         // to prevent a double deletion.
0697         // this works only because the styles below aren't really shared
0698         // Dirk said we need another construct as soon as these are shared
0699         prev->pseudoStyle = nullptr;
0700         prev->deref();
0701     }
0702 }
0703 
0704 bool RenderStyle::operator==(const RenderStyle &o) const
0705 {
0706 // compare everything except the pseudoStyle pointer
0707     return (inherited_flags == o.inherited_flags &&
0708             noninherited_flags == o.noninherited_flags &&
0709             box == o.box &&
0710             visual == o.visual &&
0711             background == o.background &&
0712             surround == o.surround &&
0713             generated == o.generated &&
0714             css3NonInheritedData == o.css3NonInheritedData &&
0715             css3InheritedData == o.css3InheritedData &&
0716             inherited == o.inherited &&
0717             m_svgStyle == o.m_svgStyle); // SVG
0718 }
0719 
0720 enum EPseudoBit { NO_BIT = 0x0,
0721                   FIRST_LINE_BIT = 0x1, FIRST_LETTER_BIT = 0x2, SELECTION_BIT = 0x4,
0722                   BEFORE_BIT = 0x8, AFTER_BIT = 0x10, MARKER_BIT = 0x20,
0723                   REPLACED_BIT = 0x40
0724                 };
0725 
0726 static int pseudoBit(RenderStyle::PseudoId pseudo)
0727 {
0728     switch (pseudo) {
0729     case RenderStyle::BEFORE:
0730         return BEFORE_BIT;
0731     case RenderStyle::AFTER:
0732         return AFTER_BIT;
0733     case RenderStyle::MARKER:
0734         return MARKER_BIT;
0735     case RenderStyle::REPLACED:
0736         return REPLACED_BIT;
0737     case RenderStyle::FIRST_LINE:
0738         return FIRST_LINE_BIT;
0739     case RenderStyle::FIRST_LETTER:
0740         return FIRST_LETTER_BIT;
0741     case RenderStyle::SELECTION:
0742         return SELECTION_BIT;
0743     default:
0744         return NO_BIT;
0745     }
0746 }
0747 
0748 bool RenderStyle::hasPseudoStyle(PseudoId pseudo) const
0749 {
0750     return (pseudoBit(pseudo) & noninherited_flags.f._pseudoBits) != 0;
0751 }
0752 
0753 void RenderStyle::setHasPseudoStyle(PseudoId pseudo, bool b)
0754 {
0755     if (b) {
0756         noninherited_flags.f._pseudoBits |= pseudoBit(pseudo);
0757     } else {
0758         noninherited_flags.f._pseudoBits &= ~(pseudoBit(pseudo));
0759     }
0760 }
0761 
0762 RenderStyle *RenderStyle::getPseudoStyle(PseudoId pid) const
0763 {
0764     if (!hasPseudoStyle(pid)) {
0765         return nullptr;
0766     }
0767 
0768     RenderStyle *ps = nullptr;
0769     if (noninherited_flags.f._styleType == NOPSEUDO)
0770         for (ps = pseudoStyle; ps; ps = ps->pseudoStyle)
0771             if (ps->noninherited_flags.f._styleType == pid) {
0772                 break;
0773             }
0774     return ps;
0775 }
0776 
0777 RenderStyle *RenderStyle::addPseudoStyle(PseudoId pid)
0778 {
0779     if (hasPseudoStyle(pid)) {
0780         return getPseudoStyle(pid);
0781     }
0782 
0783     RenderStyle *ps = nullptr;
0784 
0785     switch (pid) {
0786     case FIRST_LETTER:             // pseudo-elements (FIRST_LINE has a special handling)
0787     case SELECTION:
0788     case BEFORE:
0789     case AFTER:
0790         ps = new RenderStyle();
0791         break;
0792     default:
0793         ps = new RenderStyle(*this); // use the real copy constructor to get an identical copy
0794     }
0795     ps->ref();
0796     ps->noninherited_flags.f._styleType = pid;
0797     ps->pseudoStyle = pseudoStyle;
0798 
0799     pseudoStyle = ps;
0800 
0801     setHasPseudoStyle(pid, true);
0802 
0803     return ps;
0804 }
0805 
0806 void RenderStyle::removePseudoStyle(PseudoId pid)
0807 {
0808     RenderStyle *ps = pseudoStyle;
0809     RenderStyle *prev = this;
0810 
0811     while (ps) {
0812         if (ps->noninherited_flags.f._styleType == pid) {
0813             prev->pseudoStyle = ps->pseudoStyle;
0814             ps->deref();
0815             return;
0816         }
0817         prev = ps;
0818         ps = ps->pseudoStyle;
0819     }
0820 
0821     setHasPseudoStyle(pid, false);
0822 }
0823 
0824 bool RenderStyle::inheritedNotEqual(RenderStyle *other) const
0825 {
0826     return
0827         (
0828             inherited_flags != other->inherited_flags ||
0829             inherited != other->inherited ||
0830             css3InheritedData != other->css3InheritedData ||
0831             m_svgStyle->inheritedNotEqual(other->m_svgStyle.get())
0832         );
0833 }
0834 
0835 /*
0836   compares two styles. The result gives an idea of the action that
0837   needs to be taken when replacing the old style with a new one.
0838 
0839   CbLayout: The containing block of the object needs a relayout.
0840   Layout: the RenderObject needs a relayout after the style change
0841   Visible: The change is visible, but no relayout is needed
0842   NonVisible: The object does need neither repaint nor relayout after
0843        the change.
0844 
0845   ### TODO:
0846   A lot can be optimised here based on the display type, lots of
0847   optimizations are unimplemented, and currently result in the
0848   worst case result causing a relayout of the containing block.
0849 */
0850 RenderStyle::Diff RenderStyle::diff(const RenderStyle *other) const
0851 {
0852     if (m_svgStyle != other->m_svgStyle) {
0853         return Layout;
0854     }
0855     // we anyway assume they are the same
0856 //  EDisplay _display : 5;
0857 
0858     // NonVisible:
0859 //  ECursor _cursor_style : 4;
0860 //  EUserInput _user_input : 2; as long as :enabled is not impl'd
0861 
0862 // ### this needs work to know more exactly if we need a relayout
0863 //     or just a repaint
0864 
0865 // non-inherited attributes
0866 //     DataRef<StyleBoxData> box;
0867 //     DataRef<StyleVisualData> visual;
0868 //     DataRef<StyleSurroundData> surround;
0869 
0870 // inherited attributes
0871 //     DataRef<StyleInheritedData> inherited;
0872 
0873     if (*box.get() != *other->box.get() ||
0874             *visual.get() != *other->visual.get() ||
0875             (*surround.get() != *other->surround.get()
0876              && (other->position() == PSTATIC || other->position() != position())) ||
0877             !(inherited->indent == other->inherited->indent) ||
0878             !(inherited->line_height == other->inherited->line_height) ||
0879             !(inherited->style_image == other->inherited->style_image) ||
0880             !(inherited->font == other->inherited->font) ||
0881             !(inherited->border_hspacing == other->inherited->border_hspacing) ||
0882             !(inherited->border_vspacing == other->inherited->border_vspacing) ||
0883             !(inherited_flags.f._visuallyOrdered == other->inherited_flags.f._visuallyOrdered) ||
0884             !(inherited_flags.f._htmlHacks == other->inherited_flags.f._htmlHacks) ||
0885             !(noninherited_flags.f._textOverflow == other->noninherited_flags.f._textOverflow)) {
0886         return CbLayout;
0887     }
0888 
0889     // changes causing Layout changes:
0890 
0891 // only for tables:
0892 //  _border_collapse
0893 //  EEmptyCell _empty_cells : 2 ;
0894 //  ECaptionSide _caption_side : 2;
0895 //     ETableLayout _table_layout : 1;
0896 //     EPosition _position : 2;
0897 //     EFloat _floating : 2;
0898     if (((int)noninherited_flags.f._display) >= TABLE) {
0899         if (!(inherited_flags.f._empty_cells == other->inherited_flags.f._empty_cells) ||
0900                 !(inherited_flags.f._caption_side == other->inherited_flags.f._caption_side) ||
0901                 !(inherited_flags.f._border_collapse == other->inherited_flags.f._border_collapse) ||
0902                 !(noninherited_flags.f._table_layout == other->noninherited_flags.f._table_layout) ||
0903                 !(noninherited_flags.f._position == other->noninherited_flags.f._position) ||
0904                 !(noninherited_flags.f._floating == other->noninherited_flags.f._floating) ||
0905                 !(noninherited_flags.f._flowAroundFloats == other->noninherited_flags.f._flowAroundFloats) ||
0906                 !(noninherited_flags.f._unicodeBidi == other->noninherited_flags.f._unicodeBidi)) {
0907             return CbLayout;
0908         }
0909     }
0910 
0911 // only for lists:
0912 //  EListStyleType _list_style_type : 5 ;
0913 //  EListStylePosition _list_style_position :1;
0914     if (noninherited_flags.f._display == LIST_ITEM) {
0915         if (!(inherited_flags.f._list_style_type == other->inherited_flags.f._list_style_type) ||
0916                 !(inherited_flags.f._list_style_position == other->inherited_flags.f._list_style_position)) {
0917             return Layout;
0918         }
0919     }
0920 
0921 // ### These could be better optimised
0922 //  ETextAlign _text_align : 3;
0923 //  ETextTransform _text_transform : 4;
0924 //  EDirection _direction : 1;
0925 //  EWhiteSpace _white_space : 2;
0926 //     EClear _clear : 2;
0927     if (!(inherited_flags.f._text_align == other->inherited_flags.f._text_align) ||
0928             !(inherited_flags.f._text_transform == other->inherited_flags.f._text_transform) ||
0929             !(inherited_flags.f._direction == other->inherited_flags.f._direction) ||
0930             !(inherited_flags.f._white_space == other->inherited_flags.f._white_space) ||
0931             !(noninherited_flags.f._clear == other->noninherited_flags.f._clear)
0932        ) {
0933         return Layout;
0934     }
0935 
0936     // Overflow returns a layout hint.
0937     if (noninherited_flags.f._overflowX != other->noninherited_flags.f._overflowX ||
0938             noninherited_flags.f._overflowY != other->noninherited_flags.f._overflowY) {
0939         return Layout;
0940     }
0941 
0942 // only for inline:
0943 //     EVerticalAlign _vertical_align : 4;
0944 
0945     if (!(noninherited_flags.f._display == INLINE) &&
0946             !(noninherited_flags.f._vertical_align == other->noninherited_flags.f._vertical_align)) {
0947         return Layout;
0948     }
0949 
0950     if (*surround.get() != *other->surround.get()) {
0951         assert(other->position() != PSTATIC);                        // this style is positioned or relatively positioned
0952         if (surround->hasSamePBMData(*other->surround.get()) &&     // padding/border/margin are identical
0953                 (other->position() == PRELATIVE ||
0954                  (!(other->left().isAuto() && other->right().isAuto()) &&  // X isn't static
0955                   !(other->top().isAuto() && other->bottom().isAuto()))))    // neither is Y
0956             // therefore only the offset is different
0957         {
0958             return Position;
0959         }
0960         return Layout;
0961     }
0962 
0963     // Visible:
0964 //  EVisibility _visibility : 2;
0965 //  int _text_decorations : 4;
0966 //     DataRef<StyleBackgroundData> background;
0967     if (inherited->color != other->inherited->color ||
0968             !(inherited_flags.f._visibility == other->inherited_flags.f._visibility) ||
0969             !(inherited_flags.f._text_decorations == other->inherited_flags.f._text_decorations) ||
0970             !(noninherited_flags.f._hasClip == other->noninherited_flags.f._hasClip) ||
0971             visual->textDecoration != other->visual->textDecoration ||
0972             *background.get() != *other->background.get() ||
0973             css3NonInheritedData->opacity != other->css3NonInheritedData->opacity ||
0974             !css3InheritedData->shadowDataEquivalent(*other->css3InheritedData.get())
0975        ) {
0976         return Visible;
0977     }
0978 
0979     RenderStyle::Diff ch = Equal;
0980     // Check for visible pseudo-changes:
0981     if (hasPseudoStyle(FIRST_LINE) != other->hasPseudoStyle(FIRST_LINE)) {
0982         ch = Visible;
0983     } else if (hasPseudoStyle(FIRST_LINE) && other->hasPseudoStyle(FIRST_LINE)) {
0984         ch = getPseudoStyle(FIRST_LINE)->diff(other->getPseudoStyle(FIRST_LINE));
0985     }
0986 
0987     if (ch != Equal) {
0988         return ch;
0989     }
0990 
0991     // Check for visible pseudo-changes:
0992     if (hasPseudoStyle(SELECTION) != other->hasPseudoStyle(SELECTION)) {
0993         ch = Visible;
0994     } else if (hasPseudoStyle(SELECTION) && other->hasPseudoStyle(SELECTION)) {
0995         ch = getPseudoStyle(SELECTION)->diff(other->getPseudoStyle(SELECTION));
0996     }
0997 
0998     return ch;
0999 }
1000 
1001 RenderStyle *RenderStyle::_default = nullptr;
1002 
1003 void RenderStyle::cleanup()
1004 {
1005     delete _default;
1006     _default = nullptr;
1007 }
1008 
1009 void RenderStyle::setPaletteColor(QPalette::ColorGroup g, QPalette::ColorRole r, const QColor &c)
1010 {
1011     visual.access()->palette.setColor(g, r, c);
1012 }
1013 
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 
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 
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 
1047 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 
1058 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 
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 
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 
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 
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
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
1196 void RenderStyle::setContentNone()
1197 {
1198     setContentNormal();
1199     generated.access()->content = new ContentData;
1200 }
1201 
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 
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 
1238 ContentData::~ContentData()
1239 {
1240     clearContent();
1241 }
1242 
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 
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 
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 
1290 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 
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 
1313 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 
1322 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 
1331 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 
1350 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 
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 
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 
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 
1423 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 
1440 RenderPageStyle::RenderPageStyle() : next(nullptr), m_pageType(ANY_PAGE)
1441 {
1442 }
1443 
1444 RenderPageStyle::~RenderPageStyle()
1445 {
1446     delete next;
1447 }
1448 
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 
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 
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 }