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

📄 bidi.cpp

📁 konqueror3 embedded版本, KDE环境下的当家浏览器的嵌入式版本源码包.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/** * This file is part of the html renderer for KDE. * * Copyright (C) 2000-2003 Lars Knoll (knoll@kde.org) *           (C) 2003-2004 Apple Computer, Inc. *           (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 "rendering/bidi.h"#include "rendering/break_lines.h"#include "rendering/render_block.h"#include "rendering/render_text.h"#include "rendering/render_arena.h"#include "rendering/render_layer.h"#include "rendering/render_canvas.h"#include "xml/dom_docimpl.h"#include "kdebug.h"#include "qdatetime.h"#include "qfontmetrics.h"#define BIDI_DEBUG 0//#define DEBUG_LINEBREAKS//#define PAGE_DEBUGnamespace 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 previousLineBrokeAtBR = 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.isVariable())        return (cssUnit.isFixed() ? 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){    RenderObject *next = 0;    while(current != 0)    {        //kdDebug( 6040 ) << "current = " << current << endl;        if (!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) {            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 (!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)        sFirstBidiRun = sLastBidiRun = bidiRun;    else {        sLastBidiRun->nextRun = bidiRun;        sLastBidiRun = bidiRun;    }    sBidiRunCount++;    bidiRun->compact = sBuildingCompactRuns;    // Compute the number of spaces in this run,    if (bidiRun->obj && bidiRun->obj->isText()) {        RenderText* text = static_cast<RenderText*>(bidiRun->obj);        if (text->text()) {            for (int i = bidiRun->start; i < bidiRun->stop; i++) {                const QChar c = text->text()[i];                if (c.category() == QChar::Separator_Space || c == '\n')                    numSpaces++;            }        }    }

⌨️ 快捷键说明

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