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

📄 render_text.cpp

📁 手机浏览器源码程序,功能强大
💻 CPP
📖 第 1 页 / 共 5 页
字号:
                    selectionTextShadow = pseudoStyle->textShadow();
            }
        }
    }

    if (!paintSelectedTextOnly && !paintSelectedTextSeparately) {
        // paint all the text
        // FIXME: Handle RTL direction, handle reversed strings.  For now truncation can only be turned on
        // for non-reversed LTR strings.
        int endPoint = m_len;
        if (m_truncation != cNoTruncation)
            endPoint = m_truncation - m_start;
        font->drawText(i.p, m_x + tx, m_y + ty + m_baseline,
                       textObject()->string()->s, textObject()->string()->l, m_start, endPoint,
                       m_toAdd, m_reversed ? QPainter::RTL : QPainter::LTR, styleToUse->visuallyOrdered());
    } else {
        int sPos, ePos;
        selectionStartEnd(sPos, ePos);
        if (paintSelectedTextSeparately) {
            // paint only the text that is not selected
            if (sPos >= ePos) {
                font->drawText(i.p, m_x + tx, m_y + ty + m_baseline,
                               textObject()->string()->s, textObject()->string()->l, m_start, m_len,
                               m_toAdd, m_reversed ? QPainter::RTL : QPainter::LTR, styleToUse->visuallyOrdered());
            } else {
                if (sPos - 1 >= 0) {
                    font->drawText(i.p, m_x + tx, m_y + ty + m_baseline, textObject()->string()->s,
                                   textObject()->string()->l, m_start, m_len,
                                   m_toAdd, m_reversed ? QPainter::RTL : QPainter::LTR, styleToUse->visuallyOrdered(), 0, sPos);
                }
                if (ePos < m_start + m_len) {
                    font->drawText(i.p, m_x + tx, m_y + ty + m_baseline, textObject()->string()->s,
                                   textObject()->string()->l, m_start, m_len,
                                   m_toAdd, m_reversed ? QPainter::RTL : QPainter::LTR, styleToUse->visuallyOrdered(), ePos, -1);
                }
            }
        }

        if (sPos < ePos) {
            // paint only the text that is selected
            if (selectionColor != i.p->pen().color())
                i.p->setPen(selectionColor);

            if (selectionTextShadow)
                i.p->setShadow(selectionTextShadow->x,
                               selectionTextShadow->y,
                               selectionTextShadow->blur,
                               selectionTextShadow->color);
            font->drawText(i.p, m_x + tx, m_y + ty + m_baseline, textObject()->string()->s,
                           textObject()->string()->l, m_start, m_len,
                           m_toAdd, m_reversed ? QPainter::RTL : QPainter::LTR, styleToUse->visuallyOrdered(), sPos, ePos);
            if (selectionTextShadow)
                i.p->clearShadow();
        }
    }

    // Paint decorations
    if (d != TDNONE && i.phase != PaintActionSelection && styleToUse->htmlHacks()) {
        i.p->setPen(styleToUse->color());
        paintDecoration(i.p, tx, ty, d);
    }

    // Draw any doc markers that touch this run
    // Note end() points at the last char, not one past it like endOffset and ranges do
    if (i.phase != PaintActionSelection) {
        for ( ; markerIt != markers.end(); markerIt++) {
            DocumentMarker marker = *markerIt;

            if (marker.endOffset <= start())
                // marker is completely before this run.  This might be a marker that sits before the
                // first run we draw, or markers that were within runs we skipped due to truncation.
                continue;

            if (marker.startOffset <= end()) {
                // marker intersects this run.  Paint it.
                paintMarker(i.p, tx, ty, marker);
                if (marker.endOffset > end() + 1)
                    // marker also runs into the next run. Bail now, no more marker advancement.
                    break;
            } else
                // marker is completely after this run, bail.  A later run will paint it.
                break;
        }


        for ( ; underlineIt != underlines.end(); underlineIt++) {
            KWQKHTMLPart::MarkedTextUnderline underline = *underlineIt;

            if (underline.endOffset <= start())
                // underline is completely before this run.  This might be an underlinethat sits
                // before the first run we draw, or underlines that were within runs we skipped
                // due to truncation.
                continue;

            if (underline.startOffset <= end()) {
                // underline intersects this run.  Paint it.
                paintMarkedTextUnderline(i.p, tx, ty, underline);
                if (underline.endOffset > end() + 1)
                    // underline also runs into the next run. Bail now, no more marker advancement.
                    break;
            } else
                // underline is completely after this run, bail.  A later run will paint it.
                break;
        }



    }

    if (setShadow)
        i.p->clearShadow();
}

void InlineTextBox::selectionStartEnd(int& sPos, int& ePos)
{
    int startPos, endPos;
    if (object()->selectionState() == RenderObject::SelectionInside) {
        startPos = 0;
        endPos = textObject()->string()->l;
    } else {
        textObject()->selectionStartEnd(startPos, endPos);
        if (object()->selectionState() == RenderObject::SelectionStart)
            endPos = textObject()->string()->l;
        else if (object()->selectionState() == RenderObject::SelectionEnd)
            startPos = 0;
    }

    sPos = kMax(startPos - m_start, 0);
    ePos = kMin(endPos - m_start, (int)m_len);
}

void InlineTextBox::paintSelection(QPainter* p, int tx, int ty, RenderStyle* style, const Font* f)
{
    // See if we have a selection to paint at all.
    int sPos, ePos;
    selectionStartEnd(sPos, ePos);
    if (sPos >= ePos)
        return;

    // Macintosh-style text highlighting is to draw with a particular background color, not invert.
    QColor textColor = style->color();
    QColor c = object()->selectionColor(p);
    if (!c.isValid())
        return;

    // If the text color ends up being the same as the selection background, invert the selection
    // background.  This should basically never happen, since the selection has transparency.
    if (textColor == c)
        c = QColor(0xff - c.red(), 0xff - c.green(), 0xff - c.blue());

    p->save();
    p->setPen(c); // Don't draw text at all!
    RootInlineBox* r = root();
    int x = m_x + tx;
    int y = r->selectionTop();
    int h = r->selectionHeight();
    f->drawHighlightForText(p, x, y + ty, h,
                            textObject()->str->s, textObject()->str->l, m_start, m_len,
                            m_toAdd, m_reversed ? QPainter::RTL : QPainter::LTR, style->visuallyOrdered(), sPos, ePos, c);
    p->restore();
}

void InlineTextBox::paintMarkedTextBackground(QPainter* p, int tx, int ty, RenderStyle* style, const Font* f, int startPos, int endPos)
{
    int offset = m_start;
    int sPos = kMax(startPos - offset, 0);
    int ePos = kMin(endPos - offset, (int)m_len);

    if (sPos >= ePos)
        return;

    p->save();

    QColor c = QColor(225, 221, 85);

    p->setPen(c); // Don't draw text at all!

    RootInlineBox* r = root();
    int x = m_x + tx;
    int y = r->selectionTop();
    int h = r->selectionHeight();
    f->drawHighlightForText(p, x, y + ty, h, textObject()->str->s, textObject()->str->l, m_start, m_len,
		m_toAdd, m_reversed ? QPainter::RTL : QPainter::LTR, style->visuallyOrdered(), sPos, ePos, c);
    p->restore();
}

void 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);
    }
}

void InlineTextBox::paintMarker(QPainter *pt, int _tx, int _ty, DocumentMarker marker)
{
#if !NOKIA_CHANGES
    _tx += m_x;
    _ty += m_y;

    if (m_truncation == cFullTruncation)
        return;

    int start = 0;                  // start of line to draw, relative to _tx
    int width = m_width;            // how much line to draw
    bool useWholeWidth = true;
    ulong paintStart = m_start;
    ulong paintEnd = end()+1;      // end points at the last char, not past it
    if (paintStart <= marker.startOffset) {
        paintStart = marker.startOffset;
        useWholeWidth = false;
        start = static_cast<RenderText*>(m_object)->width(m_start, paintStart - m_start, m_firstLine);
    }
    if (paintEnd != marker.endOffset) {      // end points at the last char, not past it
        paintEnd = kMin(paintEnd, marker.endOffset);
        useWholeWidth = false;
    }
    if (m_truncation != cNoTruncation) {
        paintEnd = kMin(paintEnd, (ulong)m_truncation);
        useWholeWidth = false;
    }
    if (!useWholeWidth) {
        width = static_cast<RenderText*>(m_object)->width(paintStart, paintEnd - paintStart, m_firstLine);
    }

    // IMPORTANT: The misspelling underline is not considered when calculating the text bounds, so we have to
    // make sure to fit within those bounds.  This means the top pixel(s) of the underline will overlap the
    // bottom pixel(s) of the glyphs in smaller font sizes.  The alternatives are to increase the line spacing (bad!!)
    // or decrease the underline thickness.  The overlap is actually the most useful, and matches what AppKit does.
    // So, we generally place the underline at the bottom of the text, but in larger fonts that's not so good so
    // we pin to two pixels under the baseline.
    int lineThickness = pt->misspellingLineThickness();
    int descent = m_height - m_baseline;
    int underlineOffset;
    if (descent <= (2 + lineThickness)) {
        // place the underline at the very bottom of the text in small/medium fonts
        underlineOffset = m_height - lineThickness;
    } else {
        // in larger fonts, tho, place the underline up near the baseline to prevent big gap
        underlineOffset = m_baseline + 2;
    }
    pt->drawLineForMisspelling(_tx + start, _ty + underlineOffset, width);
#endif
}

void InlineTextBox::paintMarkedTextUnderline(QPainter *pt, int _tx, int _ty, KWQKHTMLPart::MarkedTextUnderline underline)
{
    _tx += m_x;
    _ty += m_y;

    if (m_truncation == cFullTruncation)
        return;

    int start = 0;                  // start of line to draw, relative to _tx
    int width = m_width;            // how much line to draw
    bool useWholeWidth = true;
    ulong paintStart = m_start;
    ulong paintEnd = end()+1;      // end points at the last char, not past it
    if (paintStart <= underline.startOffset) {
        paintStart = underline.startOffset;
        useWholeWidth = false;
        start = static_cast<RenderText*>(m_object)->width(m_start, paintStart - m_start, m_firstLine);
    }
    if (paintEnd != underline.endOffset) {      // end points at the last char, not past it
        paintEnd = kMin(paintEnd, (ulong)underline.endOffset);
        useWholeWidth = false;
    }
    if (m_truncation != cNoTruncation) {
        paintEnd = kMin(paintEnd, (ulong)m_truncation);
        useWholeWidth = false;
    }
    if (!useWholeWidth) {
        width = static_cast<RenderText*>(m_object)->width(paintStart, paintEnd - paintStart, m_firstLine);
    }

    int underlineOffset = m_height - 3;
    pt->setPen(QPen(underline.color, underline.thick ? 2 : 0));
    pt->drawLineForText(_tx + start, _ty, underlineOffset, width);
}

long 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;
}

#if HAVE_ICU_LIBRARY

static UBreakIterator *getCharacterBreakIterator(const DOMStringImpl *i)
{
    // The locale is currently ignored when determining character cluster breaks.  This may change
    // in the future (according to Deborah Goldsmith).
    static bool createdIterator = false;
    static UBreakIterator *iterator;
    UErrorCode status;
    if (!createdIterator) {
        status = U_ZERO_ERROR;
        iterator = ubrk_open(UBRK_CHARACTER, "en_us", NULL, 0, &status);
        createdIterator = true;
    }
    if (!iterator) {
        return NULL;
    }
    status = U_ZERO_ERROR;
    ubrk_setText(iterator, reinterpret_cast<const UChar *>(i->s), i->l, &status);
    if (status != U_ZERO_ERROR) {
        return NULL;
    }
    return iterator;
}

#endif

long RenderText::previousOffset (long current) const
{
#if HAVE_ICU_LIBRARY
    UBreakIterator *iterator = getCharacterBreakIterator(str);
    if (iterator) {
        return ubrk_preceding(iterator, current);
    }
#endif
    return current - 1;
}

long RenderText::nextOffset (long current) const
{
#if HAVE_ICU_LIBRARY
    UBreakIterator *iterator = getCharacterBreakIterator(str);
    if (iterator) {
        return ubrk_following(iterator, current);
    }
#endif
    return current + 1;
}

#define LOCAL_WIDTH_BUF_SIZE	1024

int 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);
}

// -------------------------------------------------------------------------------------

⌨️ 快捷键说明

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