MarkerPaintable.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. /*
  2. * Copyright (c) 2018-2022, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibGfx/StylePainter.h>
  7. #include <LibWeb/Layout/ListItemMarkerBox.h>
  8. #include <LibWeb/Painting/MarkerPaintable.h>
  9. namespace Web::Painting {
  10. NonnullRefPtr<MarkerPaintable> MarkerPaintable::create(Layout::ListItemMarkerBox const& layout_box)
  11. {
  12. return adopt_ref(*new MarkerPaintable(layout_box));
  13. }
  14. MarkerPaintable::MarkerPaintable(Layout::ListItemMarkerBox const& layout_box)
  15. : PaintableBox(layout_box)
  16. {
  17. }
  18. Layout::ListItemMarkerBox const& MarkerPaintable::layout_box() const
  19. {
  20. return static_cast<Layout::ListItemMarkerBox const&>(layout_node());
  21. }
  22. void MarkerPaintable::paint(PaintContext& context, PaintPhase phase) const
  23. {
  24. if (phase != PaintPhase::Foreground)
  25. return;
  26. auto enclosing = enclosing_int_rect(absolute_rect());
  27. if (auto const* list_style_image = layout_box().list_style_image_bitmap()) {
  28. context.painter().blit(enclosing.location(), *list_style_image, list_style_image->rect());
  29. return;
  30. }
  31. auto color = computed_values().color();
  32. int marker_width = (int)enclosing.height() / 2;
  33. Gfx::IntRect marker_rect { 0, 0, marker_width, marker_width };
  34. marker_rect.center_within(enclosing);
  35. switch (layout_box().list_style_type()) {
  36. case CSS::ListStyleType::Square:
  37. context.painter().fill_rect(marker_rect, color);
  38. break;
  39. case CSS::ListStyleType::Circle:
  40. // For some reason for draw_ellipse() the ellipse is outside of the rect while for fill_ellipse() the ellipse is inside.
  41. // Scale the marker_rect with sqrt(2) to get an ellipse arc (circle) that appears as if it was inside of the marker_rect.
  42. marker_rect.set_height(marker_rect.height() / 1.41);
  43. marker_rect.set_width(marker_rect.width() / 1.41);
  44. marker_rect.center_within(enclosing);
  45. context.painter().draw_ellipse_intersecting(marker_rect, color);
  46. break;
  47. case CSS::ListStyleType::Disc:
  48. context.painter().fill_ellipse(marker_rect, color);
  49. break;
  50. case CSS::ListStyleType::Decimal:
  51. case CSS::ListStyleType::DecimalLeadingZero:
  52. case CSS::ListStyleType::LowerAlpha:
  53. case CSS::ListStyleType::LowerLatin:
  54. case CSS::ListStyleType::LowerRoman:
  55. case CSS::ListStyleType::UpperAlpha:
  56. case CSS::ListStyleType::UpperLatin:
  57. case CSS::ListStyleType::UpperRoman:
  58. if (layout_box().text().is_null())
  59. break;
  60. context.painter().draw_text(enclosing, layout_box().text(), Gfx::TextAlignment::Center);
  61. break;
  62. case CSS::ListStyleType::None:
  63. return;
  64. default:
  65. VERIFY_NOT_REACHED();
  66. }
  67. }
  68. }