File indexing completed on 2024-04-28 15:23:52

0001 /*
0002  * This file is part of the HTML rendering engine for KDE.
0003  *
0004  * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
0005  *
0006  * This library is free software; you can redistribute it and/or
0007  * modify it under the terms of the GNU Library General Public
0008  * License as published by the Free Software Foundation; either
0009  * version 2 of the License, or (at your option) any later version.
0010  *
0011  * This library is distributed in the hope that it will be useful,
0012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014  * Library General Public License for more details.
0015  *
0016  * You should have received a copy of the GNU Library General Public License
0017  * along with this library; see the file COPYING.LIB.  If not, write to
0018  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0019  * Boston, MA 02110-1301, USA.
0020  *
0021  */
0022 
0023 #include "rendering/counter_tree.h"
0024 
0025 namespace khtml
0026 {
0027 
0028 CounterNode::CounterNode(RenderObject *o)
0029     : m_hasCounters(false), m_isVisual(false),
0030       m_value(0), m_count(0), m_parent(nullptr), m_previous(nullptr), m_next(nullptr),
0031       m_renderer(o) {}
0032 
0033 CounterNode::~CounterNode()
0034 {
0035     if (m_parent) {
0036         m_parent->removeChild(this);
0037     }
0038 }
0039 
0040 void CounterNode::insertAfter(CounterNode *, CounterNode *)
0041 {
0042     Q_ASSERT(false);
0043 }
0044 
0045 void CounterNode::removeChild(CounterNode *)
0046 {
0047     Q_ASSERT(false);
0048 }
0049 
0050 void CounterNode::remove()
0051 {
0052     if (m_parent) {
0053         m_parent->removeChild(this);
0054     } else {
0055         Q_ASSERT(isReset());
0056         // abandon our children
0057         CounterNode *n = firstChild();
0058         for (; n; n = n->m_next) {
0059             n->m_parent = nullptr;
0060         }
0061     }
0062 }
0063 
0064 void CounterNode::setHasCounters()
0065 {
0066     m_hasCounters = true;
0067     if (parent()) {
0068         parent()->setHasCounters();
0069     }
0070 }
0071 
0072 void CounterNode::recount(bool first)
0073 {
0074     int old_count = m_count;
0075     if (m_previous) {
0076         m_count = m_previous->count() + m_value;
0077     } else {
0078         assert(m_parent->firstChild() == this);
0079         m_count = m_parent->value() + m_value;
0080     }
0081     if (old_count != m_count && !first) {
0082         setSelfDirty();
0083     }
0084     if (old_count != m_count || first) {
0085         if (m_parent) {
0086             m_parent->updateTotal(m_count);
0087         }
0088         if (m_next) {
0089             m_next->recount();
0090         }
0091     }
0092 }
0093 
0094 void CounterNode::setSelfDirty()
0095 {
0096     if (m_renderer && m_isVisual) {
0097         m_renderer->setNeedsLayoutAndMinMaxRecalc();
0098     }
0099 }
0100 
0101 void CounterNode::setParentDirty()
0102 {
0103     if (m_renderer && m_isVisual && m_hasCounters) {
0104         m_renderer->setNeedsLayoutAndMinMaxRecalc();
0105     }
0106 }
0107 
0108 CounterReset::CounterReset(RenderObject *o) : CounterNode(o), m_total(0), m_first(nullptr), m_last(nullptr) {}
0109 CounterReset::~CounterReset() {}
0110 
0111 void CounterReset::insertAfter(CounterNode *newChild, CounterNode *refChild)
0112 {
0113     Q_ASSERT(newChild);
0114     Q_ASSERT(!refChild || refChild->parent() == this);
0115 
0116     newChild->m_parent = this;
0117     newChild->m_previous = refChild;
0118 
0119     if (refChild) {
0120         newChild->m_next = refChild->m_next;
0121         refChild->m_next = newChild;
0122     } else {
0123         newChild->m_next = m_first;
0124         m_first = newChild;
0125     }
0126 
0127     if (newChild->m_next) {
0128         assert(newChild->m_next->m_previous == refChild);
0129         newChild->m_next->m_previous = newChild;
0130     } else {
0131         assert(m_last == refChild);
0132         m_last = newChild;
0133     }
0134 
0135     newChild->recount(true);
0136 }
0137 
0138 void CounterReset::removeChild(CounterNode *oldChild)
0139 {
0140     Q_ASSERT(oldChild);
0141 
0142     CounterNode *next = oldChild->m_next;
0143     CounterNode *prev = oldChild->m_previous;
0144 
0145     if (oldChild->firstChild()) {
0146         CounterNode *first = oldChild->firstChild();
0147         CounterNode *last = oldChild->lastChild();
0148         if (prev) {
0149             prev->m_next = first;
0150             first->m_previous = prev;
0151         } else {
0152             assert(m_first == oldChild);
0153             m_first = first;
0154         }
0155 
0156         if (next) {
0157             next->m_previous = last;
0158             last->m_next = next;
0159         } else {
0160             assert(m_last == oldChild);
0161             m_last = last;
0162         }
0163 
0164         next = first;
0165         while (next) {
0166             next->m_parent = this;
0167             if (next == last) {
0168                 break;
0169             }
0170             next = next->m_next;
0171         }
0172 
0173         first->recount(true);
0174     } else {
0175         if (prev) {
0176             prev->m_next = next;
0177         } else {
0178             assert(m_first == oldChild);
0179             m_first = next;
0180         }
0181         if (next) {
0182             next->m_previous = prev;
0183         } else {
0184             assert(m_last == oldChild);
0185             m_last = prev;
0186         }
0187         if (next) {
0188             next->recount();
0189         }
0190     }
0191 
0192     oldChild->m_next = nullptr;
0193     oldChild->m_previous = nullptr;
0194     oldChild->m_parent = nullptr;
0195 }
0196 
0197 void CounterReset::recount(bool first)
0198 {
0199     int old_count = m_count;
0200     if (m_previous) {
0201         m_count = m_previous->count();
0202     } else if (m_parent) {
0203         m_count = m_parent->value();
0204     } else {
0205         m_count = 0;
0206     }
0207 
0208     updateTotal(m_value);
0209     if (!first) {
0210         setSelfDirty();
0211     }
0212     if (first || m_count != old_count) {
0213         if (m_next) {
0214             m_next->recount();
0215         }
0216     }
0217 }
0218 
0219 void CounterReset::setSelfDirty()
0220 {
0221     setParentDirty();
0222 }
0223 
0224 void CounterReset::setParentDirty()
0225 {
0226     if (hasCounters()) {
0227         if (m_renderer && m_isVisual) {
0228             m_renderer->setNeedsLayoutAndMinMaxRecalc();
0229         }
0230         CounterNode *n = firstChild();
0231         for (; n; n = n->nextSibling()) {
0232             n->setParentDirty();
0233         }
0234     }
0235 }
0236 
0237 void CounterReset::updateTotal(int value)
0238 {
0239     if (value > m_total) {
0240         m_total = value;
0241     }
0242 }
0243 
0244 } // namespace