GCC Code Coverage Report


Directory: src/gate/
File: src/gate/ui/graphics.c
Date: 2026-05-04 21:11:01
Exec Total Coverage
Lines: 260 354 73.4%
Functions: 24 44 54.5%
Branches: 57 110 51.8%

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_WINAPI)
33
34 #include "gate/ui/gateui_winapi.h"
35 #include "gate/platforms.h"
36 #include "gate/debugging.h"
37 #include <shellapi.h>
38
39 #if !defined(GATE_SYS_WIN16)
40 #include <commctrl.h>
41 #endif
42
43 #define GATE_UI_GRAPHICS_HDC(graph) ((HDC)(graph)->resources[0])
44 #define GATE_UI_GRAPHICS_BACKUP(graph) ((HBITMAP)(graph)->resources[1])
45 #define GATE_UI_GRAPHICS_WINDOW(graph) ((HWND)(graph)->resources[2])
46 #define GATE_UI_GRAPHICS_BYTEBUFFER(graph) ((void*)(graph)->resources[3])
47
48 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)
49 {
50 HWND desk = GetDesktopWindow();
51 HDC deskdc = GetDC(desk);
52 HDC dc;
53 HBITMAP bmp;
54 gate_mem_clear(graph, sizeof(gate_ui_graphics_t));
55 dc = CreateCompatibleDC(deskdc);
56 if (dc == NULL)
57 {
58 ReleaseDC(desk, deskdc);
59 return GATE_RESULT_FAILED;
60 }
61 bmp = CreateCompatibleBitmap(deskdc, (int)width, (int)height);
62 ReleaseDC(desk, deskdc);
63 if (bmp == NULL)
64 {
65 DeleteDC(dc);
66 return GATE_RESULT_OUTOFRESOURCES;
67 }
68 graph->host = host;
69 graph->width = width;
70 graph->height = height;
71 graph->resources[0] = dc;
72 graph->resources[1] = SelectObject(dc, (HGDIOBJ)bmp);
73 return GATE_RESULT_OK;
74 }
75
76 typedef struct gate_ui_bitmap_header_class
77 {
78 BITMAPINFO info;
79 RGBQUAD palette[256];
80 } gate_ui_bitmap_header_t;
81
82 static gate_size_t resolve_color_index(gate_uint8_t r, gate_uint8_t g, gate_uint8_t b)
83 {
84 const gate_size_t nr = ((gate_size_t)r + 26u) / 51u;
85 const gate_size_t ng = ((gate_size_t)g + 26u) / 51u;
86 const gate_size_t nb = ((gate_size_t)b + 26u) / 51u;
87
88 const gate_size_t ndx = nr * 36u + ng * 6u + nb;
89 return ndx;
90 }
91
92 static DWORD create_palette_8(RGBQUAD* ptr_quad)
93 {
94 unsigned short r, g, b;
95 for (r = 0; r < 6; ++r)
96 {
97 for (g = 0; g < 6; ++g)
98 {
99 for (b = 0; b < 6; ++b)
100 {
101 ptr_quad->rgbBlue = (unsigned char)(b * 51);
102 ptr_quad->rgbGreen = (unsigned char)(g * 51);
103 ptr_quad->rgbRed = (unsigned char)(r * 51);
104 ptr_quad->rgbReserved = 0;
105 ++ptr_quad;
106 }
107 }
108 }
109 return 216;
110 }
111
112 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)
113 {
114 gate_result_t ret;
115 HWND desk = GetDesktopWindow();
116 HDC deskdc = GetDC(desk);
117 HDC dc = NULL;
118 HBITMAP hbitmap;
119 HBITMAP hbackup;
120 gate_ui_bitmap_header_t bitmapinfo;
121 gate_uint8_t r;
122 gate_size_t linelen;
123 gate_size_t bufferlen;
124 void* buffer;
125 RGBQUAD* ptr_quad;
126
127 do
128 {
129 gate_mem_clear(graph, sizeof(gate_ui_graphics_t));
130
131 if (deskdc == NULL)
132 {
133 ret = GATE_RESULT_OUTOFRESOURCES;
134 break;
135 }
136 dc = CreateCompatibleDC(deskdc);
137 if (dc == NULL)
138 {
139 ret = GATE_RESULT_OUTOFRESOURCES;
140 break;
141 }
142
143
144 bitmapinfo.info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
145 bitmapinfo.info.bmiHeader.biWidth = width;
146 bitmapinfo.info.bmiHeader.biHeight = height;
147 bitmapinfo.info.bmiHeader.biPlanes = 1;
148 bitmapinfo.info.bmiHeader.biBitCount = depth;
149 bitmapinfo.info.bmiHeader.biCompression = BI_RGB;
150 bitmapinfo.info.bmiHeader.biSizeImage = 0;
151 bitmapinfo.info.bmiHeader.biXPelsPerMeter = 0;
152 bitmapinfo.info.bmiHeader.biYPelsPerMeter = 0;
153 bitmapinfo.info.bmiHeader.biClrImportant = 0;
154
155 if (depth == 1)
156 {
157 bitmapinfo.info.bmiHeader.biClrUsed = 2;
158
159 /* black */
160 bitmapinfo.info.bmiColors[0].rgbBlue = 0;
161 bitmapinfo.info.bmiColors[0].rgbGreen = 0;
162 bitmapinfo.info.bmiColors[0].rgbRed = 0;
163 bitmapinfo.info.bmiColors[0].rgbReserved = 0;
164
165 /* white */
166 bitmapinfo.info.bmiColors[1].rgbBlue = 255;
167 bitmapinfo.info.bmiColors[1].rgbGreen = 255;
168 bitmapinfo.info.bmiColors[1].rgbRed = 255;
169 bitmapinfo.info.bmiColors[1].rgbReserved = 0;
170 }
171 else if (depth < 8)
172 {
173 static gate_color_rgb_t vga_pal[16];
174 static gate_bool_t vga_pal_init = false;
175 if (!vga_pal_init)
176 {
177 gate_color_palette_rgb4_create(vga_pal);
178 vga_pal_init = true;
179 }
180
181 bitmapinfo.info.bmiHeader.biClrUsed = 16;
182 ptr_quad = &bitmapinfo.info.bmiColors[0];
183 for (r = 0; r < 16; ++r)
184 {
185 ptr_quad->rgbBlue = vga_pal[r].b;
186 ptr_quad->rgbGreen = vga_pal[r].g;
187 ptr_quad->rgbRed = vga_pal[r].r;
188 ptr_quad->rgbReserved = 0;
189 ++ptr_quad;
190 }
191 }
192 else if (depth < 16)
193 {
194 ptr_quad = &bitmapinfo.info.bmiColors[0];
195 bitmapinfo.info.bmiHeader.biClrUsed = create_palette_8(ptr_quad);
196 }
197 else
198 {
199 bitmapinfo.info.bmiHeader.biClrUsed = 0;
200 }
201
202 linelen = (bitmapinfo.info.bmiHeader.biWidth * bitmapinfo.info.bmiHeader.biBitCount + 7) / 8;
203 if (linelen % 4 != 0)
204 {
205 linelen += (4 - (linelen % 4));
206 }
207 bufferlen = linelen * bitmapinfo.info.bmiHeader.biHeight;
208 #if defined(GATE_SYS_WIN16)
209 buffer = gate_mem_alloc(bufferlen);
210 gate_mem_clear(buffer, bufferlen);
211 hbitmap = CreateDIBitmap(deskdc, &bitmapinfo.info.bmiHeader, CBM_INIT, buffer, &bitmapinfo.info, DIB_RGB_COLORS);
212 #else
213 buffer = NULL;
214 hbitmap = CreateDIBSection(deskdc, &bitmapinfo.info, DIB_RGB_COLORS, &buffer, NULL, 0);
215 #endif
216 if (hbitmap == NULL)
217 {
218 ret = GATE_RESULT_FAILED;
219 break;
220 }
221 hbackup = SelectObject(dc, hbitmap);
222
223 graph->width = width;
224 graph->height = height;
225 graph->host = host;
226 graph->resources[0] = dc;
227 graph->resources[1] = hbackup;
228 graph->resources[2] = NULL;
229 graph->resources[3] = buffer;
230 ret = GATE_RESULT_OK;
231
232 } while (0);
233
234 if (deskdc != NULL)
235 {
236 ReleaseDC(desk, deskdc);
237 }
238
239 return ret;
240 }
241
242 gate_result_t gate_ui_graphics_create_image_from(gate_ui_graphics_t* graph, gate_ui_host_t* host, gate_rasterimage_t const* rasterimage)
243 {
244
245 gate_uint32_t x, y;
246 gate_result_t ret;
247 #if defined(GATE_WIN32_ANSI)
248
249 # if 0
250 /* use 8-bit DIB */
251 ret = gate_ui_graphics_create_image(graph, host, rasterimage->width, rasterimage->height, 8);
252 if (GATE_SUCCEEDED(ret))
253 {
254 gate_uint8_t* ptrbytes = (gate_uint8_t*)GATE_UI_GRAPHICS_BYTEBUFFER(graph);
255 unsigned line_patch = (unsigned)(rasterimage->width % 4);
256 if (line_patch != 0)
257 {
258 line_patch = 4 - line_patch;
259 }
260 for (y = 0; y != rasterimage->height; ++y)
261 {
262 gate_color_t const* ptrpixels = (gate_color_t const*)gate_rasterimage_get_line_ptr(rasterimage, (rasterimage->height - 1 - y));
263 for (x = 0; x != rasterimage->width; ++x)
264 {
265 gate_uint16_t col16;
266 col16 = (((gate_uint16_t)ptrpixels->r + 25) / 51) * 36;
267 col16 += (((gate_uint16_t)ptrpixels->g + 25) / 51) * 6;
268 col16 += (((gate_uint16_t)ptrpixels->b + 25) / 51);
269
270 *(ptrbytes++) = (gate_uint8_t)(col16 & 0xff);
271 ++ptrpixels;
272 }
273 ptrbytes += line_patch;
274 }
275 }
276 # else
277 /* use 16-bit DIB */
278 ret = gate_ui_graphics_create_image(graph, host, rasterimage->width, rasterimage->height, 16);
279 if (GATE_SUCCEEDED(ret))
280 {
281 gate_uint8_t* ptrbytes = (gate_uint8_t*)GATE_UI_GRAPHICS_BYTEBUFFER(graph);
282 unsigned line_patch = (unsigned)(rasterimage->width % 2) * 2;
283 for (y = 0; y != rasterimage->height; ++y)
284 {
285 gate_color_t const* ptrpixels = (gate_color_t const*)gate_rasterimage_get_line_ptr(rasterimage, (rasterimage->height - 1 - y));
286 for (x = 0; x != rasterimage->width; ++x)
287 {
288 gate_uint16_t col16
289 = ((gate_uint16_t)(ptrpixels->b & 0xF8) >> 3)
290 | ((gate_uint16_t)(ptrpixels->g & 0xF8) << 2)
291 | ((gate_uint16_t)(ptrpixels->r & 0xF8) << 7);
292
293 *(ptrbytes++) = (gate_uint8_t)(col16 & 0xff);
294 *(ptrbytes++) = (gate_uint8_t)(col16 >> 8);
295 ++ptrpixels;
296 }
297 ptrbytes += line_patch;
298 }
299 }
300 # endif
301
302 #else
303 ret = gate_ui_graphics_create_image(graph, host, rasterimage->width, rasterimage->height, 32);
304 if (GATE_SUCCEEDED(ret))
305 {
306 gate_uint8_t* ptrbytes = (gate_uint8_t*)GATE_UI_GRAPHICS_BYTEBUFFER(graph);
307 for (y = 0; y != rasterimage->height; ++y)
308 {
309 gate_color_t const* ptrpixels = (gate_color_t const*)gate_rasterimage_get_line_ptr(rasterimage, (rasterimage->height - 1 - y));
310 for (x = 0; x != rasterimage->width; ++x)
311 {
312 *(ptrbytes++) = ptrpixels->b;
313 *(ptrbytes++) = ptrpixels->g;
314 *(ptrbytes++) = ptrpixels->r;
315 *(ptrbytes++) = ptrpixels->a;
316 ++ptrpixels;
317 }
318 }
319 }
320 #endif
321 return ret;
322 }
323
324
325 gate_result_t gate_ui_graphics_create_ctrl(gate_ui_graphics_t* graph, gate_ui_ctrl_t* ctrl)
326 {
327 HWND hwnd = (HWND)GATE_UI_WINAPI_GET_HWND(ctrl);
328 RECT rect;
329
330 gate_mem_clear(graph, sizeof(gate_ui_graphics_t));
331
332 GetClientRect(hwnd, &rect);
333
334 graph->host = GATE_UI_WINAPI_GET_HOST(ctrl);
335 graph->width = rect.right - rect.left;
336 graph->height = rect.bottom - rect.top;
337 graph->resources[0] = GetDC(hwnd);
338 graph->resources[2] = hwnd;
339 return GATE_RESULT_OK;
340 }
341 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)
342 {
343 GATE_UNUSED_ARG(param);
344 gate_mem_clear(graph, sizeof(gate_ui_graphics_t));
345 graph->host = host;
346 graph->resources[0] = graphics;
347 graph->resources[3] = (void*)(gate_intptr_t)(-1); ///< no-release flag
348 graph->width = width;
349 graph->height = height;
350 return GATE_RESULT_OK;
351 }
352 gate_result_t gate_ui_graphics_destroy(gate_ui_graphics_t* graph)
353 {
354 gate_bool_t success = true;
355 HDC hdc = GATE_UI_GRAPHICS_HDC(graph);
356 HBITMAP hbmp = GATE_UI_GRAPHICS_BACKUP(graph);
357 HWND hwnd = GATE_UI_GRAPHICS_WINDOW(graph);
358 void* buffer_ptr = GATE_UI_GRAPHICS_BYTEBUFFER(graph);
359
360 if (-1 == (gate_intptr_t)buffer_ptr)
361 {
362 // no-release flag is active
363 }
364 else
365 {
366 if (hbmp != NULL)
367 {
368 success &= (FALSE != DeleteObject(SelectObject(hdc, (HGDIOBJ)hbmp)));
369 }
370
371 if (hwnd != NULL)
372 {
373 success &= (0 != ReleaseDC(hwnd, hdc));
374 }
375 else
376 {
377 success &= (FALSE != DeleteDC(hdc));
378 }
379
380 if (buffer_ptr != NULL)
381 {
382 #if defined(GATE_SYS_WIN16)
383 gate_mem_dealloc(buffer_ptr);
384 #else
385 /* win32 dib section will release the buffer bits automatically */
386 #endif
387 }
388
389 }
390
391 return success ? GATE_RESULT_OK : GATE_RESULT_FAILED;
392 }
393
394 gate_int32_t gate_ui_graphics_width(gate_ui_graphics_t* graph)
395 {
396 return (graph != NULL) ? graph->width : 0;
397 }
398 gate_int32_t gate_ui_graphics_height(gate_ui_graphics_t* graph)
399 {
400 return (graph != NULL) ? graph->height : 0;
401 }
402
403 #ifndef CLR_INVALID
404 #define CLR_INVALID 0xffffffff
405 #endif
406
407 gate_result_t gate_ui_graphics_set_pixel(gate_ui_graphics_t* graph, gate_ui_point_t pos, gate_ui_color_t col)
408 {
409 HDC hdc = GATE_UI_GRAPHICS_HDC(graph);
410 COLORREF colref = RGB(col.r, col.g, col.b);
411 COLORREF result = SetPixel(hdc, (int)pos.x, (int)pos.y, colref);
412 if (result == CLR_INVALID)
413 {
414 return GATE_RESULT_FAILED;
415 }
416 else
417 {
418 return GATE_RESULT_OK;
419 }
420 }
421 gate_result_t gate_ui_graphics_get_pixel(gate_ui_graphics_t* graph, gate_ui_point_t pos, gate_ui_color_t* col)
422 {
423 HDC hdc = GATE_UI_GRAPHICS_HDC(graph);
424 COLORREF colref = GetPixel(hdc, (int)pos.x, (int)pos.y);
425 if (colref == CLR_INVALID)
426 {
427 return GATE_RESULT_FAILED;
428 }
429 else
430 {
431 col->r = GetRValue(colref);
432 col->g = GetGValue(colref);
433 col->b = GetBValue(colref);
434 col->a = 255;
435 return GATE_RESULT_OK;
436 }
437 }
438 gate_result_t gate_ui_graphics_draw(gate_ui_graphics_t* graph, gate_ui_graphics_t* srcgraph,
439 gate_ui_point_t const* dst, gate_ui_size_t const* size, gate_ui_point_t const* srcpos)
440 {
441 HDC hdc_dst = GATE_UI_GRAPHICS_HDC(graph);
442 HDC hdc_src = GATE_UI_GRAPHICS_HDC(srcgraph);
443 int dst_x = dst ? dst->x : 0;
444 int dst_y = dst ? dst->y : 0;
445 int width = size ? size->width : -1;
446 int height = size ? size->height : -1;
447 int src_x = srcpos ? srcpos->x : 0;
448 int src_y = srcpos ? srcpos->y : 0;
449
450 if (width < 0)
451 {
452 width += gate_ui_graphics_width(srcgraph) + 1;
453 }
454 if (height < 0)
455 {
456 height += gate_ui_graphics_height(srcgraph) + 1;
457 }
458
459 if (FALSE == BitBlt(hdc_dst, dst_x, dst_y, width, height, hdc_src, src_x, src_y, SRCCOPY))
460 {
461 return GATE_RESULT_FAILED;
462 }
463 else
464 {
465 return GATE_RESULT_OK;
466 }
467 }
468
469 gate_result_t gate_ui_graphics_draw_ex(gate_ui_graphics_t* graph, gate_ui_graphics_t* src_graph,
470 gate_ui_position_t const* dest_rect, gate_ui_position_t const* src_rect)
471 {
472 HDC hdc_dst = GATE_UI_GRAPHICS_HDC(graph);
473 HDC hdc_src = GATE_UI_GRAPHICS_HDC(src_graph);
474 int dst_x = dest_rect ? dest_rect->pos.x : 0;
475 int dst_y = dest_rect ? dest_rect->pos.y : 0;
476 int dst_width = dest_rect ? dest_rect->size.width : -1;
477 int dst_height = dest_rect ? dest_rect->size.height : -1;
478 int src_x = src_rect ? src_rect->pos.x : 0;
479 int src_y = src_rect ? src_rect->pos.y : 0;
480 int src_width = src_rect ? src_rect->size.width : -1;
481 int src_height = src_rect ? src_rect->size.height : -1;
482
483 if (dst_width < 0)
484 {
485 dst_width += gate_ui_graphics_width(graph) + 1;
486 }
487 if (dst_height < 0)
488 {
489 dst_height += gate_ui_graphics_height(graph) + 1;
490 }
491
492 if (src_width < 0)
493 {
494 src_width += gate_ui_graphics_width(src_graph) + 1;
495 }
496 if (src_height < 0)
497 {
498 src_height += gate_ui_graphics_height(src_graph) + 1;
499 }
500 #if defined(COLORONCOLOR) && !defined(__MINGW32CE__)
501 SetStretchBltMode(hdc_dst, COLORONCOLOR);
502 #endif
503
504 if (FALSE == StretchBlt(hdc_dst, dst_x, dst_y, dst_width, dst_height, hdc_src,
505 src_x, src_y, src_width, src_height, SRCCOPY))
506 {
507 return GATE_RESULT_FAILED;
508 }
509 else
510 {
511 return GATE_RESULT_OK;
512 }
513 }
514
515 gate_result_t gate_ui_graphics_draw_image(gate_ui_graphics_t* graph, gate_rasterimage_t const* srcimage,
516 gate_ui_point_t const* dst, gate_ui_size_t const* size, gate_ui_point_t const* srcpos)
517 {
518 gate_ui_graphics_t src_graph;
519 gate_result_t ret = gate_ui_graphics_create_image_from(&src_graph, graph->host, srcimage);
520 if (GATE_SUCCEEDED(ret))
521 {
522 ret = gate_ui_graphics_draw(graph, &src_graph, dst, size, srcpos);
523 gate_ui_graphics_destroy(&src_graph);
524 }
525 return ret;
526 }
527
528
529 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)
530 {
531 gate_result_t ret = GATE_RESULT_FAILED;
532 HDC hdc = GATE_UI_GRAPHICS_HDC(graph);
533 COLORREF colref = RGB(col.r, col.g, col.b);
534 HPEN hpen = CreatePen(PS_SOLID, linewidth, colref);
535 HGDIOBJ hselpen = SelectObject(hdc, (HGDIOBJ)hpen);
536 if (MoveToEx(hdc, (int)from.x, (int)from.y, NULL))
537 {
538 if (LineTo(hdc, (int)to.x, (int)to.y))
539 {
540 SetPixel(hdc, (int)to.x, (int)to.y, colref);
541 ret = GATE_RESULT_OK;
542 }
543 }
544 DeleteObject(SelectObject(hdc, hselpen));
545 return ret;
546 }
547 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)
548 {
549 gate_result_t success = true;
550 HDC hdc = GATE_UI_GRAPHICS_HDC(graph);
551 RECT r;
552 HGDIOBJ hbackup;
553 HBRUSH hbrush;
554 HPEN hpen;
555 COLORREF colref;
556
557 if (colfill != NULL)
558 {
559 colref = RGB(colfill->r, colfill->g, colfill->b);
560 hbrush = CreateSolidBrush(colref);
561 r.left = rect.pos.x;
562 r.top = rect.pos.y;
563 r.right = rect.pos.x + rect.size.width + 1;
564 r.bottom = rect.pos.y + rect.size.height + 1;
565 success &= (0 != FillRect(hdc, &r, hbrush));
566 DeleteObject(hbrush);
567 }
568 if (colline != NULL)
569 {
570 colref = RGB(colline->r, colline->g, colline->b);
571 hpen = CreatePen(PS_SOLID, (int)linewidth, colref);
572 hbackup = SelectObject(hdc, hpen);
573 success &= (FALSE != MoveToEx(hdc, rect.pos.x, rect.pos.y, NULL));
574 success &= (FALSE != LineTo(hdc, rect.pos.x + rect.size.width, rect.pos.y));
575 success &= (FALSE != LineTo(hdc, rect.pos.x + rect.size.width, rect.pos.y + rect.size.height));
576 success &= (FALSE != LineTo(hdc, rect.pos.x, rect.pos.y + rect.size.height));
577 success &= (FALSE != LineTo(hdc, rect.pos.x, rect.pos.y));
578 DeleteObject(SelectObject(hdc, hbackup));
579 }
580 return success ? GATE_RESULT_OK : GATE_RESULT_FAILED;
581 }
582 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)
583 {
584 gate_result_t success = true;
585 HDC hdc = GATE_UI_GRAPHICS_HDC(graph);
586 HGDIOBJ hbackup;
587 HGDIOBJ hbackup2;
588 HPEN hpen;
589 HBRUSH hbrush;
590 COLORREF colref;
591 gate_size_t ndx;
592 POINT pnts[1024];
593
594 if (colfill != NULL)
595 {
596 colref = RGB(colfill->r, colfill->g, colfill->b);
597 if (pointcount > sizeof(pnts) / sizeof(pnts[0]))
598 {
599 pointcount = sizeof(pnts) / sizeof(pnts[0]);
600 }
601 for (ndx = 0; ndx < pointcount; ++ndx)
602 {
603 pnts[ndx].x = (int)points[ndx].x;
604 pnts[ndx].y = (int)points[ndx].y;
605 }
606 hpen = CreatePen(PS_NULL, 0, 0);
607 hbackup = SelectObject(hdc, (HGDIOBJ)hpen);
608 hbrush = CreateSolidBrush(colref);
609 hbackup2 = SelectObject(hdc, (HGDIOBJ)hbrush);
610
611 success &= (FALSE != Polygon(hdc, pnts, (int)pointcount));
612
613 DeleteObject(SelectObject(hdc, hbackup2));
614 DeleteObject(SelectObject(hdc, hbackup));
615 }
616
617 if (colline != NULL)
618 {
619 colref = RGB(colline->r, colline->g, colline->b);
620 hpen = CreatePen(PS_SOLID, linewidth, colref);
621 hbackup = SelectObject(hdc, (HGDIOBJ)hpen);
622 success &= (FALSE != MoveToEx(hdc, (int)points[0].x, (int)points[0].y, NULL));
623 for (ndx = 1; ndx != pointcount; ++ndx)
624 {
625 success &= (FALSE != LineTo(hdc, (int)points[ndx].x, (int)points[ndx].y));
626 }
627 success &= (FALSE != LineTo(hdc, (int)points[0].x, (int)points[0].y));
628 DeleteObject(SelectObject(hdc, hbackup));
629 }
630 return success ? GATE_RESULT_OK : GATE_RESULT_FAILED;
631 }
632
633 #if defined(GATE_SYS_WIN16)
634
635 static BOOL GetTextExtentExPoint(HDC hdc, LPCSTR lpszString, int cchString, int nMaxExtent, LPINT lpnFit, LPINT lpnDx, LPSIZE lpSize)
636 {
637 SIZE sz;
638 SIZE szchr;
639 GATE_UNUSED_ARG(nMaxExtent);
640 GATE_UNUSED_ARG(lpnFit);
641 sz.cx = 0;
642 sz.cy = 0;
643 while (cchString-- > 0)
644 {
645 GetTextExtentPoint(hdc, lpszString, 1, &szchr);
646 sz.cx += szchr.cx;
647 *lpnDx = szchr.cx;
648
649 ++lpszString;
650 ++lpnDx;
651 }
652 lpSize->cx = sz.cx;
653 lpSize->cy = sz.cy;
654 return TRUE;
655 }
656
657 #define GetTextExtentPoint32 GetTextExtentPoint
658
659 #endif
660
661 gate_result_t gate_ui_graphics_get_char_size(gate_ui_graphics_t* graph, gate_ui_font_t const* font,
662 gate_char32_t const* chars, gate_size_t charcount, gate_int32_t* charlens)
663 {
664 /* NOTICE: this function only supports up to 2048 characters! */
665 gate_result_t ret = GATE_RESULT_FAILED;
666 HDC hdc = GATE_UI_GRAPHICS_HDC(graph);
667 TCHAR buffer[2048];
668 int lengths[2048];
669 gate_size_t bufferused = gate_win32_utf32_2_winstr(chars, charcount, buffer, sizeof(buffer) / sizeof(buffer[0]));
670 HGDIOBJ hbackup;
671 HFONT hfont = (HFONT)gate_ui_winapi_create_font(font);
672 SIZE sz = { 0, 0 };
673 gate_size_t index;
674
675 hbackup = SelectObject(hdc, (HGDIOBJ)hfont);
676
677 if (FALSE == GetTextExtentExPoint(hdc, buffer, (int)bufferused, 0, NULL, lengths, &sz))
678 {
679 gate_win32_print_lasterror(&ret, NULL, 0);
680 }
681 else
682 {
683 for (index = 0; index != bufferused; ++index)
684 {
685 charlens[index] = lengths[index];
686 }
687 ret = GATE_RESULT_OK;
688 }
689
690 DeleteObject(SelectObject(hdc, hbackup));
691 return ret;
692 }
693 gate_result_t gate_ui_graphics_get_text_size(gate_ui_graphics_t* graph, gate_ui_font_t const* font,
694 gate_string_t const* txt, gate_int32_t* width, gate_int32_t* height)
695 {
696 gate_result_t ret = GATE_RESULT_FAILED;
697 HDC hdc = GATE_UI_GRAPHICS_HDC(graph);
698 HGDIOBJ hbackup = NULL;
699 TCHAR buffer[4096];
700 gate_size_t bufferused = gate_win32_utf8_2_winstr(txt->str, txt->length, buffer, sizeof(buffer) / sizeof(buffer[0]));
701 HFONT hfont = (HFONT)gate_ui_winapi_create_font(font);
702 SIZE sz = { 0, 0 };
703
704 hbackup = SelectObject(hdc, (HGDIOBJ)hfont);
705
706 if (FALSE == GetTextExtentPoint32(hdc, buffer, (int)bufferused, &sz))
707 {
708 gate_win32_print_lasterror(&ret, NULL, 0);
709 }
710 else
711 {
712 if (width)
713 {
714 *width = (gate_int32_t)sz.cx;
715 }
716 if (height)
717 {
718 *height = (gate_int32_t)sz.cy;
719 }
720 ret = GATE_RESULT_OK;
721 }
722
723 DeleteObject(SelectObject(hdc, hbackup));
724 return ret;
725 }
726 gate_result_t gate_ui_graphics_print(gate_ui_graphics_t* graph, gate_ui_font_t const* font,
727 gate_string_t const* text, gate_ui_position_t const* pos)
728 {
729 gate_bool_t success = true;
730 HDC hdc = GATE_UI_GRAPHICS_HDC(graph);
731 HGDIOBJ hbackup;
732 HFONT hfont = (HFONT)gate_ui_winapi_create_font(font);
733 TCHAR buffer[4096];
734 RECT rect;
735 UINT flags = DT_LEFT | DT_NOPREFIX | DT_NOCLIP;
736 gate_size_t bufferused = gate_win32_utf8_2_winstr(text->str, text->length, buffer, sizeof(buffer) / sizeof(buffer[0]));
737 rect.left = pos->pos.x;
738 rect.top = pos->pos.y;
739 if ((pos->size.width == 0) && (pos->size.height == 0))
740 {
741 rect.bottom = graph->width;
742 rect.right = graph->height;
743 }
744 else
745 {
746 rect.bottom = pos->pos.x + pos->size.width + 1;
747 rect.right = pos->pos.y + pos->size.height + 1;
748 flags |= DT_VCENTER;
749 }
750 SetTextColor(hdc, RGB(font->color.r, font->color.g, font->color.b));
751 SetBkMode(hdc, TRANSPARENT);
752 hbackup = SelectObject(hdc, (HGDIOBJ)hfont);
753 success &= ((0 != DrawText(hdc, buffer, (int)bufferused, &rect, flags)) ? true : false);
754 DeleteObject(SelectObject(hdc, hbackup));
755 return success ? GATE_RESULT_OK : GATE_RESULT_FAILED;
756 }
757
758 void* gate_ui_graphics_handle(gate_ui_graphics_t* graph)
759 {
760 return (void*)GATE_UI_GRAPHICS_HDC(graph);
761 }
762 void* gate_ui_graphics_surface(gate_ui_graphics_t* graph)
763 {
764 return (void*)GATE_UI_GRAPHICS_WINDOW(graph);
765 }
766
767
768 /*****************************
769 * icon WIN32 implementation *
770 *****************************/
771
772 gate_result_t gate_ui_icon_create_native(gate_ui_icon_t* icon, gate_ui_host_t* host, void* handle, gate_uint32_t flags)
773 {
774 icon->host = host;
775 icon->resources[0] = handle;
776 icon->flags = flags;
777 return GATE_RESULT_OK;
778 }
779
780 typedef UINT(WINAPI* ExtractIconEx_funcptr_t)(LPCTSTR lpszFile, int nIconIndex, HICON* phiconLarge, HICON* phiconSmall, UINT nIcons);
781 static ExtractIconEx_funcptr_t ExtractIconEx_function = NULL;
782
783 static HICON gate_ui_extract_icon(LPCTSTR file, int icon_index, gate_uint32_t flags)
784 {
785 gate_bool_t is_small = GATE_FLAG_ENABLED(flags, GATE_UI_ICON_FLAG_SMALL);
786 HICON hicon = NULL;
787 HMODULE hmod;
788 UINT extracted;
789 do
790 {
791 if (ExtractIconEx_function == NULL)
792 {
793 hmod = gate_win32_get_shell_module();
794 if (hmod != NULL)
795 {
796 gate_win32_get_proc_address(hmod, GATE_WINAPI_DUAL_NAME("ExtractIconEx"), &ExtractIconEx_function);
797 }
798 }
799 if (ExtractIconEx_function != NULL)
800 {
801 extracted = ExtractIconEx_function(file, icon_index, is_small ? NULL : &hicon, is_small ? &hicon : NULL, 1);
802 if (extracted == 0)
803 {
804 hicon = NULL;
805 }
806 }
807 } while (0);
808 return hicon;
809 }
810
811 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)
812 {
813 gate_result_t ret = GATE_RESULT_FAILED;
814 HICON hicon = NULL;
815
816 #if defined(GATE_SYS_WINCE)
817 hicon = LoadCursor(NULL, IDC_APPSTARTING);
818 #else
819 LPCTSTR icon_source_file = _T("shell32.dll");
820 int icon_source_index = -1;
821 int icon_source_index_alt = -1;
822
823 switch (stock_id)
824 {
825 case GATE_UI_ICON_STOCK_APP: icon_source_index = 2; break;
826 case GATE_UI_ICON_STOCK_DOCUMENT: icon_source_index = 1; break;
827 case GATE_UI_ICON_STOCK_FOLDER: icon_source_index = 3; break;
828 case GATE_UI_ICON_STOCK_FOLDEROPEN: icon_source_index = 4; break;
829 case GATE_UI_ICON_STOCK_NEWFILE: icon_source_index = 70; icon_source_index_alt = 1; break;
830 case GATE_UI_ICON_STOCK_OPENFILE: icon_source_index = 126; icon_source_index_alt = 85; break;
831 case GATE_UI_ICON_STOCK_SAVEFILE: icon_source_index = 258; icon_source_index_alt = 6; break;
832 case GATE_UI_ICON_STOCK_PRINTER: icon_source_index = 16; break;
833 case GATE_UI_ICON_STOCK_CUT: icon_source_index = 259; icon_source_index_alt = 65; break;
834 case GATE_UI_ICON_STOCK_COPY: icon_source_index = 134; icon_source_index_alt = 54; break;
835 case GATE_UI_ICON_STOCK_PASTE: icon_source_index = 260; icon_source_index_alt = 66; break;
836 case GATE_UI_ICON_STOCK_DELETE: icon_source_index = 131; icon_source_index_alt = 105; break;
837 case GATE_UI_ICON_STOCK_FIND: icon_source_index = 22; break;
838 case GATE_UI_ICON_STOCK_HELP: icon_source_index = 23; break;
839
840 case GATE_UI_ICON_STOCK_STORAGE: icon_source_index = 8; icon_source_index_alt = 8; break;
841 case GATE_UI_ICON_STOCK_COMPUTER: icon_source_index = 15; icon_source_index_alt = 15; break;
842 case GATE_UI_ICON_STOCK_NETWORK: icon_source_index = 18; icon_source_index_alt = 18; break;
843 case GATE_UI_ICON_STOCK_GLOBE: icon_source_index = 13; icon_source_index_alt = 13; break;
844 case GATE_UI_ICON_STOCK_SETTINGS: icon_source_index = 90; icon_source_index_alt = 21; break;
845 case GATE_UI_ICON_STOCK_HOME: icon_source_index = 150; icon_source_index_alt = 39; break;
846 case GATE_UI_ICON_STOCK_IMAGE: icon_source_index = 117; icon_source_index_alt = 34; break;
847 case GATE_UI_ICON_STOCK_AUDIO: icon_source_index = 116; icon_source_index_alt = 40; break;
848 case GATE_UI_ICON_STOCK_VIDEO: icon_source_index = 115; icon_source_index_alt = 79; break;
849 case GATE_UI_ICON_STOCK_MAIL: icon_source_index = 156; icon_source_index_alt = 91; break;
850
851 default: break;
852 }
853
854 if (icon_source_index < 0)
855 {
856 return GATE_RESULT_NOMATCH;
857 }
858
859 hicon = gate_ui_extract_icon(icon_source_file, icon_source_index, flags);
860 if ((hicon == NULL) && (icon_source_index_alt >= 0))
861 {
862 hicon = gate_ui_extract_icon(icon_source_file, icon_source_index_alt, flags);
863 }
864 #endif
865
866 if (hicon == NULL)
867 {
868 return GATE_RESULT_NOTAVAILABLE;
869 }
870
871 ret = gate_ui_icon_create_native(icon, host, (void*)hicon, (flags & GATE_UI_ICON_FLAG_SMALL) | GATE_UI_ICON_FLAG_STOCK);
872 if (GATE_FAILED(ret))
873 {
874 DestroyIcon(hicon);
875 }
876 else
877 {
878 icon->resources[1] = (void*)(gate_uintptr_t)stock_id;
879 }
880 return ret;
881 }
882
883 #if defined(GATE_SYS_WIN16)
884
885 static HICON gate_ui_icon_create_from_image(gate_ui_host_t* host, gate_rasterimage_t const* image, gate_uint32_t hx, gate_uint32_t hy)
886 {
887 /* TODO */
888 return CreateIcon(NULL, 32, 32, 2, 2, NULL, NULL);
889 }
890
891 #else /* GATE_SYS_WIN16 */
892
893 static HICON gate_ui_icon_create_from_image(gate_ui_host_t* host, gate_rasterimage_t const* image, gate_uint32_t hx, gate_uint32_t hy)
894 {
895 HICON ret = NULL;
896
897 do
898 {
899 gate_ui_position_t imagerect;
900 gate_ui_color_t maskcolor = { 255, 255, 255, 255 };
901 gate_ui_point_t pos;
902 gate_uint32_t icon_flags = 0;
903 static COLORREF color_black = RGB(0, 0, 0);
904 static COLORREF color_white = RGB(255, 255, 255);
905 COLORREF color_bg = GetSysColor(COLOR_3DFACE);
906
907 ICONINFO iconinfo;
908
909 HBITMAP hbmptmp1 = NULL;
910 HBITMAP hbmptmp2 = NULL;
911 HBITMAP bmpmask = NULL;
912 HBITMAP bmpimage = NULL;
913 HDC desk = NULL;
914 HDC hmask = NULL;
915 HDC himage = NULL;
916 gate_color_t const* ptrpixels;
917
918 iconinfo.fIcon = TRUE;
919 iconinfo.xHotspot = hx;
920 iconinfo.yHotspot = hy;
921 iconinfo.hbmMask = NULL;
922 iconinfo.hbmColor = NULL;
923
924 imagerect.pos.x = 0;
925 imagerect.pos.y = 0;
926 imagerect.size.width = image->width;
927 imagerect.size.height = image->height;
928
929 desk = GetDC(NULL);
930 hmask = CreateCompatibleDC(desk);
931 himage = CreateCompatibleDC(desk);
932
933 bmpmask = CreateBitmap(image->width, image->height, 1, 1, NULL);
934 bmpimage = CreateCompatibleBitmap(desk, image->width, image->height);
935
936 hbmptmp1 = (HBITMAP)SelectObject(hmask, bmpmask);
937 hbmptmp2 = (HBITMAP)SelectObject(himage, bmpimage);
938
939 ptrpixels = (gate_color_t const*)gate_rasterimage_get_line_ptr(image, 0);
940 for (pos.y = 0; pos.y != image->height; ++pos.y)
941 {
942 for (pos.x = 0; pos.x != image->width; ++pos.x)
943 {
944 SetPixel(hmask, pos.x, pos.y, (ptrpixels->a > 127) ? color_black : color_white);
945 SetPixel(himage, pos.x, pos.y, (ptrpixels->a > 127) ? RGB(ptrpixels->r, ptrpixels->g, ptrpixels->b) : color_black);
946 ++ptrpixels;
947 }
948 }
949 SelectObject(hmask, hbmptmp1);
950 SelectObject(himage, hbmptmp2);
951 DeleteDC(hmask);
952 DeleteDC(himage);
953 ReleaseDC(NULL, desk);
954
955 if (image->height < 24)
956 {
957 icon_flags |= GATE_UI_ICON_FLAG_SMALL;
958 }
959 if (image->height > 40)
960 {
961 icon_flags |= GATE_UI_ICON_FLAG_LARGE;
962 }
963
964 iconinfo.hbmMask = bmpmask;
965 iconinfo.hbmColor = bmpimage;
966
967 ret = CreateIconIndirect(&iconinfo);
968 GATE_DEBUG_ASSERT(ret != NULL);
969
970 DeleteObject(bmpmask);
971 DeleteObject(bmpimage);
972 } while (0);
973
974 return ret;
975 }
976
977 #endif /* GATE_SYS_WIN16 */
978
979 gate_result_t gate_ui_icon_create_image(gate_ui_icon_t* icon, gate_ui_host_t* host, gate_rasterimage_t const* image)
980 {
981 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
982 HICON hicon = gate_ui_icon_create_from_image(host, image, 0, 0);
983 if (hicon == NULL)
984 {
985 ret = GATE_RESULT_FAILED;
986 }
987 else
988 {
989 icon->resources[0] = hicon;
990 icon->resources[1] = NULL;
991 icon->host = host;
992 if (image->height < 28)
993 {
994 icon->flags = GATE_UI_ICON_FLAG_SMALL;
995 }
996 else if (image->height > 36)
997 {
998 icon->flags = GATE_UI_ICON_FLAG_LARGE;
999 }
1000
1001 ret = GATE_RESULT_OK;
1002 }
1003 return ret;
1004 }
1005 gate_result_t gate_ui_icon_create_file(gate_ui_icon_t* icon, gate_ui_host_t* host, gate_string_t const* filepath)
1006 {
1007 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
1008 /* TODO */
1009 return ret;
1010 }
1011 gate_result_t gate_ui_icon_copy(gate_ui_icon_t* dsticon, gate_ui_icon_t const* srcicon)
1012 {
1013 gate_result_t ret = GATE_RESULT_OK;
1014 dsticon->host = srcicon->host;
1015
1016 #if !defined(GATE_SYS_WINCE)
1017 if (!GATE_FLAG_ENABLED(srcicon->flags, GATE_UI_ICON_FLAG_STOCK))
1018 {
1019 /* managed icon */
1020 dsticon->flags = srcicon->flags;
1021 #if defined(GATE_SYS_WIN16)
1022 dsticon->resources[0] = (void*)CopyIcon(NULL, (HICON)srcicon->resources[0]);
1023 #else
1024 dsticon->resources[0] = (void*)CopyIcon((HICON)srcicon->resources[0]);
1025 #endif
1026 if (dsticon->resources[0] == NULL)
1027 {
1028 ret = GATE_RESULT_FAILED;
1029 }
1030 dsticon->resources[1] = NULL;
1031 }
1032 else
1033 #endif
1034 {
1035 dsticon->resources[0] = srcicon->resources[0];
1036 dsticon->resources[1] = srcicon->resources[1];
1037 }
1038 return ret;
1039 }
1040
1041 gate_result_t gate_ui_icon_destroy(gate_ui_icon_t* icon)
1042 {
1043 gate_result_t ret = GATE_RESULT_OK;
1044 if (!GATE_FLAG_ENABLED(icon->flags, GATE_UI_ICON_FLAG_STOCK))
1045 {
1046 /* managed icon */
1047 if (!DestroyIcon((HICON)icon->resources[0]))
1048 {
1049 ret = GATE_RESULT_FAILED;
1050 }
1051 }
1052 return ret;
1053 }
1054
1055
1056
1057 /******************
1058 * iconlist WIN32 *
1059 ******************/
1060 #if !defined(ILC_COLOR16) && defined(ILC_COLOR)
1061 # define ILC_COLOR16 ILC_COLOR
1062 #endif
1063
1064 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)
1065 {
1066 #if defined(GATE_SYS_WIN16)
1067 return GATE_RESULT_NOTIMPLEMENTED;
1068 #else
1069 int const x = (int)width;
1070 int const y = (int)height;
1071 static UINT const flags = ILC_COLOR16 | ILC_MASK;
1072 HIMAGELIST hlst = (HIMAGELIST)gate_ui_winapi_imagelist_create(x, y, flags, 1, 1);
1073 if (!hlst)
1074 {
1075 return GATE_RESULT_FAILED;
1076 }
1077 gate_ui_winapi_imagelist_set_bkcolor(hlst, NULL);
1078 gate_mem_clear(ilst, sizeof(gate_ui_iconlist_t));
1079 ilst->host = host;
1080 ilst->flags = 0;
1081 ilst->width = width;
1082 ilst->height = height;
1083 ilst->resources[0] = hlst;
1084 return GATE_RESULT_OK;
1085 #endif
1086 }
1087
1088 gate_result_t gate_ui_iconlist_destroy(gate_ui_iconlist_t* ilst)
1089 {
1090 #if defined(GATE_SYS_WIN16)
1091 return GATE_RESULT_NOTIMPLEMENTED;
1092 #else
1093 if (ilst->resources[0] != NULL)
1094 {
1095 gate_ui_winapi_imagelist_destroy((HIMAGELIST)ilst->resources[0]);
1096 }
1097 gate_mem_clear(ilst, sizeof(gate_ui_iconlist_t));
1098 return GATE_RESULT_OK;
1099 #endif
1100 }
1101 gate_size_t gate_ui_iconlist_count(gate_ui_iconlist_t* ilst)
1102 {
1103 return 0;
1104 }
1105 gate_result_t gate_ui_iconlist_add_icon(gate_ui_iconlist_t* ilst, gate_ui_icon_t const* icon, gate_intptr_t* icon_key)
1106 {
1107 #if defined(GATE_SYS_WIN16)
1108 return GATE_RESULT_NOTIMPLEMENTED;
1109 #else
1110 HIMAGELIST hlst = (HIMAGELIST)ilst->resources[0];
1111 int index;
1112
1113 if (!hlst)
1114 {
1115 return GATE_RESULT_INVALIDSTATE;
1116 }
1117
1118 index = gate_ui_winapi_imagelist_replace_icon(hlst, -1, (HICON)icon->resources[0]);
1119 if (index < 0)
1120 {
1121 return GATE_RESULT_FAILED;
1122 }
1123 else
1124 {
1125 if (icon_key)
1126 {
1127 *icon_key = index;
1128 }
1129 return GATE_RESULT_OK;
1130 }
1131 #endif
1132 }
1133
1134 gate_result_t gate_ui_iconlist_add_image(gate_ui_iconlist_t* ilst, gate_rasterimage_t const* image, gate_intptr_t* icon_key)
1135 {
1136 #if defined(GATE_SYS_WIN16)
1137 return GATE_RESULT_NOTIMPLEMENTED;
1138 #else
1139 gate_ui_icon_t icon = GATE_INIT_EMPTY;
1140 gate_result_t ret = gate_ui_icon_create_image(&icon, ilst->host, image);
1141 if (GATE_SUCCEEDED(ret))
1142 {
1143 ret = gate_ui_iconlist_add_icon(ilst, &icon, icon_key);
1144 gate_ui_icon_destroy(&icon);
1145 }
1146 return ret;
1147 #endif
1148 }
1149
1150 gate_result_t gate_ui_iconlist_get_icon(gate_ui_iconlist_t* ilst, gate_intptr_t icon_key, gate_ui_icon_t* icon)
1151 {
1152 #if defined(GATE_SYS_WIN16)
1153 return GATE_RESULT_NOTIMPLEMENTED;
1154 #else
1155 UINT flags = ILD_TRANSPARENT;
1156 gate_uint32_t icon_flags;
1157 HICON hicon = (HICON)gate_ui_winapi_imagelist_get_icon((HIMAGELIST)ilst->resources[0], (int)icon_key, flags);
1158 if (!hicon)
1159 {
1160 return GATE_RESULT_FAILED;
1161 }
1162 else
1163 {
1164 icon_flags = GATE_UI_ICON_FLAG_STOCK;
1165 if (ilst->height < 24)
1166 {
1167 icon_flags |= GATE_UI_ICON_FLAG_SMALL;
1168 }
1169 if (ilst->height > 40)
1170 {
1171 icon_flags |= GATE_UI_ICON_FLAG_LARGE;
1172 }
1173 return gate_ui_icon_create_native(icon, ilst->host, hicon, icon_flags);
1174 }
1175 #endif
1176 }
1177
1178 void* gate_ui_iconlist_get_handle(gate_ui_iconlist_t* ilst, gate_intptr_t icon_key)
1179 {
1180 #if defined(GATE_SYS_WIN16)
1181 return NULL;
1182 #else
1183 UINT flags = ILD_TRANSPARENT;
1184 HICON hicon = (HICON)gate_ui_winapi_imagelist_get_icon((HIMAGELIST)ilst->resources[0], (int)icon_key, flags);
1185 return (void*)hicon;
1186 #endif
1187 }
1188
1189
1190
1191
1192
1193 /****************
1194 * cursor WIN32 *
1195 ****************/
1196
1197 #ifndef IDC_APPSTARTING
1198 #define IDC_APPSTARTING IDC_WAIT
1199 #endif
1200
1201 #ifndef IDC_NO
1202 #define IDC_NO IDC_ICON
1203 #endif
1204
1205 gate_result_t gate_ui_cursor_create_stock(gate_ui_cursor_t* cursor, gate_ui_host_t* host, gate_uint32_t stock_id)
1206 {
1207 LPCTSTR resourceId = NULL;
1208 HCURSOR hcursor = NULL;
1209
1210 switch (stock_id)
1211 {
1212 case GATE_UI_CURSOR_STOCK_POINTER: resourceId = IDC_ARROW; break;
1213 case GATE_UI_CURSOR_STOCK_BUSY: resourceId = IDC_WAIT; break;
1214 case GATE_UI_CURSOR_STOCK_STARTING: resourceId = IDC_APPSTARTING; break;
1215 case GATE_UI_CURSOR_STOCK_HAND: resourceId = /*IDC_HAND*/ IDC_UPARROW; break;
1216 case GATE_UI_CURSOR_STOCK_TEXT: resourceId = IDC_IBEAM; break;
1217 case GATE_UI_CURSOR_STOCK_REJECTED: resourceId = IDC_NO; break;
1218 case GATE_UI_CURSOR_STOCK_SIZE_ALL: resourceId = IDC_SIZE; break;
1219 case GATE_UI_CURSOR_STOCK_SIZE_LEFTRIGHT: resourceId = IDC_SIZEWE; break;
1220 case GATE_UI_CURSOR_STOCK_SIZE_UPDOWN: resourceId = IDC_SIZENS; break;
1221 case GATE_UI_CURSOR_STOCK_SIZE_LEFTUPRIGHTDOWN: resourceId = IDC_SIZENWSE; break;
1222 case GATE_UI_CURSOR_STOCK_SIZE_RIGHTUPKEFTDOWN: resourceId = IDC_SIZENESW; break;
1223 default: return GATE_RESULT_INVALIDARG;
1224 }
1225
1226 hcursor = LoadCursor(NULL, resourceId);
1227 if (NULL == hcursor)
1228 {
1229 return GATE_RESULT_FAILED;
1230 }
1231 cursor->host = host;
1232 cursor->resources[0] = (void*)hcursor;
1233 cursor->resources[1] = NULL;
1234 cursor->flags = GATE_UI_CURSOR_FLAG_STOCK;
1235 return GATE_RESULT_OK;
1236 }
1237 gate_result_t gate_ui_cursor_create_native(gate_ui_cursor_t* cursor, gate_ui_host_t* host, void* handle, gate_uint32_t flags)
1238 {
1239 cursor->host = host;
1240 cursor->resources[0] = handle;
1241 cursor->resources[1] = NULL;
1242 cursor->flags = flags;
1243 return GATE_RESULT_OK;
1244 }
1245 gate_result_t gate_ui_cursor_create_image(gate_ui_cursor_t* cursor, gate_ui_host_t* host, gate_rasterimage_t const* image, gate_uint16_t x, gate_uint16_t y)
1246 {
1247 gate_result_t ret = GATE_RESULT_FAILED;
1248 HCURSOR hcursor = (HCURSOR)gate_ui_icon_create_from_image(host, image, x, y);
1249 if (hcursor)
1250 {
1251 cursor->resources[0] = (void*)hcursor;
1252 cursor->resources[1] = NULL;
1253 cursor->host = host;
1254 cursor->flags = 0;
1255 ret = GATE_RESULT_OK;
1256 }
1257 return ret;
1258 }
1259 gate_result_t gate_ui_cursor_create_file(gate_ui_cursor_t* cursor, gate_ui_host_t* host, gate_string_t const* filepath)
1260 {
1261 return GATE_RESULT_NOTIMPLEMENTED;
1262 }
1263
1264 gate_result_t gate_ui_cursor_copy(gate_ui_cursor_t* dsticon, gate_ui_cursor_t const* srcicon)
1265 {
1266 gate_result_t ret = GATE_RESULT_FAILED;
1267 #if !defined(GATE_SYS_WINCE) && !defined(GATE_SYS_WIN16)
1268 if (!GATE_FLAG_ENABLED(srcicon->flags, GATE_UI_CURSOR_FLAG_STOCK))
1269 {
1270 dsticon->resources[0] = (void*)CopyImage((HANDLE)srcicon->resources[0], IMAGE_CURSOR, 0, 0, 0);
1271 if (dsticon->resources[0])
1272 {
1273 dsticon->resources[1] = NULL;
1274 dsticon->host = srcicon->host;
1275 dsticon->flags = 0;
1276 }
1277 }
1278 else
1279 #endif /* ! GATE_SYS_WINCE */
1280 {
1281 gate_mem_copy(dsticon, srcicon, sizeof(gate_ui_cursor_t));
1282 }
1283 return ret;
1284 }
1285 gate_result_t gate_ui_cursor_destroy(gate_ui_cursor_t* cursor)
1286 {
1287 gate_result_t ret = GATE_RESULT_FAILED;
1288 if (cursor)
1289 {
1290 ret = GATE_RESULT_OK;
1291 if (!GATE_FLAG_ENABLED(cursor->flags, GATE_UI_CURSOR_FLAG_STOCK))
1292 {
1293 #if !defined(GATE_SYS_WINCE)
1294 if (!DestroyCursor((HCURSOR)cursor->resources[0]))
1295 {
1296 ret = GATE_RESULT_FAILED;
1297 }
1298 #endif
1299 }
1300 }
1301 return ret;
1302 }
1303
1304
1305
1306 #endif /* GATE_UI_WINAPI */
1307
1308
1309 #if defined(GATE_UI_GTK)
1310
1311 #include "gate/ui/gateui_gtk.h"
1312
1313 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)
1314 {
1315 return gate_ui_graphics_create_image(graph, host, width, height, 32);
1316 }
1317
1318 static cairo_format_t gate_ui_graphics_resolve_format(gate_uint32_t depth)
1319 {
1320 if ((depth == 0) || (depth > 24))
1321 {
1322 return CAIRO_FORMAT_ARGB32;
1323 }
1324 else if (depth > 16)
1325 {
1326 return CAIRO_FORMAT_RGB24;
1327 }
1328 else if (depth > 8)
1329 {
1330 return CAIRO_FORMAT_RGB16_565;
1331 }
1332 else if (depth > 2)
1333 {
1334 return CAIRO_FORMAT_A8;
1335 }
1336 else
1337 {
1338 return CAIRO_FORMAT_A1;
1339 }
1340
1341 }
1342
1343 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)
1344 {
1345 gate_result_t ret = GATE_RESULT_FAILED;
1346 cairo_t* cr = NULL;
1347 cairo_surface_t* surface = NULL;
1348 cairo_format_t format;
1349
1350 do
1351 {
1352 gate_mem_clear(graph, sizeof(gate_ui_graphics_t));
1353 format = gate_ui_graphics_resolve_format(depth);
1354
1355 surface = cairo_image_surface_create(format, width, height);
1356 if (surface == NULL)
1357 {
1358 ret = GATE_RESULT_OUTOFRESOURCES;
1359 break;
1360 }
1361 cr = cairo_create(surface);
1362 if (cr == NULL)
1363 {
1364 cairo_surface_destroy(surface);
1365 ret = GATE_RESULT_OUTOFRESOURCES;
1366 break;
1367 }
1368
1369 graph->host = host;
1370 graph->width = width;
1371 graph->height = height;
1372 graph->resources[0] = cr;
1373 graph->resources[1] = surface;
1374
1375 ret = GATE_RESULT_OK;
1376 } while (0);
1377
1378 return ret;
1379 }
1380 gate_result_t gate_ui_graphics_create_image_from(gate_ui_graphics_t* graph, gate_ui_host_t* host, gate_rasterimage_t const* rasterimage)
1381 {
1382 gate_result_t ret = gate_ui_graphics_create_image(graph, host, rasterimage->width, rasterimage->height, 32);
1383
1384 if (GATE_SUCCEEDED(ret))
1385 {
1386 gate_ui_point_t pnt = { 0, 0 };
1387 gate_ui_size_t sz = { rasterimage->width, rasterimage->height };
1388 ret = gate_ui_graphics_draw_image(graph, rasterimage, &pnt, &sz, &pnt);
1389 if (GATE_FAILED(ret))
1390 {
1391 gate_ui_graphics_destroy(graph);
1392 gate_mem_clear(graph, sizeof(gate_ui_graphics_t));
1393 }
1394 }
1395 return ret;
1396 }
1397 gate_result_t gate_ui_graphics_create_ctrl(gate_ui_graphics_t* graph, gate_ui_ctrl_t* ctrl)
1398 {
1399 gate_result_t ret = GATE_RESULT_FAILED;
1400 cairo_surface_t* surface = NULL;
1401 cairo_t* cr = NULL;
1402
1403 do
1404 {
1405 gate_ui_host_t* host = GATE_UI_GTK_GET_CTRL_HOST(ctrl);
1406 GtkWidget* widget = GATE_UI_GTK_GET_CTRL_WIDGET(ctrl);
1407 GdkWindow* window = NULL;
1408 int width, height;
1409
1410 if (!host || !widget)
1411 {
1412 ret = GATE_RESULT_NOTAVAILABLE;
1413 break;
1414 }
1415
1416 window = gtk_widget_get_window(widget);
1417 width = gtk_widget_get_allocated_width(widget);
1418 height = gtk_widget_get_allocated_height(widget);
1419 surface = gdk_window_create_similar_surface(window, CAIRO_CONTENT_COLOR, width, height);
1420 if (!surface)
1421 {
1422 ret = GATE_RESULT_OUTOFRESOURCES;
1423 break;
1424 }
1425 cr = cairo_create(surface);
1426 if (!cr)
1427 {
1428 ret = GATE_RESULT_FAILED;
1429 break;
1430 }
1431
1432 gate_mem_clear(graph, sizeof(gate_ui_graphics_t));
1433 graph->host = host;
1434 graph->width = width;
1435 graph->height = height;
1436 graph->resources[0] = cr;
1437 graph->resources[1] = surface;
1438 cr = NULL;
1439 surface = NULL;
1440 ret = GATE_RESULT_OK;
1441 } while (0);
1442
1443 if (cr)
1444 {
1445 cairo_destroy(cr);
1446 }
1447 if (surface)
1448 {
1449 cairo_surface_destroy(surface);
1450 }
1451 return ret;
1452 }
1453 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)
1454 {
1455 gate_result_t ret = GATE_RESULT_FAILED;
1456
1457 do
1458 {
1459 gate_mem_clear(graph, sizeof(gate_ui_graphics_t));
1460 graph->host = host;
1461 graph->resources[0] = cairo_reference((cairo_t*)graphics); /**< cairo_t */
1462 graph->resources[1] = param; /**< surface */
1463 graph->width = width;
1464 graph->height = height;
1465 ret = GATE_RESULT_OK;
1466 } while (0);
1467
1468 return ret;
1469 }
1470 gate_result_t gate_ui_graphics_destroy(gate_ui_graphics_t* graph)
1471 {
1472 cairo_t* cr = graph->resources[0];
1473 cairo_surface_t* surface = graph->resources[1];
1474
1475 if (surface)
1476 {
1477 cairo_surface_destroy(surface);
1478 }
1479 if (cr)
1480 {
1481 cairo_destroy(cr);
1482 }
1483 return GATE_RESULT_OK;
1484 }
1485
1486
1487 gate_int32_t gate_ui_graphics_width(gate_ui_graphics_t* graph)
1488 {
1489 return graph->width;
1490 }
1491 gate_int32_t gate_ui_graphics_height(gate_ui_graphics_t* graph)
1492 {
1493 return graph->height;
1494 }
1495 gate_result_t gate_ui_graphics_set_pixel(gate_ui_graphics_t* graph, gate_ui_point_t pos, gate_ui_color_t col)
1496 {
1497 cairo_t* cr = (cairo_t*)graph->resources[0];
1498 cairo_set_source_rgb(cr, col.r, col.g, col.b);
1499 cairo_rectangle(cr, (double)pos.x, (double)pos.y, 1.0, 1.0);
1500 cairo_fill(cr);
1501 return GATE_RESULT_OK;
1502 }
1503 gate_result_t gate_ui_graphics_get_pixel(gate_ui_graphics_t* graph, gate_ui_point_t pos, gate_ui_color_t* col)
1504 {
1505 return GATE_RESULT_NOTIMPLEMENTED;
1506 }
1507 gate_result_t gate_ui_graphics_draw(gate_ui_graphics_t* graph, gate_ui_graphics_t* srcgraph,
1508 gate_ui_point_t const* dst, gate_ui_size_t const* size, gate_ui_point_t const* src)
1509 {
1510 cairo_t* cr = (cairo_t*)graph->resources[0];
1511 cairo_surface_t* src_surface = srcgraph->resources[1];
1512 if (src_surface == NULL)
1513 {
1514 return GATE_RESULT_INVALIDINPUT;
1515 }
1516
1517 cairo_set_source_surface(cr, src_surface, dst ? dst->x : 0, dst ? dst->y : 0);
1518 /* TODO: dst/src */
1519 cairo_paint(cr);
1520 return GATE_RESULT_OK;
1521 }
1522
1523 gate_result_t gate_ui_graphics_draw_ex(gate_ui_graphics_t* graph, gate_ui_graphics_t* src_graph,
1524 gate_ui_position_t const* dest_rect, gate_ui_position_t const* src_rect)
1525 {
1526 cairo_t* cr = (cairo_t*)graph->resources[0];
1527 cairo_surface_t* src_surface = src_graph->resources[1];
1528 if (src_surface == NULL)
1529 {
1530 return GATE_RESULT_INVALIDINPUT;
1531 }
1532
1533 cairo_set_source_surface(cr, src_surface, 0, 0);
1534 /* TODO: dst/src */
1535 cairo_paint(cr);
1536 return GATE_RESULT_OK;
1537 }
1538
1539 static GdkPixbuf* gate_ui_gtk_raster_to_pixbuf(gate_rasterimage_t const* srcimage,
1540 gate_int32_t src_x, gate_int32_t src_y, gate_int32_t width, gate_int32_t height)
1541 {
1542 GdkPixbuf* buf;
1543 gate_int32_t x, y;
1544
1545 if (src_x + width > (gate_int32_t)srcimage->width)
1546 {
1547 width = (gate_int32_t)srcimage->width - src_x;
1548 }
1549 if (src_y + height > (gate_int32_t)srcimage->height)
1550 {
1551 height = (gate_int32_t)srcimage->height - src_y;
1552 }
1553
1554 buf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, (int)width, (int)height);
1555 if (buf != NULL)
1556 {
1557 guchar* pixels = gdk_pixbuf_get_pixels(buf);
1558
1559 for (y = 0; y < height; ++y)
1560 {
1561 guchar* dst_pixels = pixels + (y * width) * 4;
1562 gate_color_t const* src_pixels = (((gate_color_t*)gate_rasterimage_get_line_ptr(srcimage, (src_y + y))) + src_x);
1563 for (x = 0; x < width; ++x)
1564 {
1565 dst_pixels[0] = src_pixels->r;
1566 dst_pixels[1] = src_pixels->g;
1567 dst_pixels[2] = src_pixels->b;
1568 dst_pixels[3] = src_pixels->a;
1569 dst_pixels += 4;
1570 src_pixels++;
1571 }
1572 }
1573 }
1574 return buf;
1575 }
1576
1577 gate_result_t gate_ui_graphics_draw_image(gate_ui_graphics_t* graph, gate_rasterimage_t const* srcimage,
1578 gate_ui_point_t const* dst, gate_ui_size_t const* size, gate_ui_point_t const* srcpos)
1579 {
1580 cairo_t* cr = (cairo_t*)graph->resources[0];
1581 int width, height;
1582 GdkPixbuf* buf;
1583 gate_int32_t src_x = 0;
1584 gate_int32_t src_y = 0;
1585 gate_int32_t dst_x = 0;
1586 gate_int32_t dst_y = 0;
1587
1588 width = srcimage->width;
1589 height = srcimage->height;
1590 if (size)
1591 {
1592 width = size->width;
1593 height = size->height;
1594 }
1595 if (dst)
1596 {
1597 dst_x = dst->x;
1598 dst_y = dst->y;
1599 }
1600 if (srcpos)
1601 {
1602 src_x = srcpos->x;
1603 src_y = srcpos->y;
1604 }
1605
1606 buf = gate_ui_gtk_raster_to_pixbuf(srcimage, src_x, src_y, width, height);
1607 if (buf == NULL)
1608 {
1609 return GATE_RESULT_OUTOFRESOURCES;
1610 }
1611
1612 gdk_cairo_set_source_pixbuf(cr, buf, dst_x, dst_y);
1613 cairo_paint(cr);
1614 g_object_unref(buf);
1615
1616 return GATE_RESULT_OK;
1617 }
1618
1619
1620 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)
1621 {
1622 cairo_t* cr = (cairo_t*)graph->resources[0];
1623
1624 cairo_set_source_rgba(cr, (double)col.r / 255.0, (double)col.g / 255.0, (double)col.b / 255.0, (double)col.a / 255.0);
1625 cairo_set_line_width(cr, (double)linewidth);
1626 cairo_move_to(cr, from.x, from.y);
1627 cairo_line_to(cr, to.x, to.y);
1628 cairo_stroke(cr);
1629 return GATE_RESULT_OK;
1630 }
1631 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)
1632 {
1633 cairo_t* cr = (cairo_t*)graph->resources[0];
1634
1635 if (colfill)
1636 {
1637 cairo_set_source_rgba(cr, (double)colfill->r / 255.0, (double)colfill->g / 255.0, (double)colfill->b / 255.0, (double)colfill->a / 255.0);
1638 cairo_rectangle(cr, rect.pos.x, rect.pos.y, rect.size.width, rect.size.height);
1639 cairo_fill(cr);
1640 }
1641
1642 if (colline)
1643 {
1644 cairo_set_source_rgba(cr, (double)colline->r / 255.0, (double)colline->g / 255.0, (double)colline->b / 255.0, (double)colline->a / 255.0);
1645 cairo_set_line_width(cr, (double)linewidth);
1646 cairo_rectangle(cr, rect.pos.x, rect.pos.y, rect.size.width, rect.size.height);
1647 cairo_stroke(cr);
1648 }
1649
1650 return GATE_RESULT_OK;
1651 }
1652 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)
1653 {
1654 cairo_t* cr = (cairo_t*)graph->resources[0];
1655
1656 if (pointcount > 2)
1657 {
1658 cairo_move_to(cr, points->x, points->y);
1659 --pointcount;
1660 ++points;
1661
1662 while (pointcount-- != 0)
1663 {
1664 cairo_line_to(cr, points->x, points->y);
1665 cairo_move_to(cr, points->x, points->y);
1666 ++points;
1667 }
1668
1669 if (colfill)
1670 {
1671 cairo_set_source_rgba(cr, (double)colfill->r / 255.0, (double)colfill->g / 255.0, (double)colfill->b / 255.0, (double)colfill->a / 255.0);
1672 if (colline)
1673 {
1674 cairo_fill_preserve(cr);
1675 }
1676 else
1677 {
1678 cairo_fill(cr);
1679 }
1680 }
1681
1682 if (colline)
1683 {
1684 cairo_set_source_rgba(cr, (double)colline->r / 255.0, (double)colline->g / 255.0, (double)colline->b / 255.0, (double)colline->a / 255.0);
1685 cairo_set_line_width(cr, (double)linewidth);
1686 cairo_stroke(cr);
1687 }
1688
1689 }
1690 return GATE_RESULT_OK;
1691 }
1692
1693 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* textlens)
1694 {
1695 return GATE_RESULT_NOTIMPLEMENTED;
1696 }
1697
1698 gate_result_t gate_ui_graphics_get_text_size(gate_ui_graphics_t* graph, gate_ui_font_t const* font, gate_string_t const* text, gate_int32_t* width, gate_int32_t* height)
1699 {
1700 cairo_t* cr = (cairo_t*)graph->resources[0];
1701 /*cairo_scaled_font_t* sf = cairo_get_scaled_font(cr);*/
1702 cairo_text_extents_t extents;
1703 gate_cstrbuffer_t buffer;
1704 if(NULL == gate_cstrbuffer_create_string(&buffer, text, false))
1705 {
1706 return GATE_RESULT_OUTOFMEMORY;
1707 }
1708 cairo_set_font_size(cr, font->size);
1709 cairo_text_extents(cr, gate_cstrbuffer_get(&buffer), &extents);
1710 if (width) *width = (gate_int32_t)extents.width + 0.5;
1711 if (height) *height = (gate_int32_t)extents.height + 0.5;
1712 return GATE_RESULT_OK;
1713 }
1714
1715 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)
1716 {
1717 cairo_t* cr = (cairo_t*)graph->resources[0];
1718 gate_cstrbuffer_t buffer;
1719 if(NULL == gate_cstrbuffer_create_string(&buffer, text, false))
1720 {
1721 return GATE_RESULT_OUTOFMEMORY;
1722 }
1723 cairo_set_source_rgb(cr, font->color.r / 255.0, font->color.g / 255.0, font->color.b / 255.0);
1724 cairo_set_font_size(cr, font->size);
1725 cairo_move_to(cr, (double)pos->pos.x, (double)pos->pos.y);
1726 cairo_show_text(cr, gate_cstrbuffer_get(&buffer));
1727 /*
1728 cairo_set_source_rgb(cr, 0.1, 0.1, 0.1);
1729
1730 cairo_select_font_face(cr, "Purisa",
1731 CAIRO_FONT_SLANT_NORMAL,
1732 CAIRO_FONT_WEIGHT_BOLD);
1733
1734 cairo_set_font_size(cr, 13);
1735
1736 cairo_move_to(cr, 20, 30);
1737 cairo_show_text(cr, "Most relationships seem so transitory");
1738 cairo_move_to(cr, 20, 60);
1739 cairo_show_text(cr, "They're all good but not the permanent one");
1740
1741 cairo_move_to(cr, 20, 120);
1742 cairo_show_text(cr, "Who doesn't long for someone to hold");
1743
1744 cairo_move_to(cr, 20, 150);
1745 cairo_show_text(cr, "Who knows how to love you without being told");
1746 cairo_move_to(cr, 20, 180);
1747 cairo_show_text(cr, "Somebody tell me why I'm on my own");
1748 cairo_move_to(cr, 20, 210);
1749 cairo_show_text(cr, "If there's a soulmate for everyone");
1750
1751 */
1752 return GATE_RESULT_OK;
1753 }
1754
1755 void* gate_ui_graphics_handle(gate_ui_graphics_t* graph)
1756 {
1757 return graph->resources[0];
1758 }
1759 void* gate_ui_graphics_surface(gate_ui_graphics_t* graph)
1760 {
1761 return graph->resources[1];
1762 }
1763
1764
1765
1766
1767
1768 /************
1769 * icon GTK *
1770 ************/
1771
1772 /* https://specifications.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html */
1773
1774 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)
1775 {
1776 gate_result_t ret = GATE_RESULT_OK;
1777 char const* gtk_stock_id = NULL;
1778 GtkIconTheme* theme = NULL;
1779 GtkIconInfo* info = NULL;
1780 gint size;
1781 GError* error = NULL;
1782 GdkPixbuf* pixbuf = NULL;
1783
1784 do
1785 {
1786 if (GATE_FLAG_ENABLED(flags, GATE_UI_ICON_FLAG_LARGE))
1787 {
1788 size = 48;
1789 }
1790 else if (GATE_FLAG_ENABLED(flags, GATE_UI_ICON_FLAG_SMALL))
1791 {
1792 size = 16;
1793 }
1794 else
1795 {
1796 size = 32;
1797 }
1798
1799 theme = gtk_icon_theme_get_default();
1800 if (theme == NULL)
1801 {
1802 ret = GATE_RESULT_NOTAVAILABLE;
1803 break;
1804 }
1805
1806 switch (stock_id)
1807 {
1808 case GATE_UI_ICON_STOCK_APP: gtk_stock_id = "system-run"; break;
1809 case GATE_UI_ICON_STOCK_DOCUMENT: gtk_stock_id = "document-properties"; break;
1810 case GATE_UI_ICON_STOCK_FOLDER: gtk_stock_id = "folder"; break;
1811 case GATE_UI_ICON_STOCK_FOLDEROPEN: gtk_stock_id = "folder-open"; break;
1812 case GATE_UI_ICON_STOCK_NEWFILE: gtk_stock_id = "document-new"; break;
1813 case GATE_UI_ICON_STOCK_OPENFILE: gtk_stock_id = "document-open"; break;
1814 case GATE_UI_ICON_STOCK_SAVEFILE: gtk_stock_id = "document-save"; break;
1815 case GATE_UI_ICON_STOCK_PRINTER: gtk_stock_id = "document-print"; break;
1816 case GATE_UI_ICON_STOCK_CUT: gtk_stock_id = "edit-cut"; break;
1817 case GATE_UI_ICON_STOCK_COPY: gtk_stock_id = "edit-copy"; break;
1818 case GATE_UI_ICON_STOCK_PASTE: gtk_stock_id = "edit-paste"; break;
1819 case GATE_UI_ICON_STOCK_DELETE: gtk_stock_id = "edit-delete"; break;
1820
1821 case GATE_UI_ICON_STOCK_FIND: gtk_stock_id = "edit-find"; break;
1822 case GATE_UI_ICON_STOCK_HELP: gtk_stock_id = "help-contents"; break;
1823
1824 case GATE_UI_ICON_STOCK_STORAGE: gtk_stock_id = "drive-harddisk"; break;
1825 case GATE_UI_ICON_STOCK_COMPUTER: gtk_stock_id = "computer"; break;
1826 case GATE_UI_ICON_STOCK_NETWORK: gtk_stock_id = "network-wired"; break;
1827 case GATE_UI_ICON_STOCK_GLOBE: gtk_stock_id = "applications-internet"; break;
1828 case GATE_UI_ICON_STOCK_SETTINGS: gtk_stock_id = "preferences-system"; break;
1829 case GATE_UI_ICON_STOCK_HOME: gtk_stock_id = "go-home"; break;
1830 case GATE_UI_ICON_STOCK_IMAGE: gtk_stock_id = "image-x-generic"; break;
1831 case GATE_UI_ICON_STOCK_AUDIO: gtk_stock_id = "audio-x-generic"; break;
1832 case GATE_UI_ICON_STOCK_VIDEO: gtk_stock_id = "video-x-generic"; break;
1833 case GATE_UI_ICON_STOCK_MAIL: gtk_stock_id = "mail-send-receive"; break;
1834 default: break;
1835 }
1836
1837 info = gtk_icon_theme_lookup_icon(theme, gtk_stock_id, size, GTK_ICON_LOOKUP_USE_BUILTIN | GTK_ICON_LOOKUP_GENERIC_FALLBACK);
1838 if (info == NULL)
1839 {
1840 ret = GATE_RESULT_NOMATCH;
1841 break;
1842 }
1843
1844 pixbuf = gtk_icon_info_load_icon(info, &error);
1845 if (pixbuf == NULL)
1846 {
1847 ret = GATE_RESULT_FAILED;
1848 break;
1849 }
1850
1851 gate_mem_clear(icon, sizeof(gate_ui_icon_t));
1852 icon->host = host;
1853 icon->flags = flags & (GATE_UI_ICON_FLAG_SMALL | GATE_UI_ICON_FLAG_LARGE);
1854 icon->resources[0] = pixbuf;
1855
1856 ret = GATE_RESULT_OK;
1857 } while (0);
1858
1859 return ret;
1860 }
1861 gate_result_t gate_ui_icon_create_native(gate_ui_icon_t* icon, gate_ui_host_t* host, void* handle, gate_uint32_t flags)
1862 {
1863 gate_mem_clear(icon, sizeof(gate_ui_icon_t));
1864 icon->host = host;
1865 icon->flags = flags;
1866 icon->resources[0] = handle;
1867 return GATE_RESULT_OK;
1868 }
1869 gate_result_t gate_ui_icon_create_image(gate_ui_icon_t* icon, gate_ui_host_t* host, gate_rasterimage_t const* image)
1870 {
1871 GdkPixbuf* buf = gate_ui_gtk_raster_to_pixbuf(image, 0, 0, image->width, image->height);
1872 if (buf == NULL)
1873 {
1874 return GATE_RESULT_OUTOFRESOURCES;
1875 }
1876 gate_mem_clear(icon, sizeof(gate_ui_icon_t));
1877 icon->host = host;
1878 icon->flags = 0;
1879 icon->resources[0] = buf;
1880 return GATE_RESULT_OK;
1881 }
1882 gate_result_t gate_ui_icon_create_file(gate_ui_icon_t* icon, gate_ui_host_t* host, gate_string_t const* filepath)
1883 {
1884 gate_result_t ret = GATE_RESULT_FAILED;
1885 char file_buffer[GATE_MAX_FILEPATH_LENGTH];
1886 GtkWidget* image_widget = NULL;
1887 gint pix_size = 0;
1888 gate_uint32_t flags = 0;
1889
1890 GATE_STRING_TO_BUFFER(filepath, file_buffer);
1891 image_widget = gtk_image_new_from_file(file_buffer);
1892 if (image_widget != NULL)
1893 {
1894 pix_size = gtk_image_get_pixel_size(GTK_IMAGE(image_widget));
1895 if (pix_size < 24) flags |= GATE_UI_ICON_FLAG_SMALL;
1896 if (pix_size > 40) flags |= GATE_UI_ICON_FLAG_LARGE;
1897 ret = gate_ui_icon_create_native(icon, host, image_widget, flags);
1898 if (GATE_FAILED(ret))
1899 {
1900 gtk_widget_destroy(image_widget);
1901 }
1902 }
1903 return ret;
1904 }
1905 gate_result_t gate_ui_icon_copy(gate_ui_icon_t* dsticon, gate_ui_icon_t const* srcicon)
1906 {
1907 gate_mem_copy(dsticon, srcicon, sizeof(gate_ui_icon_t));
1908 if (!GATE_FLAG_ENABLED(srcicon->flags, GATE_UI_ICON_FLAG_STOCK))
1909 {
1910 if (srcicon->resources[0])
1911 {
1912 dsticon->resources[0] = g_object_ref((gpointer)srcicon->resources[0]);
1913 }
1914 }
1915 return GATE_RESULT_OK;
1916 }
1917 gate_result_t gate_ui_icon_destroy(gate_ui_icon_t* icon)
1918 {
1919 if (icon->resources[0])
1920 {
1921 g_object_unref((gpointer)icon->resources[0]);
1922 }
1923 gate_mem_clear(icon, sizeof(gate_ui_icon_t));
1924 return GATE_RESULT_OK;
1925 }
1926
1927
1928
1929
1930
1931 /****************
1932 * iconlist GTK *
1933 ****************/
1934
1935 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)
1936 {
1937 gate_result_t ret = GATE_RESULT_FAILED;
1938 do
1939 {
1940 gate_mem_clear(ilst, sizeof(gate_ui_iconlist_t));
1941 ilst->resources[0] = gate_arraylist_create(sizeof(gate_ui_icon_t), NULL, 8, NULL, NULL);
1942 if (NULL == ilst->resources[0])
1943 {
1944 ret = GATE_RESULT_OUTOFMEMORY;
1945 break;
1946 }
1947 ilst->host = host;
1948 ilst->width = width;
1949 ilst->height = height;
1950 ilst->flags = 0;
1951 ret = GATE_RESULT_OK;
1952 } while (0);
1953 return ret;
1954 }
1955 gate_result_t gate_ui_iconlist_destroy(gate_ui_iconlist_t* ilst)
1956 {
1957 gate_result_t ret = GATE_RESULT_OK;
1958 gate_ui_icon_t* ptr_icon;
1959 gate_size_t count;
1960 gate_arraylist_t arr;
1961 do
1962 {
1963 arr = (gate_arraylist_t)ilst->resources[0];
1964 if (!arr)
1965 {
1966 break;
1967 }
1968 count = gate_arraylist_length(arr);
1969 if (count != 0)
1970 {
1971 ptr_icon = gate_arraylist_get(arr, 0);
1972 while (count-- != 0)
1973 {
1974 gate_ui_icon_destroy(ptr_icon);
1975 ++ptr_icon;
1976 }
1977 }
1978 gate_arraylist_release(arr);
1979 ret = GATE_RESULT_OK;
1980 } while (0);
1981 return ret;
1982 }
1983 gate_size_t gate_ui_iconlist_count(gate_ui_iconlist_t* ilst)
1984 {
1985 gate_size_t ret = 0;
1986 gate_arraylist_t arr = (gate_arraylist_t)ilst->resources[0];
1987 if (arr)
1988 {
1989 ret = gate_arraylist_length(arr);
1990 }
1991 return ret;
1992 }
1993 gate_result_t gate_ui_iconlist_add_icon(gate_ui_iconlist_t* ilst, gate_ui_icon_t const* icon, gate_intptr_t* icon_key)
1994 {
1995 gate_ui_icon_t new_icon = GATE_INIT_EMPTY;
1996 gate_arraylist_t arr = (gate_arraylist_t)ilst->resources[0];
1997 gate_result_t ret = gate_ui_icon_copy(&new_icon, icon);
1998 gate_size_t index;
1999 if (GATE_SUCCEEDED(ret))
2000 {
2001 index = gate_arraylist_length(arr);
2002 if (NULL == gate_arraylist_add(arr, &new_icon))
2003 {
2004 ret = GATE_RESULT_OUTOFMEMORY;
2005 gate_ui_icon_destroy(&new_icon);
2006 }
2007 else
2008 {
2009 if (icon_key)
2010 {
2011 *icon_key = (gate_intptr_t)index;
2012 }
2013 }
2014 }
2015 return ret;
2016 }
2017 gate_result_t gate_ui_iconlist_add_image(gate_ui_iconlist_t* ilst, gate_rasterimage_t const* image, gate_intptr_t* icon_key)
2018 {
2019 gate_ui_icon_t new_icon = GATE_INIT_EMPTY;
2020 gate_arraylist_t arr = (gate_arraylist_t)ilst->resources[0];
2021 gate_result_t ret = gate_ui_icon_create_image(&new_icon, ilst->host, image);
2022 gate_size_t index;
2023 if (GATE_SUCCEEDED(ret))
2024 {
2025 index = gate_arraylist_length(arr);
2026 if (NULL == gate_arraylist_add(arr, &new_icon))
2027 {
2028 ret = GATE_RESULT_OUTOFMEMORY;
2029 gate_ui_icon_destroy(&new_icon);
2030 }
2031 else
2032 {
2033 if (icon_key)
2034 {
2035 *icon_key = (gate_intptr_t)index;
2036 }
2037 }
2038 }
2039 return ret;
2040 }
2041 gate_result_t gate_ui_iconlist_get_icon(gate_ui_iconlist_t* ilst, gate_intptr_t icon_key, gate_ui_icon_t* icon)
2042 {
2043 gate_result_t ret = GATE_RESULT_FAILED;
2044 gate_ui_icon_t new_icon = GATE_INIT_EMPTY;
2045 gate_arraylist_t arr = (gate_arraylist_t)ilst->resources[0];
2046 gate_ui_icon_t const* ptr_icon = NULL;
2047
2048 ptr_icon = (gate_ui_icon_t const*)gate_arraylist_get(arr, (gate_size_t)icon_key);
2049 if (NULL == ptr_icon)
2050 {
2051 ret = GATE_RESULT_NOTAVAILABLE;
2052 }
2053 else
2054 {
2055 ret = gate_ui_icon_copy(icon, ptr_icon);
2056 }
2057 return ret;
2058 }
2059
2060 void* gate_ui_iconlist_get_handle(gate_ui_iconlist_t* ilst, gate_intptr_t icon_key)
2061 {
2062 /* TODO */
2063 return NULL;
2064 }
2065
2066
2067 /**************
2068 * cursor GTK *
2069 **************/
2070
2071 gate_result_t gate_ui_cursor_create_stock(gate_ui_cursor_t* cursor, gate_ui_host_t* host, gate_uint32_t stock_id)
2072 {
2073 gate_result_t ret = GATE_RESULT_FAILED;
2074 char const* cursor_name = NULL;
2075 GdkCursor* gdk_cursor = NULL;
2076 GdkDisplay* display = NULL;
2077
2078 switch (stock_id)
2079 {
2080 case GATE_UI_CURSOR_STOCK_POINTER: cursor_name = "default"; break;
2081 case GATE_UI_CURSOR_STOCK_BUSY: cursor_name = "wait"; break;
2082 case GATE_UI_CURSOR_STOCK_STARTING: cursor_name = "progress"; break;
2083 case GATE_UI_CURSOR_STOCK_HAND: cursor_name = "pointer"; break;
2084 case GATE_UI_CURSOR_STOCK_TEXT: cursor_name = "text"; break;
2085 case GATE_UI_CURSOR_STOCK_REJECTED: cursor_name = "not-allowed"; break;
2086 case GATE_UI_CURSOR_STOCK_SIZE_ALL: cursor_name = "all-scroll"; break;
2087 case GATE_UI_CURSOR_STOCK_SIZE_LEFTRIGHT: cursor_name = "ew-resize"; break;
2088 case GATE_UI_CURSOR_STOCK_SIZE_UPDOWN: cursor_name = "ns-resize"; break;
2089 case GATE_UI_CURSOR_STOCK_SIZE_LEFTUPRIGHTDOWN: cursor_name = "nwse-resize"; break;
2090 case GATE_UI_CURSOR_STOCK_SIZE_RIGHTUPKEFTDOWN: cursor_name = "nesw-resize"; break;
2091 }
2092 if (cursor_name == NULL)
2093 {
2094 ret = GATE_RESULT_NOTSUPPORTED;
2095 }
2096 else
2097 {
2098 gdk_cursor = gdk_cursor_new_from_name(display, cursor_name);
2099 if (NULL == gdk_cursor)
2100 {
2101 ret = GATE_RESULT_FAILED;
2102 }
2103 else
2104 {
2105 cursor->resources[0] = gdk_cursor;
2106 cursor->resources[1] = display;
2107 cursor->host = host;
2108 cursor->flags = GATE_UI_CURSOR_FLAG_STOCK;
2109 ret = GATE_RESULT_OK;
2110 }
2111 }
2112 return ret;
2113 }
2114 gate_result_t gate_ui_cursor_create_native(gate_ui_cursor_t* cursor, gate_ui_host_t* host, void* handle, gate_uint32_t flags)
2115 {
2116 cursor->resources[0] = handle;
2117 cursor->resources[1] = gdk_cursor_get_image((GdkCursor*)handle);
2118 cursor->host = host;
2119 cursor->flags = flags;
2120 return GATE_RESULT_OK;
2121 }
2122 gate_result_t gate_ui_cursor_create_image(gate_ui_cursor_t* cursor, gate_ui_host_t* host, gate_rasterimage_t const* image,
2123 gate_uint16_t x, gate_uint16_t y)
2124 {
2125 return GATE_RESULT_NOTIMPLEMENTED;
2126 }
2127 gate_result_t gate_ui_cursor_create_file(gate_ui_cursor_t* cursor, gate_ui_host_t* host, gate_string_t const* filepath)
2128 {
2129 return GATE_RESULT_NOTIMPLEMENTED;
2130 }
2131 gate_result_t gate_ui_cursor_copy(gate_ui_cursor_t* dstcursor, gate_ui_cursor_t const* srccursor)
2132 {
2133 GdkCursor* gdk_src_cursor = (GdkCursor*)dstcursor->resources[0];
2134 GdkCursor* gdk_dst_cursor = gdk_cursor_new_from_pixbuf((GdkDisplay*)srccursor->resources[1], gdk_cursor_get_image(gdk_src_cursor), -1, -1);
2135 if (gdk_dst_cursor)
2136 {
2137 dstcursor->resources[0] = gdk_dst_cursor;
2138 dstcursor->resources[1] = srccursor->resources[1];
2139 dstcursor->host = srccursor->host;
2140 dstcursor->flags = srccursor->flags;
2141 return GATE_RESULT_OK;
2142 }
2143 else
2144 {
2145 return GATE_RESULT_FAILED;
2146 }
2147 }
2148 gate_result_t gate_ui_cursor_destroy(gate_ui_cursor_t* cursor)
2149 {
2150 GdkCursor* gdk_cursor = (GdkCursor*)cursor->resources[0];
2151 if (gdk_cursor)
2152 {
2153 g_object_unref(gdk_cursor);
2154 }
2155 gate_mem_clear(cursor, sizeof(gate_ui_cursor_t));
2156 return GATE_RESULT_OK;
2157 }
2158
2159 #endif /* GATE_UI_GTK */
2160
2161
2162
2163 #if defined(GATE_UI_MOTIF)
2164
2165 #include "gate/debugging.h"
2166 #include "gate/ui/gateui_motif.h"
2167
2168 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)
2169 {
2170 2 return gate_ui_graphics_create_image(graph, host, width, height, 0);
2171 }
2172 7 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)
2173 {
2174 7 gate_result_t ret = GATE_RESULT_FAILED;
2175
2176 do
2177 {
2178 Display* display;
2179 int screen;
2180 int xdepth;
2181 Window root_window;
2182 Pixmap pixmap;
2183 GC context;
2184
2185 7 gate_mem_clear(graph, sizeof(gate_ui_graphics_t));
2186
2187 7 display = GATE_UI_MOTIF_GET_HOST_DISPLAY(host);
2188 7 screen = XDefaultScreen(display);
2189
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 xdepth = (depth == 0) ? XDefaultDepth(display, screen) : depth;
2190 7 root_window = XDefaultRootWindow(display);
2191 7 pixmap = XCreatePixmap(display, root_window, width, height, xdepth);
2192 7 context = XCreateGC(display, root_window, 0, 0);
2193 7 XFillRectangle(display, pixmap, context, 0, 0, width, height);
2194
2195 7 graph->host = host;
2196 7 graph->resources[0] = (void*)context;
2197 7 graph->resources[1] = (void*)(Drawable)pixmap;
2198 7 graph->width = width;
2199 7 graph->height = height;
2200
2201 7 XSetGraphicsExposures(display, context, 0);
2202 7 ret = GATE_RESULT_OK;
2203 } while (0);
2204 7 return ret;
2205 }
2206 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)
2207 {
2208 gate_result_t ret;
2209 do
2210 {
2211 4 ret = gate_ui_graphics_create_image(graph, host, rasterimage->width, rasterimage->height, 0);
2212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_BREAK_IF_FAILED(ret);
2213
2214 4 ret = gate_ui_graphics_draw_image(graph, rasterimage, NULL, NULL, NULL);
2215
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (GATE_FAILED(ret))
2216 {
2217 gate_ui_graphics_destroy(graph);
2218 break;
2219 }
2220
2221 4 ret = GATE_RESULT_OK;
2222 } while (0);
2223
2224 4 return ret;
2225 }
2226 2 gate_result_t gate_ui_graphics_create_ctrl(gate_ui_graphics_t* graph, gate_ui_ctrl_t* ctrl)
2227 {
2228 2 gate_result_t ret = GATE_RESULT_FAILED;
2229 do
2230 {
2231 2 gate_ui_host_t* host = GATE_UI_MOTIF_GET_CTRL_HOST(ctrl);
2232 2 Display* display = GATE_UI_MOTIF_GET_HOST_DISPLAY(host);
2233 2 Widget w = GATE_UI_MOTIF_GET_CTRL_WIDGET(ctrl);
2234 2 Window wnd = XtWindow(w);
2235 2 Dimension xwidth = 0, xheight = 0;
2236 2 GC context = XCreateGC(display, wnd, 0, NULL);
2237
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!context)
2238 {
2239 ret = GATE_RESULT_OUTOFRESOURCES;
2240 break;
2241 }
2242 2 XtVaGetValues(w, XtNwidth, &xwidth, XtNheight, &xheight, NULL, NULL);
2243
2244 2 graph->host = host;
2245 2 graph->resources[0] = (void*)context;
2246 2 graph->resources[1] = (void*)(Drawable)wnd;
2247 2 graph->resources[2] = (void*)wnd;
2248 2 graph->width = xwidth;
2249 2 graph->height = xheight;
2250
2251 2 XSetGraphicsExposures(display, context, 0);
2252 2 ret = GATE_RESULT_OK;
2253 } while (0);
2254 2 return ret;
2255 }
2256 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)
2257 {
2258 return GATE_RESULT_NOTIMPLEMENTED;
2259 }
2260 9 gate_result_t gate_ui_graphics_destroy(gate_ui_graphics_t* graph)
2261 {
2262 9 Display* display = GATE_UI_MOTIF_GET_HOST_DISPLAY(graph->host);
2263 9 GC context = (GC)graph->resources[0];
2264 9 Drawable drawable = (Drawable)graph->resources[1];
2265 9 Window window = (Window)graph->resources[2];
2266
2267
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if (display)
2268 {
2269
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2 times.
9 if (window == 0)
2270 {
2271 /* no window, expect a Pixmap surface */
2272
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
7 if (drawable != 0)
2273 {
2274 4 XFreePixmap(display, (Pixmap)drawable);
2275 }
2276 }
2277 else
2278 {
2279 }
2280
2281
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if (context)
2282 {
2283 9 XFreeGC(display, context);
2284 }
2285 }
2286
2287 9 return GATE_RESULT_NOTIMPLEMENTED;
2288 }
2289
2290 672 static unsigned long XGetRgbPixel(Display* display, gate_uint8_t r, gate_uint8_t g, gate_uint8_t b)
2291 {
2292 672 int screen = XDefaultScreen(display);
2293 672 Colormap cmap = XDefaultColormap(display, screen);
2294 XColor col;
2295 672 col.pixel = 0;
2296 672 col.red = ((gate_uint16_t)r) << 8;
2297 672 col.green = ((gate_uint16_t)g) << 8;
2298 672 col.blue = ((gate_uint16_t)b) << 8;
2299 672 col.flags = DoRed | DoGreen | DoBlue;
2300 672 XAllocColor(display, cmap, &col);
2301 672 return col.pixel;
2302 }
2303
2304 2 gate_int32_t gate_ui_graphics_width(gate_ui_graphics_t* graph)
2305 {
2306 2 return graph->width;
2307 }
2308
2309 2 gate_int32_t gate_ui_graphics_height(gate_ui_graphics_t* graph)
2310 {
2311 2 return graph->height;
2312 }
2313
2314 2 gate_result_t gate_ui_graphics_set_pixel(gate_ui_graphics_t* graph, gate_ui_point_t pos, gate_ui_color_t col)
2315 {
2316 2 Display* const display = GATE_UI_MOTIF_GET_HOST_DISPLAY(graph->host);
2317 2 GC const context = (GC)graph->resources[0];
2318 2 Drawable const drawable = (Drawable)graph->resources[1];
2319
2320 2 XSetForeground(display, context, XGetRgbPixel(display, col.r, col.g, col.b));
2321 2 XDrawPoint(display, drawable, context, pos.x, pos.y);
2322 2 return GATE_RESULT_OK;
2323 }
2324
2325 2 gate_result_t gate_ui_graphics_get_pixel(gate_ui_graphics_t* graph, gate_ui_point_t pos, gate_ui_color_t* col)
2326 {
2327 2 return GATE_RESULT_NOTIMPLEMENTED;
2328 }
2329
2330 2 gate_result_t gate_ui_graphics_draw(gate_ui_graphics_t* graph, gate_ui_graphics_t* srcgraph,
2331 gate_ui_point_t const* dst, gate_ui_size_t const* size, gate_ui_point_t const* srcpos)
2332 {
2333 2 Display* const display = GATE_UI_MOTIF_GET_HOST_DISPLAY(graph->host);
2334 2 GC const context = (GC)graph->resources[0];
2335 2 Drawable const target = (Drawable)graph->resources[1];
2336 2 Drawable const source = (Drawable)srcgraph->resources[1];
2337 int src_x, src_y, width, height, dst_x, dst_y;
2338 2 dst_x = dst->x;
2339 2 dst_y = dst->y;
2340 2 src_x = srcpos->x;
2341 2 src_y = srcpos->y;
2342 2 width = size->width;
2343 2 height = size->height;
2344
2345 2 XCopyArea(display, source, target, context, src_x, src_y, width, height, dst_x, dst_y);
2346 2 return GATE_RESULT_OK;
2347 }
2348
2349 2 gate_result_t gate_ui_graphics_draw_ex(gate_ui_graphics_t* graph, gate_ui_graphics_t* src_graph,
2350 gate_ui_position_t const* dest_rect, gate_ui_position_t const* src_rect)
2351 {
2352 2 Display* const display = GATE_UI_MOTIF_GET_HOST_DISPLAY(graph->host);
2353 2 GC const context = (GC)graph->resources[0];
2354 2 Drawable const target = (Drawable)graph->resources[1];
2355 2 Drawable const source = (Drawable)src_graph->resources[1];
2356 int src_x, src_y, width, height, dst_x, dst_y;
2357 2 dst_x = dest_rect->pos.x;
2358 2 dst_y = dest_rect->pos.y;
2359 2 src_x = src_rect->pos.x;
2360 2 src_y = src_rect->pos.y;
2361 /* TODO */
2362 2 width = dest_rect->size.width;
2363 2 height = dest_rect->size.height;
2364
2365 2 XCopyArea(display, source, target, context, src_x, src_y, width, height, dst_x, dst_y);
2366 2 return GATE_RESULT_OK;
2367 }
2368
2369 5 gate_result_t gate_ui_graphics_draw_image(gate_ui_graphics_t* graph, gate_rasterimage_t const* srcimage,
2370 gate_ui_point_t const* dst, gate_ui_size_t const* size, gate_ui_point_t const* srcpos)
2371 {
2372 5 Display* const display = GATE_UI_MOTIF_GET_HOST_DISPLAY(graph->host);
2373 5 GC const context = (GC)graph->resources[0];
2374 5 Drawable const drawable = (Drawable)graph->resources[1];
2375
2376 gate_color_t pixel;
2377 5 gate_uint32_t pixel_cache = 0;
2378 int src_x, src_y, width, height, dst_x, dst_y;
2379 int x, y;
2380
2381
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (srcpos)
2382 {
2383 src_x = srcpos->x;
2384 src_y = srcpos->y;
2385 }
2386 else
2387 {
2388 5 src_x = 0;
2389 5 src_y = 0;
2390 }
2391
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (size)
2392 {
2393 width = size->width;
2394 height = size->height;
2395 }
2396 else
2397 {
2398 5 width = srcimage->width;
2399 5 height = srcimage->height;
2400 }
2401
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (dst)
2402 {
2403 dst_x = dst->x;
2404 dst_y = dst->y;
2405 }
2406 else
2407 {
2408 5 dst_x = 0;
2409 5 dst_y = 0;
2410 }
2411
2412
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 5 times.
85 for (y = 0; y != height; ++y)
2413 {
2414
2/2
✓ Branch 0 taken 1280 times.
✓ Branch 1 taken 80 times.
1360 for (x = 0; x != width; ++x)
2415 {
2416 1280 gate_rasterimage_get_pixel(srcimage, src_x + x, src_y + y, &pixel);
2417
2/2
✓ Branch 0 taken 917 times.
✓ Branch 1 taken 363 times.
1280 if (pixel.a > 127)
2418 {
2419
2/2
✓ Branch 0 taken 658 times.
✓ Branch 1 taken 259 times.
917 if (pixel.rgba != pixel_cache)
2420 {
2421 658 unsigned long x11_color = XGetRgbPixel(display, pixel.r, pixel.g, pixel.b);
2422 658 pixel_cache = pixel.rgba;
2423 658 XSetForeground(display, context, x11_color);
2424 }
2425 917 XDrawPoint(display, drawable, context, dst_x + x, dst_y + y);
2426 }
2427 }
2428 }
2429 5 return GATE_RESULT_OK;
2430 }
2431
2432 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)
2433 {
2434 4 Display* const display = GATE_UI_MOTIF_GET_HOST_DISPLAY(graph->host);
2435 4 GC const context = (GC)graph->resources[0];
2436 4 Drawable const drawable = (Drawable)graph->resources[1];
2437
2438 4 XSetForeground(display, context, XGetRgbPixel(display, col.r, col.g, col.b));
2439 4 XDrawLine(display, drawable, context, from.x, from.y, to.x, to.y);
2440 4 return GATE_RESULT_OK;
2441 }
2442
2443 3 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)
2444 {
2445 3 Display* const display = GATE_UI_MOTIF_GET_HOST_DISPLAY(graph->host);
2446 3 GC const context = (GC)graph->resources[0];
2447 3 Drawable const drawable = (Drawable)graph->resources[1];
2448 unsigned long pixel;
2449
2450
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (colfill)
2451 {
2452 3 pixel = XGetRgbPixel(display, colfill->r, colfill->g, colfill->b);
2453 3 XSetForeground(display, context, pixel);
2454 3 XFillRectangle(display, drawable, context, rect.pos.x, rect.pos.y, rect.size.width, rect.size.height);
2455 }
2456
2457
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (colline)
2458 {
2459 3 pixel = XGetRgbPixel(display, colline->r, colline->g, colline->b);
2460 3 XSetForeground(display, context, pixel);
2461 3 XDrawRectangle(display, drawable, context, rect.pos.x, rect.pos.y, rect.size.width, rect.size.height);
2462 }
2463 3 return GATE_RESULT_OK;
2464 }
2465
2466 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)
2467 {
2468 2 Display* const display = GATE_UI_MOTIF_GET_HOST_DISPLAY(graph->host);
2469 2 GC const context = (GC)graph->resources[0];
2470 2 Drawable const drawable = (Drawable)graph->resources[1];
2471 unsigned long pixel;
2472 gate_size_t ndx;
2473 XPoint xp[64];
2474
2475
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)))
2476 {
2477 /* nothing to do */
2478 return GATE_RESULT_OK;
2479 }
2480
2481
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pointcount > 64)
2482 {
2483 pointcount = 64;
2484 }
2485
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
12 for (ndx = 0; ndx != pointcount; ++ndx)
2486 {
2487 10 xp[ndx].x = points[ndx].x;
2488 10 xp[ndx].y = points[ndx].y;
2489 }
2490
2491
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (colfill)
2492 {
2493 pixel = XGetRgbPixel(display, colfill->r, colfill->g, colfill->b);
2494 XSetForeground(display, context, pixel);
2495 XFillPolygon(display, drawable, context, xp, (int)pointcount, Complex, CoordModeOrigin);
2496 }
2497
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (colline)
2498 {
2499 2 pixel = XGetRgbPixel(display, colline->r, colline->g, colline->b);
2500 2 XSetForeground(display, context, pixel);
2501
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 for (ndx = 0; ndx != pointcount - 1; ++ndx)
2502 {
2503 8 XDrawLine(display, drawable, context, xp[ndx].x, xp[ndx].y, xp[ndx + 1].x, xp[ndx + 1].y);
2504 }
2505 2 XDrawLine(display, drawable, context, xp[pointcount - 1].x, xp[pointcount - 1].y, xp[0].x, xp[0].y);
2506 }
2507 2 return GATE_RESULT_OK;
2508 }
2509
2510 static gate_bool_t find_best_font_name(Display* display, gate_ui_font_t* font)
2511 {
2512 gate_bool_t ret = false;
2513 int max_fonts = 1024;
2514 int fonts_returned = 0;
2515 char** fonts = XListFonts(display, "*", max_fonts, &fonts_returned);
2516
2517 do
2518 {
2519 int ndx;
2520 char const* pattern = font->font_name;
2521 gate_size_t pattern_len = gate_str_length(font->font_name);
2522
2523 if (fonts == NULL)
2524 {
2525 break;
2526 }
2527 for (ndx = 0; ndx < fonts_returned; ++ndx)
2528 {
2529 char* font_name = fonts[ndx];
2530 gate_size_t font_name_len = gate_str_length(font_name);
2531 gate_size_t pos;
2532 if(font_name_len == 0)
2533 {
2534 continue;
2535 }
2536 pos = gate_str_pos(font_name, font_name_len, pattern, pattern_len, 0);
2537 if(pos != GATE_STR_NPOS)
2538 {
2539 gate_str_print_text(font->font_name, sizeof(font->font_name), font_name, font_name_len);
2540 ret = true;
2541 break;
2542 }
2543 }
2544 /* code */
2545 } while (0);
2546
2547 if(fonts != NULL)
2548 {
2549 XFreeFontNames(fonts);
2550 }
2551
2552 return ret;
2553 }
2554
2555 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)
2556 {
2557 return GATE_RESULT_NOTIMPLEMENTED;
2558 }
2559
2560
2561
2562 static void print_font_name(char* name_buffer, gate_size_t name_capacity, gate_ui_font_t const* font)
2563 {
2564 gate_strbuilder_t builder;
2565
2566 gate_strbuilder_create_static(&builder, name_buffer, name_capacity, 0);
2567 gate_strbuilder_append_cstr(&builder, "-");
2568 gate_strbuilder_append_cstr(&builder, font->font_name);
2569 gate_strbuilder_append_cstr(&builder, font->bold ? "-bold" : "-medium");
2570 gate_strbuilder_append_cstr(&builder, font->italic ? "-i" : "-r");
2571 gate_strbuilder_append_cstr(&builder, "-*-");
2572 gate_strbuilder_append_int32(&builder, font->size);
2573 gate_strbuilder_append_cstr(&builder, "-*");
2574 }
2575
2576 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)
2577 {
2578 2 Display* const display = GATE_UI_MOTIF_GET_HOST_DISPLAY(graph->host);
2579 2 GC const context = (GC)graph->resources[0];
2580 2 Drawable const drawable = (Drawable)graph->resources[1];
2581
2582 XFontStruct* fontstruct;
2583
2584 2 fontstruct = XLoadQueryFont(display, "fixed");
2585
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));
2586
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (height) *height = fontstruct->ascent + fontstruct->descent;
2587 2 XFreeFont(display, fontstruct);
2588 2 return GATE_RESULT_OK;
2589 }
2590
2591 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)
2592 {
2593 2 Display* const display = GATE_UI_MOTIF_GET_HOST_DISPLAY(graph->host);
2594 2 GC const context = (GC)graph->resources[0];
2595 2 Drawable const drawable = (Drawable)graph->resources[1];
2596 gate_ui_font_t updated_font;
2597
2598 XFontStruct* fontstruct;
2599
2600 2 fontstruct = XLoadQueryFont(display, "fixed");
2601
2602 2 XSetFont(display, context, fontstruct->fid);
2603 2 XDrawString(display, drawable, context, pos->pos.x, pos->pos.y + fontstruct->ascent, text->str, text->length);
2604
2605 2 XFreeFont(display, fontstruct);
2606 2 return GATE_RESULT_OK;
2607 }
2608
2609 void* gate_ui_graphics_handle(gate_ui_graphics_t* graph)
2610 {
2611 return graph->resources[0];
2612 }
2613 1 void* gate_ui_graphics_surface(gate_ui_graphics_t* graph)
2614 {
2615 1 return graph->resources[1];
2616 }
2617
2618
2619
2620
2621 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)
2622 {
2623 return GATE_RESULT_NOTIMPLEMENTED;
2624 }
2625 gate_result_t gate_ui_icon_create_native(gate_ui_icon_t* icon, gate_ui_host_t* host, void* handle, gate_uint32_t flags)
2626 {
2627 return GATE_RESULT_NOTIMPLEMENTED;
2628 }
2629 gate_result_t gate_ui_icon_create_image(gate_ui_icon_t* icon, gate_ui_host_t* host, gate_rasterimage_t const* image)
2630 {
2631 return GATE_RESULT_NOTIMPLEMENTED;
2632 }
2633 gate_result_t gate_ui_icon_create_file(gate_ui_icon_t* icon, gate_ui_host_t* host, gate_string_t const* filepath)
2634 {
2635 return GATE_RESULT_NOTIMPLEMENTED;
2636 }
2637 gate_result_t gate_ui_icon_copy(gate_ui_icon_t* dsticon, gate_ui_icon_t const* srcicon)
2638 {
2639 return GATE_RESULT_NOTIMPLEMENTED;
2640 }
2641 gate_result_t gate_ui_icon_destroy(gate_ui_icon_t* icon)
2642 {
2643 return GATE_RESULT_NOTIMPLEMENTED;
2644 }
2645
2646
2647
2648 /**
2649 * A motif ICON list is an array of Pixmap instances.
2650 * Each ICON entry is represented by two Pixmaps, the first is the mask pixmap,
2651 * the second one holds the icon pixels
2652 *
2653 */
2654
2655 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)
2656 {
2657 gate_arraylist_t pixmap_list;
2658
2659
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_DEBUG_ASSERT(ilst !=NULL);
2660
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_DEBUG_ASSERT(host != NULL);
2661
2662 3 gate_mem_clear(ilst, sizeof(gate_ui_iconlist_t));
2663 3 ilst->host = host;
2664 3 ilst->flags = 0;
2665 3 ilst->width = width;
2666 3 ilst->height = height;
2667 3 ilst->resources[0] = NULL;
2668 3 return GATE_RESULT_OK;
2669 }
2670
2671 1 gate_result_t gate_ui_iconlist_destroy(gate_ui_iconlist_t* ilst)
2672 {
2673 gate_arraylist_t pixmap_list;
2674
2675
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_ASSERT(ilst != NULL);
2676
2677 1 pixmap_list = (gate_arraylist_t)ilst->resources[0];
2678
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (pixmap_list != NULL)
2679 {
2680 1 Display* display = GATE_UI_MOTIF_GET_HOST_DISPLAY(ilst->host);
2681 gate_size_t ndx;
2682 1 gate_size_t cnt = gate_arraylist_length(pixmap_list);
2683
2684
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 for(ndx = 0; ndx != cnt; ++ndx)
2685 {
2686 2 Pixmap* ptr_pixmap = gate_arraylist_get(pixmap_list, ndx);
2687
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if(ptr_pixmap != NULL)
2688 {
2689 2 XFreePixmap(display, (Pixmap)*ptr_pixmap);
2690 }
2691 }
2692 1 gate_arraylist_release(pixmap_list);
2693 1 ilst->resources[0] = NULL;
2694 }
2695 1 return GATE_RESULT_OK;
2696 }
2697 gate_size_t gate_ui_iconlist_count(gate_ui_iconlist_t* ilst)
2698 {
2699 gate_size_t ret = 0;
2700 gate_arraylist_t pixmap_list;
2701
2702 GATE_DEBUG_ASSERT(ilst != NULL);
2703
2704 pixmap_list = (gate_arraylist_t)ilst->resources[0];
2705 if (pixmap_list != NULL)
2706 {
2707 gate_size_t const cnt = gate_arraylist_length(pixmap_list);
2708 ret = cnt / 2;
2709 }
2710 return ret;
2711 }
2712
2713 2 static Pixmap create_mask_pixmap(gate_ui_host_t* host, gate_rasterimage_t const* image)
2714 {
2715 2 Display* dpy = GATE_UI_MOTIF_GET_HOST_DISPLAY(host);
2716 2 Window win = XDefaultRootWindow(dpy);
2717 Pixmap pm;
2718 GC gc;
2719 gate_color_t col;
2720 unsigned int x, y, width, height;
2721
2722 2 width = gate_rasterimage_width(image);
2723 2 height = gate_rasterimage_height(image);
2724
2725 2 pm = XCreatePixmap(dpy, win, image->width, image->height, 1);
2726 2 gc = XCreateGC(dpy, pm, 0, NULL);
2727 2 XSetForeground(dpy, gc, 0);
2728 2 XFillRectangle(dpy, pm, gc, 0, 0, width, height);
2729 2 XSetForeground(dpy, gc, 1);
2730
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 2 times.
34 for (y = 0; y != height; ++y)
2731 {
2732
2/2
✓ Branch 0 taken 512 times.
✓ Branch 1 taken 32 times.
544 for (x = 0; x != width; ++x)
2733 {
2734 512 gate_rasterimage_get_pixel(image, x, y, &col);
2735
2/2
✓ Branch 0 taken 338 times.
✓ Branch 1 taken 174 times.
512 if (col.a > 127)
2736 {
2737 338 XDrawPoint(dpy, pm, gc, x, y);
2738 }
2739 }
2740 }
2741 2 XFreeGC(dpy, gc);
2742 2 return pm;
2743 }
2744
2745 gate_result_t gate_ui_iconlist_add_icon(gate_ui_iconlist_t* ilst, gate_ui_icon_t const* icon, gate_intptr_t* icon_key)
2746 {
2747 /* TODO */
2748 return GATE_RESULT_NOTIMPLEMENTED;
2749 }
2750
2751 2 gate_result_t gate_ui_iconlist_add_image(gate_ui_iconlist_t* ilst, gate_rasterimage_t const* image, gate_intptr_t* icon_key)
2752 {
2753 gate_result_t ret;
2754
2755
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_DEBUG_ASSERT(ilst != NULL);
2756
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_DEBUG_ASSERT(image != NULL);
2757
2758 do
2759 {
2760 gate_ui_graphics_t graph;
2761 Pixmap pm;
2762 gate_size_t len;
2763 2 gate_arraylist_t pixmap_list = ilst->resources[0];
2764
2765
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (pixmap_list == NULL)
2766 {
2767 2 pixmap_list = gate_arraylist_create(sizeof(Pixmap), NULL, 16, NULL, NULL);
2768
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (NULL == pixmap_list)
2769 {
2770 GATE_DEBUG_TRACE("Failed to allocate pixmap array");
2771 ret = GATE_RESULT_OUTOFMEMORY;
2772 break;
2773 }
2774 2 ilst->resources[0] = (void*)pixmap_list;
2775 }
2776
2777 2 pm = create_mask_pixmap(ilst->host, image);
2778
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (NULL == gate_arraylist_add(pixmap_list, &pm))
2779 {
2780 ret = GATE_RESULT_OUTOFMEMORY;
2781 break;
2782 }
2783
2784 2 ret = gate_ui_graphics_create_image_from(&graph, ilst->host, image);
2785
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
2786
2787 2 pm = (Pixmap)graph.resources[1];
2788 2 graph.resources[1] = 0;
2789 2 gate_ui_graphics_destroy(&graph);
2790
2791 2 gate_arraylist_add(pixmap_list, &pm);
2792 2 len = gate_arraylist_length(pixmap_list);
2793
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (icon_key)
2794 {
2795 2 *icon_key = (gate_intptr_t)len;
2796 }
2797 2 ret = GATE_RESULT_OK;
2798 } while (0);
2799 2 return ret;
2800 }
2801 gate_result_t gate_ui_iconlist_get_icon(gate_ui_iconlist_t* ilst, gate_intptr_t icon_key, gate_ui_icon_t* icon)
2802 {
2803 /* TODO */
2804 return GATE_RESULT_NOTIMPLEMENTED;
2805 }
2806 13 void* gate_ui_iconlist_get_handle(gate_ui_iconlist_t* ilst, gate_intptr_t icon_key)
2807 {
2808 13 void* ret = NULL;
2809
2810
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 GATE_DEBUG_ASSERT(ilst != NULL);
2811 do
2812 {
2813 gate_arraylist_t pixmap_list;
2814 gate_size_t cnt;
2815 13 gate_size_t ndx = (gate_size_t)icon_key;
2816
2817
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if(ilst->resources[0] == NULL) break;
2818
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if(ndx < 2) break;
2819 13 ndx -= 2; /* key == length after add, we need to go two steps back to point to the first pixmap */
2820
2821 13 pixmap_list = ilst->resources[0];
2822 13 cnt = gate_arraylist_length(pixmap_list);
2823
2824 13 ret = gate_arraylist_get(pixmap_list, ndx);
2825 /* ret == Pixmap* to mask pixmap */
2826 } while (0);
2827
2828 13 return ret;
2829 }
2830
2831
2832
2833
2834
2835 gate_result_t gate_ui_cursor_create_stock(gate_ui_cursor_t* cursor, gate_ui_host_t* host, gate_uint32_t stock_id)
2836 {
2837 return GATE_RESULT_NOTIMPLEMENTED;
2838 }
2839 gate_result_t gate_ui_cursor_create_native(gate_ui_cursor_t* cursor, gate_ui_host_t* host, void* handle, gate_uint32_t flags)
2840 {
2841 return GATE_RESULT_NOTIMPLEMENTED;
2842 }
2843 gate_result_t gate_ui_cursor_create_image(gate_ui_cursor_t* cursor, gate_ui_host_t* host, gate_rasterimage_t const* image,
2844 gate_uint16_t x, gate_uint16_t y)
2845 {
2846 return GATE_RESULT_NOTIMPLEMENTED;
2847 }
2848 gate_result_t gate_ui_cursor_create_file(gate_ui_cursor_t* cursor, gate_ui_host_t* host, gate_string_t const* filepath)
2849 {
2850 return GATE_RESULT_NOTIMPLEMENTED;
2851 }
2852 gate_result_t gate_ui_cursor_copy(gate_ui_cursor_t* dstcursor, gate_ui_cursor_t const* srccursor)
2853 {
2854 return GATE_RESULT_NOTIMPLEMENTED;
2855 }
2856 gate_result_t gate_ui_cursor_destroy(gate_ui_cursor_t* cursor)
2857 {
2858 return GATE_RESULT_NOTIMPLEMENTED;
2859 }
2860
2861
2862 #endif /* GATE_UI_MOTIF */
2863