/* * Copyright (c) 2023, MacDue * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include #include #include #include #include "TVGIconEngine.h" #include "Utilities.h" void TVGIconEngine::paint(QPainter* qpainter, QRect const& rect, QIcon::Mode mode, QIcon::State state) { qpainter->drawPixmap(rect, pixmap(rect.size(), mode, state)); } QIconEngine* TVGIconEngine::clone() const { return new TVGIconEngine(*this); } QPixmap TVGIconEngine::pixmap(QSize const& size, QIcon::Mode mode, QIcon::State state) { QPixmap pixmap; auto key = pixmap_cache_key(size, mode, state); if (QPixmapCache::find(key, &pixmap)) return pixmap; auto bitmap = MUST(Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, { size.width(), size.height() })); Gfx::Painter painter { *bitmap }; auto icon_rect = m_image_data->rect().to_type(); auto scale = min(size.width() / icon_rect.width(), size.height() / icon_rect.height()) * m_scale; auto centered = Gfx::FloatRect { {}, icon_rect.size().scaled_by(scale) } .centered_within(Gfx::FloatRect { {}, { size.width(), size.height() } }); auto transform = Gfx::AffineTransform {} .translate(centered.location()) .multiply(Gfx::AffineTransform {}.scale(scale, scale)); m_image_data->draw_transformed(painter, transform); for (auto const& filter : m_filters) { if (filter->mode() == mode) { painter.blit_filtered({}, *bitmap, bitmap->rect(), filter->function(), false); break; } } QImage qimage { bitmap->scanline_u8(0), bitmap->width(), bitmap->height(), QImage::Format::Format_ARGB32 }; pixmap = QPixmap::fromImage(qimage); if (!pixmap.isNull()) QPixmapCache::insert(key, pixmap); return pixmap; } QString TVGIconEngine::pixmap_cache_key(QSize const& size, QIcon::Mode mode, QIcon::State state) { return qstring_from_ak_string( MUST(String::formatted("$sernity_tvgicon_{}_{}x{}_{}_{}", m_cache_id, size.width(), size.height(), to_underlying(mode), to_underlying(state)))); } void TVGIconEngine::add_filter(QIcon::Mode mode, Function filter) { m_filters.empend(adopt_ref(*new Filter(mode, move(filter)))); invalidate_cache(); } TVGIconEngine* TVGIconEngine::from_file(QString const& path) { QFile icon_resource(path); if (!icon_resource.open(QIODeviceBase::ReadOnly)) return nullptr; auto icon_data = icon_resource.readAll(); FixedMemoryStream icon_bytes { ReadonlyBytes { icon_data.data(), static_cast(icon_data.size()) } }; if (auto tvg = Gfx::TinyVGDecodedImageData::decode(icon_bytes); !tvg.is_error()) return new TVGIconEngine(tvg.release_value()); return nullptr; }