GCC Code Coverage Report


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