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 }