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.alpha()) return; RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer()); ASSERT(textRenderer); if (!textShouldBePainted(textRenderer)) return; RenderStyle* style = parentRenderer->style(); ASSERT(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); paintInfo.context->fillRect(selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, style), backgroundColor); m_paintingResourceMode = ApplyToDefaultMode; } ASSERT(!m_paintingResource); }
void SVGInlineTextBoxPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { ASSERT(paintInfo.shouldPaintWithinRoot(&m_svgInlineTextBox.layoutObject())); ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection); ASSERT(m_svgInlineTextBox.truncation() == cNoTruncation); if (m_svgInlineTextBox.layoutObject().style()->visibility() != VISIBLE) return; // We're explicitly 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. if (paintInfo.phase == PaintPhaseSelection && !shouldPaintSelection()) return; LayoutSVGInlineText& textLayoutObject = toLayoutSVGInlineText(m_svgInlineTextBox.layoutObject()); if (!textShouldBePainted(textLayoutObject)) return; DisplayItem::Type displayItemType = DisplayItem::paintPhaseToDrawingType(paintInfo.phase); if (!DrawingRecorder::useCachedDrawingIfPossible(*paintInfo.context, m_svgInlineTextBox, displayItemType)) { LayoutObject& parentLayoutObject = m_svgInlineTextBox.parent()->layoutObject(); const ComputedStyle& style = parentLayoutObject.styleRef(); DrawingRecorder recorder(*paintInfo.context, m_svgInlineTextBox, displayItemType, paintInfo.rect); InlineTextBoxPainter(m_svgInlineTextBox).paintDocumentMarkers( paintInfo.context, paintOffset, style, textLayoutObject.scaledFont(), true); if (!m_svgInlineTextBox.textFragments().isEmpty()) paintTextFragments(paintInfo, parentLayoutObject); } }
void SVGInlineTextBoxPainter::paintSelectionBackground(const PaintInfo& paintInfo) { if (m_svgInlineTextBox.layoutObject().style()->visibility() != VISIBLE) return; ASSERT(!m_svgInlineTextBox.layoutObject().document().printing()); if (paintInfo.phase == PaintPhaseSelection || !shouldPaintSelection()) return; Color backgroundColor = m_svgInlineTextBox.layoutObject().selectionBackgroundColor(); if (!backgroundColor.alpha()) return; LayoutSVGInlineText& textLayoutObject = toLayoutSVGInlineText(m_svgInlineTextBox.layoutObject()); if (!textShouldBePainted(textLayoutObject)) return; const ComputedStyle& style = m_svgInlineTextBox.parent()->layoutObject().styleRef(); int startPosition, endPosition; m_svgInlineTextBox.selectionStartEnd(startPosition, endPosition); int fragmentStartPosition = 0; int fragmentEndPosition = 0; AffineTransform fragmentTransform; unsigned textFragmentsSize = m_svgInlineTextBox.textFragments().size(); for (unsigned i = 0; i < textFragmentsSize; ++i) { SVGTextFragment& fragment = m_svgInlineTextBox.textFragments().at(i); fragmentStartPosition = startPosition; fragmentEndPosition = endPosition; if (!m_svgInlineTextBox.mapStartEndPositionsIntoFragmentCoordinates(fragment, fragmentStartPosition, fragmentEndPosition)) continue; GraphicsContextStateSaver stateSaver(*paintInfo.context); fragment.buildFragmentTransform(fragmentTransform); if (!fragmentTransform.isIdentity()) paintInfo.context->concatCTM(fragmentTransform); paintInfo.context->setFillColor(backgroundColor); paintInfo.context->fillRect(m_svgInlineTextBox.selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, style), backgroundColor); } }
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, 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. auto& parentRenderer = parent()->renderer(); bool paintSelectedTextOnly = paintInfo.phase == PaintPhaseSelection; bool hasSelection = !parentRenderer.document().printing() && selectionState() != RenderObject::SelectionNone; if (!hasSelection && paintSelectedTextOnly) return; if (!textShouldBePainted(renderer())) return; RenderStyle& style = parentRenderer.style(); const SVGRenderStyle& svgStyle = style.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(); if (!hasFill) hasFill = svgSelectionStyle.hasFill(); if (!hasVisibleStroke) hasVisibleStroke = svgSelectionStyle.hasVisibleStroke(); } else selectionStyle = &style; } if (renderer().view().frameView().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()); fragment.buildFragmentTransform(fragmentTransform); if (!fragmentTransform.isIdentity()) 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. int decorations = style.textDecorationsInEffect(); if (decorations & TextDecorationUnderline) paintDecoration(paintInfo.context(), TextDecorationUnderline, fragment); if (decorations & TextDecorationOverline) paintDecoration(paintInfo.context(), TextDecorationOverline, fragment); auto paintOrder = style.svgStyle().paintTypesForPaintOrder(); for (unsigned i = 0; i < paintOrder.size(); ++i) { switch (paintOrder.at(i)) { case PaintTypeFill: if (!hasFill) continue; m_paintingResourceMode = ApplyToFillMode | ApplyToTextMode; paintText(paintInfo.context(), &style, selectionStyle, fragment, hasSelection, paintSelectedTextOnly); break; case PaintTypeStroke: if (!hasVisibleStroke) continue; m_paintingResourceMode = ApplyToStrokeMode | ApplyToTextMode; paintText(paintInfo.context(), &style, selectionStyle, fragment, hasSelection, paintSelectedTextOnly); break; case PaintTypeMarkers: continue; } } // 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; } // Finally, paint the outline if any. if (renderer().style().hasOutline() && is<RenderInline>(parentRenderer)) downcast<RenderInline>(parentRenderer).paintOutline(paintInfo, paintOffset); ASSERT(!m_paintingResource); }
void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint&, 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); 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; } 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); fragment.buildFragmentTransform(fragmentTransform); if (!fragmentTransform.isIdentity()) 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. 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; } ASSERT(!m_paintingResource); }