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

0001 /*
0002  * This file is part of the html renderer for KDE.
0003  *
0004  * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
0005  * Copyright (C) 2003 Apple Computer, Inc.
0006  *
0007  * This library is free software; you can redistribute it and/or
0008  * modify it under the terms of the GNU Library General Public
0009  * License as published by the Free Software Foundation; either
0010  * version 2 of the License, or (at your option) any later version.
0011  *
0012  * This library is distributed in the hope that it will be useful,
0013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015  * Library General Public License for more details.
0016  *
0017  * You should have received a copy of the GNU Library General Public License
0018  * along with this library; see the file COPYING.LIB.  If not, write to
0019  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0020  * Boston, MA 02110-1301, USA.
0021  *
0022  */
0023 #ifndef BIDI_H
0024 #define BIDI_H
0025 
0026 #include <QString>
0027 #include "rendering/render_object.h"
0028 
0029 namespace khtml
0030 {
0031 class RenderArena;
0032 class RenderObject;
0033 class InlineBox;
0034 
0035 class BidiContext
0036 {
0037 public:
0038     BidiContext(unsigned char level, QChar::Direction embedding, BidiContext *parent = nullptr, bool override = false);
0039     ~BidiContext();
0040 
0041     void ref() const;
0042     void deref() const;
0043 
0044     unsigned char level;
0045     bool override : 1;
0046     QChar::Direction dir : 5;
0047     QChar::Direction basicDir : 5;
0048 
0049     BidiContext *parent;
0050 
0051     // refcounting....
0052     mutable int count;
0053 };
0054 
0055 struct BidiRun {
0056     BidiRun(int _start, int _stop, RenderObject *_obj, BidiContext *context, QChar::Direction dir)
0057         :  start(_start), stop(_stop), obj(_obj), box(nullptr), nextRun(nullptr)
0058     {
0059         if (dir == QChar::DirON) {
0060             dir = context->dir;
0061         }
0062 
0063         level = context->level;
0064 
0065         // add level of run (cases I1 & I2)
0066         if (level % 2) {
0067             if (dir == QChar::DirL || dir == QChar::DirAN || dir == QChar::DirEN) {
0068                 level++;
0069             }
0070         } else {
0071             if (dir == QChar::DirR) {
0072                 level++;
0073             } else if (dir == QChar::DirAN || dir == QChar::DirEN) {
0074                 level += 2;
0075             }
0076         }
0077     }
0078 
0079     void detach(RenderArena *renderArena);
0080 
0081     // Overloaded new operator.
0082     void *operator new(size_t sz, RenderArena *renderArena) throw();
0083 
0084     // Overridden to prevent the normal delete from being called.
0085     void operator delete(void *ptr, size_t sz);
0086 
0087 private:
0088     // The normal operator new is disallowed.
0089     void *operator new(size_t sz) throw();
0090 
0091 public:
0092     int start;
0093     int stop;
0094 
0095     RenderObject *obj;
0096     InlineBox *box;
0097 
0098     // explicit + implicit levels here
0099     uchar level;
0100 
0101     bool compact : 1;
0102 
0103     BidiRun *nextRun;
0104 };
0105 
0106 struct BidiIterator;
0107 struct BidiState;
0108 
0109 struct BidiStatus {
0110     BidiStatus() : eor(QChar::DirON), lastStrong(QChar::DirON), last(QChar::DirON) {}
0111 
0112     QChar::Direction eor;
0113     QChar::Direction lastStrong;
0114     QChar::Direction last;
0115 };
0116 
0117 struct InlineMinMaxIterator {
0118     /* InlineMinMaxIterator is a class that will iterate over all render objects that contribute to
0119        inline min/max width calculations.  Note the following about the way it walks:
0120        (1) Positioned content is skipped (since it does not contribute to min/max width of a block)
0121        (2) We do not drill into the children of floats or replaced elements, since you can't break
0122            in the middle of such an element.
0123        (3) Inline flows (e.g., <a>, <span>, <i>) are walked twice, since each side can have
0124            distinct borders/margin/padding that contribute to the min/max width.
0125     */
0126     RenderObject *parent;
0127     RenderObject *current;
0128     bool endOfInline;
0129     bool skipPositioned;
0130     InlineMinMaxIterator(RenderObject *p, RenderObject *o, bool eOI = false, bool skipPos = true)
0131         : parent(p), current(o), endOfInline(eOI), skipPositioned(skipPos) {}
0132     inline RenderObject *next();
0133 };
0134 
0135 inline RenderObject *InlineMinMaxIterator::next()
0136 {
0137     RenderObject *result = nullptr;
0138     bool oldEndOfInline = endOfInline;
0139     endOfInline = false;
0140     while (current != nullptr || (current == parent)) {
0141         //qCDebug(KHTML_LOG) << "current = " << current;
0142         if (!oldEndOfInline &&
0143                 (current == parent ||
0144                  (!current->isFloating() && !current->isReplaced() && !current->isPositioned()))) {
0145             result = current->firstChild();
0146         }
0147         if (!result) {
0148             // We hit the end of our inline. (It was empty, e.g., <span></span>.)
0149             if (!oldEndOfInline && current->isInlineFlow()) {
0150                 result = current;
0151                 endOfInline = true;
0152                 break;
0153             }
0154             while (current && current != parent) {
0155                 result = current->nextSibling();
0156                 if (result) {
0157                     break;
0158                 }
0159                 current = current->parent();
0160                 if (current && current != parent && current->isInlineFlow()) {
0161                     result = current;
0162                     endOfInline = true;
0163                     break;
0164                 }
0165             }
0166         }
0167 
0168         if (!result) {
0169             break;
0170         }
0171 
0172         if ((!skipPositioned || !result->isPositioned()) && (result->isText() || result->isBR() ||
0173                 result->isFloatingOrPositioned() || result->isReplaced() || result->isGlyph() || result->isInlineFlow())) {
0174             break;
0175         }
0176 
0177         current = result;
0178         result = nullptr;
0179     }
0180 
0181     // Update our position.
0182     current = result;
0183     return current;
0184 }
0185 }
0186 
0187 #endif