ImageResource.cpp 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. /*
  2. * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibGfx/Bitmap.h>
  7. #include <LibWeb/ImageDecoding.h>
  8. #include <LibWeb/Loader/ImageResource.h>
  9. namespace Web {
  10. ImageResource::ImageResource(const LoadRequest& request)
  11. : Resource(Type::Image, request)
  12. {
  13. }
  14. ImageResource::~ImageResource()
  15. {
  16. }
  17. int ImageResource::frame_duration(size_t frame_index) const
  18. {
  19. decode_if_needed();
  20. if (frame_index >= m_decoded_frames.size())
  21. return 0;
  22. return m_decoded_frames[frame_index].duration;
  23. }
  24. void ImageResource::decode_if_needed() const
  25. {
  26. if (!has_encoded_data())
  27. return;
  28. if (m_has_attempted_decode)
  29. return;
  30. if (!m_decoded_frames.is_empty())
  31. return;
  32. NonnullRefPtr decoder = image_decoder_client();
  33. auto image = decoder->decode_image(encoded_data());
  34. if (image.has_value()) {
  35. m_loop_count = image.value().loop_count;
  36. m_animated = image.value().is_animated;
  37. m_decoded_frames.resize(image.value().frames.size());
  38. for (size_t i = 0; i < m_decoded_frames.size(); ++i) {
  39. auto& frame = m_decoded_frames[i];
  40. frame.bitmap = image.value().frames[i].bitmap;
  41. frame.duration = image.value().frames[i].duration;
  42. }
  43. }
  44. m_has_attempted_decode = true;
  45. }
  46. const Gfx::Bitmap* ImageResource::bitmap(size_t frame_index) const
  47. {
  48. decode_if_needed();
  49. if (frame_index >= m_decoded_frames.size())
  50. return nullptr;
  51. return m_decoded_frames[frame_index].bitmap;
  52. }
  53. void ImageResource::update_volatility()
  54. {
  55. bool visible_in_viewport = false;
  56. for_each_client([&](auto& client) {
  57. if (static_cast<const ImageResourceClient&>(client).is_visible_in_viewport())
  58. visible_in_viewport = true;
  59. });
  60. if (!visible_in_viewport) {
  61. for (auto& frame : m_decoded_frames) {
  62. if (frame.bitmap)
  63. frame.bitmap->set_volatile();
  64. }
  65. return;
  66. }
  67. bool still_has_decoded_image = true;
  68. for (auto& frame : m_decoded_frames) {
  69. if (!frame.bitmap) {
  70. still_has_decoded_image = false;
  71. } else {
  72. bool was_purged = false;
  73. bool bitmap_has_memory = frame.bitmap->set_nonvolatile(was_purged);
  74. if (!bitmap_has_memory || was_purged)
  75. still_has_decoded_image = false;
  76. }
  77. }
  78. if (still_has_decoded_image)
  79. return;
  80. m_decoded_frames.clear();
  81. m_has_attempted_decode = false;
  82. }
  83. ImageResourceClient::~ImageResourceClient()
  84. {
  85. }
  86. }