ImageWidget.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. /*
  2. * Copyright (c) 2020, Hüseyin Aslıtürk <asliturk@hotmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/MappedFile.h>
  7. #include <LibGUI/ImageWidget.h>
  8. #include <LibGUI/Painter.h>
  9. #include <LibGfx/Bitmap.h>
  10. #include <LibGfx/ImageDecoder.h>
  11. REGISTER_WIDGET(GUI, ImageWidget)
  12. namespace GUI {
  13. ImageWidget::ImageWidget(const StringView&)
  14. : m_timer(Core::Timer::construct())
  15. {
  16. set_frame_thickness(0);
  17. set_frame_shadow(Gfx::FrameShadow::Plain);
  18. set_frame_shape(Gfx::FrameShape::NoFrame);
  19. set_auto_resize(true);
  20. REGISTER_BOOL_PROPERTY("auto_resize", auto_resize, set_auto_resize);
  21. REGISTER_BOOL_PROPERTY("should_stretch", should_stretch, set_should_stretch);
  22. }
  23. ImageWidget::~ImageWidget()
  24. {
  25. }
  26. void ImageWidget::set_bitmap(const Gfx::Bitmap* bitmap)
  27. {
  28. if (m_bitmap == bitmap)
  29. return;
  30. m_bitmap = bitmap;
  31. if (m_bitmap && m_auto_resize)
  32. set_fixed_size(m_bitmap->size());
  33. update();
  34. }
  35. void ImageWidget::set_auto_resize(bool value)
  36. {
  37. m_auto_resize = value;
  38. if (m_bitmap)
  39. set_fixed_size(m_bitmap->size());
  40. }
  41. // Same as ImageViewer::ViewWidget::animate(), you probably want to keep any changes in sync
  42. void ImageWidget::animate()
  43. {
  44. m_current_frame_index = (m_current_frame_index + 1) % m_image_decoder->frame_count();
  45. const auto& current_frame = m_image_decoder->frame(m_current_frame_index);
  46. set_bitmap(current_frame.image);
  47. if (current_frame.duration != m_timer->interval()) {
  48. m_timer->restart(current_frame.duration);
  49. }
  50. if (m_current_frame_index == m_image_decoder->frame_count() - 1) {
  51. ++m_loops_completed;
  52. if (m_loops_completed > 0 && m_loops_completed == m_image_decoder->loop_count()) {
  53. m_timer->stop();
  54. }
  55. }
  56. }
  57. void ImageWidget::load_from_file(const StringView& path)
  58. {
  59. auto file_or_error = MappedFile::map(path);
  60. if (file_or_error.is_error())
  61. return;
  62. auto& mapped_file = *file_or_error.value();
  63. m_image_decoder = Gfx::ImageDecoder::try_create(mapped_file.bytes());
  64. VERIFY(m_image_decoder);
  65. auto bitmap = m_image_decoder->bitmap();
  66. VERIFY(bitmap);
  67. set_bitmap(bitmap);
  68. if (m_image_decoder->is_animated() && m_image_decoder->frame_count() > 1) {
  69. const auto& first_frame = m_image_decoder->frame(0);
  70. m_timer->set_interval(first_frame.duration);
  71. m_timer->on_timeout = [this] { animate(); };
  72. m_timer->start();
  73. }
  74. }
  75. void ImageWidget::mousedown_event(GUI::MouseEvent&)
  76. {
  77. if (on_click)
  78. on_click();
  79. }
  80. void ImageWidget::paint_event(PaintEvent& event)
  81. {
  82. Frame::paint_event(event);
  83. if (!m_bitmap) {
  84. return;
  85. }
  86. Painter painter(*this);
  87. painter.add_clip_rect(event.rect());
  88. if (m_should_stretch) {
  89. painter.draw_scaled_bitmap(frame_inner_rect(), *m_bitmap, m_bitmap->rect(), (float)opacity_percent() / 100.0f);
  90. } else {
  91. auto location = frame_inner_rect().center().translated(-(m_bitmap->width() / 2), -(m_bitmap->height() / 2));
  92. painter.blit(location, *m_bitmap, m_bitmap->rect(), (float)opacity_percent() / 100.0f);
  93. }
  94. }
  95. void ImageWidget::set_opacity_percent(int percent)
  96. {
  97. if (m_opacity_percent == percent)
  98. return;
  99. m_opacity_percent = percent;
  100. update();
  101. }
  102. }