blob: 171b6347800056520ca7865a23c28743cebf4d78 [file] [log] [blame]
/*
* Copyright (C) 2007, 2008 Rob Buis <buis@kde.org>
* Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
* Copyright (C) 2007 Eric Seidel <eric@webkit.org>
* Copyright (C) 2009 Google, Inc. All rights reserved.
* Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
* Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "third_party/blink/renderer/core/paint/scoped_svg_paint_state.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.h"
#include "third_party/blink/renderer/core/layout/svg/svg_resources.h"
#include "third_party/blink/renderer/core/paint/clip_path_clipper.h"
#include "third_party/blink/renderer/core/paint/svg_mask_painter.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
namespace blink {
ScopedSVGPaintState::~ScopedSVGPaintState() {
// Paint mask before clip path as mask because if both exist, the ClipPathMask
// effect node is a child of the Mask node (see object_paint_properties.h for
// the node hierarchy), to ensure the clip-path mask will be applied to the
// mask to create an intersection of the masks, then the intersection will be
// applied to the masked content.
if (should_paint_mask_)
SVGMaskPainter::Paint(paint_info_.context, object_, display_item_client_);
if (should_paint_clip_path_as_mask_image_) {
ClipPathClipper::PaintClipPathAsMaskImage(
paint_info_.context, object_, display_item_client_, PhysicalOffset());
}
}
void ScopedSVGPaintState::ApplyEffects() {
#if DCHECK_IS_ON()
DCHECK(!apply_effects_called_);
apply_effects_called_ = true;
#endif
const auto* properties = object_.FirstFragment().PaintProperties();
if (properties)
ApplyPaintPropertyState(*properties);
// When rendering clip paths as masks, only geometric operations should be
// included so skip non-geometric operations such as compositing, masking,
// and filtering.
if (paint_info_.IsRenderingClipPathAsMaskImage()) {
DCHECK(!object_.IsSVGRoot());
if (properties && properties->ClipPathMask())
should_paint_clip_path_as_mask_image_ = true;
return;
}
// LayoutSVGRoot and LayoutSVGForeignObject always have a self-painting
// PaintLayer (hence comments below about PaintLayerPainter).
bool is_svg_root_or_foreign_object =
object_.IsSVGRoot() || object_.IsSVGForeignObject();
if (is_svg_root_or_foreign_object) {
// PaintLayerPainter takes care of clip path.
DCHECK(object_.HasLayer() || !properties || !properties->ClipPathMask());
} else if (properties && properties->ClipPathMask()) {
should_paint_clip_path_as_mask_image_ = true;
}
ApplyMaskIfNecessary();
}
void ScopedSVGPaintState::ApplyPaintPropertyState(
const ObjectPaintProperties& properties) {
// SVGRoot works like normal CSS replaced element and its effects are
// applied as stacking context effect by PaintLayerPainter.
if (object_.IsSVGRoot())
return;
auto& paint_controller = paint_info_.context.GetPaintController();
auto state = paint_controller.CurrentPaintChunkProperties();
if (const auto* filter = properties.Filter())
state.SetEffect(*filter);
else if (const auto* effect = properties.Effect())
state.SetEffect(*effect);
if (const auto* mask_clip = properties.MaskClip())
state.SetClip(*mask_clip);
else if (const auto* clip_path_clip = properties.ClipPathClip())
state.SetClip(*clip_path_clip);
scoped_paint_chunk_properties_.emplace(
paint_controller, state, display_item_client_,
DisplayItem::PaintPhaseToSVGEffectType(paint_info_.phase));
}
void ScopedSVGPaintState::ApplyMaskIfNecessary() {
SVGResourceClient* client = SVGResources::GetClient(object_);
if (!client)
return;
if (GetSVGResourceAsType<LayoutSVGResourceMasker>(
*client, object_.StyleRef().MaskerResource()))
should_paint_mask_ = true;
}
} // namespace blink