Line data Source code
1 : /* File: draw_classifier_icon.c; Copyright and License: see below */
2 :
3 : #include "draw/draw_classifier_icon.h"
4 : #include "layout/layout_visible_set.h"
5 : #include "u8/u8_trace.h"
6 : #include <stdio.h>
7 : #include <stdlib.h>
8 : #include <assert.h>
9 :
10 : /*! where to place the control points of a bezier curve to get a good approximation for a 90 degree curve */
11 : const static double BEZIER_CTRL_POINT_FOR_90_DEGREE_CIRCLE = 0.552284749831;
12 :
13 : const double DRAW_CLASSIFIER_ICON_ARTIFACT_ICON_WIDTH_TO_HEIGHT = 0.7;
14 : const double DRAW_CLASSIFIER_ICON_COMPONENT_ICON_WIDTH_TO_HEIGHT = 1.4;
15 :
16 0 : void draw_classifier_icon_draw_component ( const draw_classifier_icon_t *this_,
17 : geometry_rectangle_t bounds,
18 : cairo_t *cr )
19 : {
20 0 : U8_TRACE_BEGIN();
21 0 : assert( NULL != cr );
22 :
23 : /* determine linewidth to avoid that drawings overlap to the outside of bounds */
24 : {
25 0 : const double ln_w = cairo_get_line_width( cr );
26 0 : geometry_rectangle_enlarge( &bounds, -ln_w, -ln_w );
27 0 : geometry_rectangle_shift( &bounds, ln_w/2.0, ln_w/2.0 );
28 : }
29 :
30 : /* calculate component bounds */
31 0 : const double comp_right = geometry_rectangle_get_right( &bounds );
32 0 : const double comp_top = geometry_rectangle_get_top( &bounds );
33 0 : const double comp_bottom = geometry_rectangle_get_bottom( &bounds );
34 0 : const double comp_height = geometry_rectangle_get_height( &bounds );
35 0 : const double port_half_width = comp_height * 0.2;
36 0 : const double comp_left = geometry_rectangle_get_left( &bounds ) + port_half_width;
37 : //const double comp_width = geometry_rectangle_get_width( &bounds ) - port_half_width;
38 :
39 : /* calculate bounds of the two ports */
40 0 : const double port_left = comp_left - port_half_width;
41 0 : const double port_width = 2.0*port_half_width;
42 0 : const double port_height = 0.2*comp_height;
43 0 : const double port1_top = comp_top + 0.2*comp_height;
44 0 : const double port2_top = comp_top + 0.6*comp_height;
45 :
46 : /* draw the icon */
47 0 : cairo_move_to ( cr, comp_left, port1_top );
48 0 : cairo_line_to ( cr, comp_left, comp_top );
49 0 : cairo_line_to ( cr, comp_right, comp_top );
50 0 : cairo_line_to ( cr, comp_right, comp_bottom );
51 0 : cairo_line_to ( cr, comp_left, comp_bottom );
52 0 : cairo_line_to ( cr, comp_left, port2_top + port_height );
53 0 : cairo_stroke (cr);
54 0 : cairo_move_to ( cr, comp_left, port2_top );
55 0 : cairo_line_to ( cr, comp_left, port1_top + port_height );
56 0 : cairo_stroke (cr);
57 0 : cairo_rectangle ( cr, port_left, port1_top, port_width, port_height );
58 0 : cairo_stroke (cr);
59 0 : cairo_rectangle ( cr, port_left, port2_top, port_width, port_height );
60 0 : cairo_stroke (cr);
61 :
62 0 : U8_TRACE_END();
63 0 : }
64 :
65 0 : void draw_classifier_icon_draw_artifact ( const draw_classifier_icon_t *this_,
66 : geometry_rectangle_t bounds,
67 : cairo_t *cr )
68 : {
69 0 : U8_TRACE_BEGIN();
70 0 : assert( NULL != cr );
71 :
72 : /* determine linewith to avoid that drawings overlap to the outside of bounds */
73 : {
74 0 : const double ln_w = cairo_get_line_width( cr );
75 0 : geometry_rectangle_enlarge( &bounds, -ln_w, -ln_w );
76 0 : geometry_rectangle_shift( &bounds, ln_w/2.0, ln_w/2.0 );
77 : }
78 :
79 : /* calculate artifact bounds */
80 0 : const double art_left = geometry_rectangle_get_left( &bounds );
81 0 : const double art_right = geometry_rectangle_get_right( &bounds );
82 0 : const double art_top = geometry_rectangle_get_top( &bounds );
83 0 : const double art_bottom = geometry_rectangle_get_bottom( &bounds );
84 0 : const double art_height = geometry_rectangle_get_height( &bounds );
85 : //const double art_width = geometry_rectangle_get_width( &bounds );
86 0 : const double art_corner_edge = art_height * 0.3;
87 :
88 : /* draw the icon */
89 0 : cairo_move_to ( cr, art_right, art_top + art_corner_edge );
90 0 : cairo_line_to ( cr, art_right - art_corner_edge, art_top + art_corner_edge );
91 0 : cairo_line_to ( cr, art_right - art_corner_edge, art_top );
92 0 : cairo_line_to ( cr, art_left, art_top );
93 0 : cairo_line_to ( cr, art_left, art_bottom );
94 0 : cairo_line_to ( cr, art_right, art_bottom );
95 0 : cairo_line_to ( cr, art_right, art_top + art_corner_edge );
96 0 : cairo_line_to ( cr, art_right - art_corner_edge, art_top );
97 0 : cairo_stroke (cr);
98 :
99 0 : U8_TRACE_END();
100 0 : }
101 :
102 0 : void draw_classifier_icon_draw_actor ( const draw_classifier_icon_t *this_,
103 : geometry_rectangle_t bounds,
104 : cairo_t *cr )
105 : {
106 0 : U8_TRACE_BEGIN();
107 0 : assert( NULL != cr );
108 :
109 : /* determine linewith to avoid that drawings overlap to the outside of bounds */
110 : {
111 0 : const double ln_w = cairo_get_line_width( cr );
112 0 : geometry_rectangle_enlarge( &bounds, -ln_w, -ln_w );
113 0 : geometry_rectangle_shift( &bounds, ln_w/2.0, ln_w/2.0 );
114 : }
115 :
116 : /* calculate actor bounds */
117 0 : const double act_left = geometry_rectangle_get_left( &bounds );
118 0 : const double act_right = geometry_rectangle_get_right( &bounds );
119 0 : const double act_top = geometry_rectangle_get_top( &bounds );
120 0 : const double act_bottom = geometry_rectangle_get_bottom( &bounds );
121 0 : const double act_height = geometry_rectangle_get_height( &bounds );
122 0 : const double act_width = geometry_rectangle_get_width( &bounds );
123 :
124 : /* draw the icon */
125 0 : const double radius = act_width/2.0;
126 0 : const double ctrl_offset = radius * (1.0-BEZIER_CTRL_POINT_FOR_90_DEGREE_CIRCLE);
127 0 : const double head_bottom = act_top + act_height/3.0;
128 0 : const double leg_top = act_top + act_height*0.6;
129 0 : const double arm_top = act_top + act_height*0.45;
130 :
131 0 : cairo_move_to ( cr, act_left + radius, head_bottom );
132 0 : cairo_curve_to ( cr, act_left + ctrl_offset, head_bottom, act_left, head_bottom - ctrl_offset, act_left /* end point x */, act_top + radius /* end point y */ );
133 0 : cairo_curve_to ( cr, act_left, act_top + ctrl_offset, act_left + ctrl_offset, act_top, act_left + radius /* end point x */, act_top /* end point y */ );
134 0 : cairo_curve_to ( cr, act_right - ctrl_offset, act_top, act_right, act_top + ctrl_offset, act_right /* end point x */, act_top + radius /* end point y */ );
135 0 : cairo_curve_to ( cr, act_right, head_bottom - ctrl_offset, act_right - ctrl_offset, head_bottom, act_left + radius /* end point x */, head_bottom /* end point y */ );
136 0 : cairo_line_to ( cr, act_left + radius, leg_top );
137 0 : cairo_line_to ( cr, act_left, act_bottom );
138 0 : cairo_move_to ( cr, act_right, act_bottom );
139 0 : cairo_line_to ( cr, act_left + radius, leg_top );
140 0 : cairo_move_to ( cr, act_right, arm_top );
141 0 : cairo_line_to ( cr, act_left, arm_top );
142 0 : cairo_stroke (cr);
143 :
144 0 : U8_TRACE_END();
145 0 : }
146 :
147 0 : void draw_classifier_icon_draw_circle ( const draw_classifier_icon_t *this_,
148 : geometry_rectangle_t bounds,
149 : const pencil_size_t *pencil_size,
150 : bool stroke,
151 : bool fill,
152 : bool shallow_history,
153 : bool deep_history,
154 : cairo_t *cr )
155 : {
156 0 : U8_TRACE_BEGIN();
157 0 : assert ( NULL != pencil_size );
158 0 : assert ( NULL != cr );
159 :
160 : /* determine linewith to avoid that drawings overlap to the outside of bounds */
161 : {
162 0 : const double ln_w = cairo_get_line_width( cr );
163 0 : geometry_rectangle_enlarge( &bounds, -ln_w, -ln_w );
164 0 : geometry_rectangle_shift( &bounds, ln_w/2.0, ln_w/2.0 );
165 : }
166 :
167 0 : const double circle_top = geometry_rectangle_get_top( &bounds );
168 0 : const double circle_bottom = geometry_rectangle_get_bottom( &bounds );
169 0 : const double center_x = geometry_rectangle_get_center_x( &bounds );
170 0 : const double center_y = geometry_rectangle_get_center_y( &bounds );
171 0 : const double circle_left = geometry_rectangle_get_left( &bounds );
172 0 : const double circle_right = geometry_rectangle_get_right( &bounds );
173 0 : const double circle_width = geometry_rectangle_get_width( &bounds );
174 0 : const double circle_height = geometry_rectangle_get_height( &bounds );
175 0 : const double circle_x_radius = center_x - circle_left;
176 0 : const double circle_y_radius = center_y - circle_top;
177 :
178 0 : const double gap = pencil_size_get_standard_object_border( pencil_size );
179 :
180 0 : if ( stroke )
181 : {
182 0 : const double ctrl_x_offset = circle_x_radius * (1.0-BEZIER_CTRL_POINT_FOR_90_DEGREE_CIRCLE);
183 0 : const double ctrl_y_offset = circle_y_radius * (1.0-BEZIER_CTRL_POINT_FOR_90_DEGREE_CIRCLE);
184 :
185 0 : cairo_move_to ( cr, center_x, circle_bottom );
186 0 : cairo_curve_to ( cr, circle_left + ctrl_x_offset, circle_bottom, circle_left, circle_bottom - ctrl_y_offset, circle_left /* end point x */, center_y /* end point y */ );
187 0 : cairo_curve_to ( cr, circle_left, circle_top + ctrl_y_offset, circle_left + ctrl_x_offset, circle_top, center_x /* end point x */, circle_top /* end point y */ );
188 0 : cairo_curve_to ( cr, circle_right - ctrl_x_offset, circle_top, circle_right, circle_top + ctrl_y_offset, circle_right /* end point x */, center_y /* end point y */ );
189 0 : cairo_curve_to ( cr, circle_right, circle_bottom - ctrl_y_offset, circle_right - ctrl_x_offset, circle_bottom, center_x /* end point x */, circle_bottom /* end point y */ );
190 0 : cairo_stroke (cr);
191 : }
192 :
193 0 : if ( fill )
194 : {
195 0 : const double circle2_x_radius = circle_x_radius - gap;
196 0 : const double circle2_y_radius = circle_y_radius - gap;
197 0 : const double circle2_top = circle_top + gap;
198 0 : const double circle2_bottom = circle_bottom - gap;
199 0 : const double circle2_left = circle_left + gap;
200 0 : const double circle2_right = circle_right - gap;
201 0 : const double ctrl2_x_offset = circle2_x_radius * (1.0-BEZIER_CTRL_POINT_FOR_90_DEGREE_CIRCLE);
202 0 : const double ctrl2_y_offset = circle2_y_radius * (1.0-BEZIER_CTRL_POINT_FOR_90_DEGREE_CIRCLE);
203 :
204 : /* draw a smaller filled circle */
205 0 : cairo_move_to ( cr, center_x, circle2_bottom );
206 0 : cairo_curve_to ( cr, circle2_left + ctrl2_x_offset, circle2_bottom, circle2_left, circle2_bottom - ctrl2_y_offset, circle2_left /* end point x */, center_y /* end point y */ );
207 0 : cairo_curve_to ( cr, circle2_left, circle2_top + ctrl2_y_offset, circle2_left + ctrl2_x_offset, circle2_top, center_x /* end point x */, circle2_top /* end point y */ );
208 0 : cairo_curve_to ( cr, circle2_right - ctrl2_x_offset, circle2_top, circle2_right, circle2_top + ctrl2_y_offset, circle2_right /* end point x */, center_y /* end point y */ );
209 0 : cairo_curve_to ( cr, circle2_right, circle2_bottom - ctrl2_y_offset, circle2_right - ctrl2_x_offset, circle2_bottom, center_x /* end point x */, circle2_bottom /* end point y */ );
210 0 : cairo_fill (cr);
211 : }
212 :
213 0 : if ( shallow_history )
214 : {
215 0 : const double quarter_x_font = 0.15 * circle_width;
216 0 : const double quarter_y_font = 0.15 * circle_height;
217 0 : cairo_move_to ( cr, center_x - quarter_x_font, center_y - 2.0 * quarter_y_font );
218 0 : cairo_line_to ( cr, center_x - quarter_x_font, center_y + 2.0 * quarter_y_font );
219 0 : cairo_move_to ( cr, center_x - quarter_x_font, center_y );
220 0 : cairo_line_to ( cr, center_x + quarter_x_font, center_y );
221 0 : cairo_move_to ( cr, center_x + quarter_x_font, center_y - 2.0 * quarter_y_font );
222 0 : cairo_line_to ( cr, center_x + quarter_x_font, center_y + 2.0 * quarter_y_font );
223 0 : cairo_stroke (cr);
224 : }
225 0 : else if ( deep_history )
226 : {
227 0 : const double quarter_x_font = 0.15 * circle_width;
228 0 : const double quarter_y_font = 0.15 * circle_height;
229 0 : cairo_move_to ( cr, center_x - 1.5 * quarter_x_font, center_y - 2.0 * quarter_y_font );
230 0 : cairo_line_to ( cr, center_x - 1.5 * quarter_x_font, center_y + 2.0 * quarter_y_font );
231 0 : cairo_move_to ( cr, center_x - 1.5 * quarter_x_font, center_y );
232 0 : cairo_line_to ( cr, center_x + 0.3 * quarter_x_font, center_y );
233 0 : cairo_move_to ( cr, center_x + 0.3 * quarter_x_font, center_y - 2.0 * quarter_y_font );
234 0 : cairo_line_to ( cr, center_x + 0.3 * quarter_x_font, center_y + 2.0 * quarter_y_font );
235 0 : cairo_stroke (cr);
236 0 : cairo_move_to ( cr, center_x + 1.5 * quarter_x_font, center_y - 2.0 * quarter_y_font );
237 0 : cairo_line_to ( cr, center_x + 1.5 * quarter_x_font, center_y );
238 0 : cairo_move_to ( cr, center_x + 0.8 * quarter_x_font, center_y - 1.6 * quarter_y_font );
239 0 : cairo_line_to ( cr, center_x + 2.2 * quarter_x_font, center_y - 0.4 * quarter_y_font );
240 0 : cairo_move_to ( cr, center_x + 2.2 * quarter_x_font, center_y - 1.6 * quarter_y_font );
241 0 : cairo_line_to ( cr, center_x + 0.8 * quarter_x_font, center_y - 0.4 * quarter_y_font );
242 0 : cairo_stroke (cr);
243 : }
244 :
245 0 : U8_TRACE_END();
246 0 : }
247 :
248 0 : void draw_classifier_icon_draw_time ( const draw_classifier_icon_t *this_,
249 : geometry_rectangle_t bounds,
250 : cairo_t *cr )
251 : {
252 0 : U8_TRACE_BEGIN();
253 0 : assert( NULL != cr );
254 :
255 : /* determine linewith to avoid that drawings overlap to the outside of bounds */
256 : {
257 0 : const double ln_w = cairo_get_line_width( cr );
258 0 : geometry_rectangle_enlarge( &bounds, -ln_w, -ln_w );
259 0 : geometry_rectangle_shift( &bounds, ln_w/2.0, ln_w/2.0 );
260 : }
261 :
262 0 : const double top = geometry_rectangle_get_top( &bounds );
263 0 : const double bottom = geometry_rectangle_get_bottom( &bounds );
264 0 : const double left = geometry_rectangle_get_left( &bounds );
265 0 : const double right = geometry_rectangle_get_right( &bounds );
266 :
267 0 : cairo_move_to ( cr, right, bottom );
268 0 : cairo_line_to ( cr, left, top );
269 0 : cairo_line_to ( cr, right, top );
270 0 : cairo_line_to ( cr, left, bottom );
271 0 : cairo_line_to ( cr, right, bottom );
272 0 : cairo_stroke (cr);
273 :
274 0 : U8_TRACE_END();
275 0 : }
276 :
277 0 : void draw_classifier_icon_draw_sync ( const draw_classifier_icon_t *this_,
278 : geometry_rectangle_t bounds,
279 : cairo_t *cr )
280 : {
281 0 : U8_TRACE_BEGIN();
282 0 : assert( NULL != cr );
283 :
284 : /* when filling rectangles, no line overlaps the bounds due to its line width */
285 :
286 0 : const double left = geometry_rectangle_get_left( &bounds );
287 0 : const double top = geometry_rectangle_get_top( &bounds );
288 0 : const double width = geometry_rectangle_get_width( &bounds );
289 0 : const double height = geometry_rectangle_get_height( &bounds );
290 :
291 0 : cairo_rectangle ( cr, left, top, width, height );
292 0 : cairo_fill (cr);
293 :
294 0 : U8_TRACE_END();
295 0 : }
296 :
297 :
298 : /*
299 : Copyright 2016-2024 Andreas Warnke
300 : http://www.apache.org/licenses/LICENSE-2.0
301 :
302 : Licensed under the Apache License, Version 2.0 (the "License");
303 : you may not use this file except in compliance with the License.
304 : You may obtain a copy of the License at
305 :
306 :
307 : Unless required by applicable law or agreed to in writing, software
308 : distributed under the License is distributed on an "AS IS" BASIS,
309 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
310 : See the License for the specific language governing permissions and
311 : limitations under the License.
312 : */
|