⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bidi.cpp

📁 khtml在gtk上的移植版本
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/** * This file is part of the html renderer for KDE. * * Copyright (C) 2000 Lars Knoll (knoll@kde.org) * Copyright (C) 2004 Apple Computer, Inc. * * 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., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * */#include "bidi.h"#include "break_lines.h"#include "render_block.h"#include "render_text.h"#include "render_arena.h"#include "render_canvas.h"#include "khtmlview.h"#include "xml/dom_docimpl.h"#include "kdebug.h"#include "qdatetime.h"#include "qfontmetrics.h"#define BIDI_DEBUG 0//#define DEBUG_LINEBREAKSusing DOM::AtomicString;namespace khtml {// an iterator which goes through a BidiParagraphstruct BidiIterator{    BidiIterator() : par(0), obj(0), pos(0) {}    BidiIterator(RenderBlock *_par, RenderObject *_obj, unsigned int _pos) : par(_par), obj(_obj), pos(_pos) {}        void increment( BidiState &bidi );        bool atEnd() const;        const QChar &current() const;    QChar::Direction direction() const;        RenderBlock *par;    RenderObject *obj;    unsigned int pos;};struct BidiStatus {    BidiStatus() : eor(QChar::DirON), lastStrong(QChar::DirON), last(QChar::DirON) {}        QChar::Direction eor;    QChar::Direction lastStrong;    QChar::Direction last;};    struct BidiState {    BidiState() : context(0) {}        BidiIterator sor;    BidiIterator eor;    BidiIterator last;    BidiIterator current;    BidiContext *context;    BidiStatus status;};// Used to track a list of chained bidi runs.static BidiRun* sFirstBidiRun;static BidiRun* sLastBidiRun;static int sBidiRunCount;static BidiRun* sCompactFirstBidiRun;static BidiRun* sCompactLastBidiRun;static int sCompactBidiRunCount;static bool sBuildingCompactRuns;// Midpoint globals.  The goal is not to do any allocation when dealing with// these midpoints, so we just keep an array around and never clear it.  We track// the number of items and position using the two other variables.static QMemArray<BidiIterator> *smidpoints;static uint sNumMidpoints;static uint sCurrMidpoint;static bool betweenMidpoints;static bool isLineEmpty = true;static bool previousLineBrokeCleanly = true;static QChar::Direction dir;static bool adjustEmbedding;static bool emptyRun = true;static int numSpaces;static void embed( QChar::Direction d, BidiState &bidi );static void appendRun( BidiState &bidi );static int getBPMWidth(int childValue, Length cssUnit){    if (cssUnit.type != Variable)        return (cssUnit.type == Fixed ? cssUnit.value : childValue);    return 0;}static int getBorderPaddingMargin(RenderObject* child, bool endOfInline){    RenderStyle* cstyle = child->style();    int result = 0;    bool leftSide = (cstyle->direction() == LTR) ? !endOfInline : endOfInline;    result += getBPMWidth((leftSide ? child->marginLeft() : child->marginRight()),                          (leftSide ? cstyle->marginLeft() :                           cstyle->marginRight()));    result += getBPMWidth((leftSide ? child->paddingLeft() : child->paddingRight()),                          (leftSide ? cstyle->paddingLeft() :                           cstyle->paddingRight()));    result += leftSide ? child->borderLeft() : child->borderRight();    return result;}static int inlineWidth(RenderObject* child, bool start = true, bool end = true){    int extraWidth = 0;    RenderObject* parent = child->parent();    while (parent->isInline() && !parent->isInlineBlockOrInlineTable()) {        if (start && parent->firstChild() == child)            extraWidth += getBorderPaddingMargin(parent, false);        if (end && parent->lastChild() == child)            extraWidth += getBorderPaddingMargin(parent, true);        child = parent;        parent = child->parent();    }    return extraWidth;}#ifndef NDEBUGstatic bool inBidiRunDetach;#endifvoid BidiRun::detach(RenderArena* renderArena){#ifndef NDEBUG    inBidiRunDetach = true;#endif    delete this;#ifndef NDEBUG    inBidiRunDetach = false;#endif    // Recover the size left there for us by operator delete and free the memory.    renderArena->free(*(size_t *)this, this);}void* BidiRun::operator new(size_t sz, RenderArena* renderArena) throw(){    return renderArena->allocate(sz);}void BidiRun::operator delete(void* ptr, size_t sz){    assert(inBidiRunDetach);    // Stash size where detach can find it.    *(size_t*)ptr = sz;}static void deleteBidiRuns(RenderArena* arena){    if (!sFirstBidiRun)        return;    BidiRun* curr = sFirstBidiRun;    while (curr) {        BidiRun* s = curr->nextRun;        curr->detach(arena);        curr = s;    }        sFirstBidiRun = 0;    sLastBidiRun = 0;    sBidiRunCount = 0;}// ---------------------------------------------------------------------/* a small helper class used internally to resolve Bidi embedding levels.   Each line of text caches the embedding level at the start of the line for faster   relayouting*/BidiContext::BidiContext(unsigned char l, QChar::Direction e, BidiContext *p, bool o)    : level(l) , override(o), dir(e){    parent = p;    if(p) {        p->ref();        basicDir = p->basicDir;    } else        basicDir = e;    count = 0;}BidiContext::~BidiContext(){    if(parent) parent->deref();}void BidiContext::ref() const{    count++;}void BidiContext::deref() const{    count--;    if(count <= 0) delete this;}// ---------------------------------------------------------------------inline bool operator==( const BidiIterator &it1, const BidiIterator &it2 ){    if(it1.pos != it2.pos) return false;    if(it1.obj != it2.obj) return false;    return true;}inline bool operator!=( const BidiIterator &it1, const BidiIterator &it2 ){    if(it1.pos != it2.pos) return true;    if(it1.obj != it2.obj) return true;    return false;}static inline RenderObject *Bidinext(RenderObject *par, RenderObject *current, BidiState &bidi,                                     bool skipInlines = true, bool* endOfInline = 0){    RenderObject *next = 0;    bool oldEndOfInline = endOfInline ? *endOfInline : false;    if (endOfInline)        *endOfInline = false;    while(current != 0)    {        //kdDebug( 6040 ) << "current = " << current << endl;        if (!oldEndOfInline && !current->isFloating() && !current->isReplaced() && !current->isPositioned()) {            next = current->firstChild();            if ( next && adjustEmbedding ) {                EUnicodeBidi ub = next->style()->unicodeBidi();                if ( ub != UBNormal && !emptyRun ) {                    EDirection dir = next->style()->direction();QChar::Direction d = ( ub == Embed ? ( dir == RTL ? QChar::DirRLE : QChar::DirLRE )                                   : ( dir == RTL ? QChar::DirRLO : QChar::DirLRO ) );                    embed( d, bidi );                }            }        }        if (!next) {            if (!skipInlines && !oldEndOfInline && current->isInlineFlow())            {                next = current;                if (endOfInline)                    *endOfInline = true;                break;            }            while (current && current != par) {                next = current->nextSibling();                if (next) break;                if ( adjustEmbedding && current->style()->unicodeBidi() != UBNormal && !emptyRun ) {                    embed( QChar::DirPDF, bidi );                }                current = current->parent();                if (!skipInlines && current && current != par && current->isInlineFlow()) {                    next = current;                    if (endOfInline)                        *endOfInline = true;                    break;                }            }        }        if (!next) break;        if (next->isText() || next->isBR() || next->isFloating() || next->isReplaced() || next->isPositioned()            || ((!skipInlines || !next->firstChild()) // Always return EMPTY inlines.                && next->isInlineFlow()))            break;        current = next;    }    return next;}static RenderObject *first( RenderObject *par, BidiState &bidi, bool skipInlines = true ){    if(!par->firstChild()) return 0;    RenderObject *o = par->firstChild();    if (o->isInlineFlow()) {        if (skipInlines && o->firstChild())            o = Bidinext( par, o, bidi, skipInlines );        else            return o; // Never skip empty inlines.    }    if (o && !o->isText() && !o->isBR() && !o->isReplaced() && !o->isFloating() && !o->isPositioned())        o = Bidinext( par, o, bidi, skipInlines );    return o;}inline void BidiIterator::increment (BidiState &bidi){    if(!obj) return;    if(obj->isText()) {        pos++;        if(pos >= static_cast<RenderText *>(obj)->stringLength()) {            obj = Bidinext( par, obj, bidi );            pos = 0;        }    } else {        obj = Bidinext( par, obj, bidi );        pos = 0;    }}inline bool BidiIterator::atEnd() const{    if(!obj) return true;    return false;}const QChar &BidiIterator::current() const{    static QChar nonBreakingSpace(0xA0);        if (!obj || !obj->isText())      return nonBreakingSpace;        RenderText* text = static_cast<RenderText*>(obj);    if (!text->text())        return nonBreakingSpace;        return text->text()[pos];}inline QChar::Direction BidiIterator::direction() const{    if(!obj || !obj->isText() ) return QChar::DirON;        RenderText *renderTxt = static_cast<RenderText *>( obj );    if ( pos >= renderTxt->stringLength() )        return QChar::DirON;    return renderTxt->text()[pos].direction();}// -------------------------------------------------------------------------------------------------static void addRun(BidiRun* bidiRun){    if (!sFirstBidiRun)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -