|
|
|
/*
|
|
|
|
* This file is part of the DOM implementation for KDE.
|
|
|
|
*
|
|
|
|
* Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
|
|
|
|
* Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
|
|
|
|
* Copyright (C) 2002-2003 Dirk Mueller (mueller@kde.org)
|
|
|
|
* Copyright (C) 2002-2005 Apple Computer, Inc.
|
|
|
|
* Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Library General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Library General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Library General Public License
|
|
|
|
* along with this library; see the file COPYING.LIB. If not, write to
|
|
|
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
* Boston, MA 02110-1301, USA.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "xml/dom_stringimpl.h"
|
|
|
|
#include "css/cssstyleselector.h"
|
|
|
|
#include "css/css_valueimpl.h"
|
|
|
|
#include "render_style.h"
|
|
|
|
|
|
|
|
#include "kdebug.h"
|
|
|
|
|
|
|
|
using namespace khtml;
|
|
|
|
using namespace DOM;
|
|
|
|
|
|
|
|
/* CSS says Fixed for the default padding value, but we treat variable as 0 padding anyways, and like
|
|
|
|
* this is works fine for table paddings aswell
|
|
|
|
*/
|
|
|
|
StyleSurroundData::StyleSurroundData()
|
|
|
|
: margin( Fixed ), padding( Variable )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
StyleSurroundData::StyleSurroundData(const StyleSurroundData& o )
|
|
|
|
: Shared<StyleSurroundData>(),
|
|
|
|
offset( o.offset ), margin( o.margin ), padding( o.padding ),
|
|
|
|
border( o.border )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StyleSurroundData::operator==(const StyleSurroundData& o) const
|
|
|
|
{
|
|
|
|
return offset==o.offset && margin==o.margin &&
|
|
|
|
padding==o.padding && border==o.border;
|
|
|
|
}
|
|
|
|
|
|
|
|
StyleBoxData::StyleBoxData()
|
|
|
|
: z_index( 0 ), z_auto( true )
|
|
|
|
{
|
|
|
|
min_width = min_height = RenderStyle::initialMinSize();
|
|
|
|
max_width = max_height = RenderStyle::initialMaxSize();
|
|
|
|
box_sizing = RenderStyle::initialBoxSizing();
|
|
|
|
}
|
|
|
|
|
|
|
|
StyleBoxData::StyleBoxData(const StyleBoxData& o )
|
|
|
|
: Shared<StyleBoxData>(),
|
|
|
|
width( o.width ), height( o.height ),
|
|
|
|
min_width( o.min_width ), max_width( o.max_width ),
|
|
|
|
min_height ( o.min_height ), max_height( o.max_height ),
|
|
|
|
box_sizing( o.box_sizing),
|
|
|
|
z_index( o.z_index ), z_auto( o.z_auto )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StyleBoxData::operator==(const StyleBoxData& o) const
|
|
|
|
{
|
|
|
|
return
|
|
|
|
width == o.width &&
|
|
|
|
height == o.height &&
|
|
|
|
min_width == o.min_width &&
|
|
|
|
max_width == o.max_width &&
|
|
|
|
min_height == o.min_height &&
|
|
|
|
max_height == o.max_height &&
|
|
|
|
box_sizing == o.box_sizing &&
|
|
|
|
z_index == o.z_index &&
|
|
|
|
z_auto == o.z_auto;
|
|
|
|
}
|
|
|
|
|
|
|
|
StyleVisualData::StyleVisualData()
|
|
|
|
: textDecoration(RenderStyle::initialTextDecoration()),
|
|
|
|
palette( TQApplication::palette() )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
StyleVisualData::~StyleVisualData() {
|
|
|
|
}
|
|
|
|
|
|
|
|
StyleVisualData::StyleVisualData(const StyleVisualData& o )
|
|
|
|
: Shared<StyleVisualData>(),
|
|
|
|
clip( o.clip ), textDecoration(o.textDecoration),
|
|
|
|
palette( o.palette )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
BackgroundLayer::BackgroundLayer()
|
|
|
|
:m_image(RenderStyle::initialBackgroundImage()),
|
|
|
|
m_bgAttachment(RenderStyle::initialBackgroundAttachment()),
|
|
|
|
m_bgClip(RenderStyle::initialBackgroundClip()),
|
|
|
|
m_bgOrigin(RenderStyle::initialBackgroundOrigin()),
|
|
|
|
m_bgRepeat(RenderStyle::initialBackgroundRepeat()),
|
|
|
|
m_backgroundSize(RenderStyle::initialBackgroundSize()),
|
|
|
|
m_next(0)
|
|
|
|
{
|
|
|
|
m_imageSet = m_attachmentSet = m_clipSet = m_originSet =
|
|
|
|
m_repeatSet = m_xPosSet = m_yPosSet = m_backgroundSizeSet = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
BackgroundLayer::BackgroundLayer(const BackgroundLayer& o)
|
|
|
|
{
|
|
|
|
m_next = o.m_next ? new BackgroundLayer(*o.m_next) : 0;
|
|
|
|
m_image = o.m_image;
|
|
|
|
m_xPosition = o.m_xPosition;
|
|
|
|
m_yPosition = o.m_yPosition;
|
|
|
|
m_bgAttachment = o.m_bgAttachment;
|
|
|
|
m_bgClip = o.m_bgClip;
|
|
|
|
m_bgOrigin = o.m_bgOrigin;
|
|
|
|
m_bgRepeat = o.m_bgRepeat;
|
|
|
|
m_backgroundSize = o.m_backgroundSize;
|
|
|
|
m_imageSet = o.m_imageSet;
|
|
|
|
m_attachmentSet = o.m_attachmentSet;
|
|
|
|
m_clipSet = o.m_clipSet;
|
|
|
|
m_originSet = o.m_originSet;
|
|
|
|
m_repeatSet = o.m_repeatSet;
|
|
|
|
m_xPosSet = o.m_xPosSet;
|
|
|
|
m_yPosSet = o.m_yPosSet;
|
|
|
|
m_backgroundSizeSet = o.m_backgroundSizeSet;
|
|
|
|
}
|
|
|
|
|
|
|
|
BackgroundLayer::~BackgroundLayer()
|
|
|
|
{
|
|
|
|
delete m_next;
|
|
|
|
}
|
|
|
|
|
|
|
|
BackgroundLayer& BackgroundLayer::operator=(const BackgroundLayer& o) {
|
|
|
|
if (m_next != o.m_next) {
|
|
|
|
delete m_next;
|
|
|
|
m_next = o.m_next ? new BackgroundLayer(*o.m_next) : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_image = o.m_image;
|
|
|
|
m_xPosition = o.m_xPosition;
|
|
|
|
m_yPosition = o.m_yPosition;
|
|
|
|
m_bgAttachment = o.m_bgAttachment;
|
|
|
|
m_bgClip = o.m_bgClip;
|
|
|
|
m_bgOrigin = o.m_bgOrigin;
|
|
|
|
m_bgRepeat = o.m_bgRepeat;
|
|
|
|
m_backgroundSize = o.m_backgroundSize;
|
|
|
|
|
|
|
|
m_imageSet = o.m_imageSet;
|
|
|
|
m_attachmentSet = o.m_attachmentSet;
|
|
|
|
m_originSet = o.m_originSet;
|
|
|
|
m_repeatSet = o.m_repeatSet;
|
|
|
|
m_xPosSet = o.m_xPosSet;
|
|
|
|
m_yPosSet = o.m_yPosSet;
|
|
|
|
m_backgroundSizeSet = o.m_backgroundSizeSet;
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BackgroundLayer::operator==(const BackgroundLayer& o) const {
|
|
|
|
return m_image == o.m_image && m_xPosition == o.m_xPosition && m_yPosition == o.m_yPosition &&
|
|
|
|
m_bgAttachment == o.m_bgAttachment && m_bgClip == o.m_bgClip && m_bgOrigin == o.m_bgOrigin && m_bgRepeat == o.m_bgRepeat &&
|
|
|
|
m_backgroundSize.width == o.m_backgroundSize.width && m_backgroundSize.height == o.m_backgroundSize.height &&
|
|
|
|
m_imageSet == o.m_imageSet && m_attachmentSet == o.m_attachmentSet && m_repeatSet == o.m_repeatSet &&
|
|
|
|
m_xPosSet == o.m_xPosSet && m_yPosSet == o.m_yPosSet && m_backgroundSizeSet == o.m_backgroundSizeSet &&
|
|
|
|
((m_next && o.m_next) ? *m_next == *o.m_next : m_next == o.m_next);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BackgroundLayer::fillUnsetProperties()
|
|
|
|
{
|
|
|
|
BackgroundLayer* curr;
|
|
|
|
for (curr = this; curr && curr->isBackgroundImageSet(); curr = curr->next());
|
|
|
|
if (curr && curr != this) {
|
|
|
|
// We need to fill in the remaining values with the pattern specified.
|
|
|
|
for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
|
|
|
|
curr->m_image = pattern->m_image;
|
|
|
|
pattern = pattern->next();
|
|
|
|
if (pattern == curr || !pattern)
|
|
|
|
pattern = this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (curr = this; curr && curr->isBackgroundXPositionSet(); curr = curr->next());
|
|
|
|
if (curr && curr != this) {
|
|
|
|
// We need to fill in the remaining values with the pattern specified.
|
|
|
|
for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
|
|
|
|
curr->m_xPosition = pattern->m_xPosition;
|
|
|
|
pattern = pattern->next();
|
|
|
|
if (pattern == curr || !pattern)
|
|
|
|
pattern = this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (curr = this; curr && curr->isBackgroundYPositionSet(); curr = curr->next());
|
|
|
|
if (curr && curr != this) {
|
|
|
|
// We need to fill in the remaining values with the pattern specified.
|
|
|
|
for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
|
|
|
|
curr->m_yPosition = pattern->m_yPosition;
|
|
|
|
pattern = pattern->next();
|
|
|
|
if (pattern == curr || !pattern)
|
|
|
|
pattern = this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (curr = this; curr && curr->isBackgroundAttachmentSet(); curr = curr->next());
|
|
|
|
if (curr && curr != this) {
|
|
|
|
// We need to fill in the remaining values with the pattern specified.
|
|
|
|
for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
|
|
|
|
curr->m_bgAttachment = pattern->m_bgAttachment;
|
|
|
|
pattern = pattern->next();
|
|
|
|
if (pattern == curr || !pattern)
|
|
|
|
pattern = this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (curr = this; curr && curr->isBackgroundClipSet(); curr = curr->next());
|
|
|
|
if (curr && curr != this) {
|
|
|
|
// We need to fill in the remaining values with the pattern specified.
|
|
|
|
for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
|
|
|
|
curr->m_bgClip = pattern->m_bgClip;
|
|
|
|
pattern = pattern->next();
|
|
|
|
if (pattern == curr || !pattern)
|
|
|
|
pattern = this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (curr = this; curr && curr->isBackgroundOriginSet(); curr = curr->next());
|
|
|
|
if (curr && curr != this) {
|
|
|
|
// We need to fill in the remaining values with the pattern specified.
|
|
|
|
for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
|
|
|
|
curr->m_bgOrigin = pattern->m_bgOrigin;
|
|
|
|
pattern = pattern->next();
|
|
|
|
if (pattern == curr || !pattern)
|
|
|
|
pattern = this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (curr = this; curr && curr->isBackgroundRepeatSet(); curr = curr->next());
|
|
|
|
if (curr && curr != this) {
|
|
|
|
// We need to fill in the remaining values with the pattern specified.
|
|
|
|
for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
|
|
|
|
curr->m_bgRepeat = pattern->m_bgRepeat;
|
|
|
|
pattern = pattern->next();
|
|
|
|
if (pattern == curr || !pattern)
|
|
|
|
pattern = this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (curr = this; curr && curr->isBackgroundSizeSet(); curr = curr->next());
|
|
|
|
if (curr && curr != this) {
|
|
|
|
// We need to fill in the remaining values with the pattern specified.
|
|
|
|
for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
|
|
|
|
curr->m_backgroundSize = pattern->m_backgroundSize;
|
|
|
|
pattern = pattern->next();
|
|
|
|
if (pattern == curr || !pattern)
|
|
|
|
pattern = this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BackgroundLayer::cullEmptyLayers()
|
|
|
|
{
|
|
|
|
BackgroundLayer *next;
|
|
|
|
for (BackgroundLayer *p = this; p; p = next) {
|
|
|
|
next = p->m_next;
|
|
|
|
if (next && !next->isBackgroundImageSet() &&
|
|
|
|
!next->isBackgroundXPositionSet() && !next->isBackgroundYPositionSet() &&
|
|
|
|
!next->isBackgroundAttachmentSet() && !next->isBackgroundClipSet() &&
|
|
|
|
!next->isBackgroundOriginSet() && !next->isBackgroundRepeatSet() &&
|
|
|
|
!next->isBackgroundSizeSet()) {
|
|
|
|
delete next;
|
|
|
|
p->m_next = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
StyleBackgroundData::StyleBackgroundData()
|
|
|
|
{}
|
|
|
|
|
|
|
|
StyleBackgroundData::StyleBackgroundData(const StyleBackgroundData& o)
|
|
|
|
: Shared<StyleBackgroundData>(), m_background(o.m_background), m_outline(o.m_outline)
|
|
|
|
{}
|
|
|
|
|
|
|
|
bool StyleBackgroundData::operator==(const StyleBackgroundData& o) const
|
|
|
|
{
|
|
|
|
return m_background == o.m_background && m_color == o.m_color && m_outline == o.m_outline;
|
|
|
|
}
|
|
|
|
|
|
|
|
StyleGeneratedData::StyleGeneratedData() : Shared<StyleGeneratedData>(), content(0), counter_reset(0), counter_increment(0) {}
|
|
|
|
|
|
|
|
StyleGeneratedData::~StyleGeneratedData()
|
|
|
|
{
|
|
|
|
if (counter_reset) counter_reset->deref();
|
|
|
|
if (counter_increment) counter_increment->deref();
|
|
|
|
delete content;
|
|
|
|
}
|
|
|
|
|
|
|
|
StyleGeneratedData::StyleGeneratedData(const StyleGeneratedData& o)
|
|
|
|
: Shared<StyleGeneratedData>(), content(0),
|
|
|
|
counter_reset(o.counter_reset), counter_increment(o.counter_increment)
|
|
|
|
{
|
|
|
|
if (o.content) content = new ContentData(*o.content);
|
|
|
|
if (counter_reset) counter_reset->ref();
|
|
|
|
if (counter_increment) counter_increment->ref();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StyleGeneratedData::contentDataEquivalent(const StyleGeneratedData* otherStyle) const
|
|
|
|
{
|
|
|
|
ContentData* c1 = content;
|
|
|
|
ContentData* c2 = otherStyle->content;
|
|
|
|
|
|
|
|
while (c1 && c2) {
|
|
|
|
if (c1->_contentType != c2->_contentType)
|
|
|
|
return false;
|
|
|
|
if (c1->_contentType == CONTENT_TEXT) {
|
|
|
|
DOM::DOMString c1Str(c1->_content.text);
|
|
|
|
DOM::DOMString c2Str(c2->_content.text);
|
|
|
|
if (c1Str != c2Str)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else if (c1->_contentType == CONTENT_OBJECT) {
|
|
|
|
if (c1->_content.object != c2->_content.object)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else if (c1->_contentType == CONTENT_COUNTER) {
|
|
|
|
if (c1->_content.counter != c2->_content.counter)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else if (c1->_contentType == CONTENT_QUOTE) {
|
|
|
|
if (c1->_content.quote != c2->_content.quote)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
c1 = c1->_nextContent;
|
|
|
|
c2 = c2->_nextContent;
|
|
|
|
}
|
|
|
|
|
|
|
|
return !c1 && !c2;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool compareCounterActList(const CSSValueListImpl* ca, const CSSValueListImpl* cb) {
|
|
|
|
// weeee....
|
|
|
|
CSSValueListImpl* a = const_cast<CSSValueListImpl*>(ca);
|
|
|
|
CSSValueListImpl* b = const_cast<CSSValueListImpl*>(cb);
|
|
|
|
|
|
|
|
if (!a && !b) return true;
|
|
|
|
if (!a || !b) return false;
|
|
|
|
if (a->length() != b->length()) return false;
|
|
|
|
for(uint i=0; i< a->length(); i++) {
|
|
|
|
CSSValueImpl *ai = a->item(i);
|
|
|
|
CSSValueImpl *bi = b->item(i);
|
|
|
|
assert(ai && ai->cssValueType() == CSSValue::CSS_CUSTOM);
|
|
|
|
assert(bi && bi->cssValueType() == CSSValue::CSS_CUSTOM);
|
|
|
|
CounterActImpl* caa = static_cast<CounterActImpl*>(ai);
|
|
|
|
CounterActImpl* cab = static_cast<CounterActImpl*>(bi);
|
|
|
|
if (caa->value() != cab->value()) return false;
|
|
|
|
if (caa->counter() != cab->counter()) return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StyleGeneratedData::counterDataEquivalent(const StyleGeneratedData* otherStyle) const
|
|
|
|
{
|
|
|
|
return compareCounterActList(counter_reset, otherStyle->counter_reset) &&
|
|
|
|
compareCounterActList(counter_increment, otherStyle->counter_increment);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StyleGeneratedData::operator==(const StyleGeneratedData& o) const
|
|
|
|
{
|
|
|
|
return contentDataEquivalent(&o) && counterDataEquivalent(&o);
|
|
|
|
}
|
|
|
|
|
|
|
|
StyleMarqueeData::StyleMarqueeData()
|
|
|
|
{
|
|
|
|
increment = RenderStyle::initialMarqueeIncrement();
|
|
|
|
speed = RenderStyle::initialMarqueeSpeed();
|
|
|
|
direction = RenderStyle::initialMarqueeDirection();
|
|
|
|
behavior = RenderStyle::initialMarqueeBehavior();
|
|
|
|
loops = RenderStyle::initialMarqueeLoopCount();
|
|
|
|
}
|
|
|
|
|
|
|
|
StyleMarqueeData::StyleMarqueeData(const StyleMarqueeData& o)
|
|
|
|
:Shared<StyleMarqueeData>(), increment(o.increment), speed(o.speed), loops(o.loops),
|
|
|
|
behavior(o.behavior), direction(o.direction)
|
|
|
|
{}
|
|
|
|
|
|
|
|
bool StyleMarqueeData::operator==(const StyleMarqueeData& o) const
|
|
|
|
{
|
|
|
|
return (increment == o.increment && speed == o.speed && direction == o.direction &&
|
|
|
|
behavior == o.behavior && loops == o.loops);
|
|
|
|
}
|
|
|
|
|
|
|
|
StyleCSS3NonInheritedData::StyleCSS3NonInheritedData()
|
|
|
|
:Shared<StyleCSS3NonInheritedData>()
|
|
|
|
, opacity(RenderStyle::initialOpacity())
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
StyleCSS3NonInheritedData::StyleCSS3NonInheritedData(const StyleCSS3NonInheritedData& o)
|
|
|
|
:Shared<StyleCSS3NonInheritedData>(),
|
|
|
|
opacity(o.opacity),
|
|
|
|
#ifdef APPLE_CHANGES
|
|
|
|
flexibleBox(o.flexibleBox),
|
|
|
|
#endif
|
|
|
|
marquee(o.marquee)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StyleCSS3NonInheritedData::operator==(const StyleCSS3NonInheritedData& o) const
|
|
|
|
{
|
|
|
|
return
|
|
|
|
opacity == o.opacity &&
|
|
|
|
#ifdef APPLE_CHANGES
|
|
|
|
flexibleBox == o.flexibleBox &&
|
|
|
|
#endif
|
|
|
|
marquee == o.marquee;
|
|
|
|
}
|
|
|
|
|
|
|
|
StyleCSS3InheritedData::StyleCSS3InheritedData()
|
|
|
|
:Shared<StyleCSS3InheritedData>(), textShadow(0), wordWrap(RenderStyle::initialWordWrap())
|
|
|
|
#ifdef APPLE_CHANGES
|
|
|
|
, userModify(READ_ONLY), textSizeAdjust(RenderStyle::initialTextSizeAdjust())
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
StyleCSS3InheritedData::StyleCSS3InheritedData(const StyleCSS3InheritedData& o)
|
|
|
|
:Shared<StyleCSS3InheritedData>()
|
|
|
|
{
|
|
|
|
textShadow = o.textShadow ? new ShadowData(*o.textShadow) : 0;
|
|
|
|
wordWrap = o.wordWrap;
|
|
|
|
#ifdef APPLE_CHANGES
|
|
|
|
userModify = o.userModify;
|
|
|
|
textSizeAdjust = o.textSizeAdjust;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
StyleCSS3InheritedData::~StyleCSS3InheritedData()
|
|
|
|
{
|
|
|
|
delete textShadow;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StyleCSS3InheritedData::operator==(const StyleCSS3InheritedData& o) const
|
|
|
|
{
|
|
|
|
return shadowDataEquivalent(o) && (wordWrap == o.wordWrap)
|
|
|
|
#ifdef APPLE_CHANGES
|
|
|
|
&& (userModify == o.userModify) && (textSizeAdjust == o.textSizeAdjust)
|
|
|
|
#endif
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StyleCSS3InheritedData::shadowDataEquivalent(const StyleCSS3InheritedData& o) const
|
|
|
|
{
|
|
|
|
if (!textShadow && o.textShadow || textShadow && !o.textShadow)
|
|
|
|
return false;
|
|
|
|
if (textShadow && o.textShadow && (*textShadow != *o.textShadow))
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
StyleInheritedData::StyleInheritedData()
|
|
|
|
: indent( RenderStyle::initialTextIndent() ), line_height( RenderStyle::initialLineHeight() ),
|
|
|
|
style_image( RenderStyle::initialListStyleImage() ),
|
|
|
|
font(), color( RenderStyle::initialColor() ),
|
|
|
|
border_hspacing( RenderStyle::initialBorderHorizontalSpacing() ),
|
|
|
|
border_vspacing( RenderStyle::initialBorderVerticalSpacing() ),
|
|
|
|
widows( RenderStyle::initialWidows() ), orphans( RenderStyle::initialOrphans() ),
|
|
|
|
quotes(0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
StyleInheritedData::~StyleInheritedData()
|
|
|
|
{
|
|
|
|
if (quotes) quotes->deref();
|
|
|
|
}
|
|
|
|
|
|
|
|
StyleInheritedData::StyleInheritedData(const StyleInheritedData& o )
|
|
|
|
: Shared<StyleInheritedData>(),
|
|
|
|
indent( o.indent ), line_height( o.line_height ), style_image( o.style_image ),
|
|
|
|
font( o.font ), color( o.color ),
|
|
|
|
border_hspacing( o.border_hspacing ),
|
|
|
|
border_vspacing( o.border_vspacing ),
|
|
|
|
widows(o.widows), orphans(o.orphans)
|
|
|
|
{
|
|
|
|
quotes = o.quotes;
|
|
|
|
if (quotes) quotes->ref();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StyleInheritedData::operator==(const StyleInheritedData& o) const
|
|
|
|
{
|
|
|
|
return
|
|
|
|
indent == o.indent &&
|
|
|
|
line_height == o.line_height &&
|
|
|
|
border_hspacing == o.border_hspacing &&
|
|
|
|
border_vspacing == o.border_vspacing &&
|
|
|
|
style_image == o.style_image &&
|
|
|
|
font == o.font &&
|
|
|
|
color == o.color &&
|
|
|
|
border_hspacing == o.border_hspacing &&
|
|
|
|
border_vspacing == o.border_vspacing &&
|
|
|
|
quotes == o.quotes &&
|
|
|
|
widows == o.widows &&
|
|
|
|
orphans == o.orphans ;
|
|
|
|
|
|
|
|
// doesn't work because structs are not packed
|
|
|
|
//return memcmp(this, &o, sizeof(*this))==0;
|
|
|
|
}
|
|
|
|
|
|
|
|
RenderStyle::RenderStyle()
|
|
|
|
{
|
|
|
|
// counter++;
|
|
|
|
if (!_default)
|
|
|
|
_default = new RenderStyle(true);
|
|
|
|
|
|
|
|
box = _default->box;
|
|
|
|
visual = _default->visual;
|
|
|
|
background = _default->background;
|
|
|
|
surround = _default->surround;
|
|
|
|
generated = _default->generated;
|
|
|
|
css3NonInheritedData = _default->css3NonInheritedData;
|
|
|
|
css3InheritedData = _default->css3InheritedData;
|
|
|
|
|
|
|
|
inherited = _default->inherited;
|
|
|
|
|
|
|
|
setBitDefaults();
|
|
|
|
|
|
|
|
pseudoStyle = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
RenderStyle::RenderStyle(bool)
|
|
|
|
{
|
|
|
|
setBitDefaults();
|
|
|
|
|
|
|
|
box.init();
|
|
|
|
visual.init();
|
|
|
|
background.init();
|
|
|
|
surround.init();
|
|
|
|
generated.init();
|
|
|
|
css3NonInheritedData.init();
|
|
|
|
#ifdef APPLE_CHANGES // ### yet to be merged
|
|
|
|
css3NonInheritedData.access()->flexibleBox.init();
|
|
|
|
#endif
|
|
|
|
css3NonInheritedData.access()->marquee.init();
|
|
|
|
css3InheritedData.init();
|
|
|
|
inherited.init();
|
|
|
|
|
|
|
|
pseudoStyle = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
RenderStyle::RenderStyle(const RenderStyle& o)
|
|
|
|
: Shared<RenderStyle>(),
|
|
|
|
inherited_flags( o.inherited_flags ), noninherited_flags( o.noninherited_flags ),
|
|
|
|
box( o.box ), visual( o.visual ), background( o.background ), surround( o.surround ), generated(o.generated),
|
|
|
|
css3NonInheritedData( o.css3NonInheritedData ), css3InheritedData( o.css3InheritedData ),
|
|
|
|
inherited( o.inherited ), pseudoStyle( 0 )
|
|
|
|
{}
|
|
|
|
|
|
|
|
void RenderStyle::inheritFrom(const RenderStyle* inheritParent)
|
|
|
|
{
|
|
|
|
css3InheritedData = inheritParent->css3InheritedData;
|
|
|
|
inherited = inheritParent->inherited;
|
|
|
|
inherited_flags = inheritParent->inherited_flags;
|
|
|
|
|
|
|
|
// Simulate ":after,:before { white-space: pre-line }"
|
|
|
|
if (styleType() == AFTER || styleType() == BEFORE)
|
|
|
|
setWhiteSpace(PRE_LINE);
|
|
|
|
}
|
|
|
|
|
|
|
|
RenderStyle::~RenderStyle()
|
|
|
|
{
|
|
|
|
RenderStyle *ps = pseudoStyle;
|
|
|
|
RenderStyle *prev = 0;
|
|
|
|
|
|
|
|
while (ps) {
|
|
|
|
prev = ps;
|
|
|
|
ps = ps->pseudoStyle;
|
|
|
|
// to prevent a double deletion.
|
|
|
|
// this works only because the styles below aren't really shared
|
|
|
|
// Dirk said we need another construct as soon as these are shared
|
|
|
|
prev->pseudoStyle = 0;
|
|
|
|
prev->deref();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool RenderStyle::operator==(const RenderStyle& o) const
|
|
|
|
{
|
|
|
|
// compare everything except the pseudoStyle pointer
|
|
|
|
return (inherited_flags == o.inherited_flags &&
|
|
|
|
noninherited_flags == o.noninherited_flags &&
|
|
|
|
box == o.box &&
|
|
|
|
visual == o.visual &&
|
|
|
|
background == o.background &&
|
|
|
|
surround == o.surround &&
|
|
|
|
generated == o.generated &&
|
|
|
|
css3NonInheritedData == o.css3NonInheritedData &&
|
|
|
|
css3InheritedData == o.css3InheritedData &&
|
|
|
|
inherited == o.inherited);
|
|
|
|
}
|
|
|
|
|
|
|
|
enum EPseudoBit { NO_BIT = 0x0,
|
|
|
|
FIRST_LINE_BIT = 0x1, FIRST_LETTER_BIT = 0x2, SELECTION_BIT = 0x4,
|
|
|
|
BEFORE_BIT = 0x8, AFTER_BIT = 0x10, MARKER_BIT = 0x20,
|
|
|
|
REPLACED_BIT = 0x40
|
|
|
|
};
|
|
|
|
|
|
|
|
static int pseudoBit(RenderStyle::PseudoId pseudo)
|
|
|
|
{
|
|
|
|
switch (pseudo) {
|
|
|
|
case RenderStyle::BEFORE:
|
|
|
|
return BEFORE_BIT;
|
|
|
|
case RenderStyle::AFTER:
|
|
|
|
return AFTER_BIT;
|
|
|
|
case RenderStyle::MARKER:
|
|
|
|
return MARKER_BIT;
|
|
|
|
case RenderStyle::REPLACED:
|
|
|
|
return REPLACED_BIT;
|
|
|
|
case RenderStyle::FIRST_LINE:
|
|
|
|
return FIRST_LINE_BIT;
|
|
|
|
case RenderStyle::FIRST_LETTER:
|
|
|
|
return FIRST_LETTER_BIT;
|
|
|
|
case RenderStyle::SELECTION:
|
|
|
|
return SELECTION_BIT;
|
|
|
|
default:
|
|
|
|
return NO_BIT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool RenderStyle::hasPseudoStyle(PseudoId pseudo) const
|
|
|
|
{
|
|
|
|
return (pseudoBit(pseudo) & noninherited_flags.f._pseudoBits) != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderStyle::setHasPseudoStyle(PseudoId pseudo, bool b)
|
|
|
|
{
|
|
|
|
if (b)
|
|
|
|
noninherited_flags.f._pseudoBits |= pseudoBit(pseudo);
|
|
|
|
else
|
|
|
|
noninherited_flags.f._pseudoBits &= ~(pseudoBit(pseudo));
|
|
|
|
}
|
|
|
|
|
|
|
|
RenderStyle* RenderStyle::getPseudoStyle(PseudoId pid) const
|
|
|
|
{
|
|
|
|
if (!hasPseudoStyle(pid)) return 0;
|
|
|
|
|
|
|
|
RenderStyle *ps = 0;
|
|
|
|
if (noninherited_flags.f._styleType==NOPSEUDO)
|
|
|
|
for (ps = pseudoStyle; ps; ps = ps->pseudoStyle)
|
|
|
|
if (ps->noninherited_flags.f._styleType==pid)
|
|
|
|
break;
|
|
|
|
return ps;
|
|
|
|
}
|
|
|
|
|
|
|
|
RenderStyle* RenderStyle::addPseudoStyle(PseudoId pid)
|
|
|
|
{
|
|
|
|
if (hasPseudoStyle(pid)) return getPseudoStyle(pid);
|
|
|
|
|
|
|
|
RenderStyle *ps = 0;
|
|
|
|
|
|
|
|
switch (pid) {
|
|
|
|
case FIRST_LETTER: // pseudo-elements (FIRST_LINE has a special handling)
|
|
|
|
case SELECTION:
|
|
|
|
case BEFORE:
|
|
|
|
case AFTER:
|
|
|
|
ps = new RenderStyle();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ps = new RenderStyle(*this); // use the real copy constructor to get an identical copy
|
|
|
|
}
|
|
|
|
ps->ref();
|
|
|
|
ps->noninherited_flags.f._styleType = pid;
|
|
|
|
ps->pseudoStyle = pseudoStyle;
|
|
|
|
|
|
|
|
pseudoStyle = ps;
|
|
|
|
|
|
|
|
setHasPseudoStyle(pid, true);
|
|
|
|
|
|
|
|
return ps;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderStyle::removePseudoStyle(PseudoId pid)
|
|
|
|
{
|
|
|
|
RenderStyle *ps = pseudoStyle;
|
|
|
|
RenderStyle *prev = this;
|
|
|
|
|
|
|
|
while (ps) {
|
|
|
|
if (ps->noninherited_flags.f._styleType==pid) {
|
|
|
|
prev->pseudoStyle = ps->pseudoStyle;
|
|
|
|
ps->deref();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
prev = ps;
|
|
|
|
ps = ps->pseudoStyle;
|
|
|
|
}
|
|
|
|
|
|
|
|
setHasPseudoStyle(pid, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool RenderStyle::inheritedNotEqual( RenderStyle *other ) const
|
|
|
|
{
|
|
|
|
return
|
|
|
|
(
|
|
|
|
inherited_flags != other->inherited_flags ||
|
|
|
|
inherited != other->inherited ||
|
|
|
|
css3InheritedData != other->css3InheritedData
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
compares two styles. The result gives an idea of the action that
|
|
|
|
needs to be taken when replacing the old style with a new one.
|
|
|
|
|
|
|
|
CbLayout: The containing block of the object needs a retqlayout.
|
|
|
|
Layout: the RenderObject needs a retqlayout after the style change
|
|
|
|
Visible: The change is visible, but no retqlayout is needed
|
|
|
|
NonVisible: The object does need neither tqrepaint nor retqlayout after
|
|
|
|
the change.
|
|
|
|
|
|
|
|
### TODO:
|
|
|
|
A lot can be optimised here based on the display type, lots of
|
|
|
|
optimisations are unimplemented, and currently result in the
|
|
|
|
worst case result causing a retqlayout of the containing block.
|
|
|
|
*/
|
|
|
|
RenderStyle::Diff RenderStyle::diff( const RenderStyle *other ) const
|
|
|
|
{
|
|
|
|
// we anyway assume they are the same
|
|
|
|
// EDisplay _display : 5;
|
|
|
|
|
|
|
|
// NonVisible:
|
|
|
|
// ECursor _cursor_style : 4;
|
|
|
|
// EUserInput _user_input : 2; as long as :enabled is not impl'd
|
|
|
|
|
|
|
|
// ### this needs work to know more exactly if we need a retqlayout
|
|
|
|
// or just a tqrepaint
|
|
|
|
|
|
|
|
// non-inherited attributes
|
|
|
|
// DataRef<StyleBoxData> box;
|
|
|
|
// DataRef<StyleVisualData> visual;
|
|
|
|
// DataRef<StyleSurroundData> surround;
|
|
|
|
|
|
|
|
// inherited attributes
|
|
|
|
// DataRef<StyleInheritedData> inherited;
|
|
|
|
|
|
|
|
if ( *box.get() != *other->box.get() ||
|
|
|
|
*visual.get() != *other->visual.get() ||
|
|
|
|
(*surround.get() != *other->surround.get()
|
|
|
|
&& (other->position() == STATIC || other->position() != position())) ||
|
|
|
|
!(inherited->indent == other->inherited->indent) ||
|
|
|
|
!(inherited->line_height == other->inherited->line_height) ||
|
|
|
|
!(inherited->style_image == other->inherited->style_image) ||
|
|
|
|
!(inherited->font == other->inherited->font) ||
|
|
|
|
!(inherited->border_hspacing == other->inherited->border_hspacing) ||
|
|
|
|
!(inherited->border_vspacing == other->inherited->border_vspacing) ||
|
|
|
|
!(inherited_flags.f._visuallyOrdered == other->inherited_flags.f._visuallyOrdered) ||
|
|
|
|
!(inherited_flags.f._htmlHacks == other->inherited_flags.f._htmlHacks) ||
|
|
|
|
!(noninherited_flags.f._textOverflow == other->noninherited_flags.f._textOverflow) )
|
|
|
|
return CbLayout;
|
|
|
|
|
|
|
|
// changes causing Layout changes:
|
|
|
|
|
|
|
|
// only for tables:
|
|
|
|
// _border_collapse
|
|
|
|
// EEmptyCell _empty_cells : 2 ;
|
|
|
|
// ECaptionSide _caption_side : 2;
|
|
|
|
// ETableLayout _table_tqlayout : 1;
|
|
|
|
// EPosition _position : 2;
|
|
|
|
// EFloat _floating : 2;
|
|
|
|
if ( ((int)noninherited_flags.f._display) >= TABLE ) {
|
|
|
|
if ( !(inherited_flags.f._empty_cells == other->inherited_flags.f._empty_cells) ||
|
|
|
|
!(inherited_flags.f._caption_side == other->inherited_flags.f._caption_side) ||
|
|
|
|
!(inherited_flags.f._border_collapse == other->inherited_flags.f._border_collapse) ||
|
|
|
|
!(noninherited_flags.f._table_tqlayout == other->noninherited_flags.f._table_tqlayout) ||
|
|
|
|
!(noninherited_flags.f._position == other->noninherited_flags.f._position) ||
|
|
|
|
!(noninherited_flags.f._floating == other->noninherited_flags.f._floating) ||
|
|
|
|
!(noninherited_flags.f._flowAroundFloats == other->noninherited_flags.f._flowAroundFloats) ||
|
|
|
|
!(noninherited_flags.f._tqunicodeBidi == other->noninherited_flags.f._tqunicodeBidi) )
|
|
|
|
return CbLayout;
|
|
|
|
}
|
|
|
|
|
|
|
|
// only for lists:
|
|
|
|
// EListStyleType _list_style_type : 5 ;
|
|
|
|
// EListStylePosition _list_style_position :1;
|
|
|
|
if (noninherited_flags.f._display == LIST_ITEM ) {
|
|
|
|
if ( !(inherited_flags.f._list_style_type == other->inherited_flags.f._list_style_type) ||
|
|
|
|
!(inherited_flags.f._list_style_position == other->inherited_flags.f._list_style_position) )
|
|
|
|
return Layout;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ### These could be better optimised
|
|
|
|
// ETextAlign _text_align : 3;
|
|
|
|
// ETextTransform _text_transform : 4;
|
|
|
|
// EDirection _direction : 1;
|
|
|
|
// EWhiteSpace _white_space : 2;
|
|
|
|
// EClear _clear : 2;
|
|
|
|
if ( !(inherited_flags.f._text_align == other->inherited_flags.f._text_align) ||
|
|
|
|
!(inherited_flags.f._text_transform == other->inherited_flags.f._text_transform) ||
|
|
|
|
!(inherited_flags.f._direction == other->inherited_flags.f._direction) ||
|
|
|
|
!(inherited_flags.f._white_space == other->inherited_flags.f._white_space) ||
|
|
|
|
!(noninherited_flags.f._clear == other->noninherited_flags.f._clear)
|
|
|
|
)
|
|
|
|
return Layout;
|
|
|
|
|
|
|
|
// Overflow returns a tqlayout hint.
|
|
|
|
if (noninherited_flags.f._overflowX != other->noninherited_flags.f._overflowX ||
|
|
|
|
noninherited_flags.f._overflowY != other->noninherited_flags.f._overflowY)
|
|
|
|
return Layout;
|
|
|
|
|
|
|
|
// only for inline:
|
|
|
|
// EVerticalAlign _vertical_align : 4;
|
|
|
|
|
|
|
|
if ( !(noninherited_flags.f._display == INLINE) &&
|
|
|
|
!(noninherited_flags.f._vertical_align == other->noninherited_flags.f._vertical_align) )
|
|
|
|
return Layout;
|
|
|
|
|
|
|
|
if (*surround.get() != *other->surround.get()) {
|
|
|
|
assert( other->position() != STATIC ); // this style is positioned or relatively positioned
|
|
|
|
if ( surround->hasSamePBMData(*other->surround.get()) && // padding/border/margin are identical
|
|
|
|
(other->position() == RELATIVE ||
|
|
|
|
!(other->left().isVariable() && other->right().isVariable()) && // X isn't static
|
|
|
|
!(other->top().isVariable() && other->bottom().isVariable()) )) // neither is Y
|
|
|
|
// therefore only the offset is different
|
|
|
|
return Position;
|
|
|
|
return Layout;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Visible:
|
|
|
|
// EVisibility _visibility : 2;
|
|
|
|
// int _text_decorations : 4;
|
|
|
|
// DataRef<StyleBackgroundData> background;
|
|
|
|
if (inherited->color != other->inherited->color ||
|
|
|
|
!(inherited_flags.f._visibility == other->inherited_flags.f._visibility) ||
|
|
|
|
!(inherited_flags.f._text_decorations == other->inherited_flags.f._text_decorations) ||
|
|
|
|
!(noninherited_flags.f._hasClip == other->noninherited_flags.f._hasClip) ||
|
|
|
|
visual->textDecoration != other->visual->textDecoration ||
|
|
|
|
*background.get() != *other->background.get() ||
|
|
|
|
css3NonInheritedData->opacity != other->css3NonInheritedData->opacity ||
|
|
|
|
!css3InheritedData->shadowDataEquivalent(*other->css3InheritedData.get())
|
|
|
|
)
|
|
|
|
return Visible;
|
|
|
|
|
|
|
|
RenderStyle::Diff ch = Equal;
|
|
|
|
// Check for visible pseudo-changes:
|
|
|
|
if (hasPseudoStyle(FIRST_LINE) != other->hasPseudoStyle(FIRST_LINE))
|
|
|
|
ch = Visible;
|
|
|
|
else
|
|
|
|
if (hasPseudoStyle(FIRST_LINE) && other->hasPseudoStyle(FIRST_LINE))
|
|
|
|
ch = getPseudoStyle(FIRST_LINE)->diff(other->getPseudoStyle(FIRST_LINE));
|
|
|
|
|
|
|
|
if (ch != Equal) return ch;
|
|
|
|
|
|
|
|
// Check for visible pseudo-changes:
|
|
|
|
if (hasPseudoStyle(SELECTION) != other->hasPseudoStyle(SELECTION))
|
|
|
|
ch = Visible;
|
|
|
|
else
|
|
|
|
if (hasPseudoStyle(SELECTION) && other->hasPseudoStyle(SELECTION))
|
|
|
|
ch = getPseudoStyle(SELECTION)->diff(other->getPseudoStyle(SELECTION));
|
|
|
|
|
|
|
|
return ch;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
RenderStyle* RenderStyle::_default = 0;
|
|
|
|
|
|
|
|
void RenderStyle::cleanup()
|
|
|
|
{
|
|
|
|
delete _default;
|
|
|
|
_default = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderStyle::setPaletteColor(TQPalette::ColorGroup g, TQColorGroup::ColorRole r, const TQColor& c)
|
|
|
|
{
|
|
|
|
visual.access()->palette.setColor(g,r,c);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderStyle::adjustBackgroundLayers()
|
|
|
|
{
|
|
|
|
if (backgroundLayers()->next()) {
|
|
|
|
// First we cull out layers that have no properties set.
|
|
|
|
accessBackgroundLayers()->cullEmptyLayers();
|
|
|
|
|
|
|
|
// Next we repeat patterns into layers that don't have some properties set.
|
|
|
|
accessBackgroundLayers()->fillUnsetProperties();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderStyle::setClip( Length top, Length right, Length bottom, Length left )
|
|
|
|
{
|
|
|
|
StyleVisualData *data = visual.access();
|
|
|
|
data->clip.top = top;
|
|
|
|
data->clip.right = right;
|
|
|
|
data->clip.bottom = bottom;
|
|
|
|
data->clip.left = left;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderStyle::setQuotes(DOM::QuotesValueImpl* q)
|
|
|
|
{
|
|
|
|
DOM::QuotesValueImpl *t = inherited->quotes;
|
|
|
|
inherited.access()->quotes = q;
|
|
|
|
if (q) q->ref();
|
|
|
|
if (t) t->deref();
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString RenderStyle::openQuote(int level) const
|
|
|
|
{
|
|
|
|
if (inherited->quotes)
|
|
|
|
return inherited->quotes->openQuote(level);
|
|
|
|
else
|
|
|
|
return "\""; // 0 is default quotes
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString RenderStyle::closeQuote(int level) const
|
|
|
|
{
|
|
|
|
if (inherited->quotes)
|
|
|
|
return inherited->quotes->closeQuote(level);
|
|
|
|
else
|
|
|
|
return "\""; // 0 is default quotes
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderStyle::addContent(CachedObject* o)
|
|
|
|
{
|
|
|
|
if (!o)
|
|
|
|
return; // The object is null. Nothing to do. Just bail.
|
|
|
|
|
|
|
|
StyleGeneratedData *t_generated = generated.access();
|
|
|
|
|
|
|
|
ContentData* lastContent = t_generated->content;
|
|
|
|
while (lastContent && lastContent->_nextContent)
|
|
|
|
lastContent = lastContent->_nextContent;
|
|
|
|
|
|
|
|
ContentData* newContentData = new ContentData;
|
|
|
|
|
|
|
|
if (lastContent)
|
|
|
|
lastContent->_nextContent = newContentData;
|
|
|
|
else
|
|
|
|
t_generated->content = newContentData;
|
|
|
|
|
|
|
|
// o->ref();
|
|
|
|
newContentData->_content.object = o;
|
|
|
|
newContentData->_contentType = CONTENT_OBJECT;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderStyle::addContent(DOM::DOMStringImpl* s)
|
|
|
|
{
|
|
|
|
if (!s)
|
|
|
|
return; // The string is null. Nothing to do. Just bail.
|
|
|
|
|
|
|
|
StyleGeneratedData *t_generated = generated.access();
|
|
|
|
|
|
|
|
ContentData* lastContent = t_generated->content;
|
|
|
|
while (lastContent && lastContent->_nextContent)
|
|
|
|
lastContent = lastContent->_nextContent;
|
|
|
|
|
|
|
|
if (lastContent) {
|
|
|
|
if (lastContent->_contentType == CONTENT_TEXT) {
|
|
|
|
// We can augment the existing string and share this ContentData node.
|
|
|
|
DOMStringImpl* oldStr = lastContent->_content.text;
|
|
|
|
DOMStringImpl* newStr = oldStr->copy();
|
|
|
|
newStr->ref();
|
|
|
|
oldStr->deref();
|
|
|
|
newStr->append(s);
|
|
|
|
lastContent->_content.text = newStr;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ContentData* newContentData = new ContentData;
|
|
|
|
|
|
|
|
if (lastContent)
|
|
|
|
lastContent->_nextContent = newContentData;
|
|
|
|
else
|
|
|
|
t_generated->content = newContentData;
|
|
|
|
|
|
|
|
newContentData->_content.text = s;
|
|
|
|
newContentData->_content.text->ref();
|
|
|
|
newContentData->_contentType = CONTENT_TEXT;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderStyle::addContent(DOM::CounterImpl* c)
|
|
|
|
{
|
|
|
|
if (!c)
|
|
|
|
return;
|
|
|
|
|
|
|
|
StyleGeneratedData *t_generated = generated.access();
|
|
|
|
|
|
|
|
ContentData* lastContent = t_generated->content;
|
|
|
|
while (lastContent && lastContent->_nextContent)
|
|
|
|
lastContent = lastContent->_nextContent;
|
|
|
|
|
|
|
|
ContentData* newContentData = new ContentData;
|
|
|
|
|
|
|
|
if (lastContent)
|
|
|
|
lastContent->_nextContent = newContentData;
|
|
|
|
else
|
|
|
|
t_generated->content = newContentData;
|
|
|
|
|
|
|
|
c->ref();
|
|
|
|
newContentData->_content.counter = c;
|
|
|
|
newContentData->_contentType = CONTENT_COUNTER;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderStyle::addContent(EQuoteContent q)
|
|
|
|
{
|
|
|
|
if (q == NO_QUOTE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
StyleGeneratedData *t_generated = generated.access();
|
|
|
|
|
|
|
|
ContentData* lastContent = t_generated->content;
|
|
|
|
while (lastContent && lastContent->_nextContent)
|
|
|
|
lastContent = lastContent->_nextContent;
|
|
|
|
|
|
|
|
ContentData* newContentData = new ContentData;
|
|
|
|
|
|
|
|
if (lastContent)
|
|
|
|
lastContent->_nextContent = newContentData;
|
|
|
|
else
|
|
|
|
t_generated->content = newContentData;
|
|
|
|
|
|
|
|
newContentData->_content.quote = q;
|
|
|
|
newContentData->_contentType = CONTENT_QUOTE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// content: normal is the same as having no content at all
|
|
|
|
void RenderStyle::setContentNormal() {
|
|
|
|
if (generated->content != 0) {
|
|
|
|
delete generated->content;
|
|
|
|
generated.access()->content = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// content: none, add an empty content node
|
|
|
|
void RenderStyle::setContentNone() {
|
|
|
|
setContentNormal();
|
|
|
|
generated.access()->content = new ContentData;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderStyle::setContentData(ContentData *data) {
|
|
|
|
if (data != generated->content) {
|
|
|
|
if (data)
|
|
|
|
generated.access()->content = new ContentData(*data);
|
|
|
|
else
|
|
|
|
generated.access()->content = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ContentData::ContentData(const ContentData& o) : _contentType(o._contentType)
|
|
|
|
{
|
|
|
|
switch (_contentType) {
|
|
|
|
case CONTENT_OBJECT:
|
|
|
|
_content.object = o._content.object;
|
|
|
|
break;
|
|
|
|
case CONTENT_TEXT:
|
|
|
|
_content.text = o._content.text;
|
|
|
|
_content.text->ref();
|
|
|
|
break;
|
|
|
|
case CONTENT_COUNTER:
|
|
|
|
_content.counter = o._content.counter;
|
|
|
|
_content.counter->ref();
|
|
|
|
break;
|
|
|
|
case CONTENT_QUOTE:
|
|
|
|
_content.quote = o._content.quote;
|
|
|
|
break;
|
|
|
|
case CONTENT_NONE:
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
_nextContent = o._nextContent ? new ContentData(*o._nextContent) : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ContentData::~ContentData()
|
|
|
|
{
|
|
|
|
clearContent();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ContentData::clearContent()
|
|
|
|
{
|
|
|
|
delete _nextContent;
|
|
|
|
_nextContent = 0;
|
|
|
|
|
|
|
|
switch (_contentType)
|
|
|
|
{
|
|
|
|
case CONTENT_OBJECT:
|
|
|
|
_content.object = 0;
|
|
|
|
break;
|
|
|
|
case CONTENT_TEXT:
|
|
|
|
_content.text->deref();
|
|
|
|
_content.text = 0;
|
|
|
|
break;
|
|
|
|
case CONTENT_COUNTER:
|
|
|
|
_content.counter->deref();
|
|
|
|
_content.counter = 0;
|
|
|
|
break;
|
|
|
|
case CONTENT_QUOTE:
|
|
|
|
_content.quote = NO_QUOTE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderStyle::setTextShadow(ShadowData* val, bool add)
|
|
|
|
{
|
|
|
|
StyleCSS3InheritedData* css3Data = css3InheritedData.access();
|
|
|
|
if (!add) {
|
|
|
|
delete css3Data->textShadow;
|
|
|
|
css3Data->textShadow = val;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ShadowData* last = css3Data->textShadow;
|
|
|
|
while (last->next) last = last->next;
|
|
|
|
last->next = val;
|
|
|
|
}
|
|
|
|
|
|
|
|
ShadowData::ShadowData(const ShadowData& o)
|
|
|
|
:x(o.x), y(o.y), blur(o.blur), color(o.color)
|
|
|
|
{
|
|
|
|
next = o.next ? new ShadowData(*o.next) : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ShadowData::operator==(const ShadowData& o) const
|
|
|
|
{
|
|
|
|
if ((next && !o.next) || (!next && o.next) ||
|
|
|
|
(next && o.next && *next != *o.next))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return x == o.x && y == o.y && blur == o.blur && color == o.color;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool hasCounter(const DOM::DOMString& c, CSSValueListImpl *l)
|
|
|
|
{
|
|
|
|
int len = l->length();
|
|
|
|
for(int i=0; i<len; i++) {
|
|
|
|
CounterActImpl* ca = static_cast<CounterActImpl*>(l->item(i));
|
|
|
|
Q_ASSERT(ca != 0);
|
|
|
|
if (ca->m_counter == c) return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool RenderStyle::hasCounterReset(const DOM::DOMString& c) const
|
|
|
|
{
|
|
|
|
if (generated->counter_reset)
|
|
|
|
return hasCounter(c, generated->counter_reset);
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool RenderStyle::hasCounterIncrement(const DOM::DOMString& c) const
|
|
|
|
{
|
|
|
|
if (generated->counter_increment)
|
|
|
|
return hasCounter(c, generated->counter_increment);
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static short readCounter(const DOM::DOMString& c, CSSValueListImpl *l)
|
|
|
|
{
|
|
|
|
int len = l->length();
|
|
|
|
for(int i=0; i<len; i++) {
|
|
|
|
CounterActImpl* ca = static_cast<CounterActImpl*>(l->item(i));
|
|
|
|
Q_ASSERT(ca != 0);
|
|
|
|
if (ca->m_counter == c) return ca->m_value;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
short RenderStyle::counterReset(const DOM::DOMString& c) const
|
|
|
|
{
|
|
|
|
if (generated->counter_reset)
|
|
|
|
return readCounter(c, generated->counter_reset);
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
short RenderStyle::counterIncrement(const DOM::DOMString& c) const
|
|
|
|
{
|
|
|
|
if (generated->counter_increment)
|
|
|
|
return readCounter(c, generated->counter_increment);
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderStyle::setCounterReset(CSSValueListImpl *l)
|
|
|
|
{
|
|
|
|
CSSValueListImpl *t = generated->counter_reset;
|
|
|
|
generated.access()->counter_reset = l;
|
|
|
|
if (l) l->ref();
|
|
|
|
if (t) t->deref();
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderStyle::setCounterIncrement(CSSValueListImpl *l)
|
|
|
|
{
|
|
|
|
CSSValueListImpl *t = generated->counter_increment;
|
|
|
|
generated.access()->counter_increment = l;
|
|
|
|
if (l) l->ref();
|
|
|
|
if (t) t->deref();
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef ENABLE_DUMP
|
|
|
|
|
|
|
|
static TQString describeFont( const TQFont &f)
|
|
|
|
{
|
|
|
|
TQString res = "'" + f.family() + "' ";
|
|
|
|
|
|
|
|
if ( f.pointSize() > 0)
|
|
|
|
res += TQString::number( f.pointSize() ) + "pt";
|
|
|
|
else
|
|
|
|
res += TQString::number( f.pixelSize() ) + "px";
|
|
|
|
|
|
|
|
if ( f.bold() )
|
|
|
|
res += " bold";
|
|
|
|
if ( f.italic() )
|
|
|
|
res += " italic";
|
|
|
|
if ( f.underline() )
|
|
|
|
res += " underline";
|
|
|
|
if ( f.overline() )
|
|
|
|
res += " overline";
|
|
|
|
if ( f.strikeOut() )
|
|
|
|
res += " strikeout";
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString RenderStyle::createDiff( const RenderStyle &parent ) const
|
|
|
|
{
|
|
|
|
TQString res;
|
|
|
|
if ( color().isValid() && parent.color() != color() )
|
|
|
|
res += " [color=" + color().name() + "]";
|
|
|
|
if ( backgroundColor().isValid() && parent.backgroundColor() != backgroundColor() )
|
|
|
|
res += " [bgcolor=" + backgroundColor().name() + "]";
|
|
|
|
if ( parent.font() != font() )
|
|
|
|
res += " [font=" + describeFont( font() ) + "]";
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
RenderPageStyle::RenderPageStyle() : next(0), m_pageType(ANY_PAGE)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
RenderPageStyle::~RenderPageStyle()
|
|
|
|
{
|
|
|
|
delete next;
|
|
|
|
}
|
|
|
|
|
|
|
|
RenderPageStyle* RenderPageStyle::getPageStyle(PageType type)
|
|
|
|
{
|
|
|
|
RenderPageStyle *ps = 0;
|
|
|
|
for (ps = this; ps; ps = ps->next)
|
|
|
|
if (ps->m_pageType==type)
|
|
|
|
break;
|
|
|
|
return ps;
|
|
|
|
}
|
|
|
|
|
|
|
|
RenderPageStyle* RenderPageStyle::addPageStyle(PageType type)
|
|
|
|
{
|
|
|
|
RenderPageStyle *ps = getPageStyle(type);
|
|
|
|
|
|
|
|
if (!ps)
|
|
|
|
{
|
|
|
|
ps = new RenderPageStyle(*this); // use the real copy constructor to get an identical copy
|
|
|
|
ps->m_pageType = type;
|
|
|
|
|
|
|
|
ps->next = next;
|
|
|
|
next = ps;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ps;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderPageStyle::removePageStyle(PageType type)
|
|
|
|
{
|
|
|
|
RenderPageStyle *ps = next;
|
|
|
|
RenderPageStyle *prev = this;
|
|
|
|
|
|
|
|
while (ps) {
|
|
|
|
if (ps->m_pageType==type) {
|
|
|
|
prev->next = ps->next;
|
|
|
|
delete ps;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
prev = ps;
|
|
|
|
ps = ps->next;
|
|
|
|
}
|
|
|
|
}
|