void RenderSVGContainer::paint(PaintInfo& paintInfo, const LayoutPoint&) { ANNOTATE_GRAPHICS_CONTEXT(paintInfo, this); if (paintInfo.context->paintingDisabled()) return; // Spec: groups w/o children still may render filter content. if (!firstChild() && !selfWillPaint()) return; FloatRect repaintRect = repaintRectInLocalCoordinates(); if (!SVGRenderSupport::paintInfoIntersectsRepaintRect(repaintRect, localToParentTransform(), paintInfo)) return; PaintInfo childPaintInfo(paintInfo); { GraphicsContextStateSaver stateSaver(*childPaintInfo.context); // Let the RenderSVGViewportContainer subclass clip if necessary applyViewportClip(childPaintInfo); childPaintInfo.applyTransform(localToParentTransform()); SVGRenderingContext renderingContext; GraphicsContextCullSaver cullSaver(*childPaintInfo.context); bool continueRendering = true; if (childPaintInfo.phase == PaintPhaseForeground) { renderingContext.prepareToRenderSVGContent(this, childPaintInfo); continueRendering = renderingContext.isRenderingPrepared(); if (continueRendering && document().settings()->containerCullingEnabled()) cullSaver.cull(repaintRectInLocalCoordinates()); } if (continueRendering) { childPaintInfo.updatePaintingRootForChildren(this); for (RenderObject* child = firstChild(); child; child = child->nextSibling()) child->paint(childPaintInfo, IntPoint()); } } // FIXME: This really should be drawn from local coordinates, but currently we hack it // to avoid our clip killing our outline rect. Thus we translate our // outline rect into parent coords before drawing. // FIXME: This means our focus ring won't share our rotation like it should. // We should instead disable our clip during PaintPhaseOutline if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth() && style()->visibility() == VISIBLE) { IntRect paintRectInParent = enclosingIntRect(localToParentTransform().mapRect(repaintRect)); paintOutline(paintInfo, paintRectInParent); } }
LayoutRect RenderSVGRoot::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const { // This is an open-coded aggregate of SVGRenderSupport::clippedOverflowRectForRepaint, // RenderSVGRoot::computeFloatRectForRepaint and RenderReplaced::clippedOverflowRectForRepaint. // The reason for this is to optimize/minimize the repaint rect when the box is not "decorated" // (does not have background/border/etc.) // Return early for any cases where we don't actually paint. if (style()->visibility() != VISIBLE && !enclosingLayer()->hasVisibleContent()) return LayoutRect(); // Compute the repaint rect of the content of the SVG in the border-box coordinate space. FloatRect contentRepaintRect = repaintRectInLocalCoordinates(); contentRepaintRect = m_localToBorderBoxTransform.mapRect(contentRepaintRect); // Apply initial viewport clip, overflow:visible content is added to visualOverflow // but the most common case is that overflow is hidden, so always intersect. contentRepaintRect.intersect(pixelSnappedBorderBoxRect()); LayoutRect repaintRect = enclosingLayoutRect(contentRepaintRect); // If the box is decorated or is overflowing, extend it to include the border-box and overflow. if (m_hasBoxDecorations || hasRenderOverflow()) { // The selectionRect can project outside of the overflowRect, so take their union // for repainting to avoid selection painting glitches. LayoutRect decoratedRepaintRect = unionRect(localSelectionRect(false), visualOverflowRect()); repaintRect.unite(decoratedRepaintRect); } // Compute the repaint rect in the parent coordinate space. LayoutRect rect = enclosingIntRect(repaintRect); RenderReplaced::computeRectForRepaint(repaintContainer, rect); return rect; }
void RenderSVGImage::paint(PaintInfo& paintInfo, const LayoutPoint&) { if (paintInfo.context->paintingDisabled() || style()->visibility() == HIDDEN || !m_imageResource->hasImage()) return; FloatRect boundingBox = repaintRectInLocalCoordinates(); if (!SVGRenderSupport::paintInfoIntersectsRepaintRect(boundingBox, m_localTransform, paintInfo)) return; PaintInfo childPaintInfo(paintInfo); bool drawsOutline = style()->outlineWidth() && (childPaintInfo.phase == PaintPhaseOutline || childPaintInfo.phase == PaintPhaseSelfOutline); if (drawsOutline || childPaintInfo.phase == PaintPhaseForeground) { GraphicsContextStateSaver stateSaver(*childPaintInfo.context); childPaintInfo.applyTransform(m_localTransform); if (childPaintInfo.phase == PaintPhaseForeground) { SVGRenderingContext renderingContext(this, childPaintInfo); if (renderingContext.isRenderingPrepared()) { if (style()->svgStyle()->bufferedRendering() == BR_STATIC && renderingContext.bufferForeground(m_bufferedForeground)) return; paintForeground(childPaintInfo); } } if (drawsOutline) paintOutline(childPaintInfo, IntRect(boundingBox)); } }
void RenderSVGImage::addFocusRingRects(Vector<LayoutRect>& rects, const LayoutPoint&, const RenderLayerModelObject*) { // this is called from paint() after the localTransform has already been applied LayoutRect contentRect = LayoutRect(repaintRectInLocalCoordinates()); if (!contentRect.isEmpty()) rects.append(contentRect); }
void RenderSVGImage::paint(PaintInfo& paintInfo, const LayoutPoint&) { if (paintInfo.context->paintingDisabled() || style()->visibility() == HIDDEN || !m_imageResource->hasImage()) return; FloatRect boundingBox = repaintRectInLocalCoordinates(); if (!SVGRenderSupport::paintInfoIntersectsRepaintRect(boundingBox, m_localTransform, paintInfo)) return; PaintInfo childPaintInfo(paintInfo); bool drawsOutline = style()->outlineWidth() && (childPaintInfo.phase == PaintPhaseOutline || childPaintInfo.phase == PaintPhaseSelfOutline); if (drawsOutline || childPaintInfo.phase == PaintPhaseForeground) { GraphicsContextStateSaver stateSaver(*childPaintInfo.context); childPaintInfo.applyTransform(m_localTransform); if (childPaintInfo.phase == PaintPhaseForeground) { SVGRenderingContext renderingContext(this, childPaintInfo); if (renderingContext.isRenderingPrepared()) { RefPtr<Image> image = m_imageResource->image(); FloatRect destRect = m_objectBoundingBox; FloatRect srcRect(0, 0, image->width(), image->height()); SVGImageElement* imageElement = static_cast<SVGImageElement*>(node()); imageElement->preserveAspectRatio().transformRect(destRect, srcRect); childPaintInfo.context->drawImage(image.get(), ColorSpaceDeviceRGB, destRect, srcRect); } } if (drawsOutline) paintOutline(childPaintInfo.context, IntRect(boundingBox)); } }
void RenderPath::paint(PaintInfo& paintInfo, int, int) { if (paintInfo.context->paintingDisabled() || style()->visibility() == HIDDEN || m_path.isEmpty()) return; paintInfo.context->save(); paintInfo.context->concatCTM(localToParentTransform()); SVGResourceFilter* filter = 0; FloatRect boundingBox = repaintRectInLocalCoordinates(); if (paintInfo.phase == PaintPhaseForeground) { PaintInfo savedInfo(paintInfo); prepareToRenderSVGContent(this, paintInfo, boundingBox, filter); if (style()->svgStyle()->shapeRendering() == SR_CRISPEDGES) paintInfo.context->setShouldAntialias(false); fillAndStrokePath(m_path, paintInfo.context, style(), this); if (static_cast<SVGStyledElement*>(node())->supportsMarkers()) m_markerBounds = drawMarkersIfNeeded(paintInfo.context, paintInfo.rect, m_path); finishRenderSVGContent(this, paintInfo, filter, savedInfo.context); } if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth()) paintOutline(paintInfo.context, static_cast<int>(boundingBox.x()), static_cast<int>(boundingBox.y()), static_cast<int>(boundingBox.width()), static_cast<int>(boundingBox.height()), style()); paintInfo.context->restore(); }
void RenderSVGImage::addFocusRingRects(Vector<IntRect>& rects, int, int) { // this is called from paint() after the localTransform has already been applied IntRect contentRect = enclosingIntRect(repaintRectInLocalCoordinates()); if (!contentRect.isEmpty()) rects.append(contentRect); }
void RenderSVGShape::paint(PaintInfo& paintInfo, const LayoutPoint&) { if (paintInfo.context().paintingDisabled() || paintInfo.phase != PaintPhaseForeground || style().visibility() == HIDDEN || isEmpty()) return; FloatRect boundingBox = repaintRectInLocalCoordinates(); if (!SVGRenderSupport::paintInfoIntersectsRepaintRect(boundingBox, m_localTransform, paintInfo)) return; PaintInfo childPaintInfo(paintInfo); GraphicsContextStateSaver stateSaver(childPaintInfo.context()); childPaintInfo.applyTransform(m_localTransform); if (childPaintInfo.phase == PaintPhaseForeground) { SVGRenderingContext renderingContext(*this, childPaintInfo); if (renderingContext.isRenderingPrepared()) { const SVGRenderStyle& svgStyle = style().svgStyle(); if (svgStyle.shapeRendering() == SR_CRISPEDGES) childPaintInfo.context().setShouldAntialias(false); fillStrokeMarkers(childPaintInfo); } } if (style().outlineWidth()) paintOutline(childPaintInfo, IntRect(boundingBox)); }
// Copied from RenderBox, this method likely requires further refactoring to work easily for both SVG and CSS Box Model content. // FIXME: This may also need to move into SVGRenderSupport as the RenderBox version depends // on borderBoundingBox() which SVG RenderBox subclases (like SVGRenderBlock) do not implement. IntRect RenderSVGModelObject::outlineBoundsForRepaint(RenderBoxModelObject* repaintContainer, IntPoint*) const { IntRect box = enclosingIntRect(repaintRectInLocalCoordinates()); adjustRectForOutlineAndShadow(box); FloatQuad containerRelativeQuad = localToContainerQuad(FloatRect(box), repaintContainer); return containerRelativeQuad.enclosingBoundingBox(); }
// Copied from RenderBox, this method likely requires further refactoring to work easily for both SVG and CSS Box Model content. // FIXME: This may also need to move into SVGRenderSupport as the RenderBox version depends // on borderBoundingBox() which SVG RenderBox subclases (like SVGRenderBlock) do not implement. LayoutRect RenderSVGModelObject::outlineBoundsForRepaint(const RenderLayerModelObject* repaintContainer, const RenderGeometryMap*) const { LayoutRect box = enclosingLayoutRect(repaintRectInLocalCoordinates()); adjustRectForOutlineAndShadow(box); FloatQuad containerRelativeQuad = localToContainerQuad(FloatRect(box), repaintContainer); return LayoutRect(snapRectToDevicePixels(LayoutRect(containerRelativeQuad.boundingBox()), document().deviceScaleFactor())); }
// Copied from RenderBox, this method likely requires further refactoring to work easily for both SVG and CSS Box Model content. // FIXME: This may also need to move into SVGRenderSupport as the RenderBox version depends // on borderBoundingBox() which SVG RenderBox subclases (like SVGRenderBlock) do not implement. LayoutRect RenderSVGModelObject::outlineBoundsForRepaint(const RenderLayerModelObject* repaintContainer, const RenderGeometryMap*) const { LayoutRect box = enclosingLayoutRect(repaintRectInLocalCoordinates()); adjustRectForOutlineAndShadow(box); FloatQuad containerRelativeQuad = localToContainerQuad(FloatRect(box), repaintContainer); return containerRelativeQuad.enclosingBoundingBox(); }
void RenderSVGContainer::paint(PaintInfo& paintInfo, int, int) { if (paintInfo.context->paintingDisabled() || !drawsContents()) return; // Spec: groups w/o children still may render filter content. if (!firstChild() && !selfWillPaint()) return; PaintInfo childPaintInfo(paintInfo); childPaintInfo.context->save(); // Let the RenderSVGViewportContainer subclass clip if necessary applyViewportClip(childPaintInfo); applyTransformToPaintInfo(childPaintInfo, localToParentTransform()); RenderSVGResourceFilter* filter = 0; FloatRect boundingBox = repaintRectInLocalCoordinates(); bool continueRendering = true; if (childPaintInfo.phase == PaintPhaseForeground) continueRendering = prepareToRenderSVGContent(this, childPaintInfo, boundingBox, filter); if (continueRendering) { childPaintInfo.paintingRoot = paintingRootForChildren(childPaintInfo); for (RenderObject* child = firstChild(); child; child = child->nextSibling()) child->paint(childPaintInfo, 0, 0); } if (paintInfo.phase == PaintPhaseForeground) finishRenderSVGContent(this, childPaintInfo, filter, paintInfo.context); childPaintInfo.context->restore(); // FIXME: This really should be drawn from local coordinates, but currently we hack it // to avoid our clip killing our outline rect. Thus we translate our // outline rect into parent coords before drawing. // FIXME: This means our focus ring won't share our rotation like it should. // We should instead disable our clip during PaintPhaseOutline IntRect paintRectInParent = enclosingIntRect(localToParentTransform().mapRect(repaintRectInLocalCoordinates())); if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth() && style()->visibility() == VISIBLE) paintOutline(paintInfo.context, paintRectInParent.x(), paintRectInParent.y(), paintRectInParent.width(), paintRectInParent.height()); }
void RenderSVGRoot::layout() { StackStats::LayoutCheckPoint layoutCheckPoint; ASSERT(needsLayout()); m_resourcesNeedingToInvalidateClients.clear(); // Arbitrary affine transforms are incompatible with LayoutState. LayoutStateDisabler layoutStateDisabler(view()); bool needsLayout = selfNeedsLayout(); LayoutRepainter repainter(*this, checkForRepaintDuringLayout() && needsLayout); LayoutSize oldSize = size(); updateLogicalWidth(); updateLogicalHeight(); buildLocalToBorderBoxTransform(); m_isLayoutSizeChanged = needsLayout || (svgSVGElement().hasRelativeLengths() && oldSize != size()); SVGRenderSupport::layoutChildren(*this, needsLayout || SVGRenderSupport::filtersForceContainerLayout(*this)); if (!m_resourcesNeedingToInvalidateClients.isEmpty()) { // Invalidate resource clients, which may mark some nodes for layout. for (auto& resource : m_resourcesNeedingToInvalidateClients) { resource->removeAllClientsFromCache(); SVGResourcesCache::clientStyleChanged(*resource, StyleDifferenceLayout, resource->style()); } m_isLayoutSizeChanged = false; SVGRenderSupport::layoutChildren(*this, false); } // At this point LayoutRepainter already grabbed the old bounds, // recalculate them now so repaintAfterLayout() uses the new bounds. if (m_needsBoundariesOrTransformUpdate) { updateCachedBoundaries(); m_needsBoundariesOrTransformUpdate = false; } clearOverflow(); if (!shouldApplyViewportClip()) { FloatRect contentRepaintRect = repaintRectInLocalCoordinates(); contentRepaintRect = m_localToBorderBoxTransform.mapRect(contentRepaintRect); addVisualOverflow(enclosingLayoutRect(contentRepaintRect)); } updateLayerTransform(); m_hasBoxDecorations = isDocumentElementRenderer() ? hasVisibleBoxDecorationStyle() : hasVisibleBoxDecorations(); invalidateBackgroundObscurationStatus(); repainter.repaintAfterLayout(); clearNeedsLayout(); }
PassRefPtr<DisplayList> RenderSVGResourceClipper::asDisplayList(GraphicsContext* context, const AffineTransform& contentTransformation) { ASSERT(context); ASSERT(frame()); context->beginRecording(repaintRectInLocalCoordinates()); // Switch to a paint behavior where all children of this <clipPath> will be rendered using special constraints: // - fill-opacity/stroke-opacity/opacity set to 1 // - masker/filter not applied when rendering the children // - fill is set to the initial fill paint server (solid, black) // - stroke is set to the initial stroke paint server (none) PaintBehavior oldBehavior = frame()->view()->paintBehavior(); frame()->view()->setPaintBehavior(oldBehavior | PaintBehaviorRenderingSVGMask); for (Node* childNode = element()->firstChild(); childNode; childNode = childNode->nextSibling()) { RenderObject* renderer = childNode->renderer(); if (!childNode->isSVGElement() || !renderer) continue; RenderStyle* style = renderer->style(); if (!style || style->display() == NONE || style->visibility() != VISIBLE) continue; WindRule newClipRule = style->svgStyle()->clipRule(); bool isUseElement = childNode->hasTagName(SVGNames::useTag); if (isUseElement) { SVGUseElement* useElement = toSVGUseElement(childNode); renderer = useElement->rendererClipChild(); if (!renderer) continue; if (!useElement->hasAttribute(SVGNames::clip_ruleAttr)) newClipRule = renderer->style()->svgStyle()->clipRule(); } // Only shapes, paths and texts are allowed for clipping. if (!renderer->isSVGShape() && !renderer->isSVGText()) continue; context->setFillRule(newClipRule); if (isUseElement) renderer = childNode->renderer(); SVGRenderingContext::renderSubtree(context, renderer, contentTransformation); } frame()->view()->setPaintBehavior(oldBehavior); return context->endRecording(); }
void RenderSVGRoot::layout() { StackStats::LayoutCheckPoint layoutCheckPoint; ASSERT(needsLayout()); m_resourcesNeedingToInvalidateClients.clear(); // Arbitrary affine transforms are incompatible with LayoutState. LayoutStateDisabler layoutStateDisabler(&view()); bool needsLayout = selfNeedsLayout(); LayoutRepainter repainter(*this, checkForRepaintDuringLayout() && needsLayout); LayoutSize oldSize = size(); updateLogicalWidth(); updateLogicalHeight(); buildLocalToBorderBoxTransform(); m_isLayoutSizeChanged = needsLayout || (svgSVGElement().hasRelativeLengths() && oldSize != size()); SVGRenderSupport::layoutChildren(*this, needsLayout || SVGRenderSupport::filtersForceContainerLayout(*this)); if (!m_resourcesNeedingToInvalidateClients.isEmpty()) { // Invalidate resource clients, which may mark some nodes for layout. HashSet<RenderSVGResourceContainer*>::iterator end = m_resourcesNeedingToInvalidateClients.end(); for (HashSet<RenderSVGResourceContainer*>::iterator it = m_resourcesNeedingToInvalidateClients.begin(); it != end; ++it) (*it)->removeAllClientsFromCache(); m_isLayoutSizeChanged = false; SVGRenderSupport::layoutChildren(*this, false); } // At this point LayoutRepainter already grabbed the old bounds, // recalculate them now so repaintAfterLayout() uses the new bounds. if (m_needsBoundariesOrTransformUpdate) { updateCachedBoundaries(); m_needsBoundariesOrTransformUpdate = false; } if (!shouldApplyViewportClip()) { FloatRect contentRepaintRect = repaintRectInLocalCoordinates(); contentRepaintRect = m_localToBorderBoxTransform.mapRect(contentRepaintRect); addVisualOverflow(enclosingLayoutRect(contentRepaintRect)); } updateLayerTransform(); repainter.repaintAfterLayout(); clearNeedsLayout(); }
LayoutRect RenderSVGRoot::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const { if (style().visibility() != VISIBLE && !enclosingLayer()->hasVisibleContent()) return LayoutRect(); FloatRect contentRepaintRect = m_localToBorderBoxTransform.mapRect(repaintRectInLocalCoordinates()); contentRepaintRect.intersect(snappedIntRect(borderBoxRect())); LayoutRect repaintRect = enclosingLayoutRect(contentRepaintRect); if (m_hasBoxDecorations || hasRenderOverflow()) repaintRect.unite(unionRect(localSelectionRect(false), visualOverflowRect())); return RenderReplaced::computeRectForRepaint(enclosingIntRect(repaintRect), repaintContainer); }
void RenderSVGRoot::paint(PaintInfo& paintInfo, int parentX, int parentY) { if (paintInfo.context->paintingDisabled()) return; IntPoint parentOriginInContainer(parentX, parentY); IntPoint borderBoxOriginInContainer = parentOriginInContainer + IntSize(x(), y()); if (hasBoxDecorations() && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection)) paintBoxDecorations(paintInfo, borderBoxOriginInContainer.x(), borderBoxOriginInContainer.y()); // An empty viewport disables rendering. FIXME: Should we still render filters? if (m_viewportSize.isEmpty()) return; // Don't paint if we don't have kids, except if we have filters we should paint those. if (!firstChild() && !selfWillPaint()) return; // Make a copy of the PaintInfo because applyTransformToPaintInfo will modify the damage rect. RenderObject::PaintInfo childPaintInfo(paintInfo); childPaintInfo.context->save(); // Apply initial viewport clip - not affected by overflow handling childPaintInfo.context->clip(overflowClipRect(borderBoxOriginInContainer.x(), borderBoxOriginInContainer.y())); // Convert from container offsets (html renderers) to a relative transform (svg renderers). // Transform from our paint container's coordinate system to our local coords. applyTransformToPaintInfo(childPaintInfo, localToRepaintContainerTransform(parentOriginInContainer)); SVGResourceFilter* filter = 0; FloatRect boundingBox = repaintRectInLocalCoordinates(); bool continueRendering = true; if (childPaintInfo.phase == PaintPhaseForeground) continueRendering = prepareToRenderSVGContent(this, childPaintInfo, boundingBox, filter); if (continueRendering) RenderBox::paint(childPaintInfo, 0, 0); if (childPaintInfo.phase == PaintPhaseForeground) finishRenderSVGContent(this, childPaintInfo, filter, paintInfo.context); childPaintInfo.context->restore(); if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth() && style()->visibility() == VISIBLE) paintOutline(paintInfo.context, borderBoxOriginInContainer.x(), borderBoxOriginInContainer.y(), width(), height(), style()); }
void RenderSVGRoot::layout() { ASSERT(needsLayout()); // Arbitrary affine transforms are incompatible with LayoutState. LayoutStateDisabler layoutStateDisabler(*this); bool needsLayout = selfNeedsLayout(); LayoutRepainter repainter(*this, checkForRepaintDuringLayout() && needsLayout); LayoutSize oldSize = size(); updateLogicalWidth(); updateLogicalHeight(); buildLocalToBorderBoxTransform(); SVGRenderSupport::layoutResourcesIfNeeded(this); SVGSVGElement* svg = toSVGSVGElement(node()); ASSERT(svg); m_isLayoutSizeChanged = needsLayout || (svg->hasRelativeLengths() && oldSize != size()); SVGRenderSupport::layoutChildren(this, needsLayout || SVGRenderSupport::filtersForceContainerLayout(this)); // At this point LayoutRepainter already grabbed the old bounds, // recalculate them now so repaintAfterLayout() uses the new bounds. if (m_needsBoundariesOrTransformUpdate) { updateCachedBoundaries(); m_needsBoundariesOrTransformUpdate = false; } m_overflow.clear(); addVisualEffectOverflow(); if (!shouldApplyViewportClip()) { FloatRect contentRepaintRect = repaintRectInLocalCoordinates(); contentRepaintRect = m_localToBorderBoxTransform.mapRect(contentRepaintRect); addVisualOverflow(enclosingLayoutRect(contentRepaintRect)); } updateLayerTransform(); m_hasBoxDecorations = isDocumentElement() ? calculateHasBoxDecorations() : hasBoxDecorations(); invalidateBackgroundObscurationStatus(); repainter.repaintAfterLayout(); clearNeedsLayout(); }
void RenderPath::paint(PaintInfo& paintInfo, int, int) { if (paintInfo.context->paintingDisabled() || style()->visibility() == HIDDEN || m_path.isEmpty()) return; FloatRect boundingBox = repaintRectInLocalCoordinates(); FloatRect nonLocalBoundingBox = m_localTransform.mapRect(boundingBox); if (!nonLocalBoundingBox.intersects(paintInfo.rect)) return; PaintInfo childPaintInfo(paintInfo); bool drawsOutline = style()->outlineWidth() && (childPaintInfo.phase == PaintPhaseOutline || childPaintInfo.phase == PaintPhaseSelfOutline); if (drawsOutline || childPaintInfo.phase == PaintPhaseForeground) { childPaintInfo.context->save(); childPaintInfo.applyTransform(m_localTransform); if (childPaintInfo.phase == PaintPhaseForeground) { PaintInfo savedInfo(childPaintInfo); if (SVGRenderSupport::prepareToRenderSVGContent(this, childPaintInfo)) { const SVGRenderStyle* svgStyle = style()->svgStyle(); if (svgStyle->shapeRendering() == SR_CRISPEDGES) childPaintInfo.context->setShouldAntialias(false); fillAndStrokePath(childPaintInfo.context); if (svgStyle->hasMarkers()) m_markerLayoutInfo.drawMarkers(childPaintInfo); } SVGRenderSupport::finishRenderSVGContent(this, childPaintInfo, savedInfo.context); } if (drawsOutline) paintOutline(childPaintInfo.context, static_cast<int>(boundingBox.x()), static_cast<int>(boundingBox.y()), static_cast<int>(boundingBox.width()), static_cast<int>(boundingBox.height())); childPaintInfo.context->restore(); } }
void RenderSVGImage::paint(PaintInfo& paintInfo, int, int) { if (paintInfo.context->paintingDisabled() || style()->visibility() == HIDDEN || !m_imageResource->hasImage()) return; FloatRect boundingBox = repaintRectInLocalCoordinates(); if (!SVGRenderSupport::paintInfoIntersectsRepaintRect(boundingBox, m_localTransform, paintInfo)) return; PaintInfo childPaintInfo(paintInfo); bool drawsOutline = style()->outlineWidth() && (childPaintInfo.phase == PaintPhaseOutline || childPaintInfo.phase == PaintPhaseSelfOutline); if (drawsOutline || childPaintInfo.phase == PaintPhaseForeground) { childPaintInfo.context->save(); childPaintInfo.applyTransform(m_localTransform); if (childPaintInfo.phase == PaintPhaseForeground) { PaintInfo savedInfo(childPaintInfo); if (SVGRenderSupport::prepareToRenderSVGContent(this, childPaintInfo)) { Image* image = m_imageResource->image(); FloatRect destRect = m_localBounds; FloatRect srcRect(0, 0, image->width(), image->height()); SVGImageElement* imageElement = static_cast<SVGImageElement*>(node()); if (imageElement->preserveAspectRatio().align() != SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_NONE) imageElement->preserveAspectRatio().transformRect(destRect, srcRect); childPaintInfo.context->drawImage(image, DeviceColorSpace, destRect, srcRect); } SVGRenderSupport::finishRenderSVGContent(this, childPaintInfo, savedInfo.context); } if (drawsOutline) paintOutline(childPaintInfo.context, static_cast<int>(boundingBox.x()), static_cast<int>(boundingBox.y()), static_cast<int>(boundingBox.width()), static_cast<int>(boundingBox.height())); childPaintInfo.context->restore(); } }
void RenderPath::paint(PaintInfo& paintInfo, int, int) { if (paintInfo.context->paintingDisabled() || style()->visibility() == HIDDEN || m_path.isEmpty()) return; FloatRect boundingBox = repaintRectInLocalCoordinates(); FloatRect nonLocalBoundingBox = m_localTransform.mapRect(boundingBox); // FIXME: The empty rect check is to deal with incorrect initial clip in renderSubtreeToImage // unfortunately fixing that problem is fairly complex unless we were willing to just futz the // rect to something "close enough" if (!nonLocalBoundingBox.intersects(paintInfo.rect) && !paintInfo.rect.isEmpty()) return; PaintInfo childPaintInfo(paintInfo); childPaintInfo.context->save(); applyTransformToPaintInfo(childPaintInfo, m_localTransform); SVGResourceFilter* filter = 0; if (childPaintInfo.phase == PaintPhaseForeground) { PaintInfo savedInfo(childPaintInfo); if (prepareToRenderSVGContent(this, childPaintInfo, boundingBox, filter)) { if (style()->svgStyle()->shapeRendering() == SR_CRISPEDGES) childPaintInfo.context->setShouldAntialias(false); fillAndStrokePath(m_path, childPaintInfo.context, style(), this); if (static_cast<SVGStyledElement*>(node())->supportsMarkers()) m_markerLayoutInfo.drawMarkers(childPaintInfo); } finishRenderSVGContent(this, childPaintInfo, filter, savedInfo.context); } if ((childPaintInfo.phase == PaintPhaseOutline || childPaintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth()) paintOutline(childPaintInfo.context, static_cast<int>(boundingBox.x()), static_cast<int>(boundingBox.y()), static_cast<int>(boundingBox.width()), static_cast<int>(boundingBox.height()), style()); childPaintInfo.context->restore(); }
void RenderSVGPath::paint(PaintInfo& paintInfo, const IntPoint&) { if (paintInfo.context->paintingDisabled() || style()->visibility() == HIDDEN || m_path.isEmpty()) return; FloatRect boundingBox = repaintRectInLocalCoordinates(); if (!SVGRenderSupport::paintInfoIntersectsRepaintRect(boundingBox, m_localTransform, paintInfo)) return; PaintInfo childPaintInfo(paintInfo); bool drawsOutline = style()->outlineWidth() && (childPaintInfo.phase == PaintPhaseOutline || childPaintInfo.phase == PaintPhaseSelfOutline); if (drawsOutline || childPaintInfo.phase == PaintPhaseForeground) { GraphicsContextStateSaver stateSaver(*childPaintInfo.context); childPaintInfo.applyTransform(m_localTransform); if (childPaintInfo.phase == PaintPhaseForeground) { PaintInfo savedInfo(childPaintInfo); if (SVGRenderSupport::prepareToRenderSVGContent(this, childPaintInfo)) { const SVGRenderStyle* svgStyle = style()->svgStyle(); if (svgStyle->shapeRendering() == SR_CRISPEDGES) childPaintInfo.context->setShouldAntialias(false); fillAndStrokePath(childPaintInfo.context); if (svgStyle->hasMarkers()) m_markerLayoutInfo.drawMarkers(childPaintInfo); } SVGRenderSupport::finishRenderSVGContent(this, childPaintInfo, savedInfo.context); } if (drawsOutline) paintOutline(childPaintInfo.context, IntRect(boundingBox)); } }
// This method is called from inside paintOutline() since we call paintOutline() // while transformed to our coord system, return local coords void RenderSVGPath::addFocusRingRects(Vector<IntRect>& rects, const IntPoint&) { IntRect rect = enclosingIntRect(repaintRectInLocalCoordinates()); if (!rect.isEmpty()) rects.append(rect); }
// addFocusRingRects is called from paintOutline and needs to be in the same coordinates as the paintOuline call void RenderSVGContainer::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint&) { IntRect paintRectInParent = enclosingIntRect(localToParentTransform().mapRect(repaintRectInLocalCoordinates())); if (!paintRectInParent.isEmpty()) rects.append(paintRectInParent); }
// addFocusRingRects is called from paintOutline and needs to be in the same coordinates as the paintOuline call void RenderSVGContainer::addFocusRingRects(GraphicsContext* graphicsContext, int, int) { IntRect paintRectInParent = enclosingIntRect(localToParentTransform().mapRect(repaintRectInLocalCoordinates())); graphicsContext->addFocusRingRect(paintRectInParent); }
// The SVG addFocusRingRects() method adds rects in local coordinates so the default absoluteFocusRingQuads // returns incorrect values for SVG objects. Overriding this method provides access to the absolute bounds. void RenderSVGModelObject::absoluteFocusRingQuads(Vector<FloatQuad>& quads) { quads.append(localToAbsoluteQuad(FloatQuad(repaintRectInLocalCoordinates()))); }
// This method is called from inside paintOutline() since we call paintOutline() // while transformed to our coord system, return local coords void RenderSVGShape::addFocusRingRects(Vector<LayoutRect>& rects, const LayoutPoint&, const RenderLayerModelObject*) { LayoutRect rect = LayoutRect(repaintRectInLocalCoordinates()); if (!rect.isEmpty()) rects.append(rect); }
// This method is called from inside paintOutline() since we call paintOutline() // while transformed to our coord system, return local coords void RenderPath::addFocusRingRects(GraphicsContext* graphicsContext, int, int) { graphicsContext->addFocusRingRect(enclosingIntRect(repaintRectInLocalCoordinates())); }
void RenderSVGImage::addFocusRingRects(GraphicsContext* graphicsContext, int, int) { // this is called from paint() after the localTransform has already been applied IntRect contentRect = enclosingIntRect(repaintRectInLocalCoordinates()); graphicsContext->addFocusRingRect(contentRect); }