FullscreenUI: Preserve aspect ratio of SVG images

pull/3745/head
Stenzek 4 months ago
parent dddc091221
commit ad676f7e3a
No known key found for this signature in database

@ -639,7 +639,7 @@ std::optional<Image> FullscreenUI::LoadTextureImage(std::string_view path, u32 s
if (svg_data.has_value())
{
image = Image();
if (!image->RasterizeSVG(svg_data->cspan(), svg_width, svg_height, &error))
if (!image->RasterizeSVG(svg_data->cspan(), svg_width, svg_height, true, &error))
{
ERROR_LOG("Failed to rasterize SVG texture file '{}': {}", path, error.GetDescription());
image.reset();
@ -698,7 +698,7 @@ std::optional<Image> FullscreenUI::LoadTextureImage(std::string_view filename, s
if (StringUtil::EqualNoCase(Path::GetExtension(filename), "svg"))
{
image = Image();
if (!image->RasterizeSVG(buffer, svg_width, svg_height, &error))
if (!image->RasterizeSVG(buffer, svg_width, svg_height, true, &error))
{
ERROR_LOG("Failed to rasterize SVG texture file '{}': {}", filename, error.GetDescription());
image.reset();

@ -388,7 +388,8 @@ bool Image::LoadFromBuffer(std::string_view filename, std::span<const u8> data,
return handler->buffer_loader(this, data, error);
}
bool Image::RasterizeSVG(const std::span<const u8> data, u32 width, u32 height, Error* error)
bool Image::RasterizeSVG(const std::span<const u8> data, u32 width, u32 height,
bool maintain_aspect_ratio /* = false */, Error* error /* = nullptr */)
{
if (width == 0 || height == 0)
{
@ -407,6 +408,42 @@ bool Image::RasterizeSVG(const std::span<const u8> data, u32 width, u32 height,
}
const plutovg_color_t current_color = {.r = 1.0f, .g = 1.0f, .b = 1.0f, .a = 1.0f};
u32 canvas_width = width;
u32 canvas_height = height;
u32 canvas_offset_x = 0;
u32 canvas_offset_y = 0;
if (maintain_aspect_ratio)
{
const float doc_width = plutosvg_document_get_width(doc.get());
const float doc_height = plutosvg_document_get_height(doc.get());
if (doc_width > 0.0f && doc_height > 0.0f)
{
const float fwidth = static_cast<float>(width);
const float fheight = static_cast<float>(height);
const float fit_ar = fwidth / fheight;
const float image_ar = doc_width / doc_height;
if (std::abs(image_ar - fit_ar) > 1e-6f)
{
if (fit_ar > image_ar)
{
// center horizontally
const float scaled_width = std::floor(fheight * image_ar);
canvas_width = width;
canvas_offset_x = static_cast<u32>((fwidth - scaled_width) * 0.5f);
width = static_cast<u32>(scaled_width);
}
else
{
// center vertically
const float scaled_height = std::floor(fwidth / image_ar);
canvas_height = height;
canvas_offset_y = static_cast<u32>((fheight - scaled_height) * 0.5f);
height = static_cast<u32>(scaled_height);
}
}
}
}
std::unique_ptr<plutovg_surface, void (*)(plutovg_surface*)> bitmap(
plutosvg_document_render_to_surface(doc.get(), nullptr, static_cast<int>(width), static_cast<int>(height),
@ -418,10 +455,14 @@ bool Image::RasterizeSVG(const std::span<const u8> data, u32 width, u32 height,
return false;
}
// pad out canvas if we're positioning it
Resize(canvas_width, canvas_height, ImageFormat::RGBA8, false);
if (canvas_width != width || canvas_height != height)
Clear();
// lunasvg works in BGRA, swap to RGBA
Resize(width, height, ImageFormat::RGBA8, false);
SwapBGRAToRGBA(m_pixels.get(), m_pitch, plutovg_surface_get_data(bitmap.get()),
plutovg_surface_get_stride(bitmap.get()), width, height);
SwapBGRAToRGBA(m_pixels.get() + (canvas_offset_y * m_pitch) + (canvas_offset_x * sizeof(u32)), m_pitch,
plutovg_surface_get_data(bitmap.get()), plutovg_surface_get_stride(bitmap.get()), width, height);
return true;
}

@ -90,7 +90,8 @@ public:
bool LoadFromFile(std::string_view filename, std::FILE* fp, Error* error = nullptr);
bool LoadFromBuffer(std::string_view filename, std::span<const u8> data, Error* error = nullptr);
bool RasterizeSVG(const std::span<const u8> data, u32 width, u32 height, Error* error = nullptr);
bool RasterizeSVG(const std::span<const u8> data, u32 width, u32 height, bool maintain_aspect_ratio = false,
Error* error = nullptr);
bool SaveToFile(const char* filename, u8 quality = DEFAULT_SAVE_QUALITY, Error* error = nullptr) const;
bool SaveToFile(std::string_view filename, std::FILE* fp, u8 quality = DEFAULT_SAVE_QUALITY,

Loading…
Cancel
Save