feat: expand and fix issues in SVG renderer
This commit is contained in:
+846
-155
File diff suppressed because it is too large
Load Diff
@@ -49,10 +49,56 @@ bool svgdoc_render(SvgDoc* doc, float target_scale, int max_edge) {
|
||||
if (new_w < 1) new_w = 1;
|
||||
if (new_h < 1) new_h = 1;
|
||||
|
||||
gui::SvgIcon icon = gui::svg_render(
|
||||
// Supersample ordinary viewing sizes to smooth path and stroke edges.
|
||||
// Very large zoomed renders stay at 1x to keep memory bounded.
|
||||
static constexpr int SS = 2;
|
||||
static constexpr int SS_MAX_OUTPUT_EDGE = 1024;
|
||||
int longest = new_w > new_h ? new_w : new_h;
|
||||
int render_ss = longest <= SS_MAX_OUTPUT_EDGE ? SS : 1;
|
||||
|
||||
gui::SvgIcon rendered = 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;
|
||||
new_w * render_ss, new_h * render_ss,
|
||||
gui::Color::from_rgb(0, 0, 0));
|
||||
if (!rendered.pixels) return false;
|
||||
|
||||
gui::SvgIcon icon = rendered;
|
||||
if (render_ss > 1) {
|
||||
uint32_t* downsampled = (uint32_t*)montauk::malloc(
|
||||
(uint64_t)new_w * (uint64_t)new_h * sizeof(uint32_t));
|
||||
if (downsampled) {
|
||||
for (int y = 0; y < new_h; ++y) {
|
||||
for (int x = 0; x < new_w; ++x) {
|
||||
uint32_t sum_a = 0, sum_pr = 0, sum_pg = 0, sum_pb = 0;
|
||||
for (int sy = 0; sy < render_ss; ++sy) {
|
||||
for (int sx = 0; sx < render_ss; ++sx) {
|
||||
uint32_t pixel = rendered.pixels[
|
||||
(y * render_ss + sy) * rendered.width + x * render_ss + sx];
|
||||
uint32_t a = (pixel >> 24) & 0xff;
|
||||
sum_a += a;
|
||||
sum_pr += ((pixel >> 16) & 0xff) * a;
|
||||
sum_pg += ((pixel >> 8) & 0xff) * a;
|
||||
sum_pb += (pixel & 0xff) * a;
|
||||
}
|
||||
}
|
||||
uint32_t samples = render_ss * render_ss;
|
||||
uint32_t a = sum_a / samples;
|
||||
uint32_t r = sum_a ? sum_pr / sum_a : 0;
|
||||
uint32_t g = sum_a ? sum_pg / sum_a : 0;
|
||||
uint32_t b = sum_a ? sum_pb / sum_a : 0;
|
||||
downsampled[y * new_w + x] = (a << 24) | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
}
|
||||
montauk::mfree(rendered.pixels);
|
||||
icon = {downsampled, new_w, new_h};
|
||||
} else {
|
||||
montauk::mfree(rendered.pixels);
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user