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

📄 render_text.cpp

📁 khtml在gtk上的移植版本
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/** * This file is part of the DOM implementation for KDE. * * (C) 1999 Lars Knoll (knoll@kde.org) * (C) 2000 Dirk Mueller (mueller@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. * *///#define DEBUG_LAYOUT//#define BIDI_DEBUG#include "rendering/render_canvas.h"#include "rendering/render_text.h"#include "rendering/break_lines.h"#include "xml/dom_nodeimpl.h"#include "xml/dom_docimpl.h"#include "xml/dom_position.h"#include "render_arena.h"#include "misc/loader.h"#include <qpainter.h>#include <kdebug.h>#include <assert.h>using namespace khtml;using namespace DOM;#ifndef NDEBUGstatic bool inInlineTextBoxDetach;#endifvoid InlineTextBox::detach(RenderArena* renderArena){#ifndef NDEBUG    inInlineTextBoxDetach = true;#endif    delete this;#ifndef NDEBUG    inInlineTextBoxDetach = false;#endif        // Recover the size left there for us by operator delete and free the memory.    renderArena->free(*(size_t *)this, this);}void* InlineTextBox::operator new(size_t sz, RenderArena* renderArena) throw(){    return renderArena->allocate(sz);}void InlineTextBox::operator delete(void* ptr, size_t sz){    assert(inInlineTextBoxDetach);        // Stash size where detach can find it.    *(size_t *)ptr = sz;}void InlineTextBox::deleteLine(RenderArena* arena){    static_cast<RenderText*>(m_object)->removeTextBox(this);    detach(arena);}void InlineTextBox::extractLine(){    if (m_extracted)        return;    static_cast<RenderText*>(m_object)->extractTextBox(this);}void InlineTextBox::attachLine(){    if (!m_extracted)        return;        static_cast<RenderText*>(m_object)->attachTextBox(this);}int InlineTextBox::placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool& foundBox){    if (foundBox) {        m_truncation = cFullTruncation;        return -1;    }    int ellipsisX = ltr ? blockEdge - ellipsisWidth : blockEdge + ellipsisWidth;        // For LTR, if the left edge of the ellipsis is to the left of our text run, then we are the run that will get truncated.    if (ltr) {        if (ellipsisX <= m_x) {            // Too far.  Just set full truncation, but return -1 and let the ellipsis just be placed at the edge of the box.            m_truncation = cFullTruncation;            foundBox = true;            return -1;        }        if (ellipsisX < m_x + m_width) {            if (m_reversed)                return -1; // FIXME: Support LTR truncation when the last run is RTL someday.            foundBox = true;            int offset = offsetForPosition(ellipsisX, false);            if (offset == 0) {                // No characters should be rendered.  Set ourselves to full truncation and place the ellipsis at the min of our start                // and the ellipsis edge.                m_truncation = cFullTruncation;                return kMin(ellipsisX, m_x);            }                        // Set the truncation index on the text run.  The ellipsis needs to be placed just after the last visible character.            m_truncation = offset + m_start;            return m_x + static_cast<RenderText*>(m_object)->width(m_start, offset, m_firstLine);        }    }    else {        // FIXME: Support RTL truncation someday, including both modes (when the leftmost run on the line is either RTL or LTR)    }    return -1;}void InlineTextBox::paintSelection(const Font *f, RenderText *text, QPainter *p, RenderStyle* style, int tx, int ty, int startPos, int endPos, bool extendSelection){    int offset = m_start;    int sPos = kMax(startPos - offset, 0);    int ePos = kMin(endPos - offset, (int)m_len);    if (sPos >= ePos)        return;    p->save();#if APPLE_CHANGES    // Macintosh-style text highlighting is to draw with a particular background color, not invert.    QColor textColor = style->color();    QColor c = p->selectedTextBackgroundColor();        // if text color and selection background color are identical, invert background color.    if (textColor == c)        c = QColor(0xff - c.red(), 0xff - c.green(), 0xff - c.blue());    RenderStyle* pseudoStyle = object()->getPseudoStyle(RenderStyle::SELECTION);    if (pseudoStyle && pseudoStyle->backgroundColor().isValid())        c = pseudoStyle->backgroundColor();    p->setPen(c); // Don't draw text at all!    #else    QColor c = style->color();    p->setPen(QColor(0xff-c.red(),0xff-c.green(),0xff-c.blue()));    ty + m_baseline;#endif    #if APPLE_CHANGES    // Do the calculations to draw selections as tall as the line.    // Use the bottom of the line above as the y position (if there is one,     // otherwise use the top of this renderer's line) and the height of the line as the height.     // This mimics Cocoa.    RenderBlock *cb = object()->containingBlock();    if (root()->prevRootBox())        ty = root()->prevRootBox()->bottomOverflow();    else        ty = root()->topOverflow();    int h = root()->bottomOverflow() - ty;    int absx, absy;    cb->absolutePosition(absx, absy);        int x = m_x + tx;    int minX = x;    int maxX = x;    if ((extendSelection || startPos < m_start) && root()->firstLeafChild() == this)        minX = absx + kMax(cb->leftOffset(ty), cb->leftOffset(root()->blockHeight()));    if ((extendSelection || endPos > m_start + m_len) && root()->lastLeafChild() == this)        maxX = absx + kMin(cb->rightOffset(ty), cb->rightOffset(root()->blockHeight()));        f->drawHighlightForText(p, x, minX, maxX, absy + ty, h, text->str->s, text->str->l, m_start, m_len,		m_toAdd, m_reversed ? QPainter::RTL : QPainter::LTR, style->visuallyOrdered(), sPos, ePos, c);#else    f->drawHighlightForText(p, m_x + tx, m_y + ty, text->str->s, text->str->l, m_start, m_len,		m_toAdd, m_reversed ? QPainter::RTL : QPainter::LTR, sPos, ePos, c);#endif    p->restore();}#ifdef APPLE_CHANGESvoid InlineTextBox::paintDecoration( QPainter *pt, int _tx, int _ty, int deco){    _tx += m_x;    _ty += m_y;    if (m_truncation == cFullTruncation)        return;        int width = (m_truncation == cNoTruncation) ?                 m_width : static_cast<RenderText*>(m_object)->width(m_start, m_truncation - m_start, m_firstLine);        // Get the text decoration colors.    QColor underline, overline, linethrough;    object()->getTextDecorationColors(deco, underline, overline, linethrough, true);        // Use a special function for underlines to get the positioning exactly right.    if (deco & UNDERLINE) {        pt->setPen(underline);        pt->drawLineForText(_tx, _ty, m_baseline, width);    }    if (deco & OVERLINE) {        pt->setPen(overline);        pt->drawLineForText(_tx, _ty, 0, width);    }    if (deco & LINE_THROUGH) {        pt->setPen(linethrough);        pt->drawLineForText(_tx, _ty, 2*m_baseline/3, width);    }}#elsevoid InlineTextBox::paintDecoration( QPainter *pt, int _tx, int _ty, int decoration){    _tx += m_x;    _ty += m_y;    int width = m_width - 1;    QColor underline, overline, linethrough;    object()->getTextDecorationColors(decoration, underline, overline, linethrough, true);        int underlineOffset = ( pt->fontMetrics().height() + m_baseline ) / 2;    if(underlineOffset <= m_baseline) underlineOffset = m_baseline+1;    if(deco & UNDERLINE){        pt->setPen(underline);        pt->drawLine(_tx, _ty + underlineOffset, _tx + width, _ty + underlineOffset );    }    if (deco & OVERLINE) {        pt->setPen(overline);        pt->drawLine(_tx, _ty, _tx + width, _ty );    }    if(deco & LINE_THROUGH) {        pt->setPen(linethrough);        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}#endiflong InlineTextBox::caretMinOffset() const{    return m_start;}long InlineTextBox::caretMaxOffset() const{    return m_start + m_len;}unsigned long InlineTextBox::caretMaxRenderedOffset() const{    return m_start + m_len;}#define LOCAL_WIDTH_BUF_SIZE	1024int InlineTextBox::offsetForPosition(int _x, bool includePartialGlyphs){    RenderText* text = static_cast<RenderText*>(m_object);    const Font* f = text->htmlFont(m_firstLine);    return f->checkSelectionPoint(text->str->s, text->str->l, m_start, m_len, m_toAdd, _x - m_x, m_reversed, includePartialGlyphs);}// -------------------------------------------------------------------------------------RenderText::RenderText(DOM::NodeImpl* node, DOMStringImpl *_str)    : RenderObject(node), m_linesDirty(false){    // init RenderObject attributes    setRenderText();   // our object inherits from RenderText    m_minWidth = -1;    m_maxWidth = -1;#ifdef APPLE_CHANGES    m_monospaceCharacterWidth = 0;    m_allAsciiChecked = false;    m_allAscii = false;#endif    str = _str;    if (str) {        str = str->replace('\\', backslashAsCurrencySymbol());        str->ref();    }    KHTMLAssert(!str || !str->l || str->s);    m_firstTextBox = m_lastTextBox = 0;        m_selectionState = SelectionNone;#ifdef DEBUG_LAYOUT    QConstString cstr(str->s, str->l);    kdDebug( 6040 ) << "RenderText ctr( "<< cstr.string().length() << " )  '" << cstr.string() << "'" << endl;#endif}void RenderText::setStyle(RenderStyle *_style){    if ( style() != _style ) {        bool needToTransformText = (!style() && _style->textTransform() != TTNONE) ||                                   (style() && style()->textTransform() != _style->textTransform());        RenderObject::setStyle( _style );        if (needToTransformText) {            DOM::DOMStringImpl* textToTransform = originalString();            if (textToTransform)                setText(textToTransform, true);        }#if APPLE_CHANGES        // setText also calls cacheWidths(), so there is no need to call it again in that case.        else            cacheWidths();#endif    }}RenderText::~RenderText(){    if(str) str->deref();}void RenderText::detach(){    if (!documentBeingDestroyed()) {        if (firstTextBox())            for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())                box->remove();        else if (parent() && isBR())            parent()->dirtyLinesFromChangedChild(this);    }    deleteTextBoxes();    RenderObject::detach();}void RenderText::extractTextBox(InlineTextBox* box){    m_lastTextBox = box->prevTextBox();    if (box == m_firstTextBox)        m_firstTextBox = 0;    if (box->prevTextBox())        box->prevTextBox()->setNextLineBox(0);    box->setPreviousLineBox(0);    for (InlineRunBox* curr = box; curr; curr = curr->nextLineBox())        curr->setExtracted();}void RenderText::attachTextBox(InlineTextBox* box){    if (m_lastTextBox) {        m_lastTextBox->setNextLineBox(box);        box->setPreviousLineBox(m_lastTextBox);    }    else        m_firstTextBox = box;    InlineTextBox* last = box;    for (InlineTextBox* curr = box; curr; curr = curr->nextTextBox()) {

⌨️ 快捷键说明

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