/* * Copyright (c) 2023, MacDue * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include namespace Gfx { struct ClipPath { Path path; Painter::WindingRule winding_rule; }; class PathClipper { public: static ErrorOr create(Painter&, ClipPath const& clip_path); ErrorOr apply_clip(Painter& painter); private: PathClipper(RefPtr saved_clip_region, IntRect bounding_box, ClipPath const& clip_path) : m_saved_clip_region(saved_clip_region) , m_bounding_box(bounding_box) , m_clip_path(clip_path) { } RefPtr m_saved_clip_region; IntRect m_bounding_box; ClipPath const& m_clip_path; }; class ScopedPathClip { AK_MAKE_NONMOVABLE(ScopedPathClip); AK_MAKE_NONCOPYABLE(ScopedPathClip); public: ScopedPathClip(Painter& painter, Optional const& clip_path) : m_painter(painter) { if (clip_path.has_value()) { auto clipper = PathClipper::create(painter, *clip_path); if (!clipper.is_error()) m_path_clipper = clipper.release_value(); else dbgln("Error: Failed to apply clip path: {}", clipper.error()); } } ~ScopedPathClip() { if (m_path_clipper.has_value()) m_path_clipper->apply_clip(m_painter).release_value_but_fixme_should_propagate_errors(); } private: Painter& m_painter; Optional m_path_clipper; }; }