void SVGInlineTextBox::paintSelectionBackground(PaintInfo& paintInfo) { ASSERT(paintInfo.shouldPaintWithinRoot(renderer())); ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection); ASSERT(truncation() == cNoTruncation); if (renderer()->style()->visibility() != VISIBLE) return; RenderObject* parentRenderer = parent()->renderer(); ASSERT(parentRenderer); ASSERT(!parentRenderer->document()->printing()); // Determine whether or not we're selected. bool paintSelectedTextOnly = paintInfo.phase == PaintPhaseSelection; bool hasSelection = selectionState() != RenderObject::SelectionNone; if (!hasSelection || paintSelectedTextOnly) return; Color backgroundColor = renderer()->selectionBackgroundColor(); if (!backgroundColor.isValid() || !backgroundColor.alpha()) return; RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer()); ASSERT(textRenderer); if (!textShouldBePainted(textRenderer)) return; RenderStyle* style = parentRenderer->style(); ASSERT(style); RenderStyle* selectionStyle = style; if (hasSelection) { selectionStyle = parentRenderer->getCachedPseudoStyle(SELECTION); if (!selectionStyle) selectionStyle = style; } int startPosition, endPosition; selectionStartEnd(startPosition, endPosition); int fragmentStartPosition = 0; int fragmentEndPosition = 0; AffineTransform fragmentTransform; unsigned textFragmentsSize = m_textFragments.size(); for (unsigned i = 0; i < textFragmentsSize; ++i) { SVGTextFragment& fragment = m_textFragments.at(i); ASSERT(!m_paintingResource); fragmentStartPosition = startPosition; fragmentEndPosition = endPosition; if (!mapStartEndPositionsIntoFragmentCoordinates(fragment, fragmentStartPosition, fragmentEndPosition)) continue; GraphicsContextStateSaver stateSaver(*paintInfo.context); fragment.buildFragmentTransform(fragmentTransform); if (!fragmentTransform.isIdentity()) paintInfo.context->concatCTM(fragmentTransform); paintInfo.context->setFillColor(backgroundColor, style->colorSpace()); paintInfo.context->fillRect(selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, style), backgroundColor, style->colorSpace()); m_paintingResourceMode = ApplyToDefaultMode; } ASSERT(!m_paintingResource); }
void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit, LayoutUnit) { ASSERT(paintInfo.shouldPaintWithinRoot(renderer())); ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection); ASSERT(truncation() == cNoTruncation); if (renderer()->style()->visibility() != VISIBLE) return; // Note: We're explicitely not supporting composition & custom underlines and custom highlighters - unlike InlineTextBox. // If we ever need that for SVG, it's very easy to refactor and reuse the code. RenderObject* parentRenderer = parent()->renderer(); ASSERT(parentRenderer); bool paintSelectedTextOnly = paintInfo.phase == PaintPhaseSelection; bool hasSelection = !parentRenderer->document().printing() && selectionState() != RenderObject::SelectionNone; if (!hasSelection && paintSelectedTextOnly) return; RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer()); ASSERT(textRenderer); if (!textShouldBePainted(textRenderer)) return; RenderStyle* style = parentRenderer->style(); ASSERT(style); paintDocumentMarkers(paintInfo.context, paintOffset, style, textRenderer->scaledFont(), true); const SVGRenderStyle* svgStyle = style->svgStyle(); ASSERT(svgStyle); bool hasFill = svgStyle->hasFill(); bool hasVisibleStroke = svgStyle->hasVisibleStroke(); RenderStyle* selectionStyle = style; if (hasSelection) { selectionStyle = parentRenderer->getCachedPseudoStyle(SELECTION); if (selectionStyle) { const SVGRenderStyle* svgSelectionStyle = selectionStyle->svgStyle(); ASSERT(svgSelectionStyle); if (!hasFill) hasFill = svgSelectionStyle->hasFill(); if (!hasVisibleStroke) hasVisibleStroke = svgSelectionStyle->hasVisibleStroke(); } else selectionStyle = style; } if (textRenderer->frame() && textRenderer->frame()->view() && textRenderer->frame()->view()->paintBehavior() & PaintBehaviorRenderingSVGMask) { hasFill = true; hasVisibleStroke = false; } AffineTransform fragmentTransform; unsigned textFragmentsSize = m_textFragments.size(); for (unsigned i = 0; i < textFragmentsSize; ++i) { SVGTextFragment& fragment = m_textFragments.at(i); ASSERT(!m_paintingResource); GraphicsContextStateSaver stateSaver(*paintInfo.context, false); fragment.buildFragmentTransform(fragmentTransform); if (!fragmentTransform.isIdentity()) { stateSaver.save(); paintInfo.context->concatCTM(fragmentTransform); } // Spec: All text decorations except line-through should be drawn before the text is filled and stroked; thus, the text is rendered on top of these decorations. unsigned decorations = style->textDecorationsInEffect(); if (decorations & TextDecorationUnderline) paintDecoration(paintInfo.context, TextDecorationUnderline, fragment); if (decorations & TextDecorationOverline) paintDecoration(paintInfo.context, TextDecorationOverline, fragment); for (int i = 0; i < 3; i++) { switch (svgStyle->paintOrderType(i)) { case PT_FILL: // Fill text if (hasFill) { m_paintingResourceMode = ApplyToFillMode | ApplyToTextMode; paintText(paintInfo.context, style, selectionStyle, fragment, hasSelection, paintSelectedTextOnly); } break; case PT_STROKE: // Stroke text if (hasVisibleStroke) { m_paintingResourceMode = ApplyToStrokeMode | ApplyToTextMode; paintText(paintInfo.context, style, selectionStyle, fragment, hasSelection, paintSelectedTextOnly); } break; case PT_MARKERS: // Markers don't apply to text break; default: ASSERT_NOT_REACHED(); break; } } // Spec: Line-through should be drawn after the text is filled and stroked; thus, the line-through is rendered on top of the text. if (decorations & TextDecorationLineThrough) paintDecoration(paintInfo.context, TextDecorationLineThrough, fragment); m_paintingResourceMode = ApplyToDefaultMode; } ASSERT(!m_paintingResource); }
void SVGInlineTextBox::paint(PaintInfo& paintInfo, int, int) { ASSERT(paintInfo.shouldPaintWithinRoot(renderer())); ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection); ASSERT(truncation() == cNoTruncation); if (renderer()->style()->visibility() != VISIBLE) return; // Note: We're explicitely not supporting composition & custom underlines and custom highlighters - unlike InlineTextBox. // If we ever need that for SVG, it's very easy to refactor and reuse the code. RenderObject* parentRenderer = parent()->renderer(); ASSERT(parentRenderer); bool paintSelectedTextOnly = paintInfo.phase == PaintPhaseSelection; bool hasSelection = !parentRenderer->document()->printing() && selectionState() != RenderObject::SelectionNone; if (!hasSelection && paintSelectedTextOnly) return; RenderStyle* style = parentRenderer->style(); ASSERT(style); const SVGRenderStyle* svgStyle = style->svgStyle(); ASSERT(svgStyle); bool hasFill = svgStyle->hasFill(); bool hasStroke = svgStyle->hasStroke(); RenderStyle* selectionStyle = style; if (hasSelection) { selectionStyle = parentRenderer->getCachedPseudoStyle(SELECTION); if (selectionStyle) { const SVGRenderStyle* svgSelectionStyle = selectionStyle->svgStyle(); ASSERT(svgSelectionStyle); if (!hasFill) hasFill = svgSelectionStyle->hasFill(); if (!hasStroke) hasStroke = svgSelectionStyle->hasStroke(); } else selectionStyle = style; } unsigned textFragmentsSize = m_textFragments.size(); for (unsigned i = 0; i < textFragmentsSize; ++i) { SVGTextFragment& fragment = m_textFragments.at(i); ASSERT(!m_paintingResource); paintInfo.context->save(); if (!fragment.transform.isIdentity()) paintInfo.context->concatCTM(fragment.transform); // Spec: All text decorations except line-through should be drawn before the text is filled and stroked; thus, the text is rendered on top of these decorations. int decorations = style->textDecorationsInEffect(); if (decorations & UNDERLINE) paintDecoration(paintInfo.context, UNDERLINE, fragment); if (decorations & OVERLINE) paintDecoration(paintInfo.context, OVERLINE, fragment); // Fill text if (hasFill) { m_paintingResourceMode = ApplyToFillMode | ApplyToTextMode; paintText(paintInfo.context, style, selectionStyle, fragment, hasSelection, paintSelectedTextOnly); } // Stroke text if (hasStroke) { m_paintingResourceMode = ApplyToStrokeMode | ApplyToTextMode; paintText(paintInfo.context, style, selectionStyle, fragment, hasSelection, paintSelectedTextOnly); } // Spec: Line-through should be drawn after the text is filled and stroked; thus, the line-through is rendered on top of the text. if (decorations & LINE_THROUGH) paintDecoration(paintInfo.context, LINE_THROUGH, fragment); m_paintingResourceMode = ApplyToDefaultMode; paintInfo.context->restore(); } ASSERT(!m_paintingResource); }