73 lines
2.2 KiB
C++
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
|