GCC Code Coverage Report


Directory: src/gate/
File: src/gate/ui/graphics.c
Date: 2026-02-03 22:06:38
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 gate_uint32_t icon_flags;
1185 HICON hicon = (HICON)gate_ui_winapi_imagelist_get_icon((HIMAGELIST)ilst->resources[0], (int)icon_key, flags);
1186 return (void*)hicon;
1187 #endif
1188 }
1189
1190
1191
1192
1193
1194 /****************
1195 * cursor WIN32 *
1196 ****************/
1197
1198 #ifndef IDC_APPSTARTING
1199 #define IDC_APPSTARTING IDC_WAIT
1200 #endif
1201
1202 #ifndef IDC_NO
1203 #define IDC_NO IDC_ICON
1204 #endif
1205
1206 gate_result_t gate_ui_cursor_create_stock(gate_ui_cursor_t* cursor, gate_ui_host_t* host, gate_uint32_t stock_id)
1207 {
1208 LPCTSTR resourceId = NULL;
1209 HCURSOR hcursor = NULL;
1210
1211 switch (stock_id)
1212 {
1213 case GATE_UI_CURSOR_STOCK_POINTER: resourceId = IDC_ARROW; break;
1214 case GATE_UI_CURSOR_STOCK_BUSY: resourceId = IDC_WAIT; break;
1215 case GATE_UI_CURSOR_STOCK_STARTING: resourceId = IDC_APPSTARTING; break;
1216 case GATE_UI_CURSOR_STOCK_HAND: resourceId = /*IDC_HAND*/ IDC_UPARROW; break;
1217 case GATE_UI_CURSOR_STOCK_TEXT: resourceId = IDC_IBEAM; break;
1218 case GATE_UI_CURSOR_STOCK_REJECTED: resourceId = IDC_NO; break;
1219 case GATE_UI_CURSOR_STOCK_SIZE_ALL: resourceId = IDC_SIZE; break;
1220 case GATE_UI_CURSOR_STOCK_SIZE_LEFTRIGHT: resourceId = IDC_SIZEWE; break;
1221 case GATE_UI_CURSOR_STOCK_SIZE_UPDOWN: resourceId = IDC_SIZENS; break;
1222 case GATE_UI_CURSOR_STOCK_SIZE_LEFTUPRIGHTDOWN: resourceId = IDC_SIZENWSE; break;
1223 case GATE_UI_CURSOR_STOCK_SIZE_RIGHTUPKEFTDOWN: resourceId = IDC_SIZENESW; break;
1224 default: return GATE_RESULT_INVALIDARG;
1225 }
1226
1227 hcursor = LoadCursor(NULL, resourceId);
1228 if (NULL == hcursor)
1229 {
1230 return GATE_RESULT_FAILED;
1231 }
1232 cursor->host = host;
1233 cursor->resources[0] = (void*)hcursor;
1234 cursor->resources[1] = NULL;
1235 cursor->flags = GATE_UI_CURSOR_FLAG_STOCK;
1236 return GATE_RESULT_OK;
1237 }
1238 gate_result_t gate_ui_cursor_create_native(gate_ui_cursor_t* cursor, gate_ui_host_t* host, void* handle, gate_uint32_t flags)
1239 {
1240 cursor->host = host;
1241 cursor->resources[0] = handle;
1242 cursor->resources[1] = NULL;
1243 cursor->flags = flags;
1244 return GATE_RESULT_OK;
1245 }
1246 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)
1247 {
1248 gate_result_t ret = GATE_RESULT_FAILED;
1249 HCURSOR hcursor = (HCURSOR)gate_ui_icon_create_from_image(host, image, x, y);
1250 if (hcursor)
1251 {
1252 cursor->resources[0] = (void*)hcursor;
1253 cursor->resources[1] = NULL;
1254 cursor->host = host;
1255 cursor->flags = 0;
1256 ret = GATE_RESULT_OK;
1257 }
1258 return ret;
1259 }
1260 gate_result_t gate_ui_cursor_create_file(gate_ui_cursor_t* cursor, gate_ui_host_t* host, gate_string_t const* filepath)
1261 {
1262 return GATE_RESULT_NOTIMPLEMENTED;
1263 }
1264
1265 gate_result_t gate_ui_cursor_copy(gate_ui_cursor_t* dsticon, gate_ui_cursor_t const* srcicon)
1266 {
1267 gate_result_t ret = GATE_RESULT_FAILED;
1268 #if !defined(GATE_SYS_WINCE) && !defined(GATE_SYS_WIN16)
1269 if (!GATE_FLAG_ENABLED(srcicon->flags, GATE_UI_CURSOR_FLAG_STOCK))
1270 {
1271 dsticon->resources[0] = (void*)CopyImage((HANDLE)srcicon->resources[0], IMAGE_CURSOR, 0, 0, 0);
1272 if (dsticon->resources[0])
1273 {
1274 dsticon->resources[1] = NULL;
1275 dsticon->host = srcicon->host;
1276 dsticon->flags = 0;
1277 }
1278 }
1279 else
1280 #endif /* ! GATE_SYS_WINCE */
1281 {
1282 gate_mem_copy(dsticon, srcicon, sizeof(gate_ui_cursor_t));
1283 }
1284 return ret;
1285 }
1286 gate_result_t gate_ui_cursor_destroy(gate_ui_cursor_t* cursor)
1287 {
1288 gate_result_t ret = GATE_RESULT_FAILED;
1289 if (cursor)
1290 {
1291 ret = GATE_RESULT_OK;
1292 if (!GATE_FLAG_ENABLED(cursor->flags, GATE_UI_CURSOR_FLAG_STOCK))
1293 {
1294 #if !defined(GATE_SYS_WINCE)
1295 if (!DestroyCursor((HCURSOR)cursor->resources[0]))
1296 {
1297 ret = GATE_RESULT_FAILED;
1298 }
1299 #endif
1300 }
1301 }
1302 return ret;
1303 }
1304
1305
1306
1307 #endif /* GATE_UI_WINAPI */
1308
1309
1310 #if defined(GATE_UI_GTK)
1311
1312 #include "gate/ui/gateui_gtk.h"
1313
1314 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)
1315 {
1316 return gate_ui_graphics_create_image(graph, host, width, height, 32);
1317 }
1318
1319 static cairo_format_t gate_ui_graphics_resolve_format(gate_uint32_t depth)
1320 {
1321 if ((depth == 0) || (depth > 24))
1322 {
1323 return CAIRO_FORMAT_ARGB32;
1324 }
1325 else if (depth > 16)
1326 {
1327 return CAIRO_FORMAT_RGB24;
1328 }
1329 else if (depth > 8)
1330 {
1331 return CAIRO_FORMAT_RGB16_565;
1332 }
1333 else if (depth > 2)
1334 {
1335 return CAIRO_FORMAT_A8;
1336 }
1337 else
1338 {
1339 return CAIRO_FORMAT_A1;
1340 }
1341
1342 }
1343
1344 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)
1345 {
1346 gate_result_t ret = GATE_RESULT_FAILED;
1347 cairo_t* cr = NULL;
1348 cairo_surface_t* surface = NULL;
1349 cairo_format_t format;
1350
1351 do
1352 {
1353 gate_mem_clear(graph, sizeof(gate_ui_graphics_t));
1354 format = gate_ui_graphics_resolve_format(depth);
1355
1356 surface = cairo_image_surface_create(format, width, height);
1357 if (surface == NULL)
1358 {
1359 ret = GATE_RESULT_OUTOFRESOURCES;
1360 break;
1361 }
1362 cr = cairo_create(surface);
1363 if (cr == NULL)
1364 {
1365 cairo_surface_destroy(surface);
1366 ret = GATE_RESULT_OUTOFRESOURCES;
1367 break;
1368 }
1369
1370 graph->host = host;
1371 graph->width = width;
1372 graph->height = height;
1373 graph->resources[0] = cr;
1374 graph->resources[1] = surface;
1375
1376 ret = GATE_RESULT_OK;
1377 } while (0);
1378
1379 return ret;
1380 }
1381 gate_result_t gate_ui_graphics_create_image_from(gate_ui_graphics_t* graph, gate_ui_host_t* host, gate_rasterimage_t const* rasterimage)
1382 {
1383 gate_result_t ret = gate_ui_graphics_create_image(graph, host, rasterimage->width, rasterimage->height, 32);
1384
1385 if (GATE_SUCCEEDED(ret))
1386 {
1387 gate_ui_point_t pnt = { 0, 0 };
1388 gate_ui_size_t sz = { rasterimage->width, rasterimage->height };
1389 ret = gate_ui_graphics_draw_image(graph, rasterimage, &pnt, &sz, &pnt);
1390 if (GATE_FAILED(ret))
1391 {
1392 gate_ui_graphics_destroy(graph);
1393 gate_mem_clear(graph, sizeof(gate_ui_graphics_t));
1394 }
1395 }
1396 return ret;
1397 }
1398 gate_result_t gate_ui_graphics_create_ctrl(gate_ui_graphics_t* graph, gate_ui_ctrl_t* ctrl)
1399 {
1400 gate_result_t ret = GATE_RESULT_FAILED;
1401 cairo_surface_t* surface = NULL;
1402 cairo_t* cr = NULL;
1403
1404 do
1405 {
1406 gate_ui_host_t* host = GATE_UI_GTK_GET_CTRL_HOST(ctrl);
1407 GtkWidget* widget = GATE_UI_GTK_GET_CTRL_WIDGET(ctrl);
1408 GdkWindow* window = NULL;
1409 int width, height;
1410
1411 if (!host || !widget)
1412 {
1413 ret = GATE_RESULT_NOTAVAILABLE;
1414 break;
1415 }
1416
1417 window = gtk_widget_get_window(widget);
1418 width = gtk_widget_get_allocated_width(widget);
1419 height = gtk_widget_get_allocated_height(widget);
1420 surface = gdk_window_create_similar_surface(window, CAIRO_CONTENT_COLOR, width, height);
1421 if (!surface)
1422 {
1423 ret = GATE_RESULT_OUTOFRESOURCES;
1424 break;
1425 }
1426 cr = cairo_create(surface);
1427 if (!cr)
1428 {
1429 ret = GATE_RESULT_FAILED;
1430 break;
1431 }
1432
1433 gate_mem_clear(graph, sizeof(gate_ui_graphics_t));
1434 graph->host = host;
1435 graph->width = width;
1436 graph->height = height;
1437 graph->resources[0] = cr;
1438 graph->resources[1] = surface;
1439 cr = NULL;
1440 surface = NULL;
1441 ret = GATE_RESULT_OK;
1442 } while (0);
1443
1444 if (cr)
1445 {
1446 cairo_destroy(cr);
1447 }
1448 if (surface)
1449 {
1450 cairo_surface_destroy(surface);
1451 }
1452 return ret;
1453 }
1454 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)
1455 {
1456 gate_result_t ret = GATE_RESULT_FAILED;
1457
1458 do
1459 {
1460 gate_mem_clear(graph, sizeof(gate_ui_graphics_t));
1461 graph->host = host;
1462 graph->resources[0] = cairo_reference((cairo_t*)graphics); /**< cairo_t */
1463 graph->resources[1] = param; /**< surface */
1464 graph->width = width;
1465 graph->height = height;
1466 ret = GATE_RESULT_OK;
1467 } while (0);
1468
1469 return ret;
1470 }
1471 gate_result_t gate_ui_graphics_destroy(gate_ui_graphics_t* graph)
1472 {
1473 cairo_t* cr = graph->resources[0];
1474 cairo_surface_t* surface = graph->resources[1];
1475
1476 if (surface)
1477 {
1478 cairo_surface_destroy(surface);
1479 }
1480 if (cr)
1481 {
1482 cairo_destroy(cr);
1483 }
1484 return GATE_RESULT_OK;
1485 }
1486
1487
1488 gate_int32_t gate_ui_graphics_width(gate_ui_graphics_t* graph)
1489 {
1490 return graph->width;
1491 }
1492 gate_int32_t gate_ui_graphics_height(gate_ui_graphics_t* graph)
1493 {
1494 return graph->height;
1495 }
1496 gate_result_t gate_ui_graphics_set_pixel(gate_ui_graphics_t* graph, gate_ui_point_t pos, gate_ui_color_t col)
1497 {
1498 cairo_t* cr = (cairo_t*)graph->resources[0];
1499 cairo_set_source_rgb(cr, col.r, col.g, col.b);
1500 cairo_rectangle(cr, (double)pos.x, (double)pos.y, 1.0, 1.0);
1501 cairo_fill(cr);
1502 return GATE_RESULT_OK;
1503 }
1504 gate_result_t gate_ui_graphics_get_pixel(gate_ui_graphics_t* graph, gate_ui_point_t pos, gate_ui_color_t* col)
1505 {
1506 return GATE_RESULT_NOTIMPLEMENTED;
1507 }
1508 gate_result_t gate_ui_graphics_draw(gate_ui_graphics_t* graph, gate_ui_graphics_t* srcgraph,
1509 gate_ui_point_t const* dst, gate_ui_size_t const* size, gate_ui_point_t const* src)
1510 {
1511 cairo_t* cr = (cairo_t*)graph->resources[0];
1512 cairo_surface_t* src_surface = srcgraph->resources[1];
1513 if (src_surface == NULL)
1514 {
1515 return GATE_RESULT_INVALIDINPUT;
1516 }
1517
1518 cairo_set_source_surface(cr, src_surface, dst ? dst->x : 0, dst ? dst->y : 0);
1519 /* TODO: dst/src */
1520 cairo_paint(cr);
1521 return GATE_RESULT_OK;
1522 }
1523
1524 gate_result_t gate_ui_graphics_draw_ex(gate_ui_graphics_t* graph, gate_ui_graphics_t* src_graph,
1525 gate_ui_position_t const* dest_rect, gate_ui_position_t const* src_rect)
1526 {
1527 cairo_t* cr = (cairo_t*)graph->resources[0];
1528 cairo_surface_t* src_surface = src_graph->resources[1];
1529 if (src_surface == NULL)
1530 {
1531 return GATE_RESULT_INVALIDINPUT;
1532 }
1533
1534 cairo_set_source_surface(cr, src_surface, 0, 0);
1535 /* TODO: dst/src */
1536 cairo_paint(cr);
1537 return GATE_RESULT_OK;
1538 }
1539
1540 static GdkPixbuf* gate_ui_gtk_raster_to_pixbuf(gate_rasterimage_t const* srcimage,
1541 gate_int32_t src_x, gate_int32_t src_y, gate_int32_t width, gate_int32_t height)
1542 {
1543 GdkPixbuf* buf;
1544 gate_int32_t x, y;
1545
1546 if (src_x + width > (gate_int32_t)srcimage->width)
1547 {
1548 width = (gate_int32_t)srcimage->width - src_x;
1549 }
1550 if (src_y + height > (gate_int32_t)srcimage->height)
1551 {
1552 height = (gate_int32_t)srcimage->height - src_y;
1553 }
1554
1555 buf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, (int)width, (int)height);
1556 if (buf != NULL)
1557 {
1558 guchar* pixels = gdk_pixbuf_get_pixels(buf);
1559
1560 for (y = 0; y < height; ++y)
1561 {
1562 guchar* dst_pixels = pixels + (y * width) * 4;
1563 gate_color_t const* src_pixels = (((gate_color_t*)gate_rasterimage_get_line_ptr(srcimage, (src_y + y))) + src_x);
1564 for (x = 0; x < width; ++x)
1565 {
1566 dst_pixels[0] = src_pixels->r;
1567 dst_pixels[1] = src_pixels->g;
1568 dst_pixels[2] = src_pixels->b;
1569 dst_pixels[3] = src_pixels->a;
1570 dst_pixels += 4;
1571 src_pixels++;
1572 }
1573 }
1574 }
1575 return buf;
1576 }
1577
1578 gate_result_t gate_ui_graphics_draw_image(gate_ui_graphics_t* graph, gate_rasterimage_t const* srcimage,
1579 gate_ui_point_t const* dst, gate_ui_size_t const* size, gate_ui_point_t const* srcpos)
1580 {
1581 cairo_t* cr = (cairo_t*)graph->resources[0];
1582 int width, height;
1583 GdkPixbuf* buf;
1584 gate_int32_t src_x = 0;
1585 gate_int32_t src_y = 0;
1586 gate_int32_t dst_x = 0;
1587 gate_int32_t dst_y = 0;
1588
1589 width = srcimage->width;
1590 height = srcimage->height;
1591 if (size)
1592 {
1593 width = size->width;
1594 height = size->height;
1595 }
1596 if (dst)
1597 {
1598 dst_x = dst->x;
1599 dst_y = dst->y;
1600 }
1601 if (srcpos)
1602 {
1603 src_x = srcpos->x;
1604 src_y = srcpos->y;
1605 }
1606
1607 buf = gate_ui_gtk_raster_to_pixbuf(srcimage, src_x, src_y, width, height);
1608 if (buf == NULL)
1609 {
1610 return GATE_RESULT_OUTOFRESOURCES;
1611 }
1612
1613 gdk_cairo_set_source_pixbuf(cr, buf, dst_x, dst_y);
1614 cairo_paint(cr);
1615 g_object_unref(buf);
1616
1617 return GATE_RESULT_OK;
1618 }
1619
1620
1621 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)
1622 {
1623 cairo_t* cr = (cairo_t*)graph->resources[0];
1624
1625 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);
1626 cairo_set_line_width(cr, (double)linewidth);
1627 cairo_move_to(cr, from.x, from.y);
1628 cairo_line_to(cr, to.x, to.y);
1629 cairo_stroke(cr);
1630 return GATE_RESULT_OK;
1631 }
1632 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)
1633 {
1634 cairo_t* cr = (cairo_t*)graph->resources[0];
1635
1636 if (colfill)
1637 {
1638 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);
1639 cairo_rectangle(cr, rect.pos.x, rect.pos.y, rect.size.width, rect.size.height);
1640 cairo_fill(cr);
1641 }
1642
1643 if (colline)
1644 {
1645 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);
1646 cairo_set_line_width(cr, (double)linewidth);
1647 cairo_rectangle(cr, rect.pos.x, rect.pos.y, rect.size.width, rect.size.height);
1648 cairo_stroke(cr);
1649 }
1650
1651 return GATE_RESULT_OK;
1652 }
1653 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)
1654 {
1655 cairo_t* cr = (cairo_t*)graph->resources[0];
1656
1657 if (pointcount > 2)
1658 {
1659 cairo_move_to(cr, points->x, points->y);
1660 --pointcount;
1661 ++points;
1662
1663 while (pointcount-- != 0)
1664 {
1665 cairo_line_to(cr, points->x, points->y);
1666 cairo_move_to(cr, points->x, points->y);
1667 ++points;
1668 }
1669
1670 if (colfill)
1671 {
1672 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);
1673 if (colline)
1674 {
1675 cairo_fill_preserve(cr);
1676 }
1677 else
1678 {
1679 cairo_fill(cr);
1680 }
1681 }
1682
1683 if (colline)
1684 {
1685 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);
1686 cairo_set_line_width(cr, (double)linewidth);
1687 cairo_stroke(cr);
1688 }
1689
1690 }
1691 return GATE_RESULT_OK;
1692 }
1693
1694 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)
1695 {
1696 return GATE_RESULT_NOTIMPLEMENTED;
1697 }
1698
1699 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)
1700 {
1701 cairo_t* cr = (cairo_t*)graph->resources[0];
1702 /*cairo_scaled_font_t* sf = cairo_get_scaled_font(cr);*/
1703 cairo_text_extents_t extents;
1704 gate_cstrbuffer_t buffer;
1705 if(NULL == gate_cstrbuffer_create_string(&buffer, text, false))
1706 {
1707 return GATE_RESULT_OUTOFMEMORY;
1708 }
1709 cairo_set_font_size(cr, font->size);
1710 cairo_text_extents(cr, gate_cstrbuffer_get(&buffer), &extents);
1711 if (width) *width = (gate_int32_t)extents.width + 0.5;
1712 if (height) *height = (gate_int32_t)extents.height + 0.5;
1713 return GATE_RESULT_OK;
1714 }
1715
1716 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)
1717 {
1718 cairo_t* cr = (cairo_t*)graph->resources[0];
1719 gate_cstrbuffer_t buffer;
1720 if(NULL == gate_cstrbuffer_create_string(&buffer, text, false))
1721 {
1722 return GATE_RESULT_OUTOFMEMORY;
1723 }
1724 cairo_set_source_rgb(cr, font->color.r / 255.0, font->color.g / 255.0, font->color.b / 255.0);
1725 cairo_set_font_size(cr, font->size);
1726 cairo_move_to(cr, (double)pos->pos.x, (double)pos->pos.y);
1727 cairo_show_text(cr, gate_cstrbuffer_get(&buffer));
1728 /*
1729 cairo_set_source_rgb(cr, 0.1, 0.1, 0.1);
1730
1731 cairo_select_font_face(cr, "Purisa",
1732 CAIRO_FONT_SLANT_NORMAL,
1733 CAIRO_FONT_WEIGHT_BOLD);
1734
1735 cairo_set_font_size(cr, 13);
1736
1737 cairo_move_to(cr, 20, 30);
1738 cairo_show_text(cr, "Most relationships seem so transitory");
1739 cairo_move_to(cr, 20, 60);
1740 cairo_show_text(cr, "They're all good but not the permanent one");
1741
1742 cairo_move_to(cr, 20, 120);
1743 cairo_show_text(cr, "Who doesn't long for someone to hold");
1744
1745 cairo_move_to(cr, 20, 150);
1746 cairo_show_text(cr, "Who knows how to love you without being told");
1747 cairo_move_to(cr, 20, 180);
1748 cairo_show_text(cr, "Somebody tell me why I'm on my own");
1749 cairo_move_to(cr, 20, 210);
1750 cairo_show_text(cr, "If there's a soulmate for everyone");
1751
1752 */
1753 return GATE_RESULT_OK;
1754 }
1755
1756 void* gate_ui_graphics_handle(gate_ui_graphics_t* graph)
1757 {
1758 return graph->resources[0];
1759 }
1760 void* gate_ui_graphics_surface(gate_ui_graphics_t* graph)
1761 {
1762 return graph->resources[1];
1763 }
1764
1765
1766
1767
1768
1769 /************
1770 * icon GTK *
1771 ************/
1772
1773 /* https://specifications.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html */
1774
1775 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)
1776 {
1777 gate_result_t ret = GATE_RESULT_OK;
1778 char const* gtk_stock_id = NULL;
1779 GtkIconTheme* theme = NULL;
1780 GtkIconInfo* info = NULL;
1781 gint size;
1782 GError* error = NULL;
1783 GdkPixbuf* pixbuf = NULL;
1784
1785 do
1786 {
1787 if (GATE_FLAG_ENABLED(flags, GATE_UI_ICON_FLAG_LARGE))
1788 {
1789 size = 48;
1790 }
1791 else if (GATE_FLAG_ENABLED(flags, GATE_UI_ICON_FLAG_SMALL))
1792 {
1793 size = 16;
1794 }
1795 else
1796 {
1797 size = 32;
1798 }
1799
1800 theme = gtk_icon_theme_get_default();
1801 if (theme == NULL)
1802 {
1803 ret = GATE_RESULT_NOTAVAILABLE;
1804 break;
1805 }
1806
1807 switch (stock_id)
1808 {
1809 case GATE_UI_ICON_STOCK_APP: gtk_stock_id = "system-run"; break;
1810 case GATE_UI_ICON_STOCK_DOCUMENT: gtk_stock_id = "document-properties"; break;
1811 case GATE_UI_ICON_STOCK_FOLDER: gtk_stock_id = "folder"; break;
1812 case GATE_UI_ICON_STOCK_FOLDEROPEN: gtk_stock_id = "folder-open"; break;
1813 case GATE_UI_ICON_STOCK_NEWFILE: gtk_stock_id = "document-new"; break;
1814 case GATE_UI_ICON_STOCK_OPENFILE: gtk_stock_id = "document-open"; break;
1815 case GATE_UI_ICON_STOCK_SAVEFILE: gtk_stock_id = "document-save"; break;
1816 case GATE_UI_ICON_STOCK_PRINTER: gtk_stock_id = "document-print"; break;
1817 case GATE_UI_ICON_STOCK_CUT: gtk_stock_id = "edit-cut"; break;
1818 case GATE_UI_ICON_STOCK_COPY: gtk_stock_id = "edit-copy"; break;
1819 case GATE_UI_ICON_STOCK_PASTE: gtk_stock_id = "edit-paste"; break;
1820 case GATE_UI_ICON_STOCK_DELETE: gtk_stock_id = "edit-delete"; break;
1821
1822 case GATE_UI_ICON_STOCK_FIND: gtk_stock_id = "edit-find"; break;
1823 case GATE_UI_ICON_STOCK_HELP: gtk_stock_id = "help-contents"; break;
1824
1825 case GATE_UI_ICON_STOCK_STORAGE: gtk_stock_id = "drive-harddisk"; break;
1826 case GATE_UI_ICON_STOCK_COMPUTER: gtk_stock_id = "computer"; break;
1827 case GATE_UI_ICON_STOCK_NETWORK: gtk_stock_id = "network-wired"; break;
1828 case GATE_UI_ICON_STOCK_GLOBE: gtk_stock_id = "applications-internet"; break;
1829 case GATE_UI_ICON_STOCK_SETTINGS: gtk_stock_id = "preferences-system"; break;
1830 case GATE_UI_ICON_STOCK_HOME: gtk_stock_id = "go-home"; break;
1831 case GATE_UI_ICON_STOCK_IMAGE: gtk_stock_id = "image-x-generic"; break;
1832 case GATE_UI_ICON_STOCK_AUDIO: gtk_stock_id = "audio-x-generic"; break;
1833 case GATE_UI_ICON_STOCK_VIDEO: gtk_stock_id = "video-x-generic"; break;
1834 case GATE_UI_ICON_STOCK_MAIL: gtk_stock_id = "mail-send-receive"; break;
1835 default: break;
1836 }
1837
1838 info = gtk_icon_theme_lookup_icon(theme, gtk_stock_id, size, GTK_ICON_LOOKUP_USE_BUILTIN | GTK_ICON_LOOKUP_GENERIC_FALLBACK);
1839 if (info == NULL)
1840 {
1841 ret = GATE_RESULT_NOMATCH;
1842 break;
1843 }
1844
1845 pixbuf = gtk_icon_info_load_icon(info, &error);
1846 if (pixbuf == NULL)
1847 {
1848 ret = GATE_RESULT_FAILED;
1849 break;
1850 }
1851
1852 gate_mem_clear(icon, sizeof(gate_ui_icon_t));
1853 icon->host = host;
1854 icon->flags = flags & (GATE_UI_ICON_FLAG_SMALL | GATE_UI_ICON_FLAG_LARGE);
1855 icon->resources[0] = pixbuf;
1856
1857 ret = GATE_RESULT_OK;
1858 } while (0);
1859
1860 return ret;
1861 }
1862 gate_result_t gate_ui_icon_create_native(gate_ui_icon_t* icon, gate_ui_host_t* host, void* handle, gate_uint32_t flags)
1863 {
1864 gate_mem_clear(icon, sizeof(gate_ui_icon_t));
1865 icon->host = host;
1866 icon->flags = flags;
1867 icon->resources[0] = handle;
1868 return GATE_RESULT_OK;
1869 }
1870 gate_result_t gate_ui_icon_create_image(gate_ui_icon_t* icon, gate_ui_host_t* host, gate_rasterimage_t const* image)
1871 {
1872 GdkPixbuf* buf = gate_ui_gtk_raster_to_pixbuf(image, 0, 0, image->width, image->height);
1873 if (buf == NULL)
1874 {
1875 return GATE_RESULT_OUTOFRESOURCES;
1876 }
1877 gate_mem_clear(icon, sizeof(gate_ui_icon_t));
1878 icon->host = host;
1879 icon->flags = 0;
1880 icon->resources[0] = buf;
1881 return GATE_RESULT_OK;
1882 }
1883 gate_result_t gate_ui_icon_create_file(gate_ui_icon_t* icon, gate_ui_host_t* host, gate_string_t const* filepath)
1884 {
1885 gate_result_t ret = GATE_RESULT_FAILED;
1886 char file_buffer[GATE_MAX_FILEPATH_LENGTH];
1887 GtkWidget* image_widget = NULL;
1888 gint pix_size = 0;
1889 gate_uint32_t flags = 0;
1890
1891 GATE_STRING_TO_BUFFER(filepath, file_buffer);
1892 image_widget = gtk_image_new_from_file(file_buffer);
1893 if (image_widget != NULL)
1894 {
1895 pix_size = gtk_image_get_pixel_size(GTK_IMAGE(image_widget));
1896 if (pix_size < 24) flags |= GATE_UI_ICON_FLAG_SMALL;
1897 if (pix_size > 40) flags |= GATE_UI_ICON_FLAG_LARGE;
1898 ret = gate_ui_icon_create_native(icon, host, image_widget, flags);
1899 if (GATE_FAILED(ret))
1900 {
1901 gtk_widget_destroy(image_widget);
1902 }
1903 }
1904 return ret;
1905 }
1906 gate_result_t gate_ui_icon_copy(gate_ui_icon_t* dsticon, gate_ui_icon_t const* srcicon)
1907 {
1908 gate_mem_copy(dsticon, srcicon, sizeof(gate_ui_icon_t));
1909 if (!GATE_FLAG_ENABLED(srcicon->flags, GATE_UI_ICON_FLAG_STOCK))
1910 {
1911 if (srcicon->resources[0])
1912 {
1913 dsticon->resources[0] = g_object_ref((gpointer)srcicon->resources[0]);
1914 }
1915 }
1916 return GATE_RESULT_OK;
1917 }
1918 gate_result_t gate_ui_icon_destroy(gate_ui_icon_t* icon)
1919 {
1920 if (icon->resources[0])
1921 {
1922 g_object_unref((gpointer)icon->resources[0]);
1923 }
1924 gate_mem_clear(icon, sizeof(gate_ui_icon_t));
1925 return GATE_RESULT_OK;
1926 }
1927
1928
1929
1930
1931
1932 /****************
1933 * iconlist GTK *
1934 ****************/
1935
1936 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)
1937 {
1938 gate_result_t ret = GATE_RESULT_FAILED;
1939 do
1940 {
1941 gate_mem_clear(ilst, sizeof(gate_ui_iconlist_t));
1942 ilst->resources[0] = gate_arraylist_create(sizeof(gate_ui_icon_t), NULL, 8, NULL, NULL);
1943 if (NULL == ilst->resources[0])
1944 {
1945 ret = GATE_RESULT_OUTOFMEMORY;
1946 break;
1947 }
1948 ilst->host = host;
1949 ilst->width = width;
1950 ilst->height = height;
1951 ilst->flags = 0;
1952 ret = GATE_RESULT_OK;
1953 } while (0);
1954 return ret;
1955 }
1956 gate_result_t gate_ui_iconlist_destroy(gate_ui_iconlist_t* ilst)
1957 {
1958 gate_result_t ret = GATE_RESULT_OK;
1959 gate_ui_icon_t* ptr_icon;
1960 gate_size_t count;
1961 gate_arraylist_t arr;
1962 do
1963 {
1964 arr = (gate_arraylist_t)ilst->resources[0];
1965 if (!arr)
1966 {
1967 break;
1968 }
1969 count = gate_arraylist_length(arr);
1970 if (count != 0)
1971 {
1972 ptr_icon = gate_arraylist_get(arr, 0);
1973 while (count-- != 0)
1974 {
1975 gate_ui_icon_destroy(ptr_icon);
1976 ++ptr_icon;
1977 }
1978 }
1979 gate_arraylist_release(arr);
1980 ret = GATE_RESULT_OK;
1981 } while (0);
1982 return ret;
1983 }
1984 gate_size_t gate_ui_iconlist_count(gate_ui_iconlist_t* ilst)
1985 {
1986 gate_size_t ret = 0;
1987 gate_arraylist_t arr = (gate_arraylist_t)ilst->resources[0];
1988 if (arr)
1989 {
1990 ret = gate_arraylist_length(arr);
1991 }
1992 return ret;
1993 }
1994 gate_result_t gate_ui_iconlist_add_icon(gate_ui_iconlist_t* ilst, gate_ui_icon_t const* icon, gate_intptr_t* icon_key)
1995 {
1996 gate_ui_icon_t new_icon = GATE_INIT_EMPTY;
1997 gate_arraylist_t arr = (gate_arraylist_t)ilst->resources[0];
1998 gate_result_t ret = gate_ui_icon_copy(&new_icon, icon);
1999 gate_size_t index;
2000 if (GATE_SUCCEEDED(ret))
2001 {
2002 index = gate_arraylist_length(arr);
2003 if (NULL == gate_arraylist_add(arr, &new_icon))
2004 {
2005 ret = GATE_RESULT_OUTOFMEMORY;
2006 gate_ui_icon_destroy(&new_icon);
2007 }
2008 else
2009 {
2010 if (icon_key)
2011 {
2012 *icon_key = (gate_intptr_t)index;
2013 }
2014 }
2015 }
2016 return ret;
2017 }
2018 gate_result_t gate_ui_iconlist_add_image(gate_ui_iconlist_t* ilst, gate_rasterimage_t const* image, gate_intptr_t* icon_key)
2019 {
2020 gate_ui_icon_t new_icon = GATE_INIT_EMPTY;
2021 gate_arraylist_t arr = (gate_arraylist_t)ilst->resources[0];
2022 gate_result_t ret = gate_ui_icon_create_image(&new_icon, ilst->host, image);
2023 gate_size_t index;
2024 if (GATE_SUCCEEDED(ret))
2025 {
2026 index = gate_arraylist_length(arr);
2027 if (NULL == gate_arraylist_add(arr, &new_icon))
2028 {
2029 ret = GATE_RESULT_OUTOFMEMORY;
2030 gate_ui_icon_destroy(&new_icon);
2031 }
2032 else
2033 {
2034 if (icon_key)
2035 {
2036 *icon_key = (gate_intptr_t)index;
2037 }
2038 }
2039 }
2040 return ret;
2041 }
2042 gate_result_t gate_ui_iconlist_get_icon(gate_ui_iconlist_t* ilst, gate_intptr_t icon_key, gate_ui_icon_t* icon)
2043 {
2044 gate_result_t ret = GATE_RESULT_FAILED;
2045 gate_ui_icon_t new_icon = GATE_INIT_EMPTY;
2046 gate_arraylist_t arr = (gate_arraylist_t)ilst->resources[0];
2047 gate_ui_icon_t const* ptr_icon = NULL;
2048
2049 ptr_icon = (gate_ui_icon_t const*)gate_arraylist_get(arr, (gate_size_t)icon_key);
2050 if (NULL == ptr_icon)
2051 {
2052 ret = GATE_RESULT_NOTAVAILABLE;
2053 }
2054 else
2055 {
2056 ret = gate_ui_icon_copy(icon, ptr_icon);
2057 }
2058 return ret;
2059 }
2060
2061 void* gate_ui_iconlist_get_handle(gate_ui_iconlist_t* ilst, gate_intptr_t icon_key)
2062 {
2063 /* TODO */
2064 return NULL;
2065 }
2066
2067
2068 /**************
2069 * cursor GTK *
2070 **************/
2071
2072 gate_result_t gate_ui_cursor_create_stock(gate_ui_cursor_t* cursor, gate_ui_host_t* host, gate_uint32_t stock_id)
2073 {
2074 gate_result_t ret = GATE_RESULT_FAILED;
2075 char const* cursor_name = NULL;
2076 GdkCursor* gdk_cursor = NULL;
2077 GdkDisplay* display = NULL;
2078
2079 switch (stock_id)
2080 {
2081 case GATE_UI_CURSOR_STOCK_POINTER: cursor_name = "default"; break;
2082 case GATE_UI_CURSOR_STOCK_BUSY: cursor_name = "wait"; break;
2083 case GATE_UI_CURSOR_STOCK_STARTING: cursor_name = "progress"; break;
2084 case GATE_UI_CURSOR_STOCK_HAND: cursor_name = "pointer"; break;
2085 case GATE_UI_CURSOR_STOCK_TEXT: cursor_name = "text"; break;
2086 case GATE_UI_CURSOR_STOCK_REJECTED: cursor_name = "not-allowed"; break;
2087 case GATE_UI_CURSOR_STOCK_SIZE_ALL: cursor_name = "all-scroll"; break;
2088 case GATE_UI_CURSOR_STOCK_SIZE_LEFTRIGHT: cursor_name = "ew-resize"; break;
2089 case GATE_UI_CURSOR_STOCK_SIZE_UPDOWN: cursor_name = "ns-resize"; break;
2090 case GATE_UI_CURSOR_STOCK_SIZE_LEFTUPRIGHTDOWN: cursor_name = "nwse-resize"; break;
2091 case GATE_UI_CURSOR_STOCK_SIZE_RIGHTUPKEFTDOWN: cursor_name = "nesw-resize"; break;
2092 }
2093 if (cursor_name == NULL)
2094 {
2095 ret = GATE_RESULT_NOTSUPPORTED;
2096 }
2097 else
2098 {
2099 gdk_cursor = gdk_cursor_new_from_name(display, cursor_name);
2100 if (NULL == gdk_cursor)
2101 {
2102 ret = GATE_RESULT_FAILED;
2103 }
2104 else
2105 {
2106 cursor->resources[0] = gdk_cursor;
2107 cursor->resources[1] = display;
2108 cursor->host = host;
2109 cursor->flags = GATE_UI_CURSOR_FLAG_STOCK;
2110 ret = GATE_RESULT_OK;
2111 }
2112 }
2113 return ret;
2114 }
2115 gate_result_t gate_ui_cursor_create_native(gate_ui_cursor_t* cursor, gate_ui_host_t* host, void* handle, gate_uint32_t flags)
2116 {
2117 cursor->resources[0] = handle;
2118 cursor->resources[1] = gdk_cursor_get_image((GdkCursor*)handle);
2119 cursor->host = host;
2120 cursor->flags = flags;
2121 return GATE_RESULT_OK;
2122 }
2123 gate_result_t gate_ui_cursor_create_image(gate_ui_cursor_t* cursor, gate_ui_host_t* host, gate_rasterimage_t const* image,
2124 gate_uint16_t x, gate_uint16_t y)
2125 {
2126 return GATE_RESULT_NOTIMPLEMENTED;
2127 }
2128 gate_result_t gate_ui_cursor_create_file(gate_ui_cursor_t* cursor, gate_ui_host_t* host, gate_string_t const* filepath)
2129 {
2130 return GATE_RESULT_NOTIMPLEMENTED;
2131 }
2132 gate_result_t gate_ui_cursor_copy(gate_ui_cursor_t* dstcursor, gate_ui_cursor_t const* srccursor)
2133 {
2134 GdkCursor* gdk_src_cursor = (GdkCursor*)dstcursor->resources[0];
2135 GdkCursor* gdk_dst_cursor = gdk_cursor_new_from_pixbuf((GdkDisplay*)srccursor->resources[1], gdk_cursor_get_image(gdk_src_cursor), -1, -1);
2136 if (gdk_dst_cursor)
2137 {
2138 dstcursor->resources[0] = gdk_dst_cursor;
2139 dstcursor->resources[1] = srccursor->resources[1];
2140 dstcursor->host = srccursor->host;
2141 dstcursor->flags = srccursor->flags;
2142 return GATE_RESULT_OK;
2143 }
2144 else
2145 {
2146 return GATE_RESULT_FAILED;
2147 }
2148 }
2149 gate_result_t gate_ui_cursor_destroy(gate_ui_cursor_t* cursor)
2150 {
2151 GdkCursor* gdk_cursor = (GdkCursor*)cursor->resources[0];
2152 if (gdk_cursor)
2153 {
2154 g_object_unref(gdk_cursor);
2155 }
2156 gate_mem_clear(cursor, sizeof(gate_ui_cursor_t));
2157 return GATE_RESULT_OK;
2158 }
2159
2160 #endif /* GATE_UI_GTK */
2161
2162
2163
2164 #if defined(GATE_UI_MOTIF)
2165
2166 #include "gate/debugging.h"
2167 #include "gate/ui/gateui_motif.h"
2168
2169 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)
2170 {
2171 2 return gate_ui_graphics_create_image(graph, host, width, height, 0);
2172 }
2173 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)
2174 {
2175 7 gate_result_t ret = GATE_RESULT_FAILED;
2176
2177 do
2178 {
2179 Display* display;
2180 int screen;
2181 int xdepth;
2182 Window root_window;
2183 Pixmap pixmap;
2184 GC context;
2185
2186 7 gate_mem_clear(graph, sizeof(gate_ui_graphics_t));
2187
2188 7 display = GATE_UI_MOTIF_GET_HOST_DISPLAY(host);
2189 7 screen = XDefaultScreen(display);
2190
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 xdepth = (depth == 0) ? XDefaultDepth(display, screen) : depth;
2191 7 root_window = XDefaultRootWindow(display);
2192 7 pixmap = XCreatePixmap(display, root_window, width, height, xdepth);
2193 7 context = XCreateGC(display, root_window, 0, 0);
2194 7 XFillRectangle(display, pixmap, context, 0, 0, width, height);
2195
2196 7 graph->host = host;
2197 7 graph->resources[0] = (void*)context;
2198 7 graph->resources[1] = (void*)(Drawable)pixmap;
2199 7 graph->width = width;
2200 7 graph->height = height;
2201
2202 7 XSetGraphicsExposures(display, context, 0);
2203 7 ret = GATE_RESULT_OK;
2204 } while (0);
2205 7 return ret;
2206 }
2207 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)
2208 {
2209 gate_result_t ret;
2210 do
2211 {
2212 4 ret = gate_ui_graphics_create_image(graph, host, rasterimage->width, rasterimage->height, 0);
2213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_BREAK_IF_FAILED(ret);
2214
2215 4 ret = gate_ui_graphics_draw_image(graph, rasterimage, NULL, NULL, NULL);
2216
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (GATE_FAILED(ret))
2217 {
2218 gate_ui_graphics_destroy(graph);
2219 break;
2220 }
2221
2222 4 ret = GATE_RESULT_OK;
2223 } while (0);
2224
2225 4 return ret;
2226 }
2227 2 gate_result_t gate_ui_graphics_create_ctrl(gate_ui_graphics_t* graph, gate_ui_ctrl_t* ctrl)
2228 {
2229 2 gate_result_t ret = GATE_RESULT_FAILED;
2230 do
2231 {
2232 2 gate_ui_host_t* host = GATE_UI_MOTIF_GET_CTRL_HOST(ctrl);
2233 2 Display* display = GATE_UI_MOTIF_GET_HOST_DISPLAY(host);
2234 2 Widget w = GATE_UI_MOTIF_GET_CTRL_WIDGET(ctrl);
2235 2 Window wnd = XtWindow(w);
2236 2 Dimension xwidth = 0, xheight = 0;
2237 2 GC context = XCreateGC(display, wnd, 0, NULL);
2238
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!context)
2239 {
2240 ret = GATE_RESULT_OUTOFRESOURCES;
2241 break;
2242 }
2243 2 XtVaGetValues(w, XtNwidth, &xwidth, XtNheight, &xheight, NULL, NULL);
2244
2245 2 graph->host = host;
2246 2 graph->resources[0] = (void*)context;
2247 2 graph->resources[1] = (void*)(Drawable)wnd;
2248 2 graph->resources[2] = (void*)wnd;
2249 2 graph->width = xwidth;
2250 2 graph->height = xheight;
2251
2252 2 XSetGraphicsExposures(display, context, 0);
2253 2 ret = GATE_RESULT_OK;
2254 } while (0);
2255 2 return ret;
2256 }
2257 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)
2258 {
2259 return GATE_RESULT_NOTIMPLEMENTED;
2260 }
2261 9 gate_result_t gate_ui_graphics_destroy(gate_ui_graphics_t* graph)
2262 {
2263 9 Display* display = GATE_UI_MOTIF_GET_HOST_DISPLAY(graph->host);
2264 9 GC context = (GC)graph->resources[0];
2265 9 Drawable drawable = (Drawable)graph->resources[1];
2266 9 Window window = (Window)graph->resources[2];
2267
2268
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if (display)
2269 {
2270
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2 times.
9 if (window == 0)
2271 {
2272 /* no window, expect a Pixmap surface */
2273
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
7 if (drawable != 0)
2274 {
2275 4 XFreePixmap(display, (Pixmap)drawable);
2276 }
2277 }
2278 else
2279 {
2280 }
2281
2282
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if (context)
2283 {
2284 9 XFreeGC(display, context);
2285 }
2286 }
2287
2288 9 return GATE_RESULT_NOTIMPLEMENTED;
2289 }
2290
2291 672 static unsigned long XGetRgbPixel(Display* display, gate_uint8_t r, gate_uint8_t g, gate_uint8_t b)
2292 {
2293 672 int screen = XDefaultScreen(display);
2294 672 Colormap cmap = XDefaultColormap(display, screen);
2295 XColor col;
2296 672 col.pixel = 0;
2297 672 col.red = ((gate_uint16_t)r) << 8;
2298 672 col.green = ((gate_uint16_t)g) << 8;
2299 672 col.blue = ((gate_uint16_t)b) << 8;
2300 672 col.flags = DoRed | DoGreen | DoBlue;
2301 672 XAllocColor(display, cmap, &col);
2302 672 return col.pixel;
2303 }
2304
2305 2 gate_int32_t gate_ui_graphics_width(gate_ui_graphics_t* graph)
2306 {
2307 2 return graph->width;
2308 }
2309
2310 2 gate_int32_t gate_ui_graphics_height(gate_ui_graphics_t* graph)
2311 {
2312 2 return graph->height;
2313 }
2314
2315 2 gate_result_t gate_ui_graphics_set_pixel(gate_ui_graphics_t* graph, gate_ui_point_t pos, gate_ui_color_t col)
2316 {
2317 2 Display* const display = GATE_UI_MOTIF_GET_HOST_DISPLAY(graph->host);
2318 2 GC const context = (GC)graph->resources[0];
2319 2 Drawable const drawable = (Drawable)graph->resources[1];
2320
2321 2 XSetForeground(display, context, XGetRgbPixel(display, col.r, col.g, col.b));
2322 2 XDrawPoint(display, drawable, context, pos.x, pos.y);
2323 2 return GATE_RESULT_OK;
2324 }
2325
2326 2 gate_result_t gate_ui_graphics_get_pixel(gate_ui_graphics_t* graph, gate_ui_point_t pos, gate_ui_color_t* col)
2327 {
2328 2 return GATE_RESULT_NOTIMPLEMENTED;
2329 }
2330
2331 2 gate_result_t gate_ui_graphics_draw(gate_ui_graphics_t* graph, gate_ui_graphics_t* srcgraph,
2332 gate_ui_point_t const* dst, gate_ui_size_t const* size, gate_ui_point_t const* srcpos)
2333 {
2334 2 Display* const display = GATE_UI_MOTIF_GET_HOST_DISPLAY(graph->host);
2335 2 GC const context = (GC)graph->resources[0];
2336 2 Drawable const target = (Drawable)graph->resources[1];
2337 2 Drawable const source = (Drawable)srcgraph->resources[1];
2338 int src_x, src_y, width, height, dst_x, dst_y;
2339 2 dst_x = dst->x;
2340 2 dst_y = dst->y;
2341 2 src_x = srcpos->x;
2342 2 src_y = srcpos->y;
2343 2 width = size->width;
2344 2 height = size->height;
2345
2346 2 XCopyArea(display, source, target, context, src_x, src_y, width, height, dst_x, dst_y);
2347 2 return GATE_RESULT_OK;
2348 }
2349
2350 2 gate_result_t gate_ui_graphics_draw_ex(gate_ui_graphics_t* graph, gate_ui_graphics_t* src_graph,
2351 gate_ui_position_t const* dest_rect, gate_ui_position_t const* src_rect)
2352 {
2353 2 Display* const display = GATE_UI_MOTIF_GET_HOST_DISPLAY(graph->host);
2354 2 GC const context = (GC)graph->resources[0];
2355 2 Drawable const target = (Drawable)graph->resources[1];
2356 2 Drawable const source = (Drawable)src_graph->resources[1];
2357 int src_x, src_y, width, height, dst_x, dst_y;
2358 2 dst_x = dest_rect->pos.x;
2359 2 dst_y = dest_rect->pos.y;
2360 2 src_x = src_rect->pos.x;
2361 2 src_y = src_rect->pos.y;
2362 /* TODO */
2363 2 width = dest_rect->size.width;
2364 2 height = dest_rect->size.height;
2365
2366 2 XCopyArea(display, source, target, context, src_x, src_y, width, height, dst_x, dst_y);
2367 2 return GATE_RESULT_OK;
2368 }
2369
2370 5 gate_result_t gate_ui_graphics_draw_image(gate_ui_graphics_t* graph, gate_rasterimage_t const* srcimage,
2371 gate_ui_point_t const* dst, gate_ui_size_t const* size, gate_ui_point_t const* srcpos)
2372 {
2373 5 Display* const display = GATE_UI_MOTIF_GET_HOST_DISPLAY(graph->host);
2374 5 GC const context = (GC)graph->resources[0];
2375 5 Drawable const drawable = (Drawable)graph->resources[1];
2376
2377 gate_color_t pixel;
2378 5 gate_uint32_t pixel_cache = 0;
2379 int src_x, src_y, width, height, dst_x, dst_y;
2380 int x, y;
2381
2382
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (srcpos)
2383 {
2384 src_x = srcpos->x;
2385 src_y = srcpos->y;
2386 }
2387 else
2388 {
2389 5 src_x = 0;
2390 5 src_y = 0;
2391 }
2392
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (size)
2393 {
2394 width = size->width;
2395 height = size->height;
2396 }
2397 else
2398 {
2399 5 width = srcimage->width;
2400 5 height = srcimage->height;
2401 }
2402
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (dst)
2403 {
2404 dst_x = dst->x;
2405 dst_y = dst->y;
2406 }
2407 else
2408 {
2409 5 dst_x = 0;
2410 5 dst_y = 0;
2411 }
2412
2413
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 5 times.
85 for (y = 0; y != height; ++y)
2414 {
2415
2/2
✓ Branch 0 taken 1280 times.
✓ Branch 1 taken 80 times.
1360 for (x = 0; x != width; ++x)
2416 {
2417 1280 gate_rasterimage_get_pixel(srcimage, src_x + x, src_y + y, &pixel);
2418
2/2
✓ Branch 0 taken 917 times.
✓ Branch 1 taken 363 times.
1280 if (pixel.a > 127)
2419 {
2420
2/2
✓ Branch 0 taken 658 times.
✓ Branch 1 taken 259 times.
917 if (pixel.rgba != pixel_cache)
2421 {
2422 658 unsigned long x11_color = XGetRgbPixel(display, pixel.r, pixel.g, pixel.b);
2423 658 pixel_cache = pixel.rgba;
2424 658 XSetForeground(display, context, x11_color);
2425 }
2426 917 XDrawPoint(display, drawable, context, dst_x + x, dst_y + y);
2427 }
2428 }
2429 }
2430 5 return GATE_RESULT_OK;
2431 }
2432
2433 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)
2434 {
2435 4 Display* const display = GATE_UI_MOTIF_GET_HOST_DISPLAY(graph->host);
2436 4 GC const context = (GC)graph->resources[0];
2437 4 Drawable const drawable = (Drawable)graph->resources[1];
2438
2439 4 XSetForeground(display, context, XGetRgbPixel(display, col.r, col.g, col.b));
2440 4 XDrawLine(display, drawable, context, from.x, from.y, to.x, to.y);
2441 4 return GATE_RESULT_OK;
2442 }
2443
2444 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)
2445 {
2446 3 Display* const display = GATE_UI_MOTIF_GET_HOST_DISPLAY(graph->host);
2447 3 GC const context = (GC)graph->resources[0];
2448 3 Drawable const drawable = (Drawable)graph->resources[1];
2449 unsigned long pixel;
2450
2451
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (colfill)
2452 {
2453 3 pixel = XGetRgbPixel(display, colfill->r, colfill->g, colfill->b);
2454 3 XSetForeground(display, context, pixel);
2455 3 XFillRectangle(display, drawable, context, rect.pos.x, rect.pos.y, rect.size.width, rect.size.height);
2456 }
2457
2458
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (colline)
2459 {
2460 3 pixel = XGetRgbPixel(display, colline->r, colline->g, colline->b);
2461 3 XSetForeground(display, context, pixel);
2462 3 XDrawRectangle(display, drawable, context, rect.pos.x, rect.pos.y, rect.size.width, rect.size.height);
2463 }
2464 3 return GATE_RESULT_OK;
2465 }
2466
2467 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)
2468 {
2469 2 Display* const display = GATE_UI_MOTIF_GET_HOST_DISPLAY(graph->host);
2470 2 GC const context = (GC)graph->resources[0];
2471 2 Drawable const drawable = (Drawable)graph->resources[1];
2472 unsigned long pixel;
2473 gate_size_t ndx;
2474 XPoint xp[64];
2475
2476
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)))
2477 {
2478 /* nothing to do */
2479 return GATE_RESULT_OK;
2480 }
2481
2482
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pointcount > 64)
2483 {
2484 pointcount = 64;
2485 }
2486
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
12 for (ndx = 0; ndx != pointcount; ++ndx)
2487 {
2488 10 xp[ndx].x = points[ndx].x;
2489 10 xp[ndx].y = points[ndx].y;
2490 }
2491
2492
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (colfill)
2493 {
2494 pixel = XGetRgbPixel(display, colfill->r, colfill->g, colfill->b);
2495 XSetForeground(display, context, pixel);
2496 XFillPolygon(display, drawable, context, xp, (int)pointcount, Complex, CoordModeOrigin);
2497 }
2498
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (colline)
2499 {
2500 2 pixel = XGetRgbPixel(display, colline->r, colline->g, colline->b);
2501 2 XSetForeground(display, context, pixel);
2502
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 for (ndx = 0; ndx != pointcount - 1; ++ndx)
2503 {
2504 8 XDrawLine(display, drawable, context, xp[ndx].x, xp[ndx].y, xp[ndx + 1].x, xp[ndx + 1].y);
2505 }
2506 2 XDrawLine(display, drawable, context, xp[pointcount - 1].x, xp[pointcount - 1].y, xp[0].x, xp[0].y);
2507 }
2508 2 return GATE_RESULT_OK;
2509 }
2510
2511 static gate_bool_t find_best_font_name(Display* display, gate_ui_font_t* font)
2512 {
2513 gate_bool_t ret = false;
2514 int max_fonts = 1024;
2515 int fonts_returned = 0;
2516 char** fonts = XListFonts(display, "*", max_fonts, &fonts_returned);
2517
2518 do
2519 {
2520 int ndx;
2521 char const* pattern = font->font_name;
2522 gate_size_t pattern_len = gate_str_length(font->font_name);
2523
2524 if (fonts == NULL)
2525 {
2526 break;
2527 }
2528 for (ndx = 0; ndx < fonts_returned; ++ndx)
2529 {
2530 char* font_name = fonts[ndx];
2531 gate_size_t font_name_len = gate_str_length(font_name);
2532 gate_size_t pos;
2533 if(font_name_len == 0)
2534 {
2535 continue;
2536 }
2537 pos = gate_str_pos(font_name, font_name_len, pattern, pattern_len, 0);
2538 if(pos != GATE_STR_NPOS)
2539 {
2540 gate_str_print_text(font->font_name, sizeof(font->font_name), font_name, font_name_len);
2541 ret = true;
2542 break;
2543 }
2544 }
2545 /* code */
2546 } while (0);
2547
2548 if(fonts != NULL)
2549 {
2550 XFreeFontNames(fonts);
2551 }
2552
2553 return ret;
2554 }
2555
2556 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)
2557 {
2558 return GATE_RESULT_NOTIMPLEMENTED;
2559 }
2560
2561
2562
2563 static void print_font_name(char* name_buffer, gate_size_t name_capacity, gate_ui_font_t const* font)
2564 {
2565 gate_strbuilder_t builder;
2566
2567 gate_strbuilder_create_static(&builder, name_buffer, name_capacity, 0);
2568 gate_strbuilder_append_cstr(&builder, "-");
2569 gate_strbuilder_append_cstr(&builder, font->font_name);
2570 gate_strbuilder_append_cstr(&builder, font->bold ? "-bold" : "-medium");
2571 gate_strbuilder_append_cstr(&builder, font->italic ? "-i" : "-r");
2572 gate_strbuilder_append_cstr(&builder, "-*-");
2573 gate_strbuilder_append_int32(&builder, font->size);
2574 gate_strbuilder_append_cstr(&builder, "-*");
2575 }
2576
2577 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)
2578 {
2579 2 Display* const display = GATE_UI_MOTIF_GET_HOST_DISPLAY(graph->host);
2580 2 GC const context = (GC)graph->resources[0];
2581 2 Drawable const drawable = (Drawable)graph->resources[1];
2582
2583 XFontStruct* fontstruct;
2584
2585 2 fontstruct = XLoadQueryFont(display, "fixed");
2586
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));
2587
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (height) *height = fontstruct->ascent + fontstruct->descent;
2588 2 XFreeFont(display, fontstruct);
2589 2 return GATE_RESULT_OK;
2590 }
2591
2592 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)
2593 {
2594 2 Display* const display = GATE_UI_MOTIF_GET_HOST_DISPLAY(graph->host);
2595 2 GC const context = (GC)graph->resources[0];
2596 2 Drawable const drawable = (Drawable)graph->resources[1];
2597 gate_ui_font_t updated_font;
2598
2599 XFontStruct* fontstruct;
2600
2601 2 fontstruct = XLoadQueryFont(display, "fixed");
2602
2603 2 XSetFont(display, context, fontstruct->fid);
2604 2 XDrawString(display, drawable, context, pos->pos.x, pos->pos.y + fontstruct->ascent, text->str, text->length);
2605
2606 2 XFreeFont(display, fontstruct);
2607 2 return GATE_RESULT_OK;
2608 }
2609
2610 void* gate_ui_graphics_handle(gate_ui_graphics_t* graph)
2611 {
2612 return graph->resources[0];
2613 }
2614 1 void* gate_ui_graphics_surface(gate_ui_graphics_t* graph)
2615 {
2616 1 return graph->resources[1];
2617 }
2618
2619
2620
2621
2622 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)
2623 {
2624 return GATE_RESULT_NOTIMPLEMENTED;
2625 }
2626 gate_result_t gate_ui_icon_create_native(gate_ui_icon_t* icon, gate_ui_host_t* host, void* handle, gate_uint32_t flags)
2627 {
2628 return GATE_RESULT_NOTIMPLEMENTED;
2629 }
2630 gate_result_t gate_ui_icon_create_image(gate_ui_icon_t* icon, gate_ui_host_t* host, gate_rasterimage_t const* image)
2631 {
2632 return GATE_RESULT_NOTIMPLEMENTED;
2633 }
2634 gate_result_t gate_ui_icon_create_file(gate_ui_icon_t* icon, gate_ui_host_t* host, gate_string_t const* filepath)
2635 {
2636 return GATE_RESULT_NOTIMPLEMENTED;
2637 }
2638 gate_result_t gate_ui_icon_copy(gate_ui_icon_t* dsticon, gate_ui_icon_t const* srcicon)
2639 {
2640 return GATE_RESULT_NOTIMPLEMENTED;
2641 }
2642 gate_result_t gate_ui_icon_destroy(gate_ui_icon_t* icon)
2643 {
2644 return GATE_RESULT_NOTIMPLEMENTED;
2645 }
2646
2647
2648
2649 /**
2650 * A motif ICON list is an array of Pixmap instances.
2651 * Each ICON entry is represented by two Pixmaps, the first is the mask pixmap,
2652 * the second one holds the icon pixels
2653 *
2654 */
2655
2656 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)
2657 {
2658 gate_arraylist_t pixmap_list;
2659
2660
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_DEBUG_ASSERT(ilst !=NULL);
2661
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_DEBUG_ASSERT(host != NULL);
2662
2663 3 gate_mem_clear(ilst, sizeof(gate_ui_iconlist_t));
2664 3 ilst->host = host;
2665 3 ilst->flags = 0;
2666 3 ilst->width = width;
2667 3 ilst->height = height;
2668 3 ilst->resources[0] = NULL;
2669 3 return GATE_RESULT_OK;
2670 }
2671
2672 1 gate_result_t gate_ui_iconlist_destroy(gate_ui_iconlist_t* ilst)
2673 {
2674 gate_arraylist_t pixmap_list;
2675
2676
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_ASSERT(ilst != NULL);
2677
2678 1 pixmap_list = (gate_arraylist_t)ilst->resources[0];
2679
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (pixmap_list != NULL)
2680 {
2681 1 Display* display = GATE_UI_MOTIF_GET_HOST_DISPLAY(ilst->host);
2682 gate_size_t ndx;
2683 1 gate_size_t cnt = gate_arraylist_length(pixmap_list);
2684
2685
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 for(ndx = 0; ndx != cnt; ++ndx)
2686 {
2687 2 Pixmap* ptr_pixmap = gate_arraylist_get(pixmap_list, ndx);
2688
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if(ptr_pixmap != NULL)
2689 {
2690 2 XFreePixmap(display, (Pixmap)*ptr_pixmap);
2691 }
2692 }
2693 1 gate_arraylist_release(pixmap_list);
2694 1 ilst->resources[0] = NULL;
2695 }
2696 1 return GATE_RESULT_OK;
2697 }
2698 gate_size_t gate_ui_iconlist_count(gate_ui_iconlist_t* ilst)
2699 {
2700 gate_size_t ret = 0;
2701 gate_arraylist_t pixmap_list;
2702
2703 GATE_DEBUG_ASSERT(ilst != NULL);
2704
2705 pixmap_list = (gate_arraylist_t)ilst->resources[0];
2706 if (pixmap_list != NULL)
2707 {
2708 gate_size_t const cnt = gate_arraylist_length(pixmap_list);
2709 ret = cnt / 2;
2710 }
2711 return ret;
2712 }
2713
2714 2 static Pixmap create_mask_pixmap(gate_ui_host_t* host, gate_rasterimage_t const* image)
2715 {
2716 2 Display* dpy = GATE_UI_MOTIF_GET_HOST_DISPLAY(host);
2717 2 Window win = XDefaultRootWindow(dpy);
2718 Pixmap pm;
2719 GC gc;
2720 gate_color_t col;
2721 unsigned int x, y, width, height;
2722
2723 2 width = gate_rasterimage_width(image);
2724 2 height = gate_rasterimage_height(image);
2725
2726 2 pm = XCreatePixmap(dpy, win, image->width, image->height, 1);
2727 2 gc = XCreateGC(dpy, pm, 0, NULL);
2728 2 XSetForeground(dpy, gc, 0);
2729 2 XFillRectangle(dpy, pm, gc, 0, 0, width, height);
2730 2 XSetForeground(dpy, gc, 1);
2731
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 2 times.
34 for (y = 0; y != height; ++y)
2732 {
2733
2/2
✓ Branch 0 taken 512 times.
✓ Branch 1 taken 32 times.
544 for (x = 0; x != width; ++x)
2734 {
2735 512 gate_rasterimage_get_pixel(image, x, y, &col);
2736
2/2
✓ Branch 0 taken 338 times.
✓ Branch 1 taken 174 times.
512 if (col.a > 127)
2737 {
2738 338 XDrawPoint(dpy, pm, gc, x, y);
2739 }
2740 }
2741 }
2742 2 XFreeGC(dpy, gc);
2743 2 return pm;
2744 }
2745
2746 gate_result_t gate_ui_iconlist_add_icon(gate_ui_iconlist_t* ilst, gate_ui_icon_t const* icon, gate_intptr_t* icon_key)
2747 {
2748 /* TODO */
2749 return GATE_RESULT_NOTIMPLEMENTED;
2750 }
2751
2752 2 gate_result_t gate_ui_iconlist_add_image(gate_ui_iconlist_t* ilst, gate_rasterimage_t const* image, gate_intptr_t* icon_key)
2753 {
2754 gate_result_t ret;
2755
2756
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_DEBUG_ASSERT(ilst != NULL);
2757
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_DEBUG_ASSERT(image != NULL);
2758
2759 do
2760 {
2761 gate_ui_graphics_t graph;
2762 Pixmap pm;
2763 gate_size_t len;
2764 2 gate_arraylist_t pixmap_list = ilst->resources[0];
2765
2766
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (pixmap_list == NULL)
2767 {
2768 2 pixmap_list = gate_arraylist_create(sizeof(Pixmap), NULL, 16, NULL, NULL);
2769
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (NULL == pixmap_list)
2770 {
2771 GATE_DEBUG_TRACE("Failed to allocate pixmap array");
2772 ret = GATE_RESULT_OUTOFMEMORY;
2773 break;
2774 }
2775 2 ilst->resources[0] = (void*)pixmap_list;
2776 }
2777
2778 2 pm = create_mask_pixmap(ilst->host, image);
2779
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (NULL == gate_arraylist_add(pixmap_list, &pm))
2780 {
2781 ret = GATE_RESULT_OUTOFMEMORY;
2782 break;
2783 }
2784
2785 2 ret = gate_ui_graphics_create_image_from(&graph, ilst->host, image);
2786
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
2787
2788 2 pm = (Pixmap)graph.resources[1];
2789 2 graph.resources[1] = 0;
2790 2 gate_ui_graphics_destroy(&graph);
2791
2792 2 gate_arraylist_add(pixmap_list, &pm);
2793 2 len = gate_arraylist_length(pixmap_list);
2794
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (icon_key)
2795 {
2796 2 *icon_key = (gate_intptr_t)len;
2797 }
2798 2 ret = GATE_RESULT_OK;
2799 } while (0);
2800 2 return ret;
2801 }
2802 gate_result_t gate_ui_iconlist_get_icon(gate_ui_iconlist_t* ilst, gate_intptr_t icon_key, gate_ui_icon_t* icon)
2803 {
2804 /* TODO */
2805 return GATE_RESULT_NOTIMPLEMENTED;
2806 }
2807 13 void* gate_ui_iconlist_get_handle(gate_ui_iconlist_t* ilst, gate_intptr_t icon_key)
2808 {
2809 13 void* ret = NULL;
2810
2811
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 GATE_DEBUG_ASSERT(ilst != NULL);
2812 do
2813 {
2814 gate_arraylist_t pixmap_list;
2815 gate_size_t cnt;
2816 13 gate_size_t ndx = (gate_size_t)icon_key;
2817
2818
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if(ilst->resources[0] == NULL) break;
2819
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if(ndx < 2) break;
2820 13 ndx -= 2; /* key == length after add, we need to go two steps back to point to the first pixmap */
2821
2822 13 pixmap_list = ilst->resources[0];
2823 13 cnt = gate_arraylist_length(pixmap_list);
2824
2825 13 ret = gate_arraylist_get(pixmap_list, ndx);
2826 /* ret == Pixmap* to mask pixmap */
2827 } while (0);
2828
2829 13 return ret;
2830 }
2831
2832
2833
2834
2835
2836 gate_result_t gate_ui_cursor_create_stock(gate_ui_cursor_t* cursor, gate_ui_host_t* host, gate_uint32_t stock_id)
2837 {
2838 return GATE_RESULT_NOTIMPLEMENTED;
2839 }
2840 gate_result_t gate_ui_cursor_create_native(gate_ui_cursor_t* cursor, gate_ui_host_t* host, void* handle, gate_uint32_t flags)
2841 {
2842 return GATE_RESULT_NOTIMPLEMENTED;
2843 }
2844 gate_result_t gate_ui_cursor_create_image(gate_ui_cursor_t* cursor, gate_ui_host_t* host, gate_rasterimage_t const* image,
2845 gate_uint16_t x, gate_uint16_t y)
2846 {
2847 return GATE_RESULT_NOTIMPLEMENTED;
2848 }
2849 gate_result_t gate_ui_cursor_create_file(gate_ui_cursor_t* cursor, gate_ui_host_t* host, gate_string_t const* filepath)
2850 {
2851 return GATE_RESULT_NOTIMPLEMENTED;
2852 }
2853 gate_result_t gate_ui_cursor_copy(gate_ui_cursor_t* dstcursor, gate_ui_cursor_t const* srccursor)
2854 {
2855 return GATE_RESULT_NOTIMPLEMENTED;
2856 }
2857 gate_result_t gate_ui_cursor_destroy(gate_ui_cursor_t* cursor)
2858 {
2859 return GATE_RESULT_NOTIMPLEMENTED;
2860 }
2861
2862
2863 #endif /* GATE_UI_MOTIF */
2864