source: mainline/uspace/app/gfxdemo/gfxdemo.c@ 5d9403d5

ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 5d9403d5 was 788c76e3, checked in by Jiri Svoboda <jiri@…>, 22 months ago

GFX demo should downsize the window with -d cons@ ui

Also do not return task value if the ui is fullscreen.

  • Property mode set to 100644
File size: 26.0 KB
RevLine 
[045186b]1/*
[bd2fab5]2 * Copyright (c) 2023 Jiri Svoboda
[045186b]3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - 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 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup gfxdemo
30 * @{
31 */
32/** @file Graphic demo
33 */
34
[a3f63ac]35#include <congfx/console.h>
[c8cf261]36#include <display.h>
[9259d20]37#include <fibril.h>
[e0545de]38#include <gfx/bitmap.h>
[045186b]39#include <gfx/color.h>
40#include <gfx/render.h>
[8fa65af0]41#include <gfx/font.h>
42#include <gfx/text.h>
43#include <gfx/typeface.h>
[9259d20]44#include <io/console.h>
[e0545de]45#include <io/pixelmap.h>
[b3c185b6]46#include <stdbool.h>
[9259d20]47#include <stdlib.h>
[00e8290]48#include <str.h>
[5bded44]49#include <task.h>
[b93ec7c0]50#include <ui/ui.h>
51#include <ui/window.h>
52#include <ui/wdecor.h>
[045186b]53
[338d0935]54static void wnd_close_event(void *);
[b3c185b6]55static void wnd_kbd_event(void *, kbd_event_t *);
56
57static display_wnd_cb_t wnd_cb = {
[338d0935]58 .close_event = wnd_close_event,
[b3c185b6]59 .kbd_event = wnd_kbd_event
60};
61
[b93ec7c0]62static void uiwnd_close_event(ui_window_t *, void *);
63static void uiwnd_kbd_event(ui_window_t *, void *, kbd_event_t *);
64
65static ui_window_cb_t ui_window_cb = {
66 .close = uiwnd_close_event,
67 .kbd = uiwnd_kbd_event
68};
69
[082feff]70static void demo_kbd_event(kbd_event_t *);
71
[b3c185b6]72static bool quit = false;
[af967ef9]73static FIBRIL_MUTEX_INITIALIZE(quit_lock);
74static FIBRIL_CONDVAR_INITIALIZE(quit_cv);
[8dbd13d]75static gfx_typeface_t *tface;
76static gfx_font_t *font;
77static gfx_coord_t vpad;
[082feff]78static console_ctrl_t *con = NULL;
[b3c185b6]79
[bc52b5b]80/** Determine if we are running in text mode.
81 *
82 * @param w Screen width
83 * @param h Screen height
84 * @return @c true iff we are running in text mode
85 */
86static bool demo_is_text(gfx_coord_t w, gfx_coord_t h)
87{
88 // XXX Need a proper way to determine text mode
89 return w <= 80;
90}
91
[af967ef9]92/** Sleep until timeout or quit request.
93 *
94 * @param msec Number of microseconds to sleep for
95 */
96static void demo_msleep(unsigned msec)
97{
[082feff]98 errno_t rc;
99 usec_t usec;
100 cons_event_t cevent;
[af967ef9]101
[082feff]102 fibril_mutex_lock(&quit_lock);
[af967ef9]103 if (!quit) {
[082feff]104 if (con != NULL) {
105 usec = (usec_t)msec * 1000;
106 while (usec > 0 && !quit) {
107 rc = console_get_event_timeout(con, &cevent, &usec);
108 if (rc == EOK) {
109 if (cevent.type == CEV_KEY) {
110 fibril_mutex_unlock(&quit_lock);
111 demo_kbd_event(&cevent.ev.key);
112 fibril_mutex_lock(&quit_lock);
113 }
114 }
115 }
116 } else {
117 (void) fibril_condvar_wait_timeout(&quit_cv, &quit_lock,
118 (usec_t)msec * 1000);
119 }
[af967ef9]120 }
121 fibril_mutex_unlock(&quit_lock);
122}
123
[587b4cb]124/** Clear screen.
125 *
126 * @param gc Graphic context
127 * @param w Screen width
128 * @param h Screen height
129 */
130static errno_t clear_scr(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
131{
132 gfx_color_t *color = NULL;
133 gfx_rect_t rect;
134 errno_t rc;
135
136 rc = gfx_color_new_rgb_i16(0, 0, 0, &color);
137 if (rc != EOK)
138 goto error;
139
140 rc = gfx_set_color(gc, color);
141 if (rc != EOK)
142 goto error;
143
144 rect.p0.x = 0;
145 rect.p0.y = 0;
146 rect.p1.x = w;
147 rect.p1.y = h;
148
149 rc = gfx_fill_rect(gc, &rect);
150 if (rc != EOK)
151 goto error;
152
153 gfx_color_delete(color);
154 return EOK;
155error:
156 if (color != NULL)
157 gfx_color_delete(color);
158 return rc;
159}
160
[8dbd13d]161/** Initialize demo font.
162 *
163 * @param gc Graphic context
164 * @param w Width
165 * @param h Height
166 * @return EOK on success or an error code
167 */
168static errno_t demo_font_init(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
169{
170 gfx_font_info_t *finfo;
171 errno_t rc;
172
173 if (quit)
174 return EOK;
175
176 /* XXX Crude way of detecting text mode */
177 if (w < 256) {
178 /* Create dummy font for text mode */
179 rc = gfx_typeface_create(gc, &tface);
180 if (rc != EOK) {
181 printf("Error creating typeface\n");
182 goto error;
183 }
184
185 rc = gfx_font_create_textmode(tface, &font);
186 if (rc != EOK) {
187 printf("Error creating font\n");
188 goto error;
189 }
190
191 vpad = 0;
192 } else {
193 /* Load font */
194 rc = gfx_typeface_open(gc, "/data/font/helena.tpf", &tface);
195 if (rc != EOK) {
196 printf("Error opening typeface\n");
197 goto error;
198 }
199
200 finfo = gfx_typeface_first_font(tface);
201 if (finfo == NULL) {
202 printf("Typeface contains no font.\n");
203 rc = ENOENT;
204 goto error;
205 }
206
207 rc = gfx_font_open(finfo, &font);
208 if (rc != EOK) {
209 printf("Error opening font.\n");
210 goto error;
211 }
212
213 vpad = 5;
214 }
215
216 return EOK;
217error:
218 if (tface != NULL)
219 gfx_typeface_destroy(tface);
220 return rc;
221}
222
223/** Finalize demo font. */
224static void demo_font_fini(void)
225{
226 if (font == NULL)
227 return;
228
229 gfx_font_close(font);
230 font = NULL;
231
232 gfx_typeface_destroy(tface);
233 tface = NULL;
234}
235
236/** Start a new demo screen.
237 *
238 * Clear the screen, display a status line and set up clipping.
239 *
240 * @param gc Graphic context
241 * @param w Width
242 * @param h Height
243 * @param text Demo screen description
244 * @return EOK on success or an error code
245 */
246static errno_t demo_begin(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h,
247 const char *text)
248{
249 gfx_text_fmt_t fmt;
250 gfx_font_metrics_t metrics;
251 gfx_coord2_t pos;
252 gfx_color_t *color;
253 gfx_rect_t rect;
254 gfx_coord_t height;
255 errno_t rc;
256
257 rc = gfx_set_clip_rect(gc, NULL);
258 if (rc != EOK)
259 return rc;
260
261 rc = clear_scr(gc, w, h);
262 if (rc != EOK)
263 return rc;
264
265 if (font != NULL) {
[bc52b5b]266 if (demo_is_text(w, h)) {
267 rc = gfx_color_new_ega(0x1e, &color);
268 if (rc != EOK)
269 goto error;
270 } else {
271 rc = gfx_color_new_rgb_i16(0xffff, 0xffff, 0xffff, &color);
272 if (rc != EOK)
273 goto error;
274 }
[8dbd13d]275
276 gfx_text_fmt_init(&fmt);
[4583015]277 fmt.font = font;
[8dbd13d]278 fmt.color = color;
279 fmt.halign = gfx_halign_center;
280 fmt.valign = gfx_valign_bottom;
281
282 pos.x = w / 2;
[901b302]283 pos.y = h;
[4583015]284 rc = gfx_puttext(&pos, &fmt, text);
[8dbd13d]285 if (rc != EOK) {
286 printf("Error rendering text.\n");
287 gfx_color_delete(color);
288 goto error;
289 }
290
291 gfx_color_delete(color);
292
293 gfx_font_get_metrics(font, &metrics);
294 height = metrics.ascent + metrics.descent + 1;
295 } else {
296 height = 0;
297 }
298
299 rect.p0.x = 0;
300 rect.p0.y = 0;
301 rect.p1.x = w;
302 rect.p1.y = h - height - vpad;
303 rc = gfx_set_clip_rect(gc, &rect);
304 if (rc != EOK)
305 return rc;
306
307 return EOK;
308error:
309 return rc;
310}
311
[00e8290]312/** Run rectangle demo on a graphic context.
313 *
314 * @param gc Graphic context
[e0545de]315 * @param w Width
316 * @param h Height
[00e8290]317 */
[1822545]318static errno_t demo_rects(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
[045186b]319{
[9259d20]320 gfx_color_t *color = NULL;
321 gfx_rect_t rect;
[e0545de]322 int i, j;
[9259d20]323 errno_t rc;
324
[4f64b7b8]325 if (quit)
326 return EOK;
327
[8dbd13d]328 rc = demo_begin(gc, w, h, "Rectangle rendering");
[587b4cb]329 if (rc != EOK)
330 return rc;
331
[e0545de]332 for (j = 0; j < 10; j++) {
[9259d20]333 rc = gfx_color_new_rgb_i16(rand() % 0x10000, rand() % 0x10000,
334 rand() % 0x10000, &color);
335 if (rc != EOK)
[00e8290]336 return rc;
[9259d20]337
338 rc = gfx_set_color(gc, color);
339 if (rc != EOK)
[00e8290]340 return rc;
[9259d20]341
342 for (i = 0; i < 10; i++) {
[00e8290]343 rect.p0.x = rand() % (w - 1);
344 rect.p0.y = rand() % (h - 1);
345 rect.p1.x = rect.p0.x + rand() % (w - 1 - rect.p0.x);
346 rect.p1.y = rect.p0.y + rand() % (h - 1 - rect.p0.y);
[9259d20]347
348 rc = gfx_fill_rect(gc, &rect);
349 if (rc != EOK)
[00e8290]350 return rc;
[9259d20]351 }
352
353 gfx_color_delete(color);
354
[af967ef9]355 demo_msleep(500);
[b3c185b6]356 if (quit)
357 break;
[9259d20]358 }
[e0545de]359
360 return EOK;
361}
362
[587b4cb]363/** Fill bitmap with tartan pattern.
364 *
365 * @param bitmap Bitmap
366 * @param w Bitmap width
367 * @param h Bitmap height
368 * @return EOK on success or an error code
369 */
370static errno_t bitmap_tartan(gfx_bitmap_t *bitmap, gfx_coord_t w, gfx_coord_t h)
371{
372 int i, j;
373 pixelmap_t pixelmap;
374 gfx_bitmap_alloc_t alloc;
375 errno_t rc;
376
377 rc = gfx_bitmap_get_alloc(bitmap, &alloc);
378 if (rc != EOK)
379 return rc;
380
381 /* In absence of anything else, use pixelmap */
382 pixelmap.width = w;
383 pixelmap.height = h;
384 pixelmap.data = alloc.pixels;
385
386 for (i = 0; i < w; i++) {
387 for (j = 0; j < h; j++) {
388 pixelmap_put_pixel(&pixelmap, i, j,
[6a87f28]389 PIXEL(0, (i % 30) < 3 ? 255 : 0,
[587b4cb]390 (j % 30) < 3 ? 255 : 0, i / 2));
391 }
392 }
393
394 return EOK;
395}
396
397/** Fill bitmap with moire pattern.
398 *
399 * @param bitmap Bitmap
400 * @param w Bitmap width
401 * @param h Bitmap height
402 * @return EOK on success or an error code
403 */
404static errno_t bitmap_moire(gfx_bitmap_t *bitmap, gfx_coord_t w, gfx_coord_t h)
405{
406 int i, j;
407 int k;
408 pixelmap_t pixelmap;
409 gfx_bitmap_alloc_t alloc;
410 errno_t rc;
411
412 rc = gfx_bitmap_get_alloc(bitmap, &alloc);
413 if (rc != EOK)
414 return rc;
415
416 /* In absence of anything else, use pixelmap */
417 pixelmap.width = w;
418 pixelmap.height = h;
419 pixelmap.data = alloc.pixels;
420
421 for (i = 0; i < w; i++) {
422 for (j = 0; j < h; j++) {
423 k = i * i + j * j;
424 pixelmap_put_pixel(&pixelmap, i, j,
[6a87f28]425 PIXEL(0, k, k, k));
[587b4cb]426 }
427 }
428
429 return EOK;
430}
431
[bea947f]432/** Render circle to a bitmap.
433 *
434 * @param bitmap Bitmap
435 * @param w Bitmap width
436 * @param h Bitmap height
437 * @return EOK on success or an error code
438 */
439static errno_t bitmap_circle(gfx_bitmap_t *bitmap, gfx_coord_t w, gfx_coord_t h)
440{
441 int i, j;
442 int k;
443 pixelmap_t pixelmap;
444 gfx_bitmap_alloc_t alloc;
445 errno_t rc;
446
447 rc = gfx_bitmap_get_alloc(bitmap, &alloc);
448 if (rc != EOK)
449 return rc;
450
451 /* In absence of anything else, use pixelmap */
452 pixelmap.width = w;
453 pixelmap.height = h;
454 pixelmap.data = alloc.pixels;
455
456 for (i = 0; i < w; i++) {
457 for (j = 0; j < h; j++) {
458 k = i * i + j * j;
459 pixelmap_put_pixel(&pixelmap, i, j,
[6a87f28]460 k < w * w / 2 ? PIXEL(0, 0, 255, 0) :
[bea947f]461 PIXEL(0, 255, 0, 255));
462 }
463 }
464
465 return EOK;
466}
467
[e0545de]468/** Run bitmap demo on a graphic context.
469 *
470 * @param gc Graphic context
471 * @param w Width
472 * @param h Height
473 */
[1822545]474static errno_t demo_bitmap(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
[e0545de]475{
476 gfx_bitmap_t *bitmap;
477 gfx_bitmap_params_t params;
478 int i, j;
479 gfx_coord2_t offs;
480 gfx_rect_t srect;
481 errno_t rc;
[587b4cb]482
[4f64b7b8]483 if (quit)
484 return EOK;
485
[8dbd13d]486 rc = demo_begin(gc, w, h, "Bitmap rendering without offset");
[587b4cb]487 if (rc != EOK)
488 return rc;
[e0545de]489
[a8eed5f]490 gfx_bitmap_params_init(&params);
[e0545de]491 params.rect.p0.x = 0;
492 params.rect.p0.y = 0;
493 params.rect.p1.x = w;
494 params.rect.p1.y = h;
495
496 rc = gfx_bitmap_create(gc, &params, NULL, &bitmap);
497 if (rc != EOK)
498 return rc;
499
[587b4cb]500 rc = bitmap_tartan(bitmap, w, h);
[e0545de]501 if (rc != EOK)
[587b4cb]502 goto error;
[e0545de]503
504 for (j = 0; j < 10; j++) {
505 for (i = 0; i < 5; i++) {
506 srect.p0.x = rand() % (w - 40);
[d18f3b7]507 srect.p0.y = rand() % (h - 20);
[e0545de]508 srect.p1.x = srect.p0.x + rand() % (w - srect.p0.x);
509 srect.p1.y = srect.p0.y + rand() % (h - srect.p0.y);
510 offs.x = 0;
511 offs.y = 0;
512
[0008c0f]513 rc = gfx_bitmap_render(bitmap, &srect, &offs);
514 if (rc != EOK)
515 goto error;
[b3c185b6]516
[af967ef9]517 demo_msleep(250);
[b3c185b6]518 if (quit)
[4f64b7b8]519 goto out;
[587b4cb]520 }
521 }
522
[4f64b7b8]523out:
[587b4cb]524 gfx_bitmap_destroy(bitmap);
525
526 return EOK;
527error:
528 gfx_bitmap_destroy(bitmap);
529 return rc;
530}
531
532/** Run second bitmap demo on a graphic context.
533 *
534 * @param gc Graphic context
535 * @param w Width
536 * @param h Height
537 */
538static errno_t demo_bitmap2(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
539{
540 gfx_bitmap_t *bitmap;
541 gfx_bitmap_params_t params;
542 int i, j;
543 gfx_coord2_t offs;
544 errno_t rc;
545
[4f64b7b8]546 if (quit)
547 return EOK;
548
[8dbd13d]549 rc = demo_begin(gc, w, h, "Bitmap rendering with offset");
[587b4cb]550 if (rc != EOK)
551 return rc;
552
[b3b00b6]553 gfx_bitmap_params_init(&params);
[587b4cb]554 params.rect.p0.x = 0;
555 params.rect.p0.y = 0;
556 params.rect.p1.x = 40;
557 params.rect.p1.y = 20;
558
559 rc = gfx_bitmap_create(gc, &params, NULL, &bitmap);
560 if (rc != EOK)
561 return rc;
562
563 rc = bitmap_moire(bitmap, 40, 20);
564 if (rc != EOK)
565 goto error;
566
567 for (j = 0; j < 10; j++) {
568 for (i = 0; i < 10; i++) {
569 offs.x = rand() % (w - 40);
570 offs.y = rand() % (h - 20);
571
572 rc = gfx_bitmap_render(bitmap, NULL, &offs);
573 if (rc != EOK)
574 goto error;
[e0545de]575 }
[587b4cb]576
[af967ef9]577 demo_msleep(500);
[b3c185b6]578 if (quit)
579 break;
[e0545de]580 }
581
582 gfx_bitmap_destroy(bitmap);
583
584 return EOK;
[0008c0f]585error:
586 gfx_bitmap_destroy(bitmap);
587 return rc;
[e0545de]588}
[8fa65af0]589
[bea947f]590/** Run bitmap color key demo on a graphic context.
591 *
592 * @param gc Graphic context
593 * @param w Width
594 * @param h Height
595 */
596static errno_t demo_bitmap_kc(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
597{
598 gfx_bitmap_t *bitmap;
599 gfx_bitmap_params_t params;
600 int i, j;
601 gfx_coord2_t offs;
602 errno_t rc;
603
[4f64b7b8]604 if (quit)
605 return EOK;
606
[8dbd13d]607 rc = demo_begin(gc, w, h, "Bitmap rendering with color key");
[bea947f]608 if (rc != EOK)
609 return rc;
610
[b3b00b6]611 gfx_bitmap_params_init(&params);
[bea947f]612 params.rect.p0.x = 0;
613 params.rect.p0.y = 0;
614 params.rect.p1.x = 40;
615 params.rect.p1.y = 40;
616 params.flags = bmpf_color_key;
617 params.key_color = PIXEL(0, 255, 0, 255);
618
619 rc = gfx_bitmap_create(gc, &params, NULL, &bitmap);
620 if (rc != EOK)
621 return rc;
622
623 rc = bitmap_circle(bitmap, 40, 40);
624 if (rc != EOK)
625 goto error;
626
627 for (j = 0; j < 10; j++) {
628 for (i = 0; i < 10; i++) {
629 offs.x = j * 20 + i * 20;
630 offs.y = i * 20;
631
632 rc = gfx_bitmap_render(bitmap, NULL, &offs);
633 if (rc != EOK)
634 goto error;
635 }
636
[af967ef9]637 demo_msleep(500);
[bea947f]638 if (quit)
639 break;
640 }
641
642 gfx_bitmap_destroy(bitmap);
643
644 return EOK;
645error:
646 gfx_bitmap_destroy(bitmap);
647 return rc;
648}
[e0545de]649
[8fa65af0]650/** Run text demo on a graphic context.
651 *
652 * @param gc Graphic context
653 * @param w Width
654 * @param h Height
655 */
656static errno_t demo_text(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
657{
658 gfx_color_t *color = NULL;
659 gfx_rect_t rect;
660 gfx_coord2_t pos;
661 gfx_text_fmt_t fmt;
662 int i;
663 errno_t rc;
664
[4f64b7b8]665 if (quit)
666 return EOK;
667
[8dbd13d]668 rc = demo_begin(gc, w, h, "Text rendering");
[8fa65af0]669 if (rc != EOK)
670 goto error;
671
672 /* Vertical bars */
673
674 for (i = 0; i < 20; i++) {
675 rc = gfx_color_new_rgb_i16(0, 0x8000 * i / 20,
676 0x8000 * i / 20, &color);
677 if (rc != EOK)
678 goto error;
679
680 rc = gfx_set_color(gc, color);
681 if (rc != EOK)
682 goto error;
683
684 rect.p0.x = w * i / 20;
685 rect.p0.y = 0;
686 rect.p1.x = w * (i + 1) / 20;
687 rect.p1.y = h;
688
689 rc = gfx_fill_rect(gc, &rect);
690 if (rc != EOK)
691 goto error;
692
693 gfx_color_delete(color);
694 }
695
696 rc = gfx_color_new_rgb_i16(0, 0, 0x8000, &color);
697 if (rc != EOK)
698 goto error;
699
700 rc = gfx_set_color(gc, color);
701 if (rc != EOK)
702 goto error;
703
704 rect.p0.x = w / 20;
[8dbd13d]705 rect.p0.y = 1 * h / 15;
[8fa65af0]706 rect.p1.x = w - w / 20;
[8dbd13d]707 rect.p1.y = 4 * h / 15;
[8fa65af0]708
709 rc = gfx_fill_rect(gc, &rect);
710 if (rc != EOK)
711 goto error;
712
713 gfx_color_delete(color);
714
[f7c12b3]715 if (demo_is_text(w, h)) {
716 rc = gfx_color_new_ega(0x1f, &color);
717 if (rc != EOK)
718 goto error;
719 } else {
720 rc = gfx_color_new_rgb_i16(0xffff, 0xffff, 0xffff, &color);
721 if (rc != EOK)
722 goto error;
723 }
[8fa65af0]724
725 gfx_text_fmt_init(&fmt);
[4583015]726 fmt.font = font;
[b433f68]727 fmt.color = color;
[8fa65af0]728
729 pos.x = rect.p0.x;
730 pos.y = rect.p0.y;
[4583015]731 rc = gfx_puttext(&pos, &fmt, "Top left");
[8fa65af0]732 if (rc != EOK) {
733 printf("Error rendering text.\n");
734 goto error;
735 }
736
[8bf9058]737 pos.x = (rect.p0.x + rect.p1.x - 1) / 2;
[8fa65af0]738 pos.y = rect.p0.y;
739 fmt.halign = gfx_halign_center;
[4583015]740 rc = gfx_puttext(&pos, &fmt, "Top center");
[8fa65af0]741 if (rc != EOK)
742 goto error;
743
[400a16d]744 pos.x = rect.p1.x;
[8fa65af0]745 pos.y = rect.p0.y;
746 fmt.halign = gfx_halign_right;
[4583015]747 rc = gfx_puttext(&pos, &fmt, "Top right");
[8fa65af0]748 if (rc != EOK)
749 goto error;
750
751 fmt.valign = gfx_valign_center;
752
753 pos.x = rect.p0.x;
[8bf9058]754 pos.y = (rect.p0.y + rect.p1.y - 1) / 2;
[8fa65af0]755 fmt.halign = gfx_halign_left;
[4583015]756 rc = gfx_puttext(&pos, &fmt, "Center left");
[8fa65af0]757 if (rc != EOK)
758 goto error;
759
[8bf9058]760 pos.x = (rect.p0.x + rect.p1.x - 1) / 2;
761 pos.y = (rect.p0.y + rect.p1.y - 1) / 2;
[8fa65af0]762 fmt.halign = gfx_halign_center;
[4583015]763 rc = gfx_puttext(&pos, &fmt, "Center");
[8fa65af0]764 if (rc != EOK)
765 goto error;
766
[400a16d]767 pos.x = rect.p1.x;
[8bf9058]768 pos.y = (rect.p0.y + rect.p1.y - 1) / 2;
[8fa65af0]769 fmt.halign = gfx_halign_right;
[4583015]770 rc = gfx_puttext(&pos, &fmt, "Center right");
[8fa65af0]771 if (rc != EOK)
772 goto error;
773
774 fmt.valign = gfx_valign_bottom;
775
776 pos.x = rect.p0.x;
[8bf9058]777 pos.y = rect.p1.y - 1;
[8fa65af0]778 fmt.halign = gfx_halign_left;
[4583015]779 rc = gfx_puttext(&pos, &fmt, "Bottom left");
[8fa65af0]780 if (rc != EOK)
781 goto error;
782
[8bf9058]783 pos.x = (rect.p0.x + rect.p1.x - 1) / 2;
[400a16d]784 pos.y = rect.p1.y;
[8fa65af0]785 fmt.halign = gfx_halign_center;
[4583015]786 rc = gfx_puttext(&pos, &fmt, "Bottom center");
[8fa65af0]787 if (rc != EOK)
788 goto error;
789
[400a16d]790 pos.x = rect.p1.x;
791 pos.y = rect.p1.y;
[8fa65af0]792 fmt.halign = gfx_halign_right;
[4583015]793 rc = gfx_puttext(&pos, &fmt, "Bottom right");
[8fa65af0]794 if (rc != EOK)
795 goto error;
796
[0d62c10]797 gfx_color_delete(color);
798
[8fa65af0]799 gfx_text_fmt_init(&fmt);
[4583015]800 fmt.font = font;
[8fa65af0]801
802 for (i = 0; i < 8; i++) {
[bc52b5b]803 if (demo_is_text(w, h)) {
[f7c12b3]804 rc = gfx_color_new_ega(i != 0 ? i : 0x10, &color);
[bc52b5b]805 if (rc != EOK)
806 goto error;
807 } else {
808 rc = gfx_color_new_rgb_i16((i & 4) ? 0xffff : 0,
809 (i & 2) ? 0xffff : 0, (i & 1) ? 0xffff : 0, &color);
810 if (rc != EOK)
811 goto error;
812 }
[0d62c10]813
[b433f68]814 fmt.color = color;
[5c27e77]815 fmt.underline = !fmt.underline;
[0d62c10]816
[8fa65af0]817 pos.x = w / 20;
[8dbd13d]818 pos.y = (6 + i) * h / 15;
[4583015]819 rc = gfx_puttext(&pos, &fmt, "The quick brown fox jumps over the lazy dog.");
[8fa65af0]820 if (rc != EOK)
821 goto error;
[0d62c10]822
823 gfx_color_delete(color);
[8fa65af0]824 }
825
826 for (i = 0; i < 10; i++) {
[af967ef9]827 demo_msleep(500);
[8fa65af0]828 if (quit)
829 break;
830 }
831
832 return EOK;
833error:
834 return rc;
835}
836
[901b302]837/** Run text abbreviation demo on a graphic context.
838 *
839 * @param gc Graphic context
840 * @param w Width
841 * @param h Height
842 */
843static errno_t demo_text_abbr(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
844{
845 gfx_color_t *color = NULL;
846 gfx_rect_t rect;
847 gfx_coord2_t pos;
848 gfx_text_fmt_t fmt;
849 int i;
850 errno_t rc;
851
852 if (quit)
853 return EOK;
854
855 rc = demo_begin(gc, w, h, "Text abbreviation");
856 if (rc != EOK)
857 goto error;
858
859 for (i = 0; i < 11; i++) {
860
861 rc = gfx_color_new_rgb_i16(0, 0, 0x8000, &color);
862 if (rc != EOK)
863 goto error;
864
865 rc = gfx_set_color(gc, color);
866 if (rc != EOK)
867 goto error;
868
869 rect.p0.x = w / 20;
870 rect.p0.y = (2 + 2 * i) * h / 25;
871 rect.p1.x = w - w / 20 - w * i / 12;
872 rect.p1.y = (3 + 2 * i) * h / 25;
873
874 rc = gfx_fill_rect(gc, &rect);
875 if (rc != EOK)
876 goto error;
877
878 gfx_color_delete(color);
879
880 if (demo_is_text(w, h)) {
881 rc = gfx_color_new_ega(0x1f, &color);
882 if (rc != EOK)
883 goto error;
884 } else {
885 rc = gfx_color_new_rgb_i16(0xffff, 0xffff, 0xffff,
886 &color);
887 if (rc != EOK)
888 goto error;
889 }
890
891 gfx_text_fmt_init(&fmt);
892 fmt.font = font;
893 fmt.color = color;
894 fmt.abbreviate = true;
895 fmt.width = rect.p1.x - rect.p0.x;
896
897 pos.x = rect.p0.x;
898 pos.y = rect.p0.y;
899 rc = gfx_puttext(&pos, &fmt,
900 "The quick brow fox jumps over the lazy dog!");
901 if (rc != EOK) {
902 printf("Error rendering text.\n");
903 goto error;
904 }
905 }
906
907 for (i = 0; i < 10; i++) {
[af967ef9]908 demo_msleep(500);
[901b302]909 if (quit)
910 break;
911 }
912
913 return EOK;
914error:
915 return rc;
916}
917
[1167ad34]918/** Run clipping demo on a graphic context.
919 *
920 * @param gc Graphic context
921 * @param w Width
922 * @param h Height
923 */
924static errno_t demo_clip(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
925{
926 gfx_bitmap_t *bitmap;
927 gfx_color_t *color;
928 gfx_bitmap_params_t params;
929 int i, j;
930 gfx_coord2_t offs;
931 gfx_rect_t rect;
932 errno_t rc;
933
934 if (quit)
935 return EOK;
936
[8dbd13d]937 rc = demo_begin(gc, w, h, "Clipping demonstration");
[1167ad34]938 if (rc != EOK)
939 return rc;
940
941 gfx_bitmap_params_init(&params);
942 params.rect.p0.x = 0;
943 params.rect.p0.y = 0;
944 params.rect.p1.x = 40;
945 params.rect.p1.y = 20;
946
947 rc = gfx_bitmap_create(gc, &params, NULL, &bitmap);
948 if (rc != EOK)
949 return rc;
950
951 rc = bitmap_moire(bitmap, 40, 20);
952 if (rc != EOK)
953 goto error;
954
955 for (j = 0; j < 10; j++) {
956 rect.p0.x = w / 8;
957 rect.p0.y = h / 8;
958 rect.p1.x = w * 7 / 8;
959 rect.p1.y = h * 3 / 8;
960
961 rc = gfx_set_clip_rect(gc, &rect);
962 if (rc != EOK)
963 return rc;
964
965 rc = gfx_color_new_rgb_i16(rand() % 0x10000, rand() % 0x10000,
966 rand() % 0x10000, &color);
967 if (rc != EOK)
968 return rc;
969
970 rc = gfx_set_color(gc, color);
971 if (rc != EOK)
972 return rc;
973
974 for (i = 0; i < 10; i++) {
975 rect.p0.x = rand() % (w - 1);
976 rect.p0.y = rand() % (h - 1);
977 rect.p1.x = rect.p0.x + rand() % (w - 1 - rect.p0.x);
978 rect.p1.y = rect.p0.y + rand() % (h - 1 - rect.p0.y);
979
980 rc = gfx_fill_rect(gc, &rect);
981 if (rc != EOK)
982 return rc;
983 }
984
985 gfx_color_delete(color);
986
987 rect.p0.x = w / 8;
988 rect.p0.y = h * 5 / 8;
989 rect.p1.x = w * 7 / 8;
990 rect.p1.y = h * 7 / 8;
991
992 rc = gfx_set_clip_rect(gc, &rect);
993 if (rc != EOK)
994 return rc;
995
996 for (i = 0; i < 10; i++) {
997 offs.x = rand() % (w - 40);
998 offs.y = rand() % (h - 20);
999
1000 rc = gfx_bitmap_render(bitmap, NULL, &offs);
1001 if (rc != EOK)
1002 goto error;
1003 }
1004
[af967ef9]1005 demo_msleep(500);
[1167ad34]1006 if (quit)
1007 break;
1008 }
1009
1010 (void) gfx_set_clip_rect(gc, NULL);
1011 gfx_bitmap_destroy(bitmap);
1012 return EOK;
1013error:
1014 (void) gfx_set_clip_rect(gc, NULL);
1015 gfx_bitmap_destroy(bitmap);
1016 return rc;
1017}
1018
[e0545de]1019/** Run demo loop on a graphic context.
1020 *
1021 * @param gc Graphic context
1022 * @param w Width
1023 * @param h Height
1024 */
[1822545]1025static errno_t demo_loop(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
[e0545de]1026{
1027 errno_t rc;
1028
[8dbd13d]1029 (void) demo_font_init(gc, w, h);
1030
[b3c185b6]1031 while (!quit) {
[e0545de]1032 rc = demo_rects(gc, w, h);
1033 if (rc != EOK)
[8dbd13d]1034 goto error;
[e0545de]1035
1036 rc = demo_bitmap(gc, w, h);
1037 if (rc != EOK)
[8dbd13d]1038 goto error;
[587b4cb]1039
1040 rc = demo_bitmap2(gc, w, h);
1041 if (rc != EOK)
[8dbd13d]1042 goto error;
[bea947f]1043
1044 rc = demo_bitmap_kc(gc, w, h);
1045 if (rc != EOK)
[8dbd13d]1046 goto error;
[8fa65af0]1047
1048 rc = demo_text(gc, w, h);
1049 if (rc != EOK)
[8dbd13d]1050 goto error;
[1167ad34]1051
[901b302]1052 rc = demo_text_abbr(gc, w, h);
1053 if (rc != EOK)
1054 goto error;
1055
[1167ad34]1056 rc = demo_clip(gc, w, h);
1057 if (rc != EOK)
[8dbd13d]1058 goto error;
[e0545de]1059 }
[b3c185b6]1060
[8dbd13d]1061 demo_font_fini();
[b3c185b6]1062 return EOK;
[8dbd13d]1063error:
1064 demo_font_fini();
1065 return rc;
[00e8290]1066}
1067
1068/** Run demo on console. */
1069static errno_t demo_console(void)
1070{
1071 console_gc_t *cgc = NULL;
1072 gfx_context_t *gc;
[c0efb2e]1073 sysarg_t cols, rows;
[00e8290]1074 errno_t rc;
1075
1076 con = console_init(stdin, stdout);
1077 if (con == NULL)
1078 return EIO;
1079
[c0efb2e]1080 rc = console_get_size(con, &cols, &rows);
1081 if (rc != EOK)
1082 return rc;
1083
[00e8290]1084 rc = console_gc_create(con, stdout, &cgc);
1085 if (rc != EOK)
1086 return rc;
1087
1088 gc = console_gc_get_ctx(cgc);
1089
[c0efb2e]1090 rc = demo_loop(gc, cols, rows);
[00e8290]1091 if (rc != EOK)
1092 return rc;
[9259d20]1093
[9be2358]1094 rc = console_gc_delete(cgc);
1095 if (rc != EOK)
[00e8290]1096 return rc;
1097
1098 return EOK;
1099}
1100
[b93ec7c0]1101/** Run demo on UI. */
1102static errno_t demo_ui(const char *display_spec)
[00e8290]1103{
[b93ec7c0]1104 ui_t *ui = NULL;
1105 ui_wnd_params_t params;
1106 ui_window_t *window = NULL;
[00e8290]1107 gfx_context_t *gc;
[b93ec7c0]1108 gfx_rect_t rect;
1109 gfx_rect_t wrect;
1110 gfx_coord2_t off;
[788c76e3]1111 gfx_rect_t ui_rect;
1112 gfx_coord2_t dims;
[00e8290]1113 errno_t rc;
1114
[b93ec7c0]1115 rc = ui_create(display_spec, &ui);
1116 if (rc != EOK) {
1117 printf("Error initializing UI (%s)\n", display_spec);
1118 goto error;
[00e8290]1119 }
1120
[788c76e3]1121 rc = ui_get_rect(ui, &ui_rect);
1122 if (rc != EOK) {
1123 printf("Error getting display size.\n");
1124 goto error;
1125 }
1126
[b93ec7c0]1127 rect.p0.x = 0;
1128 rect.p0.y = 0;
1129 rect.p1.x = 400;
1130 rect.p1.y = 300;
[00e8290]1131
[b93ec7c0]1132 ui_wnd_params_init(&params);
1133 params.caption = "GFX Demo";
[00e8290]1134
[b93ec7c0]1135 /*
1136 * Compute window rectangle such that application area corresponds
1137 * to rect
1138 */
[266ec54]1139 ui_wdecor_rect_from_app(params.style, &rect, &wrect);
[b93ec7c0]1140 off = wrect.p0;
1141 gfx_rect_rtranslate(&off, &wrect, &params.rect);
[00e8290]1142
[788c76e3]1143 gfx_rect_dims(&ui_rect, &dims);
1144
1145 /* Make sure window is not larger than the entire screen */
1146 if (params.rect.p1.x > dims.x)
1147 params.rect.p1.x = dims.x;
1148 if (params.rect.p1.y > dims.y)
1149 params.rect.p1.y = dims.y;
1150
[b93ec7c0]1151 rc = ui_window_create(ui, &params, &window);
1152 if (rc != EOK) {
1153 printf("Error creating window.\n");
1154 goto error;
[00e8290]1155 }
1156
[b93ec7c0]1157 ui_window_set_cb(window, &ui_window_cb, NULL);
[00e8290]1158
[b93ec7c0]1159 rc = ui_window_get_app_gc(window, &gc);
1160 if (rc != EOK) {
1161 printf("Error creating graphic context.\n");
1162 goto error;
1163 }
[00e8290]1164
[788c76e3]1165 ui_window_get_app_rect(window, &rect);
1166 gfx_rect_dims(&rect, &dims);
1167
1168 if (!ui_is_fullscreen(ui))
1169 task_retval(0);
[5bded44]1170
[788c76e3]1171 rc = demo_loop(gc, dims.x, dims.y);
[00e8290]1172 if (rc != EOK)
[b93ec7c0]1173 goto error;
[00e8290]1174
[b93ec7c0]1175 ui_window_destroy(window);
1176 ui_destroy(ui);
[00e8290]1177
1178 return EOK;
[b93ec7c0]1179error:
1180 if (window != NULL)
1181 ui_window_destroy(window);
1182 if (ui != NULL)
1183 ui_destroy(ui);
1184 return rc;
[00e8290]1185}
1186
[c8cf261]1187/** Run demo on display server. */
[fd11144]1188static errno_t demo_display(const char *display_svc)
[c8cf261]1189{
1190 display_t *display = NULL;
1191 gfx_context_t *gc;
[4d9c807]1192 display_wnd_params_t params;
[c8cf261]1193 display_window_t *window = NULL;
1194 errno_t rc;
1195
[fd11144]1196 rc = display_open(display_svc, &display);
[c8cf261]1197 if (rc != EOK) {
1198 printf("Error opening display.\n");
1199 return rc;
1200 }
1201
[4d9c807]1202 display_wnd_params_init(&params);
1203 params.rect.p0.x = 0;
1204 params.rect.p0.y = 0;
1205 params.rect.p1.x = 400;
1206 params.rect.p1.y = 300;
[7cc30e9]1207 params.caption = "GFX Demo";
[4d9c807]1208
1209 rc = display_window_create(display, &params, &wnd_cb, NULL, &window);
[c8cf261]1210 if (rc != EOK) {
1211 printf("Error creating window.\n");
1212 return rc;
1213 }
1214
1215 rc = display_window_get_gc(window, &gc);
1216 if (rc != EOK) {
1217 printf("Error getting graphics context.\n");
[32dde7e8]1218 return rc;
[c8cf261]1219 }
1220
[5bded44]1221 task_retval(0);
1222
[e0545de]1223 rc = demo_loop(gc, 400, 300);
[c8cf261]1224 if (rc != EOK)
1225 return rc;
1226
1227 rc = gfx_context_delete(gc);
1228 if (rc != EOK)
1229 return rc;
1230
[e49b7997]1231 display_window_destroy(window);
1232 display_close(display);
1233
[c8cf261]1234 return EOK;
1235}
1236
[af967ef9]1237static void demo_quit(void)
[338d0935]1238{
[af967ef9]1239 fibril_mutex_lock(&quit_lock);
[338d0935]1240 quit = true;
[af967ef9]1241 fibril_mutex_unlock(&quit_lock);
1242 fibril_condvar_broadcast(&quit_cv);
1243}
1244
1245static void wnd_close_event(void *arg)
1246{
1247 demo_quit();
[338d0935]1248}
1249
[f9ae472]1250static void demo_kbd_event(kbd_event_t *event)
1251{
1252 if (event->type == KEY_PRESS) {
1253 /* Ctrl-Q */
1254 if ((event->mods & KM_CTRL) != 0 &&
1255 (event->mods & KM_ALT) == 0 &&
1256 (event->mods & KM_SHIFT) == 0 &&
1257 event->key == KC_Q) {
1258 demo_quit();
1259 }
1260
1261 /* Escape */
1262 if ((event->mods & KM_CTRL) == 0 &&
1263 (event->mods & KM_ALT) == 0 &&
1264 (event->mods & KM_SHIFT) == 0 &&
1265 event->key == KC_ESCAPE) {
1266 demo_quit();
1267 }
1268 }
1269}
1270
[b3c185b6]1271static void wnd_kbd_event(void *arg, kbd_event_t *event)
1272{
[f9ae472]1273 (void)arg;
1274 demo_kbd_event(event);
[b3c185b6]1275}
1276
[b93ec7c0]1277static void uiwnd_close_event(ui_window_t *window, void *arg)
1278{
[af967ef9]1279 demo_quit();
[b93ec7c0]1280}
1281
1282static void uiwnd_kbd_event(ui_window_t *window, void *arg, kbd_event_t *event)
1283{
[f9ae472]1284 (void)window;
1285 (void)arg;
1286 demo_kbd_event(event);
[b93ec7c0]1287}
1288
[00e8290]1289static void print_syntax(void)
1290{
[bac8acab]1291 printf("Syntax: gfxdemo [-d <display>] {console|display|ui}\n");
[00e8290]1292}
1293
1294int main(int argc, char *argv[])
1295{
1296 errno_t rc;
[fd11144]1297 const char *display_svc = DISPLAY_DEFAULT;
[232bf2c]1298 const char *ui_display_spec = UI_DISPLAY_DEFAULT;
[fd11144]1299 int i;
1300
1301 i = 1;
1302 while (i < argc && argv[i][0] == '-') {
1303 if (str_cmp(argv[i], "-d") == 0) {
1304 ++i;
1305 if (i >= argc) {
1306 printf("Argument missing.\n");
1307 print_syntax();
1308 return 1;
1309 }
1310
[232bf2c]1311 display_svc = ui_display_spec = argv[i++];
[fd11144]1312 } else {
1313 printf("Invalid option '%s'.\n", argv[i]);
1314 print_syntax();
1315 return 1;
1316 }
1317 }
[00e8290]1318
[fd11144]1319 if (i >= argc || str_cmp(argv[i], "display") == 0) {
1320 rc = demo_display(display_svc);
[0b63dc2]1321 if (rc != EOK)
1322 return 1;
[fd11144]1323 } else if (str_cmp(argv[i], "console") == 0) {
[00e8290]1324 rc = demo_console();
1325 if (rc != EOK)
1326 return 1;
[b93ec7c0]1327 } else if (str_cmp(argv[i], "ui") == 0) {
[232bf2c]1328 rc = demo_ui(ui_display_spec);
[00e8290]1329 if (rc != EOK)
1330 return 1;
1331 } else {
1332 print_syntax();
1333 return 1;
1334 }
[045186b]1335}
1336
1337/** @}
1338 */
Note: See TracBrowser for help on using the repository browser.