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

📄 inlinetextbox.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* * (C) 1999 Lars Knoll (knoll@kde.org) * (C) 2000 Dirk Mueller (mueller@kde.org) * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. * * 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 "config.h"#include "InlineTextBox.h"#include "ChromeClient.h"#include "Document.h"#include "Editor.h"#include "Frame.h"#include "GraphicsContext.h"#include "HitTestResult.h"#include "Page.h"#include "RenderArena.h"#include "RenderBlock.h"#include "RenderTheme.h"#include "Text.h"#include "break_lines.h"#include <wtf/AlwaysInline.h>using namespace std;namespace WebCore {int InlineTextBox::height() const{    return m_treatAsText ? renderer()->style(m_firstLine)->font().height() : 0;}int InlineTextBox::selectionTop(){    return root()->selectionTop();}int InlineTextBox::selectionHeight(){    return root()->selectionHeight();}bool InlineTextBox::isSelected(int startPos, int endPos) const{    int sPos = max(startPos - m_start, 0);    int ePos = min(endPos - m_start, (int)m_len);    return (sPos < ePos);}RenderObject::SelectionState InlineTextBox::selectionState(){    RenderObject::SelectionState state = renderer()->selectionState();    if (state == RenderObject::SelectionStart || state == RenderObject::SelectionEnd || state == RenderObject::SelectionBoth) {        int startPos, endPos;        renderer()->selectionStartEnd(startPos, endPos);        // The position after a hard line break is considered to be past its end.        int lastSelectable = start() + len() - (isLineBreak() ? 1 : 0);        bool start = (state != RenderObject::SelectionEnd && startPos >= m_start && startPos < m_start + m_len);        bool end = (state != RenderObject::SelectionStart && endPos > m_start && endPos <= lastSelectable);        if (start && end)            state = RenderObject::SelectionBoth;        else if (start)            state = RenderObject::SelectionStart;        else if (end)            state = RenderObject::SelectionEnd;        else if ((state == RenderObject::SelectionEnd || startPos < m_start) &&                 (state == RenderObject::SelectionStart || endPos > lastSelectable))            state = RenderObject::SelectionInside;        else if (state == RenderObject::SelectionBoth)            state = RenderObject::SelectionNone;    }    return state;}IntRect InlineTextBox::selectionRect(int tx, int ty, int startPos, int endPos){    int sPos = max(startPos - m_start, 0);    int ePos = min(endPos - m_start, (int)m_len);        if (sPos >= ePos)        return IntRect();    RenderText* textObj = textRenderer();    int selTop = selectionTop();    int selHeight = selectionHeight();    const Font& f = textObj->style(m_firstLine)->font();    IntRect r = enclosingIntRect(f.selectionRectForText(TextRun(textObj->text()->characters() + m_start, m_len, textObj->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride),                                                        IntPoint(tx + m_x, ty + selTop), selHeight, sPos, ePos));    if (r.x() > tx + m_x + m_width)        r.setWidth(0);    else if (r.right() - 1 > tx + m_x + m_width)        r.setWidth(tx + m_x + m_width - r.x());    return r;}void InlineTextBox::deleteLine(RenderArena* arena){    toRenderText(renderer())->removeTextBox(this);    destroy(arena);}void InlineTextBox::extractLine(){    if (m_extracted)        return;    toRenderText(renderer())->extractTextBox(this);}void InlineTextBox::attachLine(){    if (!m_extracted)        return;        toRenderText(renderer())->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;        // Criteria for full truncation:    // LTR: the left edge of the ellipsis is to the left of our text run.    // RTL: the right edge of the ellipsis is to the right of our text run.    bool ltrFullTruncation = ltr && ellipsisX <= m_x;    bool rtlFullTruncation = !ltr && ellipsisX >= (m_x + m_width);    if (ltrFullTruncation || rtlFullTruncation) {        // 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;    }    bool ltrEllipsisWithinBox = ltr && (ellipsisX < m_x + m_width);    bool rtlEllipsisWithinBox = !ltr && (ellipsisX > m_x);    if (ltrEllipsisWithinBox || rtlEllipsisWithinBox) {        if (ltr && direction() == RTL || !ltr && direction() == LTR)            return -1; // FIXME: Support cases in which the last run's directionality differs from the context.        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 min(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;        if (ltr)            return m_x + toRenderText(renderer())->width(m_start, offset, textPos(), m_firstLine);        else            return m_x + (m_width - toRenderText(renderer())->width(m_start, offset, textPos(), m_firstLine)) - ellipsisWidth;    }    return -1;}Color correctedTextColor(Color textColor, Color backgroundColor) {    // Adjust the text color if it is too close to the background color,    // by darkening or lightening it to move it further away.        int d = differenceSquared(textColor, backgroundColor);    // semi-arbitrarily chose 65025 (255^2) value here after a few tests;     if (d > 65025) {        return textColor;    }        int distanceFromWhite = differenceSquared(textColor, Color::white);    int distanceFromBlack = differenceSquared(textColor, Color::black);    if (distanceFromWhite < distanceFromBlack) {        return textColor.dark();    }        return textColor.light();}void updateGraphicsContext(GraphicsContext* context, const Color& fillColor, const Color& strokeColor, float strokeThickness){    int mode = context->textDrawingMode();    if (strokeThickness > 0) {        int newMode = mode | cTextStroke;        if (mode != newMode) {            context->setTextDrawingMode(newMode);            mode = newMode;        }    }        if (mode & cTextFill && fillColor != context->fillColor())        context->setFillColor(fillColor);    if (mode & cTextStroke) {        if (strokeColor != context->strokeColor())            context->setStrokeColor(strokeColor);        if (strokeThickness != context->strokeThickness())            context->setStrokeThickness(strokeThickness);    }}bool InlineTextBox::isLineBreak() const{    return renderer()->isBR() || (renderer()->style()->preserveNewline() && len() == 1 && (*textRenderer()->text())[start()] == '\n');}bool InlineTextBox::nodeAtPoint(const HitTestRequest&, HitTestResult& result, int x, int y, int tx, int ty){    if (isLineBreak())        return false;    IntRect rect(tx + m_x, ty + m_y, m_width, height());    if (m_truncation != cFullTruncation && visibleToHitTesting() && rect.contains(x, y)) {        renderer()->updateHitTestResult(result, IntPoint(x - tx, y - ty));        return true;    }    return false;}static void paintTextWithShadows(GraphicsContext* context, const Font& font, const TextRun& textRun, int startOffset, int endOffset, const IntPoint& textOrigin, int x, int y, int w, int h, ShadowData* shadow, bool stroked){    do {        IntSize extraOffset;        if (shadow) {            IntSize shadowOffset(shadow->x, shadow->y);            int shadowBlur = shadow->blur;            const Color& shadowColor = shadow->color;            if (shadow->next || stroked) {                IntRect shadowRect(x, y, w, h);                shadowRect.inflate(shadowBlur);                shadowRect.move(shadowOffset);                context->save();                context->clip(shadowRect);                extraOffset = IntSize(0, 2 * h + max(0, shadowOffset.height()) + shadowBlur);                shadowOffset -= extraOffset;            }            context->setShadow(shadowOffset, shadowBlur, shadowColor);        }        if (startOffset <= endOffset)            context->drawText(font, textRun, textOrigin + extraOffset, startOffset, endOffset);        else {            if (endOffset > 0)                context->drawText(font, textRun, textOrigin + extraOffset,  0, endOffset);            if (startOffset < textRun.length())                context->drawText(font, textRun, textOrigin + extraOffset, startOffset);        }        if (!shadow)            break;        if (shadow->next || stroked)            context->restore();        else            context->clearShadow();        shadow = shadow->next;    } while (shadow || stroked);}void InlineTextBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty){    if (isLineBreak() || !renderer()->shouldPaintWithinRoot(paintInfo) || renderer()->style()->visibility() != VISIBLE ||        m_truncation == cFullTruncation || paintInfo.phase == PaintPhaseOutline)        return;        ASSERT(paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintPhaseChildOutlines);    int xPos = tx + m_x - parent()->maxHorizontalVisualOverflow();    int w = width() + 2 * parent()->maxHorizontalVisualOverflow();    if (xPos >= paintInfo.rect.right() || xPos + w <= paintInfo.rect.x())        return;    bool isPrinting = textRenderer()->document()->printing();        // Determine whether or not we're selected.    bool haveSelection = !isPrinting && paintInfo.phase != PaintPhaseTextClip && selectionState() != RenderObject::SelectionNone;    if (!haveSelection && paintInfo.phase == PaintPhaseSelection)        // When only painting the selection, don't bother to paint if there is none.        return;    GraphicsContext* context = paintInfo.context;    // Determine whether or not we have composition underlines to draw.    bool containsComposition = renderer()->node() && renderer()->document()->frame()->editor()->compositionNode() == renderer()->node();

⌨️ 快捷键说明

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