📄 inlinetextbox.cpp
字号:
bool useCustomUnderlines = containsComposition && renderer()->document()->frame()->editor()->compositionUsesCustomUnderlines(); // Set our font. RenderStyle* styleToUse = renderer()->style(m_firstLine); int d = styleToUse->textDecorationsInEffect(); const Font& font = styleToUse->font(); // 1. Paint backgrounds behind text if needed. Examples of such backgrounds include selection // and composition underlines. if (paintInfo.phase != PaintPhaseSelection && paintInfo.phase != PaintPhaseTextClip && !isPrinting) {#if PLATFORM(MAC) // Custom highlighters go behind everything else. if (styleToUse->highlight() != nullAtom && !context->paintingDisabled()) paintCustomHighlight(tx, ty, styleToUse->highlight());#endif if (containsComposition && !useCustomUnderlines) paintCompositionBackground(context, tx, ty, styleToUse, font, renderer()->document()->frame()->editor()->compositionStart(), renderer()->document()->frame()->editor()->compositionEnd()); paintDocumentMarkers(context, tx, ty, styleToUse, font, true); if (haveSelection && !useCustomUnderlines) paintSelection(context, tx, ty, styleToUse, font); } // 2. Now paint the foreground, including text and decorations like underline/overline (in quirks mode only). if (m_len <= 0) return; Color textFillColor; Color textStrokeColor; float textStrokeWidth = styleToUse->textStrokeWidth(); ShadowData* textShadow = paintInfo.forceBlackText ? 0 : styleToUse->textShadow(); if (paintInfo.forceBlackText) { textFillColor = Color::black; textStrokeColor = Color::black; } else { textFillColor = styleToUse->textFillColor(); if (!textFillColor.isValid()) textFillColor = styleToUse->color(); // Make the text fill color legible against a white background if (styleToUse->forceBackgroundsToWhite()) textFillColor = correctedTextColor(textFillColor, Color::white); textStrokeColor = styleToUse->textStrokeColor(); if (!textStrokeColor.isValid()) textStrokeColor = styleToUse->color(); // Make the text stroke color legible against a white background if (styleToUse->forceBackgroundsToWhite()) textStrokeColor = correctedTextColor(textStrokeColor, Color::white); } bool paintSelectedTextOnly = (paintInfo.phase == PaintPhaseSelection); bool paintSelectedTextSeparately = false; Color selectionFillColor = textFillColor; Color selectionStrokeColor = textStrokeColor; float selectionStrokeWidth = textStrokeWidth; ShadowData* selectionShadow = textShadow; if (haveSelection) { // Check foreground color first. Color foreground = paintInfo.forceBlackText ? Color::black : renderer()->selectionForegroundColor(); if (foreground.isValid() && foreground != selectionFillColor) { if (!paintSelectedTextOnly) paintSelectedTextSeparately = true; selectionFillColor = foreground; } if (RenderStyle* pseudoStyle = renderer()->getCachedPseudoStyle(SELECTION)) { ShadowData* shadow = paintInfo.forceBlackText ? 0 : pseudoStyle->textShadow(); if (shadow != selectionShadow) { if (!paintSelectedTextOnly) paintSelectedTextSeparately = true; selectionShadow = shadow; } float strokeWidth = pseudoStyle->textStrokeWidth(); if (strokeWidth != selectionStrokeWidth) { if (!paintSelectedTextOnly) paintSelectedTextSeparately = true; selectionStrokeWidth = strokeWidth; } Color stroke = paintInfo.forceBlackText ? Color::black : pseudoStyle->textStrokeColor(); if (!stroke.isValid()) stroke = pseudoStyle->color(); if (stroke != selectionStrokeColor) { if (!paintSelectedTextOnly) paintSelectedTextSeparately = true; selectionStrokeColor = stroke; } } } int baseline = renderer()->style(m_firstLine)->font().ascent(); IntPoint textOrigin(m_x + tx, m_y + ty + baseline); TextRun textRun(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || styleToUse->visuallyOrdered()); int sPos = 0; int ePos = 0; if (paintSelectedTextOnly || paintSelectedTextSeparately) selectionStartEnd(sPos, ePos); if (!paintSelectedTextOnly) { // For stroked painting, we have to change the text drawing mode. It's probably dangerous to leave that mutated as a side // effect, so only when we know we're stroking, do a save/restore. if (textStrokeWidth > 0) context->save(); updateGraphicsContext(context, textFillColor, textStrokeColor, textStrokeWidth); if (!paintSelectedTextSeparately || ePos <= sPos) { // FIXME: Truncate right-to-left text correctly. paintTextWithShadows(context, font, textRun, 0, m_truncation == cNoTruncation ? m_len : m_truncation, textOrigin, m_x + tx, m_y + ty, width(), height(), textShadow, textStrokeWidth > 0); } else paintTextWithShadows(context, font, textRun, ePos, sPos, textOrigin, m_x + tx, m_y + ty, width(), height(), textShadow, textStrokeWidth > 0); if (textStrokeWidth > 0) context->restore(); } if ((paintSelectedTextOnly || paintSelectedTextSeparately) && sPos < ePos) { // paint only the text that is selected if (selectionStrokeWidth > 0) context->save(); updateGraphicsContext(context, selectionFillColor, selectionStrokeColor, selectionStrokeWidth); paintTextWithShadows(context, font, textRun, sPos, ePos, textOrigin, m_x + tx, m_y + ty, width(), height(), selectionShadow, selectionStrokeWidth > 0); if (selectionStrokeWidth > 0) context->restore(); } // Paint decorations if (d != TDNONE && paintInfo.phase != PaintPhaseSelection && styleToUse->htmlHacks()) { context->setStrokeColor(styleToUse->color()); paintDecoration(context, tx, ty, d, textShadow); } if (paintInfo.phase == PaintPhaseForeground) { paintDocumentMarkers(context, tx, ty, styleToUse, font, false); if (useCustomUnderlines) { const Vector<CompositionUnderline>& underlines = renderer()->document()->frame()->editor()->customCompositionUnderlines(); size_t numUnderlines = underlines.size(); for (size_t index = 0; index < numUnderlines; ++index) { const CompositionUnderline& underline = underlines[index]; if (underline.endOffset <= start()) // underline is completely before this run. This might be an underline that 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. paintCompositionUnderline(context, 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; } } }}void InlineTextBox::selectionStartEnd(int& sPos, int& ePos){ int startPos, endPos; if (renderer()->selectionState() == RenderObject::SelectionInside) { startPos = 0; endPos = textRenderer()->textLength(); } else { textRenderer()->selectionStartEnd(startPos, endPos); if (renderer()->selectionState() == RenderObject::SelectionStart) endPos = textRenderer()->textLength(); else if (renderer()->selectionState() == RenderObject::SelectionEnd) startPos = 0; } sPos = max(startPos - m_start, 0); ePos = min(endPos - m_start, (int)m_len);}void InlineTextBox::paintSelection(GraphicsContext* context, int tx, int ty, RenderStyle* style, const Font& font){ // See if we have a selection to paint at all. int sPos, ePos; selectionStartEnd(sPos, ePos); if (sPos >= ePos) return; Color textColor = style->color(); Color c = renderer()->selectionBackgroundColor(); if (!c.isValid() || c.alpha() == 0) 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 = Color(0xff - c.red(), 0xff - c.green(), 0xff - c.blue()); context->save(); updateGraphicsContext(context, c, c, 0); // Don't draw text at all! int y = selectionTop(); int h = selectionHeight(); context->clip(IntRect(m_x + tx, y + ty, m_width, h)); context->drawHighlightForText(font, TextRun(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || style->visuallyOrdered()), IntPoint(m_x + tx, y + ty), h, c, sPos, ePos); context->restore();}void InlineTextBox::paintCompositionBackground(GraphicsContext* context, int tx, int ty, RenderStyle* style, const Font& font, int startPos, int endPos){ int offset = m_start; int sPos = max(startPos - offset, 0); int ePos = min(endPos - offset, (int)m_len); if (sPos >= ePos) return; context->save(); Color c = Color(225, 221, 85); updateGraphicsContext(context, c, c, 0); // Don't draw text at all! int y = selectionTop(); int h = selectionHeight(); context->drawHighlightForText(font, TextRun(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || style->visuallyOrdered()), IntPoint(m_x + tx, y + ty), h, c, sPos, ePos); context->restore();}#if PLATFORM(MAC)void InlineTextBox::paintCustomHighlight(int tx, int ty, const AtomicString& type){ Frame* frame = renderer()->document()->frame(); if (!frame) return; Page* page = frame->page(); if (!page) return; RootInlineBox* r = root(); FloatRect rootRect(tx + r->x(), ty + selectionTop(), r->width(), selectionHeight()); FloatRect textRect(tx + x(), rootRect.y(), width(), rootRect.height()); page->chrome()->client()->paintCustomHighlight(renderer()->node(), type, textRect, rootRect, true, false);}#endifvoid InlineTextBox::paintDecoration(GraphicsContext* context, int tx, int ty, int deco, ShadowData* shadow){ tx += m_x; ty += m_y; if (m_truncation == cFullTruncation) return; int width = m_width; if (m_truncation != cNoTruncation) { width = toRenderText(renderer())->width(m_start, m_truncation, textPos(), m_firstLine); if (direction() == RTL) tx += (m_width - width); } // Get the text decoration colors. Color underline, overline, linethrough; renderer()->getTextDecorationColors(deco, underline, overline, linethrough, true); // Use a special function for underlines to get the positioning exactly right. bool isPrinting = textRenderer()->document()->printing(); context->setStrokeThickness(1.0f); // FIXME: We should improve this rule and not always just assume 1. bool linesAreOpaque = !isPrinting && (!(deco & UNDERLINE) || underline.alpha() == 255) && (!(deco & OVERLINE) || overline.alpha() == 255) && (!(deco & LINE_THROUGH) || linethrough.alpha() == 255); int baseline = renderer()->style(m_firstLine)->font().ascent(); bool setClip = false; int extraOffset = 0; if (!linesAreOpaque && shadow && shadow->next) { context->save(); IntRect clipRect(tx, ty, width, baseline + 2); for (ShadowData* s = shadow; s; s = s->next) { IntRect shadowRect(tx, ty, width, baseline + 2); shadowRect.inflate(s->blur); shadowRect.move(s->x, s->y); clipRect.unite(shadowRect); extraOffset = max(extraOffset, max(0, s->y) + s->blur); } context->save(); context->clip(clipRect); extraOffset += baseline + 2; ty += extraOffset; setClip = true; } bool setShadow = false; do {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -