| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "core/paint/SVGContainerPainter.h" |
| |
| #include "core/layout/svg/LayoutSVGContainer.h" |
| #include "core/layout/svg/LayoutSVGViewportContainer.h" |
| #include "core/layout/svg/SVGLayoutSupport.h" |
| #include "core/paint/FloatClipRecorder.h" |
| #include "core/paint/ObjectPainter.h" |
| #include "core/paint/PaintInfo.h" |
| #include "core/paint/SVGPaintContext.h" |
| #include "core/svg/SVGSVGElement.h" |
| #include "wtf/Optional.h" |
| |
| namespace blink { |
| |
| void SVGContainerPainter::paint(const PaintInfo& paintInfo) { |
| // Spec: groups w/o children still may render filter content. |
| if (!m_layoutSVGContainer.firstChild() && |
| !m_layoutSVGContainer.selfWillPaint()) |
| return; |
| |
| FloatRect boundingBox = |
| m_layoutSVGContainer.visualRectInLocalSVGCoordinates(); |
| // LayoutSVGHiddenContainer's visual rect is always empty but we need to |
| // paint its descendants. |
| if (!m_layoutSVGContainer.isSVGHiddenContainer() && |
| !paintInfo.cullRect().intersectsCullRect( |
| m_layoutSVGContainer.localToSVGParentTransform(), boundingBox)) |
| return; |
| |
| // Spec: An empty viewBox on the <svg> element disables rendering. |
| DCHECK(m_layoutSVGContainer.element()); |
| if (isSVGSVGElement(*m_layoutSVGContainer.element()) && |
| toSVGSVGElement(*m_layoutSVGContainer.element()).hasEmptyViewBox()) |
| return; |
| |
| PaintInfo paintInfoBeforeFiltering(paintInfo); |
| paintInfoBeforeFiltering.updateCullRect( |
| m_layoutSVGContainer.localToSVGParentTransform()); |
| SVGTransformContext transformContext( |
| paintInfoBeforeFiltering.context, m_layoutSVGContainer, |
| m_layoutSVGContainer.localToSVGParentTransform()); |
| { |
| Optional<FloatClipRecorder> clipRecorder; |
| if (m_layoutSVGContainer.isSVGViewportContainer() && |
| SVGLayoutSupport::isOverflowHidden(&m_layoutSVGContainer)) { |
| FloatRect viewport = |
| m_layoutSVGContainer.localToSVGParentTransform().inverse().mapRect( |
| toLayoutSVGViewportContainer(m_layoutSVGContainer).viewport()); |
| clipRecorder.emplace(paintInfoBeforeFiltering.context, |
| m_layoutSVGContainer, paintInfoBeforeFiltering.phase, |
| viewport); |
| } |
| |
| SVGPaintContext paintContext(m_layoutSVGContainer, |
| paintInfoBeforeFiltering); |
| bool continueRendering = true; |
| if (paintContext.paintInfo().phase == PaintPhaseForeground) |
| continueRendering = paintContext.applyClipMaskAndFilterIfNecessary(); |
| |
| if (continueRendering) { |
| for (LayoutObject* child = m_layoutSVGContainer.firstChild(); child; |
| child = child->nextSibling()) |
| child->paint(paintContext.paintInfo(), IntPoint()); |
| } |
| } |
| |
| if (paintInfoBeforeFiltering.phase != PaintPhaseForeground) |
| return; |
| |
| if (m_layoutSVGContainer.style()->outlineWidth() && |
| m_layoutSVGContainer.style()->visibility() == EVisibility::kVisible) { |
| PaintInfo outlinePaintInfo(paintInfoBeforeFiltering); |
| outlinePaintInfo.phase = PaintPhaseSelfOutlineOnly; |
| ObjectPainter(m_layoutSVGContainer) |
| .paintOutline(outlinePaintInfo, LayoutPoint(boundingBox.location())); |
| } |
| |
| if (paintInfoBeforeFiltering.isPrinting()) |
| ObjectPainter(m_layoutSVGContainer) |
| .addPDFURLRectIfNeeded(paintInfoBeforeFiltering, LayoutPoint()); |
| } |
| |
| } // namespace blink |