GCC Code Coverage Report


Directory: src/gate/
File: src/gate/ui/graphics_motif.c
Date: 2026-09-21 06:26:40
Exec Total Coverage
Lines: 300 405 74.1%
Functions: 28 44 63.6%
Branches: 73 145 50.3%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright (c) 2018-2026, Stefan Meislinger <sm@opengate.at> |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #include "gate/ui/graphics.h"
30 #include "gate/results.h"
31
32 #if defined(GATE_UI_MOTIF)
33
34 #include "gate/debugging.h"
35 #include "gate/ui/gateui_motif.h"
36 #include <X11/Xlib.h>
37 #include <X11/cursorfont.h>
38 #include <Xm/Xm.h>
39
40 945 static unsigned long XGetRgbPixel(Display* display, gate_uint8_t r, gate_uint8_t g, gate_uint8_t b)
41 {
42 945 int screen = XDefaultScreen(display);
43 945 Colormap cmap = XDefaultColormap(display, screen);
44 XColor col;
45 945 col.pixel = 0;
46 945 col.red = ((gate_uint16_t)r) << 8;
47 945 col.green = ((gate_uint16_t)g) << 8;
48 945 col.blue = ((gate_uint16_t)b) << 8;
49 945 col.flags = DoRed | DoGreen | DoBlue;
50 945 XAllocColor(display, cmap, &col);
51 945 return col.pixel;
52 }
53
54 2 gate_result_t gate_ui_graphics_create_virtual(gate_ui_graphics_t* graph, gate_ui_host_t* host, gate_uint32_t width, gate_uint32_t height)
55 {
56 2 return gate_ui_graphics_create_image(graph, host, width, height, 0);
57 }
58
59 9 gate_result_t gate_ui_graphics_create_image(gate_ui_graphics_t* graph, gate_ui_host_t* host, gate_uint32_t width, gate_uint32_t height, gate_uint32_t depth)
60 {
61 9 gate_result_t ret = GATE_RESULT_FAILED;
62
63 do
64 {
65 9 Display* const display = GATE_UI_MOTIF_GET_HOST_DISPLAY(host);
66 9 int const screen = XDefaultScreen(display);;
67
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2 times.
9 int const xdepth = (depth == 0) ? XDefaultDepth(display, screen) : depth;
68 9 Window const root_window = XDefaultRootWindow(display);
69 9 Pixmap const pixmap = XCreatePixmap(display, root_window, width, height, xdepth);
70 9 GC context = XCreateGC(display, root_window, 0, 0);
71 9 unsigned long pixel = XGetRgbPixel(display, 0, 0, 0);
72
73 9 XSetForeground(display, context, pixel);
74 9 XFillRectangle(display, pixmap, context, 0, 0, width, height);
75
76 9 gate_mem_clear(graph, sizeof(gate_ui_graphics_t));
77 9 graph->host = host;
78 9 graph->resources[0] = (void*)context;
79 9 graph->resources[1] = (void*)(Drawable)pixmap;
80 9 graph->width = width;
81 9 graph->height = height;
82
83 9 XSetGraphicsExposures(display, context, 0);
84 9 ret = GATE_RESULT_OK;
85 } while (0);
86 9 return ret;
87 }
88
89 4 gate_result_t gate_ui_graphics_create_image_from(gate_ui_graphics_t* graph, gate_ui_host_t* host, gate_rasterimage_t const* rasterimage)
90 {
91 gate_result_t ret;
92 do
93 {
94 4 ret = gate_ui_graphics_create_image(graph, host, rasterimage->width, rasterimage->height, 0);
95
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_BREAK_IF_FAILED(ret);
96
97 4 ret = gate_ui_graphics_draw_image(graph, rasterimage, NULL, NULL, NULL);
98
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (GATE_FAILED(ret))
99 {
100 gate_ui_graphics_destroy(graph);
101 break;
102 }
103
104 4 ret = GATE_RESULT_OK;
105 } while (0);
106
107 4 return ret;
108 }
109
110 4 gate_result_t gate_ui_graphics_create_ctrl(gate_ui_graphics_t* graph, gate_ui_ctrl_t* ctrl)
111 {
112 4 gate_result_t ret = GATE_RESULT_FAILED;
113 do
114 {
115 4 gate_ui_host_t* host = GATE_UI_MOTIF_GET_CTRL_HOST(ctrl);
116 4 Display* display = GATE_UI_MOTIF_GET_HOST_DISPLAY(host);
117 4 Widget w = GATE_UI_MOTIF_GET_CTRL_WIDGET(ctrl);
118 4 Window wnd = XtWindow(w);
119 4 Dimension xwidth = 0, xheight = 0;
120 4 GC context = XCreateGC(display, wnd, 0, NULL);
121
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!context)
122 {
123 ret = GATE_RESULT_OUTOFRESOURCES;
124 break;
125 }
126 4 XtVaGetValues(w, XtNwidth, &xwidth, XtNheight, &xheight, NULL, NULL);
127
128 4 graph->host = host;
129 4 graph->resources[0] = (void*)context;
130 4 graph->resources[1] = (void*)(Drawable)wnd;
131 4 graph->resources[2] = (void*)wnd;
132 4 graph->width = xwidth;
133 4 graph->height = xheight;
134
135 4 XSetGraphicsExposures(display, context, 0);
136 4 ret = GATE_RESULT_OK;
137 } while (0);
138 4 return ret;
139 }
140
141 gate_result_t gate_ui_graphics_create_native(gate_ui_graphics_t* graph, gate_ui_host_t* host, void* graphics, void* param, gate_int32_t width, gate_int32_t height)
142 {
143 return GATE_RESULT_NOTIMPLEMENTED;
144 }
145
146 13 gate_result_t gate_ui_graphics_destroy(gate_ui_graphics_t* graph)
147 {
148 13 Display* display = GATE_UI_MOTIF_GET_HOST_DISPLAY(graph->host);
149 13 GC context = (GC)graph->resources[0];
150 13 Drawable drawable = (Drawable)graph->resources[1];
151 13 Window window = (Window)graph->resources[2];
152
153
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 if (display)
154 {
155
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 4 times.
13 if (window == 0)
156 {
157 /* no window, expect a Pixmap surface */
158
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
9 if (drawable != 0)
159 {
160 6 XFreePixmap(display, (Pixmap)drawable);
161 }
162 }
163 else
164 {
165 }
166
167
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 if (context)
168 {
169 13 XFreeGC(display, context);
170 }
171 }
172
173 13 return GATE_RESULT_NOTIMPLEMENTED;
174 }
175
176 2 gate_int32_t gate_ui_graphics_width(gate_ui_graphics_t* graph)
177 {
178 2 return graph->width;
179 }
180
181 2 gate_int32_t gate_ui_graphics_height(gate_ui_graphics_t* graph)
182 {
183 2 return graph->height;
184 }
185
186 2 gate_result_t gate_ui_graphics_set_pixel(gate_ui_graphics_t* graph, gate_ui_point_t pos, gate_ui_color_t col)
187 {
188 2 Display* const display = GATE_UI_MOTIF_GET_HOST_DISPLAY(graph->host);
189 2 GC const context = (GC)graph->resources[0];
190 2 Drawable const drawable = (Drawable)graph->resources[1];
191
192 2 XSetForeground(display, context, XGetRgbPixel(display, col.r, col.g, col.b));
193 2 XDrawPoint(display, drawable, context, pos.x, pos.y);
194 2 return GATE_RESULT_OK;
195 }
196
197 2 gate_result_t gate_ui_graphics_get_pixel(gate_ui_graphics_t* graph, gate_ui_point_t pos, gate_ui_color_t* col)
198 {
199 2 return GATE_RESULT_NOTIMPLEMENTED;
200 }
201
202 2 gate_result_t gate_ui_graphics_draw(gate_ui_graphics_t* graph, gate_ui_graphics_t* srcgraph,
203 gate_ui_point_t const* dst, gate_ui_size_t const* size, gate_ui_point_t const* srcpos)
204 {
205 2 Display* const display = GATE_UI_MOTIF_GET_HOST_DISPLAY(graph->host);
206 2 GC const context = (GC)graph->resources[0];
207 2 Drawable const target = (Drawable)graph->resources[1];
208 2 Drawable const source = (Drawable)srcgraph->resources[1];
209 int src_x, src_y, width, height, dst_x, dst_y;
210 2 dst_x = dst->x;
211 2 dst_y = dst->y;
212 2 src_x = srcpos->x;
213 2 src_y = srcpos->y;
214 2 width = size->width;
215 2 height = size->height;
216
217 2 XCopyArea(display, source, target, context, src_x, src_y, width, height, dst_x, dst_y);
218 2 return GATE_RESULT_OK;
219 }
220
221 2 gate_result_t gate_ui_graphics_draw_ex(gate_ui_graphics_t* graph, gate_ui_graphics_t* src_graph,
222 gate_ui_position_t const* dest_rect, gate_ui_position_t const* src_rect)
223 {
224 2 Display* const display = GATE_UI_MOTIF_GET_HOST_DISPLAY(graph->host);
225 2 GC const context = (GC)graph->resources[0];
226 2 Drawable const target = (Drawable)graph->resources[1];
227 2 Drawable const source = (Drawable)src_graph->resources[1];
228 int src_x, src_y, width, height, dst_x, dst_y;
229 2 dst_x = dest_rect->pos.x;
230 2 dst_y = dest_rect->pos.y;
231 2 src_x = src_rect->pos.x;
232 2 src_y = src_rect->pos.y;
233 /* TODO */
234 2 width = dest_rect->size.width;
235 2 height = dest_rect->size.height;
236
237 2 XCopyArea(display, source, target, context, src_x, src_y, width, height, dst_x, dst_y);
238 2 return GATE_RESULT_OK;
239 }
240
241 7 gate_result_t gate_ui_graphics_draw_image(gate_ui_graphics_t* graph, gate_rasterimage_t const* srcimage,
242 gate_ui_point_t const* dst, gate_ui_size_t const* size, gate_ui_point_t const* srcpos)
243 {
244 7 Display* const display = GATE_UI_MOTIF_GET_HOST_DISPLAY(graph->host);
245 7 GC const context = (GC)graph->resources[0];
246 7 Drawable const drawable = (Drawable)graph->resources[1];
247
248 gate_color_t pixel;
249 7 gate_uint32_t pixel_cache = 0;
250 int src_x, src_y, width, height, dst_x, dst_y;
251 int x, y;
252
253
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (srcpos)
254 {
255 src_x = srcpos->x;
256 src_y = srcpos->y;
257 }
258 else
259 {
260 7 src_x = 0;
261 7 src_y = 0;
262 }
263
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (size)
264 {
265 width = size->width;
266 height = size->height;
267 }
268 else
269 {
270 7 width = srcimage->width;
271 7 height = srcimage->height;
272 }
273
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5 times.
7 if (dst)
274 {
275 2 dst_x = dst->x;
276 2 dst_y = dst->y;
277 }
278 else
279 {
280 5 dst_x = 0;
281 5 dst_y = 0;
282 }
283
284
2/2
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 7 times.
119 for (y = 0; y != height; ++y)
285 {
286
2/2
✓ Branch 0 taken 1792 times.
✓ Branch 1 taken 112 times.
1904 for (x = 0; x != width; ++x)
287 {
288 1792 gate_rasterimage_get_pixel(srcimage, src_x + x, src_y + y, &pixel);
289
2/2
✓ Branch 0 taken 1303 times.
✓ Branch 1 taken 489 times.
1792 if (pixel.a > 127)
290 {
291
2/2
✓ Branch 0 taken 920 times.
✓ Branch 1 taken 383 times.
1303 if (pixel.bits != pixel_cache)
292 {
293 920 unsigned long x11_color = XGetRgbPixel(display, pixel.r, pixel.g, pixel.b);
294 920 pixel_cache = pixel.bits;
295 920 XSetForeground(display, context, x11_color);
296 }
297 1303 XDrawPoint(display, drawable, context, dst_x + x, dst_y + y);
298 }
299 }
300 }
301 7 return GATE_RESULT_OK;
302 }
303
304 4 gate_result_t gate_ui_graphics_line(gate_ui_graphics_t* graph, gate_ui_point_t from, gate_ui_point_t to, gate_ui_color_t col, gate_uint32_t linewidth)
305 {
306 4 Display* const display = GATE_UI_MOTIF_GET_HOST_DISPLAY(graph->host);
307 4 GC const context = (GC)graph->resources[0];
308 4 Drawable const drawable = (Drawable)graph->resources[1];
309
310 4 XSetForeground(display, context, XGetRgbPixel(display, col.r, col.g, col.b));
311 4 XDrawLine(display, drawable, context, from.x, from.y, to.x, to.y);
312 4 return GATE_RESULT_OK;
313 }
314
315 5 gate_result_t gate_ui_graphics_rect(gate_ui_graphics_t* graph, gate_ui_position_t rect, gate_ui_color_t const* colline, gate_uint32_t linewidth, gate_ui_color_t const* colfill)
316 {
317 5 Display* const display = GATE_UI_MOTIF_GET_HOST_DISPLAY(graph->host);
318 5 GC const context = (GC)graph->resources[0];
319 5 Drawable const drawable = (Drawable)graph->resources[1];
320 unsigned long pixel;
321
322
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 if (colfill)
323 {
324 3 pixel = XGetRgbPixel(display, colfill->r, colfill->g, colfill->b);
325 3 XSetForeground(display, context, pixel);
326 3 XFillRectangle(display, drawable, context, rect.pos.x, rect.pos.y, rect.size.width, rect.size.height);
327 }
328
329
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (colline)
330 {
331 5 pixel = XGetRgbPixel(display, colline->r, colline->g, colline->b);
332 5 XSetForeground(display, context, pixel);
333 5 XDrawRectangle(display, drawable, context, rect.pos.x, rect.pos.y, rect.size.width, rect.size.height);
334 }
335 5 return GATE_RESULT_OK;
336 }
337
338 2 gate_result_t gate_ui_graphics_polygon(gate_ui_graphics_t* graph, gate_ui_point_t const* points, gate_size_t pointcount, gate_ui_color_t const* colline, gate_uint32_t linewidth, gate_ui_color_t const* colfill)
339 {
340 2 Display* const display = GATE_UI_MOTIF_GET_HOST_DISPLAY(graph->host);
341 2 GC const context = (GC)graph->resources[0];
342 2 Drawable const drawable = (Drawable)graph->resources[1];
343 unsigned long pixel;
344 gate_size_t ndx;
345 XPoint xp[64];
346
347
2/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
2 if ((pointcount < 3) || ((colline == NULL) && (colfill == NULL)))
348 {
349 /* nothing to do */
350 return GATE_RESULT_OK;
351 }
352
353
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pointcount > 64)
354 {
355 pointcount = 64;
356 }
357
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
12 for (ndx = 0; ndx != pointcount; ++ndx)
358 {
359 10 xp[ndx].x = points[ndx].x;
360 10 xp[ndx].y = points[ndx].y;
361 }
362
363
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (colfill)
364 {
365 pixel = XGetRgbPixel(display, colfill->r, colfill->g, colfill->b);
366 XSetForeground(display, context, pixel);
367 XFillPolygon(display, drawable, context, xp, (int)pointcount, Complex, CoordModeOrigin);
368 }
369
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (colline)
370 {
371 2 pixel = XGetRgbPixel(display, colline->r, colline->g, colline->b);
372 2 XSetForeground(display, context, pixel);
373
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 for (ndx = 0; ndx != pointcount - 1; ++ndx)
374 {
375 8 XDrawLine(display, drawable, context, xp[ndx].x, xp[ndx].y, xp[ndx + 1].x, xp[ndx + 1].y);
376 }
377 2 XDrawLine(display, drawable, context, xp[pointcount - 1].x, xp[pointcount - 1].y, xp[0].x, xp[0].y);
378 }
379 2 return GATE_RESULT_OK;
380 }
381
382 static gate_bool_t find_best_font_name(Display* display, gate_ui_font_t* font)
383 {
384 gate_bool_t ret = false;
385 int max_fonts = 1024;
386 int fonts_returned = 0;
387 char** fonts = XListFonts(display, "*", max_fonts, &fonts_returned);
388
389 do
390 {
391 int ndx;
392 char const* pattern = font->font_name;
393 gate_size_t pattern_len = gate_str_length(font->font_name);
394
395 if (fonts == NULL)
396 {
397 break;
398 }
399 for (ndx = 0; ndx < fonts_returned; ++ndx)
400 {
401 char* font_name = fonts[ndx];
402 gate_size_t font_name_len = gate_str_length(font_name);
403 gate_size_t pos;
404 if(font_name_len == 0)
405 {
406 continue;
407 }
408 pos = gate_str_pos(font_name, font_name_len, pattern, pattern_len, 0);
409 if(pos != GATE_STR_NPOS)
410 {
411 gate_str_print_text(font->font_name, sizeof(font->font_name), font_name, font_name_len);
412 ret = true;
413 break;
414 }
415 }
416 /* code */
417 } while (0);
418
419 if(fonts != NULL)
420 {
421 XFreeFontNames(fonts);
422 }
423
424 return ret;
425 }
426
427 2 gate_result_t gate_ui_graphics_get_char_size(gate_ui_graphics_t* graph, gate_ui_font_t const* font, gate_char32_t const* chars, gate_size_t charcount, gate_int32_t* charlens)
428 {
429 2 Display* const display = GATE_UI_MOTIF_GET_HOST_DISPLAY(graph->host);
430 2 GC const context = (GC)graph->resources[0];
431 2 Drawable const drawable = (Drawable)graph->resources[1];
432
433 XFontStruct* fontstruct;
434 size_t ndx;
435
436 2 fontstruct = XLoadQueryFont(display, "fixed");
437
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for(ndx = 0; ndx < charcount; ++ndx)
438 {
439 char c[8];
440 2 gate_size_t len = gate_char_write_utf8(chars[ndx], &c[0], sizeof(c) - 1);
441 2 c[len] = 0;
442 2 charlens[ndx] = XTextWidth(fontstruct, c, (int)len);
443 }
444 2 XFreeFont(display, fontstruct);
445 2 return GATE_RESULT_OK;
446 }
447
448
449
450 static void print_font_name(char* name_buffer, gate_size_t name_capacity, gate_ui_font_t const* font)
451 {
452 gate_strbuilder_t builder;
453
454 gate_strbuilder_create_static(&builder, name_buffer, name_capacity, 0);
455 gate_strbuilder_append_cstr(&builder, "-");
456 gate_strbuilder_append_cstr(&builder, font->font_name);
457 gate_strbuilder_append_cstr(&builder, font->bold ? "-bold" : "-medium");
458 gate_strbuilder_append_cstr(&builder, font->italic ? "-i" : "-r");
459 gate_strbuilder_append_cstr(&builder, "-*-");
460 gate_strbuilder_append_int32(&builder, font->size);
461 gate_strbuilder_append_cstr(&builder, "-*");
462 }
463
464 2 gate_result_t gate_ui_graphics_get_text_size(gate_ui_graphics_t* graph, gate_ui_font_t const* font, gate_string_t const* txt, gate_int32_t* width, gate_int32_t* height)
465 {
466 2 Display* const display = GATE_UI_MOTIF_GET_HOST_DISPLAY(graph->host);
467 2 GC const context = (GC)graph->resources[0];
468 2 Drawable const drawable = (Drawable)graph->resources[1];
469
470 XFontStruct* fontstruct;
471
472 2 fontstruct = XLoadQueryFont(display, "fixed");
473
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (width) *width = XTextWidth(fontstruct, gate_string_ptr(txt, 0), (int)gate_string_length(txt));
474
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (height) *height = fontstruct->ascent + fontstruct->descent;
475 2 XFreeFont(display, fontstruct);
476 2 return GATE_RESULT_OK;
477 }
478
479 2 gate_result_t gate_ui_graphics_print(gate_ui_graphics_t* graph, gate_ui_font_t const* font, gate_string_t const* text, gate_ui_position_t const* pos)
480 {
481 2 Display* const display = GATE_UI_MOTIF_GET_HOST_DISPLAY(graph->host);
482 2 GC const context = (GC)graph->resources[0];
483 2 Drawable const drawable = (Drawable)graph->resources[1];
484 gate_ui_font_t updated_font;
485
486 XFontStruct* fontstruct;
487
488 2 fontstruct = XLoadQueryFont(display, "fixed");
489
490 2 XSetFont(display, context, fontstruct->fid);
491 2 XDrawString(display, drawable, context, pos->pos.x, pos->pos.y + fontstruct->ascent, text->str, text->length);
492
493 2 XFreeFont(display, fontstruct);
494 2 return GATE_RESULT_OK;
495 }
496
497 void* gate_ui_graphics_handle(gate_ui_graphics_t* graph)
498 {
499 return graph->resources[0];
500 }
501 1 void* gate_ui_graphics_surface(gate_ui_graphics_t* graph)
502 {
503 1 return graph->resources[1];
504 }
505
506
507
508
509 gate_result_t gate_ui_icon_create_stock(gate_ui_icon_t* icon, gate_ui_host_t* host, gate_uint32_t stock_id, gate_uint32_t flags)
510 {
511 return GATE_RESULT_NOTIMPLEMENTED;
512 }
513 gate_result_t gate_ui_icon_create_native(gate_ui_icon_t* icon, gate_ui_host_t* host, void* handle, gate_uint32_t flags)
514 {
515 return GATE_RESULT_NOTIMPLEMENTED;
516 }
517 gate_result_t gate_ui_icon_create_image(gate_ui_icon_t* icon, gate_ui_host_t* host, gate_rasterimage_t const* image)
518 {
519 return GATE_RESULT_NOTIMPLEMENTED;
520 }
521 gate_result_t gate_ui_icon_create_file(gate_ui_icon_t* icon, gate_ui_host_t* host, gate_string_t const* filepath)
522 {
523 return GATE_RESULT_NOTIMPLEMENTED;
524 }
525 gate_result_t gate_ui_icon_copy(gate_ui_icon_t* dsticon, gate_ui_icon_t const* srcicon)
526 {
527 return GATE_RESULT_NOTIMPLEMENTED;
528 }
529 gate_result_t gate_ui_icon_destroy(gate_ui_icon_t* icon)
530 {
531 return GATE_RESULT_NOTIMPLEMENTED;
532 }
533
534
535
536 /**
537 * A motif ICON list is an array of Pixmap instances.
538 * Each ICON entry is represented by two Pixmaps, the first is the mask pixmap,
539 * the second one holds the icon pixels
540 *
541 */
542
543 3 gate_result_t gate_ui_iconlist_create(gate_ui_iconlist_t* ilst, gate_ui_host_t* host, gate_int32_t width, gate_int32_t height)
544 {
545 gate_arraylist_t pixmap_list;
546
547
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_DEBUG_ASSERT(ilst !=NULL);
548
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_DEBUG_ASSERT(host != NULL);
549
550 3 gate_mem_clear(ilst, sizeof(gate_ui_iconlist_t));
551 3 ilst->host = host;
552 3 ilst->flags = 0;
553 3 ilst->width = width;
554 3 ilst->height = height;
555 3 ilst->resources[0] = NULL;
556 3 return GATE_RESULT_OK;
557 }
558
559 1 gate_result_t gate_ui_iconlist_destroy(gate_ui_iconlist_t* ilst)
560 {
561 gate_arraylist_t pixmap_list;
562
563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_ASSERT(ilst != NULL);
564
565 1 pixmap_list = (gate_arraylist_t)ilst->resources[0];
566
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (pixmap_list != NULL)
567 {
568 1 Display* display = GATE_UI_MOTIF_GET_HOST_DISPLAY(ilst->host);
569 gate_size_t ndx;
570 1 gate_size_t cnt = gate_arraylist_length(pixmap_list);
571
572
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 for(ndx = 0; ndx != cnt; ++ndx)
573 {
574 2 Pixmap* ptr_pixmap = gate_arraylist_get(pixmap_list, ndx);
575
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if(ptr_pixmap != NULL)
576 {
577 2 XFreePixmap(display, (Pixmap)*ptr_pixmap);
578 }
579 }
580 1 gate_arraylist_release(pixmap_list);
581 1 ilst->resources[0] = NULL;
582 }
583 1 return GATE_RESULT_OK;
584 }
585 gate_size_t gate_ui_iconlist_count(gate_ui_iconlist_t* ilst)
586 {
587 gate_size_t ret = 0;
588 gate_arraylist_t pixmap_list;
589
590 GATE_DEBUG_ASSERT(ilst != NULL);
591
592 pixmap_list = (gate_arraylist_t)ilst->resources[0];
593 if (pixmap_list != NULL)
594 {
595 gate_size_t const cnt = gate_arraylist_length(pixmap_list);
596 ret = cnt / 2;
597 }
598 return ret;
599 }
600
601 2 static Pixmap create_mask_pixmap(gate_ui_host_t* host, gate_rasterimage_t const* image)
602 {
603 2 Display* dpy = GATE_UI_MOTIF_GET_HOST_DISPLAY(host);
604 2 Window win = XDefaultRootWindow(dpy);
605 Pixmap pm;
606 GC gc;
607 gate_color_t col;
608 unsigned int x, y, width, height;
609
610 2 width = gate_rasterimage_width(image);
611 2 height = gate_rasterimage_height(image);
612
613 2 pm = XCreatePixmap(dpy, win, image->width, image->height, 1);
614 2 gc = XCreateGC(dpy, pm, 0, NULL);
615 2 XSetForeground(dpy, gc, 0);
616 2 XFillRectangle(dpy, pm, gc, 0, 0, width, height);
617 2 XSetForeground(dpy, gc, 1);
618
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 2 times.
34 for (y = 0; y != height; ++y)
619 {
620
2/2
✓ Branch 0 taken 512 times.
✓ Branch 1 taken 32 times.
544 for (x = 0; x != width; ++x)
621 {
622 512 gate_rasterimage_get_pixel(image, x, y, &col);
623
2/2
✓ Branch 0 taken 338 times.
✓ Branch 1 taken 174 times.
512 if (col.a > 127)
624 {
625 338 XDrawPoint(dpy, pm, gc, x, y);
626 }
627 }
628 }
629 2 XFreeGC(dpy, gc);
630 2 return pm;
631 }
632
633 gate_result_t gate_ui_iconlist_add_icon(gate_ui_iconlist_t* ilst, gate_ui_icon_t const* icon, gate_intptr_t* icon_key)
634 {
635 /* TODO */
636 return GATE_RESULT_NOTIMPLEMENTED;
637 }
638
639 2 gate_result_t gate_ui_iconlist_add_image(gate_ui_iconlist_t* ilst, gate_rasterimage_t const* image, gate_intptr_t* icon_key)
640 {
641 gate_result_t ret;
642
643
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_DEBUG_ASSERT(ilst != NULL);
644
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_DEBUG_ASSERT(image != NULL);
645
646 do
647 {
648 gate_ui_graphics_t graph;
649 Pixmap pm;
650 gate_size_t len;
651 2 gate_arraylist_t pixmap_list = ilst->resources[0];
652
653
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (pixmap_list == NULL)
654 {
655 2 pixmap_list = gate_arraylist_create(sizeof(Pixmap), NULL, 16, NULL, NULL);
656
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (NULL == pixmap_list)
657 {
658 GATE_DEBUG_TRACE("Failed to allocate pixmap array");
659 ret = GATE_RESULT_OUTOFMEMORY;
660 break;
661 }
662 2 ilst->resources[0] = (void*)pixmap_list;
663 }
664
665 2 pm = create_mask_pixmap(ilst->host, image);
666
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (NULL == gate_arraylist_add(pixmap_list, &pm))
667 {
668 ret = GATE_RESULT_OUTOFMEMORY;
669 break;
670 }
671
672 2 ret = gate_ui_graphics_create_image_from(&graph, ilst->host, image);
673
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
674
675 2 pm = (Pixmap)graph.resources[1];
676 2 graph.resources[1] = 0;
677 2 gate_ui_graphics_destroy(&graph);
678
679 2 gate_arraylist_add(pixmap_list, &pm);
680 2 len = gate_arraylist_length(pixmap_list);
681
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (icon_key)
682 {
683 2 *icon_key = (gate_intptr_t)len;
684 }
685 2 ret = GATE_RESULT_OK;
686 } while (0);
687 2 return ret;
688 }
689 gate_result_t gate_ui_iconlist_get_icon(gate_ui_iconlist_t* ilst, gate_intptr_t icon_key, gate_ui_icon_t* icon)
690 {
691 /* TODO */
692 return GATE_RESULT_NOTIMPLEMENTED;
693 }
694 13 void* gate_ui_iconlist_get_handle(gate_ui_iconlist_t* ilst, gate_intptr_t icon_key)
695 {
696 13 void* ret = NULL;
697
698
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 GATE_DEBUG_ASSERT(ilst != NULL);
699 do
700 {
701 gate_arraylist_t pixmap_list;
702 gate_size_t cnt;
703 13 gate_size_t ndx = (gate_size_t)icon_key;
704
705
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if(ilst->resources[0] == NULL) break;
706
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if(ndx < 2) break;
707 13 ndx -= 2; /* key == length after add, we need to go two steps back to point to the first pixmap */
708
709 13 pixmap_list = ilst->resources[0];
710 13 cnt = gate_arraylist_length(pixmap_list);
711
712 13 ret = gate_arraylist_get(pixmap_list, ndx);
713 /* ret == Pixmap* to mask pixmap */
714 } while (0);
715
716 13 return ret;
717 }
718
719
720
721
722
723 3 gate_result_t gate_ui_cursor_create_stock(gate_ui_cursor_t* cursor, gate_ui_host_t* host, gate_enumint_t stock_id)
724 {
725 3 Display* const dp = GATE_UI_MOTIF_GET_HOST_DISPLAY(host);
726 Cursor cur;
727 unsigned int shape;
728
1/11
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
3 switch(stock_id)
729 {
730 default:
731 case GATE_UI_CURSOR_STOCK_POINTER: shape = XC_arrow; break;
732 3 case GATE_UI_CURSOR_STOCK_BUSY: shape = XC_watch; break;
733 case GATE_UI_CURSOR_STOCK_STARTING: shape = XC_shuttle; break;
734 case GATE_UI_CURSOR_STOCK_HAND: shape = XC_hand1; break;
735 case GATE_UI_CURSOR_STOCK_TEXT: shape = XC_xterm; break;
736 case GATE_UI_CURSOR_STOCK_REJECTED: shape = XC_pirate; break;
737 case GATE_UI_CURSOR_STOCK_SIZE_ALL: shape = XC_fleur; break;
738 case GATE_UI_CURSOR_STOCK_SIZE_LEFTRIGHT: shape = XC_sb_h_double_arrow; break;
739 case GATE_UI_CURSOR_STOCK_SIZE_UPDOWN: shape = XC_sb_v_double_arrow; break;
740 case GATE_UI_CURSOR_STOCK_SIZE_LEFTUPRIGHTDOWN: shape = XC_bottom_left_corner; break;
741 case GATE_UI_CURSOR_STOCK_SIZE_RIGHTUPKEFTDOWN: shape = XC_bottom_right_corner; break;
742 }
743 3 gate_mem_clear(cursor, sizeof(gate_ui_cursor_t));
744 3 cur = XCreateFontCursor(dp, shape);
745 3 cursor->resources[0] = (void*)(gate_uintptr_t)cur;
746 3 cursor->resources[1] = (void*)(gate_uintptr_t)stock_id;
747 3 cursor->host = host;
748 3 cursor->flags = GATE_UI_CURSOR_FLAG_STOCK;
749 3 return GATE_RESULT_OK;
750 }
751 gate_result_t gate_ui_cursor_create_native(gate_ui_cursor_t* cursor, gate_ui_host_t* host, void* handle, gate_enumint_t flags)
752 {
753 GATE_DEBUG_ASSERT(cursor != NULL);
754 GATE_DEBUG_ASSERT(host != NULL);
755 gate_mem_clear(cursor, sizeof(gate_ui_cursor_t));
756 cursor->host = host;
757 cursor->flags = GATE_UI_CURSOR_FLAG_UNMANAGED;
758 cursor->resources[0] = handle;
759 return GATE_RESULT_OK;
760 }
761 gate_result_t gate_ui_cursor_create_image(gate_ui_cursor_t* cursor, gate_ui_host_t* host, gate_rasterimage_t const* image,
762 gate_uint16_t x, gate_uint16_t y)
763 {
764 return GATE_RESULT_NOTIMPLEMENTED;
765 }
766 gate_result_t gate_ui_cursor_create_file(gate_ui_cursor_t* cursor, gate_ui_host_t* host, gate_string_t const* filepath)
767 {
768 return GATE_RESULT_NOTIMPLEMENTED;
769 }
770 2 gate_result_t gate_ui_cursor_copy(gate_ui_cursor_t* dstcursor, gate_ui_cursor_t const* srccursor)
771 {
772
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_DEBUG_ASSERT(dstcursor != NULL);
773
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_DEBUG_ASSERT(srccursor != NULL);
774
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (GATE_FLAG_ENABLED(srccursor->flags, GATE_UI_CURSOR_FLAG_STOCK))
775 {
776 2 return gate_ui_cursor_create_stock(dstcursor, srccursor->host, (gate_enumint_t)(gate_uintptr_t)srccursor->resources[1]);
777 }
778 else if (GATE_FLAG_ENABLED(srccursor->flags, GATE_UI_CURSOR_FLAG_UNMANAGED))
779 {
780 gate_mem_copy(dstcursor, srccursor, sizeof(gate_ui_cursor_t));
781 return GATE_RESULT_OK;
782 }
783 else
784 {
785 /* TODO */
786 }
787 return GATE_RESULT_NOTIMPLEMENTED;
788 }
789 3 gate_result_t gate_ui_cursor_destroy(gate_ui_cursor_t* cursor)
790 {
791
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (cursor != NULL)
792 {
793
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 Display* const dp = (cursor->host != NULL) ? GATE_UI_MOTIF_GET_HOST_DISPLAY(cursor->host) : NULL;
794
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (dp != NULL)
795 {
796 2 Cursor const cur = (Cursor)cursor->resources[0];
797
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 if (cur && !GATE_FLAG_ENABLED(cursor->flags, GATE_UI_CURSOR_FLAG_UNMANAGED))
798 {
799 2 XFreeCursor(dp, cur);
800 }
801 }
802 3 gate_mem_clear(cursor, sizeof(gate_ui_cursor_t));
803 }
804 3 return GATE_RESULT_OK;
805 }
806
807 #endif /* GATE_UI_MOTIF */
808