📄 render_text.cpp
字号:
/** * This file is part of the DOM implementation for KDE. * * (C) 1999 Lars Knoll (knoll@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.3 2003/04/22 09:34:24 weiym Exp $ *///#define DEBUG_LAYOUT//#define BIDI_DEBUG#if 0// #### for debugging Qt#define private public#include <qfontmetrics.h>#undef private#include <qtextcodec.h>#endif#include <assert.h>#include "render_interface.h"#include "mgcolor.h"#include "mgpen.h"#include "mgbrush.h"#include "mgsize.h"#include "mgrect.h"#include "mgpixmap.h"#include "mgfontmetrics.h"#include "mgfontinfo.h"#include "mgpainter.h"#include "mghtml_part.h"#include "render_text.h"#include "render_style.h"#include "kdebug.h"#define CODE_BY_YMWEI 1#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(deleteText) QT_DELETE_QCHAR_VEC(m_text);}void TextSlave::print( MGPainter *p, int _tx, int _ty){ if (!m_text || len <= 0) return; QConstString s(m_text, len); //kdDebug( 6040 ) << "textSlave::printing(" << s.string() << ") at(" << x+_tx << "/" << y+_ty << ")" << endl; p->drawText(x + _tx, y + _ty, s.string());}void TextSlave::printSelection(MGPainter *p, RenderText* rt, int tx, int ty, int startPos, int endPos){ if(startPos > len) return; if(startPos < 0) startPos = 0; int _len = len; int _width = m_width; if(endPos > 0 && endPos < len) { _len = endPos; } _len -= startPos; QConstString s(m_text+startPos , _len); if (_len != len) _width = p->fontMetrics().width(s.string()); int _offset = 0; if ( startPos > 0 ) { QConstString aStr(m_text, startPos); _offset = p->fontMetrics().width(aStr.string()); } MGColor c = rt->style()->color(); p->setPen(MGColor(0xff-c.red(),0xff-c.green(),0xff-c.blue())); p->fillRect(x + tx + _offset, y + ty, _width, m_height, c); ty += m_baseline; //kdDebug( 6040 ) << "textSlave::printing(" << s.string() << ") at(" << x+_tx << "/" << y+_ty << ")" << endl; p->drawText(x + tx + _offset, y + ty, s.string());}// no blink at the moment...void TextSlave::printDecoration( MGPainter *p, int _tx, int _ty, int deco){ _tx += x; _ty += y;/* int underlineOffset = m_height/6 + m_baseline; if( underlineOffset == m_baseline ) underlineOffset++;*/ int underlineOffset = m_baseline; if(deco & UNDERLINE) p->drawLine(_tx, _ty + underlineOffset, _tx + m_width, _ty + underlineOffset ); if(deco & OVERLINE) p->drawLine(_tx, _ty, _tx + m_width, _ty ); if(deco & LINE_THROUGH) p->drawLine(_tx, _ty + 2*m_baseline/3, _tx + m_width, _ty + 2*m_baseline/3 );// ### add BLINK}void TextSlave::printBoxDecorations(MGPainter *pt, RenderText *p, int _tx, int _ty, bool begin, bool end){ _tx += x; _ty += y - p->paddingTop() - p->borderTop(); //kdDebug( 6040 ) << "renderBox::printDecorations()" << endl; RenderStyle *style = p->style(); int width = m_width; if(begin) _tx -= p->paddingLeft() + p->borderLeft(); MGColor c = style->backgroundColor(); MGCachedImage *i = style->backgroundImage(); if(c.isValid() && (!i || i->tiled_pixmap(c).mask())) pt->fillRect(_tx, _ty, width, m_height, c); if(i) { // ### might need to add some correct offsets // ### use paddingX/Y pt->drawTiledPixmap(_tx + p->borderLeft(), _ty + p->borderTop(), m_width + p->paddingLeft() + p->paddingRight(), m_height + p->paddingTop() + p->paddingBottom(), i->tiled_pixmap(c)); } if(style->hasBorder()) { int h = m_height + p->paddingTop() + p->paddingBottom() + p->borderTop() + p->borderBottom(); if(style->borderTopStyle() != BNONE) { c = style->borderTopColor(); if(!c.isValid()) c = style->color(); p->drawBorder(pt, _tx, _ty, _tx + width, _ty, style->borderTopWidth(), RenderObject::BSTop, c, style->borderTopStyle()); } if(style->borderBottomStyle() != BNONE) { c = style->borderBottomColor(); if(!c.isValid()) c = style->color(); p->drawBorder(pt, _tx, _ty + h, _tx + width, _ty + h, style->borderBottomWidth(), RenderObject::BSBottom, c, style->borderBottomStyle()); } // ### has to be changed for RTL if(style->borderLeftStyle() != BNONE && (begin)) { c = style->borderLeftColor(); if(!c.isValid()) c = style->color(); p->drawBorder(pt, _tx, _ty, _tx, _ty + h, style->borderLeftWidth(), RenderObject::BSLeft, c, style->borderLeftStyle()); } if(style->borderRightStyle() != BNONE && end) { c = style->borderRightColor(); if(!c.isValid()) c = style->color(); p->drawBorder(pt, _tx + width, _ty, _tx + width, _ty + h, style->borderRightWidth(), RenderObject::BSRight, c, style->borderRightStyle()); } }#ifdef BIDI_DEBUG int h = m_height + p->paddingTop() + p->paddingBottom() + p->borderTop() + p->borderBottom(); c = MGColor("#0000ff"); p->drawBorder(pt, _tx, _ty, _tx, _ty + h, 1, RenderObject::BSLeft, c, SOLID); p->drawBorder(pt, _tx + width, _ty, _tx + width, _ty + h, style->borderRightWidth(), RenderObject::BSRight, c, SOLID);#endif}void TextSlave::printActivation( MGPainter *p, int _tx, int _ty){ p->drawRect(_tx+x-2,_ty+y, m_width+3, m_height+2); p->drawRect(_tx+x-3,_ty+y+1, m_width+5, m_height);}bool TextSlave::checkPoint(int _x, int _y, int _tx, int _ty){ if((_ty + y > _y) || (_ty + y + m_height < _y) || (_tx + x > _x) || (_tx + x + m_width < _x)) return false; return true;}// -------------------------------------------------------------------------------------RenderText::RenderText(DOMStringImpl *_str) : RenderObject(){ // init RenderObject attributes m_isText = true; // our object inherits from RenderText m_inline = true; // our object is Inline m_first = 0; m_last = 0; m_minWidth = -1; m_maxWidth = -1; str = _str; if(str) str->ref(); fm = 0; m_selectionState = SelectionNone;#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){ RenderObject::setStyle(style); delete fm; fm = new MGFontMetrics(m_style->font(), m_part); m_contentHeight = m_style->lineHeight().width(fm->height());}RenderText::~RenderText(){ deleteSlaves(); delete fm; fm = 0; if(str) str->deref();}void RenderText::deleteSlaves(){ // delete all slaves TextSlave *s = m_first; while(s) { TextSlave *next = s->next(); delete s; s = next; } m_first = m_last = 0;}bool RenderText::checkPoint(int _x, int _y, int _tx, int _ty, int &offset){ TextSlave *s = m_first; while(s) { if( s->checkPoint(_x, _y, _tx, _ty) ) { // now we need to get the exact position int delta = _x - _tx - s->x; int pos = 0; while(pos < s->len) { // ### this will produce wrong results for RTL text!!! int w = fm->width(*(s->m_text+pos)); int w2 = w/2; w = w - w2; delta -= w2; if(delta <= 0) break; pos++; delta -= w; } offset = s->m_text - m_first->m_text + pos; //kdDebug( 6040 ) << " Text --> inside at position " << offset << endl; return true; } // ### this might be wrong, if combining chars are used ( eg arabic ) s=s->next(); } return false;}void RenderText::cursorPos(int offset, int &_x, int &_y, int &height){ if (!m_first) { _x = _y = height = -1; return; } _x = 0; TextSlave *s = m_first; int off = s->len; while(offset > off && s->next()) { s=s->next(); off = s->m_text - m_first->m_text + s->len; } // we are now in the correct text slave int pos = (offset > off ? s->len : s->len - (off - offset )); _y = s->y; height = s->m_height; QString tekst(s->m_text, s->len); _x = s->x + (fm->boundingRect(tekst, pos)).right(); if(pos) _x += fm->rightBearing( *(s->m_text + pos - 1 ) ); int absx, absy; absolutePosition(absx,absy); if (absx == -1) { // we don't know out absolute position, and there is not point returning // just a relative one _x = _y = -1; } else { _x += absx; _y += absy; }}void RenderText::absolutePosition(int &xPos, int &yPos, bool){ if(m_parent) { m_parent->absolutePosition(xPos, yPos, false); if ( m_first ) { xPos += m_first->x; yPos += m_first->y; } } else xPos = yPos = -1;}void RenderText::posOfChar(int chr, int &x, int &y){ if (!m_parent) { x = -1; y = -1; return; } m_parent->absolutePosition( x, y, false ); if( chr > (int) str->l ) chr = str->l; TextSlave *s = m_first; TextSlave *last = s; QChar *ch = str->s + chr; while ( s && ch >= s->m_text ) { last = s; s = s->next(); } x += last->x; y += last->y;}void RenderText::printObject( MGPainter *p, int /*x*/, int y, int /*w*/, int h, int tx, int ty){ //kdDebug( 6040 ) << "Text::printObject(long)" << endl; TextSlave *s = m_first; //kdDebug( 6040 ) << "Text::printObject(2)" << endl; bool start = true;#ifndef BIDI_DEBUG if(m_printSpecial && m_parent->isInline())#endif { bool breakallowed = false; while(s) { bool end = false; if(!s->next()) end = true; if(s->checkVerticalPoint(y, ty, h)) { breakallowed = true; s->printBoxDecorations(p, this, tx, ty, start, end); } else if (breakallowed) break; s=s->next(); start = false; } s = m_first; } p->setFont( m_style->font() ); //kdDebug( 6040 ) << "charset used: " << m_style->font().charSet() << endl;#if 0 kdDebug( 6040 ) << "charset used: " << m_style->font().charSet() << " mapper: " << fm->mapper()->name() << endl;#endif // ### as QPainter::drawText only honors the pen color, we can avoid
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -