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 "pencil_layout_data.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 : #ifdef PENCIL_LAYOUT_DATA_DRAW_FOR_DEBUG
63 : /* draw the rectangle */
64 : {
65 0 : cairo_set_source_rgba( cr, 1.0, 0.5, 0.6, 0.5 );
66 0 : cairo_rectangle ( cr,
67 : geometry_rectangle_get_left ( &bounds ),
68 : geometry_rectangle_get_top ( &bounds ),
69 : geometry_rectangle_get_width ( &bounds ),
70 : geometry_rectangle_get_height ( &bounds )
71 : );
72 0 : cairo_stroke (cr);
73 0 : cairo_set_source_rgba( cr, 0.0, 0.0, 0.0, 1.0 );
74 : }
75 : #endif
76 :
77 0 : U8_TRACE_END();
78 0 : }
79 :
80 0 : void draw_classifier_icon_draw_artifact ( const draw_classifier_icon_t *this_,
81 : geometry_rectangle_t bounds,
82 : cairo_t *cr )
83 : {
84 0 : U8_TRACE_BEGIN();
85 0 : assert( NULL != cr );
86 :
87 : /* determine linewith to avoid that drawings overlap to the outside of bounds */
88 : {
89 0 : const double ln_w = cairo_get_line_width( cr );
90 0 : geometry_rectangle_enlarge( &bounds, -ln_w, -ln_w );
91 0 : geometry_rectangle_shift( &bounds, ln_w/2.0, ln_w/2.0 );
92 : }
93 :
94 : /* calculate artifact bounds */
95 0 : const double art_left = geometry_rectangle_get_left( &bounds );
96 0 : const double art_right = geometry_rectangle_get_right( &bounds );
97 0 : const double art_top = geometry_rectangle_get_top( &bounds );
98 0 : const double art_bottom = geometry_rectangle_get_bottom( &bounds );
99 0 : const double art_height = geometry_rectangle_get_height( &bounds );
100 : //const double art_width = geometry_rectangle_get_width( &bounds );
101 0 : const double art_corner_edge = art_height * 0.3;
102 :
103 : /* draw the icon */
104 0 : cairo_move_to ( cr, art_right, art_top + art_corner_edge );
105 0 : cairo_line_to ( cr, art_right - art_corner_edge, art_top + art_corner_edge );
106 0 : cairo_line_to ( cr, art_right - art_corner_edge, art_top );
107 0 : cairo_line_to ( cr, art_left, art_top );
108 0 : cairo_line_to ( cr, art_left, art_bottom );
109 0 : cairo_line_to ( cr, art_right, art_bottom );
110 0 : cairo_line_to ( cr, art_right, art_top + art_corner_edge );
111 0 : cairo_line_to ( cr, art_right - art_corner_edge, art_top );
112 0 : cairo_stroke (cr);
113 :
114 : #ifdef PENCIL_LAYOUT_DATA_DRAW_FOR_DEBUG
115 : /* draw the rectangle */
116 : {
117 0 : cairo_set_source_rgba( cr, 1.0, 0.5, 0.6, 0.5 );
118 0 : cairo_rectangle ( cr,
119 : geometry_rectangle_get_left ( &bounds ),
120 : geometry_rectangle_get_top ( &bounds ),
121 : geometry_rectangle_get_width ( &bounds ),
122 : geometry_rectangle_get_height ( &bounds )
123 : );
124 0 : cairo_stroke (cr);
125 0 : cairo_set_source_rgba( cr, 0.0, 0.0, 0.0, 1.0 );
126 : }
127 : #endif
128 :
129 0 : U8_TRACE_END();
130 0 : }
131 :
132 0 : void draw_classifier_icon_draw_actor ( const draw_classifier_icon_t *this_,
133 : geometry_rectangle_t bounds,
134 : cairo_t *cr )
135 : {
136 0 : U8_TRACE_BEGIN();
137 0 : assert( NULL != cr );
138 :
139 : /* determine linewith to avoid that drawings overlap to the outside of bounds */
140 : {
141 0 : const double ln_w = cairo_get_line_width( cr );
142 0 : geometry_rectangle_enlarge( &bounds, -ln_w, -ln_w );
143 0 : geometry_rectangle_shift( &bounds, ln_w/2.0, ln_w/2.0 );
144 : }
145 :
146 : /* calculate actor bounds */
147 0 : const double act_left = geometry_rectangle_get_left( &bounds );
148 0 : const double act_right = geometry_rectangle_get_right( &bounds );
149 0 : const double act_top = geometry_rectangle_get_top( &bounds );
150 0 : const double act_bottom = geometry_rectangle_get_bottom( &bounds );
151 0 : const double act_height = geometry_rectangle_get_height( &bounds );
152 0 : const double act_width = geometry_rectangle_get_width( &bounds );
153 :
154 : /* draw the icon */
155 0 : const double radius = act_width/2.0;
156 0 : const double ctrl_offset = radius * (1.0-BEZIER_CTRL_POINT_FOR_90_DEGREE_CIRCLE);
157 0 : const double head_bottom = act_top + act_height/3.0;
158 0 : const double leg_top = act_top + act_height*0.6;
159 0 : const double arm_top = act_top + act_height*0.45;
160 :
161 0 : cairo_move_to ( cr, act_left + radius, head_bottom );
162 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 */ );
163 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 */ );
164 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 */ );
165 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 */ );
166 0 : cairo_line_to ( cr, act_left + radius, leg_top );
167 0 : cairo_line_to ( cr, act_left, act_bottom );
168 0 : cairo_move_to ( cr, act_right, act_bottom );
169 0 : cairo_line_to ( cr, act_left + radius, leg_top );
170 0 : cairo_move_to ( cr, act_right, arm_top );
171 0 : cairo_line_to ( cr, act_left, arm_top );
172 0 : cairo_stroke (cr);
173 :
174 : #ifdef PENCIL_LAYOUT_DATA_DRAW_FOR_DEBUG
175 : /* draw the rectangle */
176 : {
177 0 : cairo_set_source_rgba( cr, 1.0, 0.5, 0.6, 0.5 );
178 0 : cairo_rectangle ( cr,
179 : geometry_rectangle_get_left ( &bounds ),
180 : geometry_rectangle_get_top ( &bounds ),
181 : geometry_rectangle_get_width ( &bounds ),
182 : geometry_rectangle_get_height ( &bounds )
183 : );
184 0 : cairo_stroke (cr);
185 0 : cairo_set_source_rgba( cr, 0.0, 0.0, 0.0, 1.0 );
186 : }
187 : #endif
188 :
189 0 : U8_TRACE_END();
190 0 : }
191 :
192 0 : void draw_classifier_icon_draw_circle ( const draw_classifier_icon_t *this_,
193 : geometry_rectangle_t bounds,
194 : const pencil_size_t *pencil_size,
195 : bool stroke,
196 : bool fill,
197 : bool shallow_history,
198 : bool deep_history,
199 : cairo_t *cr )
200 : {
201 0 : U8_TRACE_BEGIN();
202 0 : assert ( NULL != pencil_size );
203 0 : assert ( NULL != cr );
204 :
205 : /* determine linewith to avoid that drawings overlap to the outside of bounds */
206 : {
207 0 : const double ln_w = cairo_get_line_width( cr );
208 0 : geometry_rectangle_enlarge( &bounds, -ln_w, -ln_w );
209 0 : geometry_rectangle_shift( &bounds, ln_w/2.0, ln_w/2.0 );
210 : }
211 :
212 0 : const double circle_top = geometry_rectangle_get_top( &bounds );
213 0 : const double circle_bottom = geometry_rectangle_get_bottom( &bounds );
214 0 : const double center_x = geometry_rectangle_get_center_x( &bounds );
215 0 : const double center_y = geometry_rectangle_get_center_y( &bounds );
216 0 : const double circle_left = geometry_rectangle_get_left( &bounds );
217 0 : const double circle_right = geometry_rectangle_get_right( &bounds );
218 0 : const double circle_width = geometry_rectangle_get_width( &bounds );
219 0 : const double circle_height = geometry_rectangle_get_height( &bounds );
220 0 : const double circle_x_radius = center_x - circle_left;
221 0 : const double circle_y_radius = center_y - circle_top;
222 :
223 0 : const double gap = pencil_size_get_standard_object_border( pencil_size );
224 :
225 0 : if ( stroke )
226 : {
227 0 : const double ctrl_x_offset = circle_x_radius * (1.0-BEZIER_CTRL_POINT_FOR_90_DEGREE_CIRCLE);
228 0 : const double ctrl_y_offset = circle_y_radius * (1.0-BEZIER_CTRL_POINT_FOR_90_DEGREE_CIRCLE);
229 :
230 0 : cairo_move_to ( cr, center_x, circle_bottom );
231 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 */ );
232 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 */ );
233 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 */ );
234 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 */ );
235 0 : cairo_stroke (cr);
236 : }
237 :
238 0 : if ( fill )
239 : {
240 0 : const double circle2_x_radius = circle_x_radius - gap;
241 0 : const double circle2_y_radius = circle_y_radius - gap;
242 0 : const double circle2_top = circle_top + gap;
243 0 : const double circle2_bottom = circle_bottom - gap;
244 0 : const double circle2_left = circle_left + gap;
245 0 : const double circle2_right = circle_right - gap;
246 0 : const double ctrl2_x_offset = circle2_x_radius * (1.0-BEZIER_CTRL_POINT_FOR_90_DEGREE_CIRCLE);
247 0 : const double ctrl2_y_offset = circle2_y_radius * (1.0-BEZIER_CTRL_POINT_FOR_90_DEGREE_CIRCLE);
248 :
249 : /* draw a smaller filled circle */
250 0 : cairo_move_to ( cr, center_x, circle2_bottom );
251 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 */ );
252 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 */ );
253 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 */ );
254 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 */ );
255 0 : cairo_fill (cr);
256 : }
257 :
258 0 : if ( shallow_history )
259 : {
260 0 : const double quarter_x_font = 0.15 * circle_width;
261 0 : const double quarter_y_font = 0.15 * circle_height;
262 0 : cairo_move_to ( cr, center_x - quarter_x_font, center_y - 2.0 * quarter_y_font );
263 0 : cairo_line_to ( cr, center_x - quarter_x_font, center_y + 2.0 * quarter_y_font );
264 0 : cairo_move_to ( cr, center_x - quarter_x_font, center_y );
265 0 : cairo_line_to ( cr, center_x + quarter_x_font, center_y );
266 0 : cairo_move_to ( cr, center_x + quarter_x_font, center_y - 2.0 * quarter_y_font );
267 0 : cairo_line_to ( cr, center_x + quarter_x_font, center_y + 2.0 * quarter_y_font );
268 0 : cairo_stroke (cr);
269 : }
270 0 : else if ( deep_history )
271 : {
272 0 : const double quarter_x_font = 0.15 * circle_width;
273 0 : const double quarter_y_font = 0.15 * circle_height;
274 0 : cairo_move_to ( cr, center_x - 1.5 * quarter_x_font, center_y - 2.0 * quarter_y_font );
275 0 : cairo_line_to ( cr, center_x - 1.5 * quarter_x_font, center_y + 2.0 * quarter_y_font );
276 0 : cairo_move_to ( cr, center_x - 1.5 * quarter_x_font, center_y );
277 0 : cairo_line_to ( cr, center_x + 0.3 * quarter_x_font, center_y );
278 0 : cairo_move_to ( cr, center_x + 0.3 * quarter_x_font, center_y - 2.0 * quarter_y_font );
279 0 : cairo_line_to ( cr, center_x + 0.3 * quarter_x_font, center_y + 2.0 * quarter_y_font );
280 0 : cairo_stroke (cr);
281 0 : cairo_move_to ( cr, center_x + 1.5 * quarter_x_font, center_y - 2.0 * quarter_y_font );
282 0 : cairo_line_to ( cr, center_x + 1.5 * quarter_x_font, center_y );
283 0 : cairo_move_to ( cr, center_x + 0.8 * quarter_x_font, center_y - 1.6 * quarter_y_font );
284 0 : cairo_line_to ( cr, center_x + 2.2 * quarter_x_font, center_y - 0.4 * quarter_y_font );
285 0 : cairo_move_to ( cr, center_x + 2.2 * quarter_x_font, center_y - 1.6 * quarter_y_font );
286 0 : cairo_line_to ( cr, center_x + 0.8 * quarter_x_font, center_y - 0.4 * quarter_y_font );
287 0 : cairo_stroke (cr);
288 : }
289 :
290 : #ifdef PENCIL_LAYOUT_DATA_DRAW_FOR_DEBUG
291 : /* draw the rectangle */
292 : {
293 0 : cairo_set_source_rgba( cr, 1.0, 0.5, 0.6, 0.5 );
294 0 : cairo_rectangle ( cr,
295 : geometry_rectangle_get_left ( &bounds ),
296 : geometry_rectangle_get_top ( &bounds ),
297 : geometry_rectangle_get_width ( &bounds ),
298 : geometry_rectangle_get_height ( &bounds )
299 : );
300 0 : cairo_stroke (cr);
301 0 : cairo_set_source_rgba( cr, 0.0, 0.0, 0.0, 1.0 );
302 : }
303 : #endif
304 :
305 0 : U8_TRACE_END();
306 0 : }
307 :
308 0 : void draw_classifier_icon_draw_time ( const draw_classifier_icon_t *this_,
309 : geometry_rectangle_t bounds,
310 : cairo_t *cr )
311 : {
312 0 : U8_TRACE_BEGIN();
313 0 : assert( NULL != cr );
314 :
315 : /* determine linewith to avoid that drawings overlap to the outside of bounds */
316 : {
317 0 : const double ln_w = cairo_get_line_width( cr );
318 0 : geometry_rectangle_enlarge( &bounds, -ln_w, -ln_w );
319 0 : geometry_rectangle_shift( &bounds, ln_w/2.0, ln_w/2.0 );
320 : }
321 :
322 0 : const double top = geometry_rectangle_get_top( &bounds );
323 0 : const double bottom = geometry_rectangle_get_bottom( &bounds );
324 0 : const double left = geometry_rectangle_get_left( &bounds );
325 0 : const double right = geometry_rectangle_get_right( &bounds );
326 :
327 0 : cairo_move_to ( cr, right, bottom );
328 0 : cairo_line_to ( cr, left, top );
329 0 : cairo_line_to ( cr, right, top );
330 0 : cairo_line_to ( cr, left, bottom );
331 0 : cairo_line_to ( cr, right, bottom );
332 0 : cairo_stroke (cr);
333 :
334 : #ifdef PENCIL_LAYOUT_DATA_DRAW_FOR_DEBUG
335 : /* draw the rectangle */
336 : {
337 0 : cairo_set_source_rgba( cr, 1.0, 0.5, 0.6, 0.5 );
338 0 : cairo_rectangle ( cr,
339 : geometry_rectangle_get_left ( &bounds ),
340 : geometry_rectangle_get_top ( &bounds ),
341 : geometry_rectangle_get_width ( &bounds ),
342 : geometry_rectangle_get_height ( &bounds )
343 : );
344 0 : cairo_stroke (cr);
345 0 : cairo_set_source_rgba( cr, 0.0, 0.0, 0.0, 1.0 );
346 : }
347 : #endif
348 :
349 0 : U8_TRACE_END();
350 0 : }
351 :
352 0 : void draw_classifier_icon_draw_sync ( const draw_classifier_icon_t *this_,
353 : geometry_rectangle_t bounds,
354 : cairo_t *cr )
355 : {
356 0 : U8_TRACE_BEGIN();
357 0 : assert( NULL != cr );
358 :
359 : /* when filling rectangles, no line overlaps the bounds due to its line width */
360 :
361 0 : const double left = geometry_rectangle_get_left( &bounds );
362 0 : const double top = geometry_rectangle_get_top( &bounds );
363 0 : const double width = geometry_rectangle_get_width( &bounds );
364 0 : const double height = geometry_rectangle_get_height( &bounds );
365 :
366 0 : cairo_rectangle ( cr, left, top, width, height );
367 0 : cairo_fill (cr);
368 :
369 : #ifdef PENCIL_LAYOUT_DATA_DRAW_FOR_DEBUG
370 : /* draw the rectangle */
371 : {
372 0 : cairo_set_source_rgba( cr, 1.0, 0.5, 0.6, 0.5 );
373 0 : cairo_rectangle ( cr,
374 : geometry_rectangle_get_left ( &bounds ),
375 : geometry_rectangle_get_top ( &bounds ),
376 : geometry_rectangle_get_width ( &bounds ),
377 : geometry_rectangle_get_height ( &bounds )
378 : );
379 0 : cairo_stroke (cr);
380 0 : cairo_set_source_rgba( cr, 0.0, 0.0, 0.0, 1.0 );
381 : }
382 : #endif
383 :
384 0 : U8_TRACE_END();
385 0 : }
386 :
387 :
388 : /*
389 : Copyright 2016-2024 Andreas Warnke
390 : http://www.apache.org/licenses/LICENSE-2.0
391 :
392 : Licensed under the Apache License, Version 2.0 (the "License");
393 : you may not use this file except in compliance with the License.
394 : You may obtain a copy of the License at
395 :
396 :
397 : Unless required by applicable law or agreed to in writing, software
398 : distributed under the License is distributed on an "AS IS" BASIS,
399 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
400 : See the License for the specific language governing permissions and
401 : limitations under the License.
402 : */
|