1 /*
2 * Copyright (C) 2020 Alexandros Theodotou <alex at zrythm dot org>
3 *
4 * This file is part of ZToolkit
5 *
6 * ZToolkit is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as
8 * published by the Free Software Foundation, either version 3 of the
9 * License, or (at your option) any later version.
10 *
11 * ZToolkit is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Affero Public License
17 * along with ZToolkit. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20 #include "ztoolkit_config.h"
21
22 #ifdef HAVE_RSVG
23
24 #include <ztoolkit/ztk.h>
25
26 #include <librsvg/rsvg.h>
27
28 /**
29 * Loads an SVG from an absolute path.
30 *
31 * @return An rsvg handle, or NULL if failed.
32 */
33 ZtkRsvgHandle *
ztk_rsvg_load_svg(const char * abs_path)34 ztk_rsvg_load_svg (
35 const char * abs_path)
36 {
37 GFile * file =
38 g_file_new_for_path (abs_path);
39 GError * err = NULL;
40 RsvgHandle * handle =
41 rsvg_handle_new_from_gfile_sync (
42 file, RSVG_HANDLE_FLAGS_NONE, NULL, &err);
43 if (err)
44 {
45 ztk_error (
46 "An error occurred parsing the SVG file at "
47 "%s: %s", abs_path, err->message);
48 g_object_unref (file);
49 return NULL;
50 }
51 g_object_unref (file);
52
53 /* common values are 75, 90, 300 */
54 rsvg_handle_set_dpi (handle, 300);
55
56 return (ZtkRsvgHandle *) handle;
57 }
58
59 /**
60 * Gets the width of the svg.
61 */
62 int
ztk_rsvg_get_width(ZtkRsvgHandle * handle)63 ztk_rsvg_get_width (
64 ZtkRsvgHandle * handle)
65 {
66 RsvgDimensionData dim;
67 rsvg_handle_get_dimensions (
68 (RsvgHandle *) handle, &dim);
69 return dim.width;
70 }
71
72 /**
73 * Gets the height of the svg.
74 */
75 int
ztk_rsvg_get_height(ZtkRsvgHandle * handle)76 ztk_rsvg_get_height (
77 ZtkRsvgHandle * handle)
78 {
79 RsvgDimensionData dim;
80 rsvg_handle_get_dimensions (
81 (RsvgHandle *) handle, &dim);
82 return dim.height;
83 }
84
85 /**
86 * Draws the SVG on the current cairo context.
87 *
88 * @return 0 if successful, non-zero if failed.
89 */
90 int
ztk_rsvg_draw(ZtkRsvgHandle * handle,cairo_t * cr,ZtkRect * rect)91 ztk_rsvg_draw (
92 ZtkRsvgHandle * handle,
93 cairo_t * cr,
94 ZtkRect * rect)
95 {
96 #ifdef HAVE_RSVG_2_46
97 RsvgRectangle viewport = {
98 rect->x, rect->y, rect->width, rect->height };
99 GError * err = NULL;
100 rsvg_handle_render_document (
101 (RsvgHandle *) handle, cr, &viewport, &err);
102 if (err)
103 {
104 return -1;
105 }
106 #else
107 int rwidth =
108 ztk_rsvg_get_width (handle);
109 int rheight =
110 ztk_rsvg_get_height (handle);
111 double xscale =
112 (double) rect->width / (double) rwidth ;
113 double yscale =
114 (double) rect->height / (double) rheight;
115 double scale = MIN (xscale, yscale);
116 double leftover_x =
117 rect->width - scale * rwidth;
118 double leftover_y =
119 rect->height - scale * rheight;
120 cairo_save (cr);
121 cairo_translate (cr, rect->x + leftover_x / 2, rect->y + leftover_y / 2);
122 cairo_scale (
123 cr, scale, scale);
124 rsvg_handle_render_cairo (
125 (RsvgHandle *) handle, cr);
126 cairo_restore (cr);
127 #endif
128
129 return 0;
130 }
131
132 #endif // HAVE_RSVG
133