GCC Code Coverage Report


Directory: src/gate/
File: src/gate/ui/graphics.c
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 0 233 0.0%
Functions: 0 41 0.0%
Branches: 0 38 0.0%

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