SVGGraphicsPaintable.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. /*
  2. * Copyright (c) 2018-2022, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibWeb/Layout/ImageBox.h>
  7. #include <LibWeb/Layout/SVGMaskBox.h>
  8. #include <LibWeb/Painting/CommandExecutorCPU.h>
  9. #include <LibWeb/Painting/SVGGraphicsPaintable.h>
  10. #include <LibWeb/Painting/StackingContext.h>
  11. #include <LibWeb/SVG/SVGMaskElement.h>
  12. #include <LibWeb/SVG/SVGSVGElement.h>
  13. namespace Web::Painting {
  14. JS::NonnullGCPtr<SVGGraphicsPaintable> SVGGraphicsPaintable::create(Layout::SVGGraphicsBox const& layout_box)
  15. {
  16. return layout_box.heap().allocate_without_realm<SVGGraphicsPaintable>(layout_box);
  17. }
  18. SVGGraphicsPaintable::SVGGraphicsPaintable(Layout::SVGGraphicsBox const& layout_box)
  19. : SVGPaintable(layout_box)
  20. {
  21. }
  22. Layout::SVGGraphicsBox const& SVGGraphicsPaintable::layout_box() const
  23. {
  24. return static_cast<Layout::SVGGraphicsBox const&>(layout_node());
  25. }
  26. Optional<CSSPixelRect> SVGGraphicsPaintable::get_masking_area() const
  27. {
  28. auto const& graphics_element = verify_cast<SVG::SVGGraphicsElement const>(*dom_node());
  29. auto* mask_box = graphics_element.layout_node()->first_child_of_type<Layout::SVGMaskBox>();
  30. if (!mask_box)
  31. return {};
  32. return mask_box->dom_node().resolve_masking_area(mask_box->paintable_box()->absolute_border_box_rect());
  33. }
  34. static Gfx::Bitmap::MaskKind mask_type_to_gfx_mask_kind(CSS::MaskType mask_type)
  35. {
  36. switch (mask_type) {
  37. case CSS::MaskType::Alpha:
  38. return Gfx::Bitmap::MaskKind::Alpha;
  39. case CSS::MaskType::Luminance:
  40. return Gfx::Bitmap::MaskKind::Luminance;
  41. default:
  42. VERIFY_NOT_REACHED();
  43. }
  44. }
  45. Optional<Gfx::Bitmap::MaskKind> SVGGraphicsPaintable::get_mask_type() const
  46. {
  47. auto const& graphics_element = verify_cast<SVG::SVGGraphicsElement const>(*dom_node());
  48. auto mask = graphics_element.mask();
  49. if (!mask)
  50. return {};
  51. return mask_type_to_gfx_mask_kind(mask->layout_node()->computed_values().mask_type());
  52. }
  53. RefPtr<Gfx::Bitmap> SVGGraphicsPaintable::calculate_mask(PaintContext& context, CSSPixelRect const& masking_area) const
  54. {
  55. auto const& graphics_element = verify_cast<SVG::SVGGraphicsElement const>(*dom_node());
  56. auto* mask_box = graphics_element.layout_node()->first_child_of_type<Layout::SVGMaskBox>();
  57. VERIFY(mask_box);
  58. auto mask_rect = context.enclosing_device_rect(masking_area);
  59. RefPtr<Gfx::Bitmap> mask_bitmap = {};
  60. auto& mask_paintable = static_cast<PaintableBox const&>(*mask_box->paintable());
  61. auto mask_bitmap_or_error = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, mask_rect.size().to_type<int>());
  62. if (mask_bitmap_or_error.is_error())
  63. return {};
  64. mask_bitmap = mask_bitmap_or_error.release_value();
  65. {
  66. CommandList painting_commands;
  67. RecordingPainter recording_painter(painting_commands);
  68. recording_painter.translate(-mask_rect.location().to_type<int>());
  69. auto paint_context = context.clone(recording_painter);
  70. paint_context.set_svg_transform(graphics_element.get_transform());
  71. StackingContext::paint_node_as_stacking_context(mask_paintable, paint_context);
  72. CommandExecutorCPU executor { *mask_bitmap };
  73. painting_commands.execute(executor);
  74. }
  75. return mask_bitmap;
  76. }
  77. }