Files
MontaukOS/programs/src/imageviewer/svg_doc.cpp
T

73 lines
2.2 KiB
C++

/*
* svg_doc.cpp
* SvgDoc: source-backed rasterizable SVG document.
* Copyright (c) 2026 Daniel Hammer
*/
#include "svg_doc.hpp"
#include <montauk/syscall.h>
#include <montauk/heap.h>
#include <gui/gui.hpp>
#include <gui/svg.hpp>
namespace imageviewer {
bool svgdoc_init(SvgDoc* doc, uint8_t* source, int source_len) {
if (!doc) return false;
*doc = {};
if (!source || source_len <= 0) return false;
doc->source = source;
doc->source_len = source_len;
gui::svg_get_natural_size((const char*)source, source_len,
&doc->natural_w, &doc->natural_h);
if (doc->natural_w < 1) doc->natural_w = 1;
if (doc->natural_h < 1) doc->natural_h = 1;
return true;
}
bool svgdoc_render(SvgDoc* doc, float target_scale, int max_edge) {
if (!doc || !doc->source) return false;
if (target_scale <= 0.0f) target_scale = 1.0f;
if (max_edge < 1) max_edge = 1;
// Clamp so the longest edge of the rasterized output stays within max_edge.
int natural_long = doc->natural_w > doc->natural_h ? doc->natural_w : doc->natural_h;
float max_scale = (float)max_edge / (float)natural_long;
if (target_scale > max_scale) target_scale = max_scale;
if (target_scale < 0.01f) target_scale = 0.01f;
// Skip if cache is already close enough (avoids re-render on float jitter).
if (doc->pixels && doc->render_scale > 0.0f) {
float ratio = target_scale / doc->render_scale;
if (ratio > 0.995f && ratio < 1.005f) return true;
}
int new_w = (int)((float)doc->natural_w * target_scale);
int new_h = (int)((float)doc->natural_h * target_scale);
if (new_w < 1) new_w = 1;
if (new_h < 1) new_h = 1;
gui::SvgIcon icon = gui::svg_render(
(const char*)doc->source, doc->source_len,
new_w, new_h, gui::Color::from_rgb(0, 0, 0));
if (!icon.pixels) return false;
if (doc->pixels) montauk::mfree(doc->pixels);
doc->pixels = icon.pixels;
doc->render_w = icon.width;
doc->render_h = icon.height;
doc->render_scale = target_scale;
return true;
}
void svgdoc_free(SvgDoc* doc) {
if (!doc) return;
if (doc->pixels) montauk::mfree(doc->pixels);
if (doc->source) montauk::mfree(doc->source);
*doc = {};
}
} // namespace imageviewer