BorderRadiusCornerClipper.h 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. /*
  2. * Copyright (c) 2022, MacDue <macdue@dueutil.tech>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <LibGfx/AntiAliasingPainter.h>
  8. #include <LibWeb/Painting/BorderPainting.h>
  9. namespace Web::Painting {
  10. enum class CornerClip {
  11. Outside,
  12. Inside
  13. };
  14. class BorderRadiusCornerClipper {
  15. public:
  16. enum class UseCachedBitmap {
  17. Yes,
  18. No
  19. };
  20. static ErrorOr<BorderRadiusCornerClipper> create(PaintContext&, DevicePixelRect const& border_rect, BorderRadiiData const& border_radii, CornerClip corner_clip = CornerClip::Outside, UseCachedBitmap use_cached_bitmap = UseCachedBitmap::Yes);
  21. void sample_under_corners(Gfx::Painter& page_painter);
  22. void blit_corner_clipping(Gfx::Painter& page_painter);
  23. private:
  24. using CornerRadius = Gfx::AntiAliasingPainter::CornerRadius;
  25. struct CornerData {
  26. struct CornerRadii {
  27. CornerRadius top_left;
  28. CornerRadius top_right;
  29. CornerRadius bottom_right;
  30. CornerRadius bottom_left;
  31. } corner_radii;
  32. struct CornerLocations {
  33. DevicePixelPoint top_left;
  34. DevicePixelPoint top_right;
  35. DevicePixelPoint bottom_right;
  36. DevicePixelPoint bottom_left;
  37. };
  38. CornerLocations page_locations;
  39. CornerLocations bitmap_locations;
  40. DevicePixelSize corner_bitmap_size;
  41. } m_data;
  42. NonnullRefPtr<Gfx::Bitmap> m_corner_bitmap;
  43. bool m_has_sampled { false };
  44. CornerClip m_corner_clip { false };
  45. BorderRadiusCornerClipper(CornerData corner_data, NonnullRefPtr<Gfx::Bitmap> corner_bitmap, CornerClip corner_clip)
  46. : m_data(move(corner_data))
  47. , m_corner_bitmap(corner_bitmap)
  48. , m_corner_clip(corner_clip)
  49. {
  50. }
  51. };
  52. struct ScopedCornerRadiusClip {
  53. ScopedCornerRadiusClip(PaintContext& context, Gfx::Painter& painter, DevicePixelRect const& border_rect, BorderRadiiData const& border_radii, CornerClip corner_clip = CornerClip::Outside, BorderRadiusCornerClipper::UseCachedBitmap use_cached_bitmap = BorderRadiusCornerClipper::UseCachedBitmap::Yes)
  54. : m_painter(painter)
  55. {
  56. if (border_radii.has_any_radius()) {
  57. auto clipper = BorderRadiusCornerClipper::create(context, border_rect, border_radii, corner_clip, use_cached_bitmap);
  58. if (!clipper.is_error()) {
  59. m_corner_clipper = clipper.release_value();
  60. m_corner_clipper->sample_under_corners(m_painter);
  61. }
  62. }
  63. }
  64. ~ScopedCornerRadiusClip()
  65. {
  66. if (m_corner_clipper.has_value()) {
  67. m_corner_clipper->blit_corner_clipping(m_painter);
  68. }
  69. }
  70. AK_MAKE_NONMOVABLE(ScopedCornerRadiusClip);
  71. AK_MAKE_NONCOPYABLE(ScopedCornerRadiusClip);
  72. private:
  73. Gfx::Painter& m_painter;
  74. Optional<BorderRadiusCornerClipper> m_corner_clipper;
  75. };
  76. }