Branch data Line data Source code
1 : : /*
2 : : * Copyright (C) 2021 James Westman <james@jwestman.net>
3 : : *
4 : : * This library is free software; you can redistribute it and/or
5 : : * modify it under the terms of the GNU Lesser General Public
6 : : * License as published by the Free Software Foundation; either
7 : : * version 2.1 of the License, or (at your option) any later version.
8 : : *
9 : : * This library is distributed in the hope that it will be useful,
10 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 : : * Lesser General Public License for more details.
13 : : *
14 : : * You should have received a copy of the GNU Lesser General Public
15 : : * License along with this library; if not, see <https://www.gnu.org/licenses/>.
16 : : */
17 : :
18 : : #include <gtk/gtk.h>
19 : : #include "shumate-vector-expression-private.h"
20 : : #include "shumate-vector-line-layer-private.h"
21 : : #include "shumate-vector-utils-private.h"
22 : : #include "shumate-vector-value-private.h"
23 : :
24 : : struct _ShumateVectorLineLayer
25 : : {
26 : : ShumateVectorLayer parent_instance;
27 : :
28 : : ShumateVectorExpression *color;
29 : : ShumateVectorExpression *opacity;
30 : : ShumateVectorExpression *width;
31 : : ShumateVectorExpression *cap;
32 : : ShumateVectorExpression *join;
33 : :
34 : : double *dashes;
35 : : int num_dashes;
36 : : };
37 : :
38 [ + + + - ]: 18 : G_DEFINE_TYPE (ShumateVectorLineLayer, shumate_vector_line_layer, SHUMATE_TYPE_VECTOR_LAYER)
39 : :
40 : :
41 : : ShumateVectorLayer *
42 : 6 : shumate_vector_line_layer_create_from_json (JsonObject *object, GError **error)
43 : : {
44 : 6 : ShumateVectorLineLayer *layer = g_object_new (SHUMATE_TYPE_VECTOR_LINE_LAYER, NULL);
45 : 6 : JsonNode *paint_node, *layout_node;
46 : :
47 [ + - ]: 6 : if ((paint_node = json_object_get_member (object, "paint")))
48 : : {
49 : 6 : JsonObject *paint;
50 : :
51 [ + - ]: 6 : if (!shumate_vector_json_get_object (paint_node, &paint, error))
52 : 0 : return NULL;
53 : :
54 [ + - ]: 6 : if (!(layer->color = shumate_vector_expression_from_json (json_object_get_member (paint, "line-color"), error)))
55 : : return NULL;
56 : :
57 [ + - ]: 6 : if (!(layer->opacity = shumate_vector_expression_from_json (json_object_get_member (paint, "line-opacity"), error)))
58 : : return NULL;
59 : :
60 [ + - ]: 6 : if (!(layer->width = shumate_vector_expression_from_json (json_object_get_member (paint, "line-width"), error)))
61 : : return NULL;
62 : :
63 : : {
64 : 6 : JsonArray *dasharray;
65 : :
66 [ - + ]: 6 : if (!shumate_vector_json_get_array_member (paint, "line-dasharray", &dasharray, error))
67 : 0 : return NULL;
68 : :
69 [ - + ]: 6 : if (dasharray != NULL)
70 : : {
71 : 0 : int i;
72 : 0 : layer->num_dashes = json_array_get_length (dasharray);
73 [ # # # # ]: 0 : layer->dashes = g_new (double, layer->num_dashes);
74 [ # # ]: 0 : for (i = 0; i < layer->num_dashes; i ++)
75 : 0 : layer->dashes[i] = json_node_get_double (json_array_get_element (dasharray, i));
76 : : }
77 : : }
78 : : }
79 : :
80 [ - + ]: 6 : if ((layout_node = json_object_get_member (object, "layout")))
81 : : {
82 : 0 : JsonObject *layout;
83 : :
84 [ # # ]: 0 : if (!shumate_vector_json_get_object (layout_node, &layout, error))
85 : 0 : return NULL;
86 : :
87 [ # # ]: 0 : if (!(layer->cap = shumate_vector_expression_from_json (json_object_get_member (layout, "line-cap"), error)))
88 : : return NULL;
89 : :
90 [ # # ]: 0 : if (!(layer->join = shumate_vector_expression_from_json (json_object_get_member (layout, "line-join"), error)))
91 : : return NULL;
92 : : }
93 : :
94 : : return (ShumateVectorLayer *)layer;
95 : : }
96 : :
97 : :
98 : : static void
99 : 6 : shumate_vector_line_layer_finalize (GObject *object)
100 : : {
101 : 6 : ShumateVectorLineLayer *self = SHUMATE_VECTOR_LINE_LAYER (object);
102 : :
103 [ + - ]: 6 : g_clear_object (&self->color);
104 [ + - ]: 6 : g_clear_object (&self->opacity);
105 [ + - ]: 6 : g_clear_object (&self->width);
106 [ - + ]: 6 : g_clear_object (&self->cap);
107 [ - + ]: 6 : g_clear_object (&self->join);
108 : :
109 [ - + ]: 6 : g_clear_pointer (&self->dashes, g_free);
110 : :
111 : 6 : G_OBJECT_CLASS (shumate_vector_line_layer_parent_class)->finalize (object);
112 : 6 : }
113 : :
114 : :
115 : : static void
116 : 6 : shumate_vector_line_layer_render (ShumateVectorLayer *layer, ShumateVectorRenderScope *scope)
117 : : {
118 : 6 : ShumateVectorLineLayer *self = SHUMATE_VECTOR_LINE_LAYER (layer);
119 : 6 : GdkRGBA color = SHUMATE_VECTOR_COLOR_BLACK;
120 : 6 : double opacity;
121 : 6 : double width;
122 : 12 : g_autofree char *cap = NULL;
123 : 6 : g_autofree char *join = NULL;
124 : :
125 : 6 : shumate_vector_expression_eval_color (self->color, scope, &color);
126 : 6 : opacity = shumate_vector_expression_eval_number (self->opacity, scope, 1.0);
127 : 6 : width = shumate_vector_expression_eval_number (self->width, scope, 1.0);
128 : 6 : cap = shumate_vector_expression_eval_string (self->cap, scope, NULL);
129 : 6 : join = shumate_vector_expression_eval_string (self->join, scope, NULL);
130 : :
131 : 6 : shumate_vector_render_scope_exec_geometry (scope);
132 : :
133 : 6 : cairo_set_source_rgba (scope->cr, color.red, color.green, color.blue, color.alpha * opacity);
134 : 6 : cairo_set_line_width (scope->cr, width * scope->scale);
135 : :
136 [ - + ]: 6 : if (g_strcmp0 (cap, "round") == 0)
137 : 0 : cairo_set_line_cap (scope->cr, CAIRO_LINE_CAP_ROUND);
138 [ - + ]: 6 : else if (g_strcmp0 (cap, "square") == 0)
139 : 0 : cairo_set_line_cap (scope->cr, CAIRO_LINE_CAP_SQUARE);
140 : : else
141 : 6 : cairo_set_line_cap (scope->cr, CAIRO_LINE_CAP_BUTT);
142 : :
143 [ - + ]: 6 : if (g_strcmp0 (join, "bevel") == 0)
144 : 0 : cairo_set_line_join (scope->cr, CAIRO_LINE_JOIN_BEVEL);
145 [ - + ]: 6 : else if (g_strcmp0 (join, "round") == 0)
146 : 0 : cairo_set_line_join (scope->cr, CAIRO_LINE_JOIN_ROUND);
147 : : else
148 : 6 : cairo_set_line_join (scope->cr, CAIRO_LINE_JOIN_MITER);
149 : :
150 [ + - ]: 6 : if (self->dashes == NULL)
151 : 6 : cairo_set_dash (scope->cr, NULL, 0, 0);
152 : : else
153 : : {
154 : 0 : int i;
155 [ # # # # ]: 0 : g_autofree double *dasharray = g_new (double, self->num_dashes);
156 : 0 : gboolean any_nonzero = FALSE;
157 : 0 : gboolean all_positive = TRUE;
158 : :
159 [ # # ]: 0 : for (i = 0; i < self->num_dashes; i ++)
160 : : {
161 : 0 : dasharray[i] = self->dashes[i] * width * scope->scale;
162 : :
163 [ # # ]: 0 : if (dasharray[i] < 0)
164 : : {
165 : : all_positive = FALSE;
166 : : break;
167 : : }
168 [ # # ]: 0 : else if (dasharray[i] != 0)
169 : 0 : any_nonzero = TRUE;
170 : : }
171 : :
172 : : /* make sure the dasharray is valid */
173 [ # # ]: 0 : if (any_nonzero && all_positive)
174 : 0 : cairo_set_dash (scope->cr, dasharray, self->num_dashes, 0);
175 : : else
176 : 0 : cairo_set_dash (scope->cr, NULL, 0, 0);
177 : : }
178 : :
179 : 6 : cairo_stroke (scope->cr);
180 : 6 : }
181 : :
182 : :
183 : : static void
184 : 6 : shumate_vector_line_layer_class_init (ShumateVectorLineLayerClass *klass)
185 : : {
186 : 6 : GObjectClass *object_class = G_OBJECT_CLASS (klass);
187 : 6 : ShumateVectorLayerClass *layer_class = SHUMATE_VECTOR_LAYER_CLASS (klass);
188 : :
189 : 6 : object_class->finalize = shumate_vector_line_layer_finalize;
190 : 6 : layer_class->render = shumate_vector_line_layer_render;
191 : : }
192 : :
193 : :
194 : : static void
195 : 6 : shumate_vector_line_layer_init (ShumateVectorLineLayer *self)
196 : : {
197 : 6 : }
|