Serenity Operating System
at master 105 lines 3.1 kB view raw
1/* 2 * Copyright (c) 2018-2022, Andreas Kling <kling@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <LibWeb/HTML/BrowsingContext.h> 8#include <LibWeb/Layout/ImageBox.h> 9#include <LibWeb/Painting/ImagePaintable.h> 10#include <LibWeb/Platform/FontPlugin.h> 11 12namespace Web::Layout { 13 14ImageBox::ImageBox(DOM::Document& document, DOM::Element& element, NonnullRefPtr<CSS::StyleProperties> style, ImageLoader const& image_loader) 15 : ReplacedBox(document, element, move(style)) 16 , m_image_loader(image_loader) 17{ 18 browsing_context().register_viewport_client(*this); 19} 20 21ImageBox::~ImageBox() = default; 22 23void ImageBox::finalize() 24{ 25 Base::finalize(); 26 27 // NOTE: We unregister from the browsing context in finalize() to avoid trouble 28 // in the scenario where our BrowsingContext has already been swept by GC. 29 browsing_context().unregister_viewport_client(*this); 30} 31 32int ImageBox::preferred_width() const 33{ 34 return dom_node().attribute(HTML::AttributeNames::width).to_int().value_or(m_image_loader.width()); 35} 36 37int ImageBox::preferred_height() const 38{ 39 return dom_node().attribute(HTML::AttributeNames::height).to_int().value_or(m_image_loader.height()); 40} 41 42void ImageBox::prepare_for_replaced_layout() 43{ 44 if (!m_image_loader.has_loaded_or_failed()) { 45 set_intrinsic_width(0); 46 set_intrinsic_height(0); 47 } else { 48 if (m_image_loader.width()) { 49 set_intrinsic_width(m_image_loader.width()); 50 } 51 if (m_image_loader.height()) { 52 set_intrinsic_height(m_image_loader.height()); 53 } 54 55 if (m_image_loader.width() && m_image_loader.height()) { 56 set_intrinsic_aspect_ratio((float)m_image_loader.width() / (float)m_image_loader.height()); 57 } else { 58 set_intrinsic_aspect_ratio({}); 59 } 60 } 61 62 if (renders_as_alt_text()) { 63 auto& image_element = verify_cast<HTML::HTMLImageElement>(dom_node()); 64 auto& font = Platform::FontPlugin::the().default_font(); 65 auto alt = image_element.alt(); 66 if (alt.is_empty()) 67 alt = image_element.src(); 68 69 CSSPixels alt_text_width = 0; 70 if (!m_cached_alt_text_width.has_value()) 71 m_cached_alt_text_width = font.width(alt); 72 alt_text_width = m_cached_alt_text_width.value(); 73 74 set_intrinsic_width(alt_text_width + 16); 75 set_intrinsic_height(font.pixel_size() + 16); 76 } 77 78 if (!has_intrinsic_width() && !has_intrinsic_height()) { 79 // FIXME: Do something. 80 } 81} 82 83void ImageBox::dom_node_did_update_alt_text(Badge<HTML::HTMLImageElement>) 84{ 85 m_cached_alt_text_width = {}; 86} 87 88bool ImageBox::renders_as_alt_text() const 89{ 90 if (is<HTML::HTMLImageElement>(dom_node())) 91 return !m_image_loader.has_image(); 92 return false; 93} 94 95void ImageBox::browsing_context_did_set_viewport_rect(CSSPixelRect const& viewport_rect) 96{ 97 m_image_loader.set_visible_in_viewport(paint_box() && viewport_rect.intersects(paint_box()->absolute_rect())); 98} 99 100JS::GCPtr<Painting::Paintable> ImageBox::create_paintable() const 101{ 102 return Painting::ImagePaintable::create(*this); 103} 104 105}