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

📄 render_text.cpp

📁 将konqueror浏览器移植到ARM9 2410中
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/** * This file is part of the DOM implementation for KDE. * * (C) 1999 Lars Knoll (knoll@kde.org) * (C) 2000 Dirk Mueller (mueller@kde.org) * * 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. * * $Id: render_text.cpp,v 1.136.2.2 2001/11/02 14:18:41 mueller Exp $ *///#define DEBUG_LAYOUT//#define BIDI_DEBUG#include "render_text.h"#include "break_lines.h"#include "render_style.h"#include "misc/loader.h"#include "misc/helper.h"#include <qfontmetrics.h>#include <qfontinfo.h>#include <qfont.h>#include <qpainter.h>#include <qstring.h>#include <qcolor.h>#include <qrect.h>#include <kdebug.h>#define QT_ALLOC_QCHAR_VEC( N ) (QChar*) new char[ sizeof(QChar)*( N ) ]#define QT_DELETE_QCHAR_VEC( P ) delete[] ((char*)( P ))using namespace khtml;using namespace DOM;TextSlave::~TextSlave(){    if(m_reversed)        QT_DELETE_QCHAR_VEC(m_text);}void TextSlave::print( QPainter *pt, int _tx, int _ty){    if (!m_text || m_len <= 0)        return;    QConstString s(m_text, m_len);    //kdDebug( 6040 ) << "textSlave::printing(" << s.string() << ") at(" << x+_tx << "/" << y+_ty << ")" << endl;    pt->drawText(m_x + _tx, m_y + _ty + m_baseline, s.string());}void TextSlave::printSelection(QPainter *p, RenderStyle* style, int tx, int ty, int startPos, int endPos){    if(startPos > m_len) return;    if(startPos < 0) startPos = 0;    int _len = m_len;    int _width = m_width;    if(endPos > 0 && endPos < m_len) {        _len = endPos;    }    _len -= startPos;    //kdDebug(6040) << "TextSlave::printSelection startPos (relative)=" << startPos << " len (of selection)=" << _len << "  (m_len=" << m_len << ")" << endl;    QConstString s(m_text+startPos , _len);    if (_len != m_len)        _width = p->fontMetrics().width(s.string());    int _offset = 0;    if ( startPos > 0 ) {        QConstString aStr(m_text, startPos);        _offset = p->fontMetrics().width(aStr.string());    }    p->save();    QColor c = style->color();    p->setPen(QColor(0xff-c.red(),0xff-c.green(),0xff-c.blue()));    QFontMetrics fm = p->fontMetrics();    p->fillRect(m_x + tx + _offset, m_y + ty + m_baseline - fm.ascent(), _width, fm.height(), c);    ty += m_baseline;    //kdDebug( 6040 ) << "textSlave::printing(" << s.string() << ") at(" << x+_tx << "/" << y+_ty << ")" << endl;    p->drawText(m_x + tx + _offset, m_y + ty, s.string());    p->restore();}void TextSlave::printDecoration( QPainter *pt, RenderText* p, int _tx, int _ty, int deco, bool begin, bool end){    _tx += m_x;    _ty += m_y;    int width = m_width;    if( begin ) 	width -= p->paddingLeft() + p->borderLeft();    if ( end )        width -= p->paddingRight() + p->borderRight();    int underlineOffset = ( pt->fontMetrics().height() + m_baseline ) / 2;    if(underlineOffset <= m_baseline) underlineOffset = m_baseline+1;    if(deco & UNDERLINE)        pt->drawLine(_tx, _ty + underlineOffset, _tx + width, _ty + underlineOffset );    if(deco & OVERLINE)        pt->drawLine(_tx, _ty, _tx + width, _ty );    if(deco & LINE_THROUGH)        pt->drawLine(_tx, _ty + 2*m_baseline/3, _tx + width, _ty + 2*m_baseline/3 );    // NO! Do NOT add BLINK! It is the most annouing feature of Netscape, and IE has a reason not to    // support it. Lars}void TextSlave::printBoxDecorations(QPainter *pt, RenderStyle* style, RenderText *p, int _tx, int _ty, bool begin, bool end){    int topExtra = p->borderTop() + p->paddingTop();    int bottomExtra = p->borderBottom() + p->paddingBottom();    // ### firstline    int halfleading = (p->m_lineHeight - style->font().pixelSize() ) / 2;    _tx += m_x;    _ty += m_y + halfleading - topExtra;    int width = m_width;    // the height of the decorations is:  topBorder + topPadding + CSS fontsize + bottomPadding + bottomBorder    int height = style->font().pixelSize() + topExtra + bottomExtra;    if( begin )	_tx -= p->paddingLeft() + p->borderLeft();    QColor c = style->backgroundColor();    CachedImage *i = style->backgroundImage();    if(c.isValid() && (!i || i->tiled_pixmap(c).mask()))         pt->fillRect(_tx, _ty, width, height, c);    if(i) {        // ### might need to add some correct offsets        // ### use paddingX/Y        pt->drawTiledPixmap(_tx, _ty, width, height, i->tiled_pixmap(c));    }    if(style->hasBorder())        p->printBorder(pt, _tx, _ty, width, height, style, begin, end);#ifdef BIDI_DEBUG    int h = p->lineHeight( false ) + p->paddingTop() + p->paddingBottom() + p->borderTop() + p->borderBottom();    QColor c2 = QColor("#0000ff");    p->drawBorder(pt, _tx, _ty, _tx, _ty + h, 1,                  RenderObject::BSLeft, c2, c2, SOLID, false, false, 0, 0);    p->drawBorder(pt, _tx + m_width, _ty, _tx + m_width, _ty + h, 1,                  RenderObject::BSRight, c2, c2, SOLID, false, false, 0, 0);#endif}FindSelectionResult TextSlave::checkSelectionPoint(int _x, int _y, int _tx, int _ty, QFontMetrics * fm, int & offset, int lineHeight){    //kdDebug(6040) << "TextSlave::checkSelectionPoint " << this << " _x=" << _x << " _y=" << _y    //              << " _tx+m_x=" << _tx+m_x << " _ty+m_y=" << _ty+m_y << endl;    offset = 0;    if ( _y < _ty + m_y )        return SelectionPointBefore; // above -> before    if ( _y > _ty + m_y + lineHeight || _x > _tx + m_x + m_width )    {        // below or on the right -> after        // Set the offset to the max        offset = m_len;        return SelectionPointAfter;    }    // The Y matches, check if we're on the left    if ( _x < _tx + m_x )        return SelectionPointBefore; // on the left (and not below) -> before    if ( m_reversed )        return SelectionPointBefore; // Abort if RTL (TODO)    int delta = _x - (_tx + m_x);    //kdDebug(6040) << "TextSlave::checkSelectionPoint delta=" << delta << endl;    int pos = 0;    while(pos < m_len)    {        // ### this will produce wrong results for RTL text!!!        int w = fm->width(*(m_text+pos));        int w2 = w/2;        w -= w2;        delta -= w2;        if(delta <= 0) break;        pos++;        delta -= w;    }    //kdDebug( 6040 ) << " Text  --> inside at position " << pos << endl;    offset = pos;    return SelectionPointInside;}// -----------------------------------------------------------------------------TextSlaveArray::TextSlaveArray(){    setAutoDelete(true);}int TextSlaveArray::compareItems( Item d1, Item d2 ){    ASSERT(d1);    ASSERT(d2);    return static_cast<TextSlave*>(d1)->m_y - static_cast<TextSlave*>(d2)->m_y;}// remove this once QVector::bsearch is fixedint TextSlaveArray::findFirstMatching(Item d) const{    int len = count();    if ( !len )	return -1;    if ( !d )	return -1;    int n1 = 0;    int n2 = len - 1;    int mid = 0;    bool found = FALSE;    while ( n1 <= n2 ) {	int  res;	mid = (n1 + n2)/2;	if ( (*this)[mid] == 0 )			// null item greater	    res = -1;	else	    res = ((QGVector*)this)->compareItems( d, (*this)[mid] );	if ( res < 0 )	    n2 = mid - 1;	else if ( res > 0 )	    n1 = mid + 1;	else {					// found it	    found = TRUE;	    break;	}    }    /* if ( !found )	return -1; */    // search to first one equal or bigger    while ( found && (mid > 0) && !((QGVector*)this)->compareItems(d, (*this)[mid-1]) )	mid--;    return mid;}// -------------------------------------------------------------------------------------RenderText::RenderText(DOMStringImpl *_str)    : RenderObject(){    // init RenderObject attributes    setRenderText();   // our object inherits from RenderText    setInline(true);   // our object is Inline    m_minWidth = -1;    m_maxWidth = -1;    str = _str;    if(str) str->ref();    assert(!str || !str->l || str->s);    m_selectionState = SelectionNone;    m_hasReturn = true;    fm = 0;#ifdef DEBUG_LAYOUT    QConstString cstr(str->s, str->l);    kdDebug( 6040 ) << "RenderText::setText '" << (const char *)cstr.string().utf8() << "'" << endl;#endif}void RenderText::setStyle(RenderStyle *_style){    bool fontchanged = ( !style() || style()->font() != _style->font() );    RenderObject::setStyle(_style);    if ( !fm || fontchanged ) {        delete fm;        fm = new QFontMetrics( style()->font() );    }    // ### FIXME firstline support    m_lineHeight = RenderObject::lineHeight(false);    if ( style()->fontVariant() == SMALL_CAPS ) {	setText( str->upper() );    } else {	// ### does not work if texttransform is set to None again!	switch(style()->textTransform()) {	    case CAPITALIZE:  setText(str->capitalize());  break;	    case UPPERCASE:   setText(str->upper());       break;	    case LOWERCASE:   setText(str->lower());       break;	    case NONE:	    default:;	}    }}RenderText::~RenderText(){    deleteSlaves();    if(str) str->deref();    delete fm;}void RenderText::deleteSlaves(){    // this is a slight variant of QArray::clear().    // We don't delete the array itself here because its    // likely to be used in the same size later again, saves    // us resize() calls    unsigned int len = m_lines.size();    for(unsigned int i=0; i < len; i++)        m_lines.remove(i);    ASSERT(m_lines.count() == 0);}TextSlave * RenderText::findTextSlave( int offset, int &pos ){    // The text slaves point to parts of the rendertext's str string    // (they don't include '\n')    // Find the text slave that includes the character at @p offset    // and return pos, which is the position of the char in the slave.    if ( m_lines.isEmpty() )        return 0L;    TextSlave* s = m_lines[0];    uint si = 0;    int off = s->m_len;    while(offset > off && si < m_lines.count())    {        s = m_lines[++si];        if ( s->m_reversed )            return 0L; // Abort if RTL (TODO)        // ### only for visuallyOrdered !        off = s->m_text - str->s + s->m_len;    }    // we are now in the correct text slave    pos = (offset > off ? s->m_len : s->m_len - (off - offset) );    return s;}bool RenderText::containsPoint(int _x, int _y, int _tx, int _ty){    int height = m_lineHeight + borderTop() + paddingTop() +                 borderBottom() + paddingBottom();    TextSlave *s = m_lines.count() ? m_lines[0] : 0;    int si = 0;    while(s) {        if((_y >=_ty + s->m_y) && (_y < _ty + s->m_y + height) &&           (_x >= _tx + s->m_x) && (_x <_tx + s->m_x + s->m_width) )            return true;        s = si < (int)m_lines.count()-1 ? m_lines[++si] : 0;    }    return false;}FindSelectionResult RenderText::checkSelectionPoint(int _x, int _y, int _tx, int _ty, int &offset){    //kdDebug(6040) << "RenderText::checkSelectionPoint " << this << " _x=" << _x << " _y=" << _y    //              << " _tx=" << _tx << " _ty=" << _ty << endl;    for(unsigned int si = 0; si < m_lines.count(); si++)    {        TextSlave* s = m_lines[si];        if ( s->m_reversed )            return SelectionPointBefore; // abort if RTL (TODO)        int result;	if ( khtml::printpainter || hasFirstLine() ) {	    QFontMetrics _fm = metrics( ( si == 0) );	    result = s->checkSelectionPoint(_x, _y, _tx, _ty, &_fm, offset, m_lineHeight);	} else {	    result = s->checkSelectionPoint(_x, _y, _tx, _ty, fm, offset, m_lineHeight);	}        //kdDebug(6040) << "RenderText::checkSelectionPoint " << this << " line " << si << " result=" << result << " offset=" << offset << endl;        if ( result == SelectionPointInside ) // x,y is inside the textslave        {            // ### only for visuallyOrdered !            offset += s->m_text - str->s; // add the offset from the previous lines            //kdDebug(6040) << "RenderText::checkSelectionPoint inside -> " << offset << endl;            return SelectionPointInside;        } else if ( result == SelectionPointBefore )        {            // x,y is before the textslave -> stop here            if ( si > 0 )            {                // ### only for visuallyOrdered !                offset = s->m_text - str->s - 1;                //kdDebug(6040) << "RenderText::checkSelectionPoint before -> " << offset << endl;                return SelectionPointInside;            } else            {                offset = 0;                //kdDebug(6040) << "RenderText::checkSelectionPoint before us -> returning Before" << endl;                return SelectionPointBefore;            }        }    }    // set offset to max    offset = str->l;    return SelectionPointAfter;}void RenderText::cursorPos(int offset, int &_x, int &_y, int &height){  if (!m_lines.count()) {    _x = _y = height = -1;    return;  }  int pos;  TextSlave * s = findTextSlave( offset, pos );  _y = s->m_y;  height = m_lineHeight; // ### firstLine!!! s->m_height;  QFontMetrics fm = metrics( false ); // #### wrong for first-line!  QString tekst(s->m_text, s->m_len);  _x = s->m_x + (fm.boundingRect(tekst, pos)).right();  if(pos)      _x += fm.rightBearing( *(s->m_text + pos - 1 ) );  int absx, absy;  RenderObject *cb = containingBlock();  if (cb && cb != this && cb->absolutePosition(absx,absy))  {    _x += absx;    _y += absy;  } else {    // we don't know our absolute position, and there is not point returning    // just a relative one    _x = _y = -1;  }}bool RenderText::absolutePosition(int &xPos, int &yPos, bool){    if(parent() && parent()->absolutePosition(xPos, yPos, false)) {        xPos -= paddingLeft() + borderLeft();        yPos -= borderTop() + paddingTop();        return true;

⌨️ 快捷键说明

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