7#include "cairo/cairo.h"
9#define NANOSVG_ALL_COLOR_KEYWORDS
10#define NANOSVG_IMPLEMENTATION
16#define min(x, y) (((x) < (y)) ? (x) : (y))
20static inline void to_rgba(
double*a,
unsigned int const c) {
21 a[0] = (c & 0xff) / 255.;
22 a[1] = ((c >> 8) & 0xff) / 255.;
23 a[2] = ((c >> 16) & 0xff) / 255.;
24 a[3] = ((c >> 24) & 0xff) / 255.;
27static inline void inverse(
double*a,
float const*
const t) {
28 double const invdet = (1. / ((double)(t[0]) * t[3] - (double)(t[2]) * t[1]));
31 a[1] = -t[1] * invdet;
32 a[2] = -t[2] * invdet;
34 a[4] = ((double)(t[2]) * t[5] - (double)(t[3]) * t[4]) * invdet;
35 a[5] = ((double)(t[1]) * t[4] - (double)(t[0]) * t[5]) * invdet;
38static inline void draw_stroke(
struct NSVGshape*
const shape, cairo_t*
const cr) {
47 cairo_set_source_rgba(cr, c[0], c[1], c[2], shape->
opacity * c[3]);
59 cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT);
63 cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
67 cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
71 cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT);
78 cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER);
83 cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND);
87 cairo_set_line_join(cr, CAIRO_LINE_JOIN_BEVEL);
91 cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER);
97 cairo_stroke_preserve(cr);
106static inline void draw_svg_shape(cairo_t*
const cr,
struct NSVGshape*
const shape) {
110 for (; path; path = path->
next) {
111 float* p = path->
pts;
113 cairo_move_to(cr, p[0], p[1]);
114 float*
const end = (p + 2 * path->
npts);
115 for (p += 2; end != p; p += 6) {
116 cairo_curve_to(cr, p[0], p[1], p[2], p[3], p[4], p[5]);
119 cairo_close_path(cr);
135 cairo_set_fill_rule(cr, CAIRO_FILL_RULE_WINDING);
139 cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
145 cairo_pattern_t* pat = {0};
152 cairo_set_source_rgba(cr, c[0], c[1], c[2], shape->
opacity * c[3]);
153 cairo_fill_preserve(cr);
154 draw_stroke(shape, cr);
162 pat = cairo_pattern_create_linear(t[4], t[5], t[4] + t[2], t[5] + t[3]);
170 inverse(t, g->
xform);
171 double const r = t[0];
172 pat = cairo_pattern_create_radial(g->
fx * -r, g->
fy * -r, 0., t[4], t[5], r);
185 cairo_pattern_set_extend(pat, CAIRO_EXTEND_PAD);
189 cairo_pattern_set_extend(pat, CAIRO_EXTEND_REFLECT);
193 cairo_pattern_set_extend(pat, CAIRO_EXTEND_REPEAT);
201 for (
int i = 0; ns != i; ++i) {
204 to_rgba(c, stop.
color);
205 cairo_pattern_add_color_stop_rgba(pat, stop.
offset,
206 c[0], c[1], c[2], shape->
opacity * c[3]);
208 cairo_set_source(cr, pat);
209 cairo_fill_preserve(cr);
210 cairo_pattern_destroy(pat);
217 draw_stroke(shape, cr);
220static void draw_svg_image(cairo_t*
const cr,
struct NSVGimage*
const image,
221 double const w,
double const h) {
222 double const sm = (min(w / image->
width, h / image->
height));
223 cairo_translate(cr, .5 * (w - sm * image->
width), .5 * (h - sm * image->
height));
224 cairo_scale(cr, sm, sm);
227 for (; shape; shape = shape->
next) {
228 draw_svg_shape(cr, shape);
233 double const x,
double const y,
double const w,
double const h) {
235 double const sm = (min(w / image->
width, h / image->
height));
236 cairo_translate(cr, x + .5 * (w - sm * image->
width), y + .5 * (h - sm * image->
height));
237 cairo_scale(cr, sm, sm);
240 for (; shape; shape = shape->
next) {
242 draw_svg_shape(cr, shape);
250 b64dst = (
char*)malloc((strlen(name)+1) *
sizeof(char));
255 int width_t = image->
width;
256 int height_t = image->
height;
257 cairo_surface_destroy(w->
image);
261 CAIRO_CONTENT_COLOR_ALPHA, width_t, height_t);
262 cairo_t *cri = cairo_create (w->
image);
263 draw_svg_image(cri, image, width_t, height_t);
271 b64dst = (
char*)malloc((strlen(name)+1) *
sizeof(char));
280 double x = (double)width_t/(
double)
width;
281 double y = (double)height_t/(
double)
height;
283 cairo_surface_t *getsvg = cairo_image_surface_create ( CAIRO_FORMAT_ARGB32,
width,
height);
284 cairo_t *cris = cairo_create (getsvg);
287 cairo_surface_destroy(w->
image);
290 CAIRO_CONTENT_COLOR_ALPHA, width_t, height_t);
291 cairo_t *cri = cairo_create (w->
image);
293 cairo_scale(cri, x,y);
294 cairo_set_source_surface (cri, getsvg,0,0);
298 cairo_surface_destroy(getsvg);
310 cairo_surface_destroy(w->
image);
314 CAIRO_CONTENT_COLOR_ALPHA, width_t, height_t);
315 cairo_t *cri = cairo_create (w->
image);
316 draw_svg_image(cri, image, width_t, height_t);
325 cairo_surface_destroy(w->
image);
329 CAIRO_CONTENT_COLOR_ALPHA, width_t, height_t);
330 cairo_t *cri = cairo_create (w->
image);
331 draw_svg_image(cri, image, width_t, height_t);
339 if (!image)
return NULL;
340 int width_t = image->
width;
341 int height_t = image->
height;
343 cairo_surface_t *getsvg = cairo_image_surface_create ( CAIRO_FORMAT_ARGB32, width_t, height_t);
344 cairo_t *cri = cairo_create (getsvg);
345 draw_svg_image(cri, image, width_t, height_t);
void b64_decode(char *b64src, char *clrdst)
b64_decode - decode to a b64 based char
NanoSVG is a simple stupid single-header-file SVG parse. The output of the parser is a list of cubic ...
NSVGimage * nsvgParseFromFile(const char *filename, const char *units, float dpi)
@ NSVG_PAINT_RADIAL_GRADIENT
@ NSVG_PAINT_LINEAR_GRADIENT
NSVGimage * nsvgParse(char *input, const char *units, float dpi)
void nsvgDelete(NSVGimage *image)
NSVGgradientStop stops[1]
void widget_get_scaled_svg(Widget_t *w, const char *name)
widget_get_scaled_svg - read svg scaled into Widget_t xlib surface
void widget_get_scaled_svg_from_file(Widget_t *w, const char *filename, int width_t, int height_t)
widget_get_scaled_svg_from_file - read svg into Widget_t xlib surface
cairo_surface_t * cairo_image_surface_create_from_svg(const char *filename)
void widget_get_svg_from_file(Widget_t *w, const char *filename)
widget_get_svg_from_file - read svg into Widget_t xlib surface
void draw_svg_image_to_pos(cairo_t *const cr, struct NSVGimage *const image, double const x, double const y, double const w, double const h)
void widget_get_svg(Widget_t *w, const char *name)
widget_get_svg - read svg into Widget_t xlib surface