source: mainline/uspace/app/gfxdemo/gfxdemo.c@ 7cc30e9

ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 7cc30e9 was 7cc30e9, checked in by Jiri Svoboda <jiri@…>, 3 years ago

Display server needs to store window caption

Even though it does not use it itself, it needs to provide it to
window managers (e.g. Task bar). We need to be able to set caption
for a new window and to change it for an existing window.

  • Property mode set to 100644
File size: 22.9 KB
Line 
1/*
2 * Copyright (c) 2022 Jiri Svoboda
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
35#include <congfx/console.h>
36#include <display.h>
37#include <fibril.h>
38#include <gfx/bitmap.h>
39#include <gfx/color.h>
40#include <gfx/render.h>
41#include <gfx/font.h>
42#include <gfx/text.h>
43#include <gfx/typeface.h>
44#include <io/console.h>
45#include <io/pixelmap.h>
46#include <stdbool.h>
47#include <stdlib.h>
48#include <str.h>
49#include <task.h>
50#include <ui/ui.h>
51#include <ui/window.h>
52#include <ui/wdecor.h>
53
54static void wnd_close_event(void *);
55static void wnd_kbd_event(void *, kbd_event_t *);
56
57static display_wnd_cb_t wnd_cb = {
58 .close_event = wnd_close_event,
59 .kbd_event = wnd_kbd_event
60};
61
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
70static bool quit = false;
71static gfx_typeface_t *tface;
72static gfx_font_t *font;
73static gfx_coord_t vpad;
74
75/** Determine if we are running in text mode.
76 *
77 * @param w Screen width
78 * @param h Screen height
79 * @return @c true iff we are running in text mode
80 */
81static bool demo_is_text(gfx_coord_t w, gfx_coord_t h)
82{
83 // XXX Need a proper way to determine text mode
84 return w <= 80;
85}
86
87/** Clear screen.
88 *
89 * @param gc Graphic context
90 * @param w Screen width
91 * @param h Screen height
92 */
93static errno_t clear_scr(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
94{
95 gfx_color_t *color = NULL;
96 gfx_rect_t rect;
97 errno_t rc;
98
99 rc = gfx_color_new_rgb_i16(0, 0, 0, &color);
100 if (rc != EOK)
101 goto error;
102
103 rc = gfx_set_color(gc, color);
104 if (rc != EOK)
105 goto error;
106
107 rect.p0.x = 0;
108 rect.p0.y = 0;
109 rect.p1.x = w;
110 rect.p1.y = h;
111
112 rc = gfx_fill_rect(gc, &rect);
113 if (rc != EOK)
114 goto error;
115
116 gfx_color_delete(color);
117 return EOK;
118error:
119 if (color != NULL)
120 gfx_color_delete(color);
121 return rc;
122}
123
124/** Initialize demo font.
125 *
126 * @param gc Graphic context
127 * @param w Width
128 * @param h Height
129 * @return EOK on success or an error code
130 */
131static errno_t demo_font_init(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
132{
133 gfx_font_info_t *finfo;
134 errno_t rc;
135
136 if (quit)
137 return EOK;
138
139 /* XXX Crude way of detecting text mode */
140 if (w < 256) {
141 /* Create dummy font for text mode */
142 rc = gfx_typeface_create(gc, &tface);
143 if (rc != EOK) {
144 printf("Error creating typeface\n");
145 goto error;
146 }
147
148 rc = gfx_font_create_textmode(tface, &font);
149 if (rc != EOK) {
150 printf("Error creating font\n");
151 goto error;
152 }
153
154 vpad = 0;
155 } else {
156 /* Load font */
157 rc = gfx_typeface_open(gc, "/data/font/helena.tpf", &tface);
158 if (rc != EOK) {
159 printf("Error opening typeface\n");
160 goto error;
161 }
162
163 finfo = gfx_typeface_first_font(tface);
164 if (finfo == NULL) {
165 printf("Typeface contains no font.\n");
166 rc = ENOENT;
167 goto error;
168 }
169
170 rc = gfx_font_open(finfo, &font);
171 if (rc != EOK) {
172 printf("Error opening font.\n");
173 goto error;
174 }
175
176 vpad = 5;
177 }
178
179 return EOK;
180error:
181 if (tface != NULL)
182 gfx_typeface_destroy(tface);
183 return rc;
184}
185
186/** Finalize demo font. */
187static void demo_font_fini(void)
188{
189 if (font == NULL)
190 return;
191
192 gfx_font_close(font);
193 font = NULL;
194
195 gfx_typeface_destroy(tface);
196 tface = NULL;
197}
198
199/** Start a new demo screen.
200 *
201 * Clear the screen, display a status line and set up clipping.
202 *
203 * @param gc Graphic context
204 * @param w Width
205 * @param h Height
206 * @param text Demo screen description
207 * @return EOK on success or an error code
208 */
209static errno_t demo_begin(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h,
210 const char *text)
211{
212 gfx_text_fmt_t fmt;
213 gfx_font_metrics_t metrics;
214 gfx_coord2_t pos;
215 gfx_color_t *color;
216 gfx_rect_t rect;
217 gfx_coord_t height;
218 errno_t rc;
219
220 rc = gfx_set_clip_rect(gc, NULL);
221 if (rc != EOK)
222 return rc;
223
224 rc = clear_scr(gc, w, h);
225 if (rc != EOK)
226 return rc;
227
228 if (font != NULL) {
229 if (demo_is_text(w, h)) {
230 rc = gfx_color_new_ega(0x1e, &color);
231 if (rc != EOK)
232 goto error;
233 } else {
234 rc = gfx_color_new_rgb_i16(0xffff, 0xffff, 0xffff, &color);
235 if (rc != EOK)
236 goto error;
237 }
238
239 gfx_text_fmt_init(&fmt);
240 fmt.font = font;
241 fmt.color = color;
242 fmt.halign = gfx_halign_center;
243 fmt.valign = gfx_valign_bottom;
244
245 pos.x = w / 2;
246 pos.y = h - 1;
247 rc = gfx_puttext(&pos, &fmt, text);
248 if (rc != EOK) {
249 printf("Error rendering text.\n");
250 gfx_color_delete(color);
251 goto error;
252 }
253
254 gfx_color_delete(color);
255
256 gfx_font_get_metrics(font, &metrics);
257 height = metrics.ascent + metrics.descent + 1;
258 } else {
259 height = 0;
260 }
261
262 rect.p0.x = 0;
263 rect.p0.y = 0;
264 rect.p1.x = w;
265 rect.p1.y = h - height - vpad;
266 rc = gfx_set_clip_rect(gc, &rect);
267 if (rc != EOK)
268 return rc;
269
270 return EOK;
271error:
272 return rc;
273}
274
275/** Run rectangle demo on a graphic context.
276 *
277 * @param gc Graphic context
278 * @param w Width
279 * @param h Height
280 */
281static errno_t demo_rects(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
282{
283 gfx_color_t *color = NULL;
284 gfx_rect_t rect;
285 int i, j;
286 errno_t rc;
287
288 if (quit)
289 return EOK;
290
291 rc = demo_begin(gc, w, h, "Rectangle rendering");
292 if (rc != EOK)
293 return rc;
294
295 for (j = 0; j < 10; j++) {
296 rc = gfx_color_new_rgb_i16(rand() % 0x10000, rand() % 0x10000,
297 rand() % 0x10000, &color);
298 if (rc != EOK)
299 return rc;
300
301 rc = gfx_set_color(gc, color);
302 if (rc != EOK)
303 return rc;
304
305 for (i = 0; i < 10; i++) {
306 rect.p0.x = rand() % (w - 1);
307 rect.p0.y = rand() % (h - 1);
308 rect.p1.x = rect.p0.x + rand() % (w - 1 - rect.p0.x);
309 rect.p1.y = rect.p0.y + rand() % (h - 1 - rect.p0.y);
310
311 rc = gfx_fill_rect(gc, &rect);
312 if (rc != EOK)
313 return rc;
314 }
315
316 gfx_color_delete(color);
317
318 fibril_usleep(500 * 1000);
319
320 if (quit)
321 break;
322 }
323
324 return EOK;
325}
326
327/** Fill bitmap with tartan pattern.
328 *
329 * @param bitmap Bitmap
330 * @param w Bitmap width
331 * @param h Bitmap height
332 * @return EOK on success or an error code
333 */
334static errno_t bitmap_tartan(gfx_bitmap_t *bitmap, gfx_coord_t w, gfx_coord_t h)
335{
336 int i, j;
337 pixelmap_t pixelmap;
338 gfx_bitmap_alloc_t alloc;
339 errno_t rc;
340
341 rc = gfx_bitmap_get_alloc(bitmap, &alloc);
342 if (rc != EOK)
343 return rc;
344
345 /* In absence of anything else, use pixelmap */
346 pixelmap.width = w;
347 pixelmap.height = h;
348 pixelmap.data = alloc.pixels;
349
350 for (i = 0; i < w; i++) {
351 for (j = 0; j < h; j++) {
352 pixelmap_put_pixel(&pixelmap, i, j,
353 PIXEL(0, (i % 30) < 3 ? 255 : 0,
354 (j % 30) < 3 ? 255 : 0, i / 2));
355 }
356 }
357
358 return EOK;
359}
360
361/** Fill bitmap with moire pattern.
362 *
363 * @param bitmap Bitmap
364 * @param w Bitmap width
365 * @param h Bitmap height
366 * @return EOK on success or an error code
367 */
368static errno_t bitmap_moire(gfx_bitmap_t *bitmap, gfx_coord_t w, gfx_coord_t h)
369{
370 int i, j;
371 int k;
372 pixelmap_t pixelmap;
373 gfx_bitmap_alloc_t alloc;
374 errno_t rc;
375
376 rc = gfx_bitmap_get_alloc(bitmap, &alloc);
377 if (rc != EOK)
378 return rc;
379
380 /* In absence of anything else, use pixelmap */
381 pixelmap.width = w;
382 pixelmap.height = h;
383 pixelmap.data = alloc.pixels;
384
385 for (i = 0; i < w; i++) {
386 for (j = 0; j < h; j++) {
387 k = i * i + j * j;
388 pixelmap_put_pixel(&pixelmap, i, j,
389 PIXEL(0, k, k, k));
390 }
391 }
392
393 return EOK;
394}
395
396/** Render circle to a bitmap.
397 *
398 * @param bitmap Bitmap
399 * @param w Bitmap width
400 * @param h Bitmap height
401 * @return EOK on success or an error code
402 */
403static errno_t bitmap_circle(gfx_bitmap_t *bitmap, gfx_coord_t w, gfx_coord_t h)
404{
405 int i, j;
406 int k;
407 pixelmap_t pixelmap;
408 gfx_bitmap_alloc_t alloc;
409 errno_t rc;
410
411 rc = gfx_bitmap_get_alloc(bitmap, &alloc);
412 if (rc != EOK)
413 return rc;
414
415 /* In absence of anything else, use pixelmap */
416 pixelmap.width = w;
417 pixelmap.height = h;
418 pixelmap.data = alloc.pixels;
419
420 for (i = 0; i < w; i++) {
421 for (j = 0; j < h; j++) {
422 k = i * i + j * j;
423 pixelmap_put_pixel(&pixelmap, i, j,
424 k < w * w / 2 ? PIXEL(0, 0, 255, 0) :
425 PIXEL(0, 255, 0, 255));
426 }
427 }
428
429 return EOK;
430}
431
432/** Run bitmap demo on a graphic context.
433 *
434 * @param gc Graphic context
435 * @param w Width
436 * @param h Height
437 */
438static errno_t demo_bitmap(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
439{
440 gfx_bitmap_t *bitmap;
441 gfx_bitmap_params_t params;
442 int i, j;
443 gfx_coord2_t offs;
444 gfx_rect_t srect;
445 errno_t rc;
446
447 if (quit)
448 return EOK;
449
450 rc = demo_begin(gc, w, h, "Bitmap rendering without offset");
451 if (rc != EOK)
452 return rc;
453
454 gfx_bitmap_params_init(&params);
455 params.rect.p0.x = 0;
456 params.rect.p0.y = 0;
457 params.rect.p1.x = w;
458 params.rect.p1.y = h;
459
460 rc = gfx_bitmap_create(gc, &params, NULL, &bitmap);
461 if (rc != EOK)
462 return rc;
463
464 rc = bitmap_tartan(bitmap, w, h);
465 if (rc != EOK)
466 goto error;
467
468 for (j = 0; j < 10; j++) {
469 for (i = 0; i < 5; i++) {
470 srect.p0.x = rand() % (w - 40);
471 srect.p0.y = rand() % (h - 20);
472 srect.p1.x = srect.p0.x + rand() % (w - srect.p0.x);
473 srect.p1.y = srect.p0.y + rand() % (h - srect.p0.y);
474 offs.x = 0;
475 offs.y = 0;
476
477 rc = gfx_bitmap_render(bitmap, &srect, &offs);
478 if (rc != EOK)
479 goto error;
480 fibril_usleep(250 * 1000);
481
482 if (quit)
483 goto out;
484 }
485 }
486
487out:
488 gfx_bitmap_destroy(bitmap);
489
490 return EOK;
491error:
492 gfx_bitmap_destroy(bitmap);
493 return rc;
494}
495
496/** Run second bitmap demo on a graphic context.
497 *
498 * @param gc Graphic context
499 * @param w Width
500 * @param h Height
501 */
502static errno_t demo_bitmap2(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
503{
504 gfx_bitmap_t *bitmap;
505 gfx_bitmap_params_t params;
506 int i, j;
507 gfx_coord2_t offs;
508 errno_t rc;
509
510 if (quit)
511 return EOK;
512
513 rc = demo_begin(gc, w, h, "Bitmap rendering with offset");
514 if (rc != EOK)
515 return rc;
516
517 gfx_bitmap_params_init(&params);
518 params.rect.p0.x = 0;
519 params.rect.p0.y = 0;
520 params.rect.p1.x = 40;
521 params.rect.p1.y = 20;
522
523 rc = gfx_bitmap_create(gc, &params, NULL, &bitmap);
524 if (rc != EOK)
525 return rc;
526
527 rc = bitmap_moire(bitmap, 40, 20);
528 if (rc != EOK)
529 goto error;
530
531 for (j = 0; j < 10; j++) {
532 for (i = 0; i < 10; i++) {
533 offs.x = rand() % (w - 40);
534 offs.y = rand() % (h - 20);
535
536 rc = gfx_bitmap_render(bitmap, NULL, &offs);
537 if (rc != EOK)
538 goto error;
539 }
540
541 fibril_usleep(500 * 1000);
542
543 if (quit)
544 break;
545 }
546
547 gfx_bitmap_destroy(bitmap);
548
549 return EOK;
550error:
551 gfx_bitmap_destroy(bitmap);
552 return rc;
553}
554
555/** Run bitmap color key demo on a graphic context.
556 *
557 * @param gc Graphic context
558 * @param w Width
559 * @param h Height
560 */
561static errno_t demo_bitmap_kc(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
562{
563 gfx_bitmap_t *bitmap;
564 gfx_bitmap_params_t params;
565 int i, j;
566 gfx_coord2_t offs;
567 errno_t rc;
568
569 if (quit)
570 return EOK;
571
572 rc = demo_begin(gc, w, h, "Bitmap rendering with color key");
573 if (rc != EOK)
574 return rc;
575
576 gfx_bitmap_params_init(&params);
577 params.rect.p0.x = 0;
578 params.rect.p0.y = 0;
579 params.rect.p1.x = 40;
580 params.rect.p1.y = 40;
581 params.flags = bmpf_color_key;
582 params.key_color = PIXEL(0, 255, 0, 255);
583
584 rc = gfx_bitmap_create(gc, &params, NULL, &bitmap);
585 if (rc != EOK)
586 return rc;
587
588 rc = bitmap_circle(bitmap, 40, 40);
589 if (rc != EOK)
590 goto error;
591
592 for (j = 0; j < 10; j++) {
593 for (i = 0; i < 10; i++) {
594 offs.x = j * 20 + i * 20;
595 offs.y = i * 20;
596
597 rc = gfx_bitmap_render(bitmap, NULL, &offs);
598 if (rc != EOK)
599 goto error;
600 }
601
602 fibril_usleep(500 * 1000);
603
604 if (quit)
605 break;
606 }
607
608 gfx_bitmap_destroy(bitmap);
609
610 return EOK;
611error:
612 gfx_bitmap_destroy(bitmap);
613 return rc;
614}
615
616/** Run text demo on a graphic context.
617 *
618 * @param gc Graphic context
619 * @param w Width
620 * @param h Height
621 */
622static errno_t demo_text(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
623{
624 gfx_color_t *color = NULL;
625 gfx_rect_t rect;
626 gfx_coord2_t pos;
627 gfx_text_fmt_t fmt;
628 int i;
629 errno_t rc;
630
631 if (quit)
632 return EOK;
633
634 rc = demo_begin(gc, w, h, "Text rendering");
635 if (rc != EOK)
636 goto error;
637
638 /* Vertical bars */
639
640 for (i = 0; i < 20; i++) {
641 rc = gfx_color_new_rgb_i16(0, 0x8000 * i / 20,
642 0x8000 * i / 20, &color);
643 if (rc != EOK)
644 goto error;
645
646 rc = gfx_set_color(gc, color);
647 if (rc != EOK)
648 goto error;
649
650 rect.p0.x = w * i / 20;
651 rect.p0.y = 0;
652 rect.p1.x = w * (i + 1) / 20;
653 rect.p1.y = h;
654
655 rc = gfx_fill_rect(gc, &rect);
656 if (rc != EOK)
657 goto error;
658
659 gfx_color_delete(color);
660 }
661
662 rc = gfx_color_new_rgb_i16(0, 0, 0x8000, &color);
663 if (rc != EOK)
664 goto error;
665
666 rc = gfx_set_color(gc, color);
667 if (rc != EOK)
668 goto error;
669
670 rect.p0.x = w / 20;
671 rect.p0.y = 1 * h / 15;
672 rect.p1.x = w - w / 20;
673 rect.p1.y = 4 * h / 15;
674
675 rc = gfx_fill_rect(gc, &rect);
676 if (rc != EOK)
677 goto error;
678
679 gfx_color_delete(color);
680
681 if (demo_is_text(w, h)) {
682 rc = gfx_color_new_ega(0x1f, &color);
683 if (rc != EOK)
684 goto error;
685 } else {
686 rc = gfx_color_new_rgb_i16(0xffff, 0xffff, 0xffff, &color);
687 if (rc != EOK)
688 goto error;
689 }
690
691 gfx_text_fmt_init(&fmt);
692 fmt.font = font;
693 fmt.color = color;
694
695 pos.x = rect.p0.x;
696 pos.y = rect.p0.y;
697 rc = gfx_puttext(&pos, &fmt, "Top left");
698 if (rc != EOK) {
699 printf("Error rendering text.\n");
700 goto error;
701 }
702
703 pos.x = (rect.p0.x + rect.p1.x - 1) / 2;
704 pos.y = rect.p0.y;
705 fmt.halign = gfx_halign_center;
706 rc = gfx_puttext(&pos, &fmt, "Top center");
707 if (rc != EOK)
708 goto error;
709
710 pos.x = rect.p1.x;
711 pos.y = rect.p0.y;
712 fmt.halign = gfx_halign_right;
713 rc = gfx_puttext(&pos, &fmt, "Top right");
714 if (rc != EOK)
715 goto error;
716
717 fmt.valign = gfx_valign_center;
718
719 pos.x = rect.p0.x;
720 pos.y = (rect.p0.y + rect.p1.y - 1) / 2;
721 fmt.halign = gfx_halign_left;
722 rc = gfx_puttext(&pos, &fmt, "Center left");
723 if (rc != EOK)
724 goto error;
725
726 pos.x = (rect.p0.x + rect.p1.x - 1) / 2;
727 pos.y = (rect.p0.y + rect.p1.y - 1) / 2;
728 fmt.halign = gfx_halign_center;
729 rc = gfx_puttext(&pos, &fmt, "Center");
730 if (rc != EOK)
731 goto error;
732
733 pos.x = rect.p1.x;
734 pos.y = (rect.p0.y + rect.p1.y - 1) / 2;
735 fmt.halign = gfx_halign_right;
736 rc = gfx_puttext(&pos, &fmt, "Center right");
737 if (rc != EOK)
738 goto error;
739
740 fmt.valign = gfx_valign_bottom;
741
742 pos.x = rect.p0.x;
743 pos.y = rect.p1.y - 1;
744 fmt.halign = gfx_halign_left;
745 rc = gfx_puttext(&pos, &fmt, "Bottom left");
746 if (rc != EOK)
747 goto error;
748
749 pos.x = (rect.p0.x + rect.p1.x - 1) / 2;
750 pos.y = rect.p1.y;
751 fmt.halign = gfx_halign_center;
752 rc = gfx_puttext(&pos, &fmt, "Bottom center");
753 if (rc != EOK)
754 goto error;
755
756 pos.x = rect.p1.x;
757 pos.y = rect.p1.y;
758 fmt.halign = gfx_halign_right;
759 rc = gfx_puttext(&pos, &fmt, "Bottom right");
760 if (rc != EOK)
761 goto error;
762
763 gfx_color_delete(color);
764
765 gfx_text_fmt_init(&fmt);
766 fmt.font = font;
767
768 for (i = 0; i < 8; i++) {
769 if (demo_is_text(w, h)) {
770 rc = gfx_color_new_ega(i != 0 ? i : 0x10, &color);
771 if (rc != EOK)
772 goto error;
773 } else {
774 rc = gfx_color_new_rgb_i16((i & 4) ? 0xffff : 0,
775 (i & 2) ? 0xffff : 0, (i & 1) ? 0xffff : 0, &color);
776 if (rc != EOK)
777 goto error;
778 }
779
780 fmt.color = color;
781 fmt.underline = !fmt.underline;
782
783 pos.x = w / 20;
784 pos.y = (6 + i) * h / 15;
785 rc = gfx_puttext(&pos, &fmt, "The quick brown fox jumps over the lazy dog.");
786 if (rc != EOK)
787 goto error;
788
789 gfx_color_delete(color);
790 }
791
792 for (i = 0; i < 10; i++) {
793 fibril_usleep(500 * 1000);
794 if (quit)
795 break;
796 }
797
798 return EOK;
799error:
800 return rc;
801}
802
803/** Run clipping demo on a graphic context.
804 *
805 * @param gc Graphic context
806 * @param w Width
807 * @param h Height
808 */
809static errno_t demo_clip(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
810{
811 gfx_bitmap_t *bitmap;
812 gfx_color_t *color;
813 gfx_bitmap_params_t params;
814 int i, j;
815 gfx_coord2_t offs;
816 gfx_rect_t rect;
817 errno_t rc;
818
819 if (quit)
820 return EOK;
821
822 rc = demo_begin(gc, w, h, "Clipping demonstration");
823 if (rc != EOK)
824 return rc;
825
826 gfx_bitmap_params_init(&params);
827 params.rect.p0.x = 0;
828 params.rect.p0.y = 0;
829 params.rect.p1.x = 40;
830 params.rect.p1.y = 20;
831
832 rc = gfx_bitmap_create(gc, &params, NULL, &bitmap);
833 if (rc != EOK)
834 return rc;
835
836 rc = bitmap_moire(bitmap, 40, 20);
837 if (rc != EOK)
838 goto error;
839
840 for (j = 0; j < 10; j++) {
841 rect.p0.x = w / 8;
842 rect.p0.y = h / 8;
843 rect.p1.x = w * 7 / 8;
844 rect.p1.y = h * 3 / 8;
845
846 rc = gfx_set_clip_rect(gc, &rect);
847 if (rc != EOK)
848 return rc;
849
850 rc = gfx_color_new_rgb_i16(rand() % 0x10000, rand() % 0x10000,
851 rand() % 0x10000, &color);
852 if (rc != EOK)
853 return rc;
854
855 rc = gfx_set_color(gc, color);
856 if (rc != EOK)
857 return rc;
858
859 for (i = 0; i < 10; i++) {
860 rect.p0.x = rand() % (w - 1);
861 rect.p0.y = rand() % (h - 1);
862 rect.p1.x = rect.p0.x + rand() % (w - 1 - rect.p0.x);
863 rect.p1.y = rect.p0.y + rand() % (h - 1 - rect.p0.y);
864
865 rc = gfx_fill_rect(gc, &rect);
866 if (rc != EOK)
867 return rc;
868 }
869
870 gfx_color_delete(color);
871
872 rect.p0.x = w / 8;
873 rect.p0.y = h * 5 / 8;
874 rect.p1.x = w * 7 / 8;
875 rect.p1.y = h * 7 / 8;
876
877 rc = gfx_set_clip_rect(gc, &rect);
878 if (rc != EOK)
879 return rc;
880
881 for (i = 0; i < 10; i++) {
882 offs.x = rand() % (w - 40);
883 offs.y = rand() % (h - 20);
884
885 rc = gfx_bitmap_render(bitmap, NULL, &offs);
886 if (rc != EOK)
887 goto error;
888 }
889
890 fibril_usleep(500 * 1000);
891
892 if (quit)
893 break;
894 }
895
896 (void) gfx_set_clip_rect(gc, NULL);
897 gfx_bitmap_destroy(bitmap);
898 return EOK;
899error:
900 (void) gfx_set_clip_rect(gc, NULL);
901 gfx_bitmap_destroy(bitmap);
902 return rc;
903}
904
905/** Run demo loop on a graphic context.
906 *
907 * @param gc Graphic context
908 * @param w Width
909 * @param h Height
910 */
911static errno_t demo_loop(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
912{
913 errno_t rc;
914
915 (void) demo_font_init(gc, w, h);
916
917 while (!quit) {
918 rc = demo_rects(gc, w, h);
919 if (rc != EOK)
920 goto error;
921
922 rc = demo_bitmap(gc, w, h);
923 if (rc != EOK)
924 goto error;
925
926 rc = demo_bitmap2(gc, w, h);
927 if (rc != EOK)
928 goto error;
929
930 rc = demo_bitmap_kc(gc, w, h);
931 if (rc != EOK)
932 goto error;
933
934 rc = demo_text(gc, w, h);
935 if (rc != EOK)
936 goto error;
937
938 rc = demo_clip(gc, w, h);
939 if (rc != EOK)
940 goto error;
941 }
942
943 demo_font_fini();
944 return EOK;
945error:
946 demo_font_fini();
947 return rc;
948}
949
950/** Run demo on console. */
951static errno_t demo_console(void)
952{
953 console_ctrl_t *con = NULL;
954 console_gc_t *cgc = NULL;
955 gfx_context_t *gc;
956 errno_t rc;
957
958 printf("Init console..\n");
959 con = console_init(stdin, stdout);
960 if (con == NULL)
961 return EIO;
962
963 printf("Create console GC\n");
964 rc = console_gc_create(con, stdout, &cgc);
965 if (rc != EOK)
966 return rc;
967
968 gc = console_gc_get_ctx(cgc);
969
970 rc = demo_loop(gc, 80, 25);
971 if (rc != EOK)
972 return rc;
973
974 rc = console_gc_delete(cgc);
975 if (rc != EOK)
976 return rc;
977
978 return EOK;
979}
980
981/** Run demo on UI. */
982static errno_t demo_ui(const char *display_spec)
983{
984 ui_t *ui = NULL;
985 ui_wnd_params_t params;
986 ui_window_t *window = NULL;
987 gfx_context_t *gc;
988 gfx_rect_t rect;
989 gfx_rect_t wrect;
990 gfx_coord2_t off;
991 errno_t rc;
992
993 printf("Init UI..\n");
994
995 rc = ui_create(display_spec, &ui);
996 if (rc != EOK) {
997 printf("Error initializing UI (%s)\n", display_spec);
998 goto error;
999 }
1000
1001 rect.p0.x = 0;
1002 rect.p0.y = 0;
1003 rect.p1.x = 400;
1004 rect.p1.y = 300;
1005
1006 ui_wnd_params_init(&params);
1007 params.caption = "GFX Demo";
1008
1009 /*
1010 * Compute window rectangle such that application area corresponds
1011 * to rect
1012 */
1013 ui_wdecor_rect_from_app(params.style, &rect, &wrect);
1014 off = wrect.p0;
1015 gfx_rect_rtranslate(&off, &wrect, &params.rect);
1016
1017 rc = ui_window_create(ui, &params, &window);
1018 if (rc != EOK) {
1019 printf("Error creating window.\n");
1020 goto error;
1021 }
1022
1023 ui_window_set_cb(window, &ui_window_cb, NULL);
1024
1025 rc = ui_window_get_app_gc(window, &gc);
1026 if (rc != EOK) {
1027 printf("Error creating graphic context.\n");
1028 goto error;
1029 }
1030
1031 task_retval(0);
1032
1033 rc = demo_loop(gc, rect.p1.x, rect.p1.y);
1034 if (rc != EOK)
1035 goto error;
1036
1037 ui_window_destroy(window);
1038 ui_destroy(ui);
1039
1040 return EOK;
1041error:
1042 if (window != NULL)
1043 ui_window_destroy(window);
1044 if (ui != NULL)
1045 ui_destroy(ui);
1046 return rc;
1047}
1048
1049/** Run demo on display server. */
1050static errno_t demo_display(const char *display_svc)
1051{
1052 display_t *display = NULL;
1053 gfx_context_t *gc;
1054 display_wnd_params_t params;
1055 display_window_t *window = NULL;
1056 errno_t rc;
1057
1058 printf("Init display..\n");
1059
1060 rc = display_open(display_svc, &display);
1061 if (rc != EOK) {
1062 printf("Error opening display.\n");
1063 return rc;
1064 }
1065
1066 display_wnd_params_init(&params);
1067 params.rect.p0.x = 0;
1068 params.rect.p0.y = 0;
1069 params.rect.p1.x = 400;
1070 params.rect.p1.y = 300;
1071 params.caption = "GFX Demo";
1072
1073 rc = display_window_create(display, &params, &wnd_cb, NULL, &window);
1074 if (rc != EOK) {
1075 printf("Error creating window.\n");
1076 return rc;
1077 }
1078
1079 rc = display_window_get_gc(window, &gc);
1080 if (rc != EOK) {
1081 printf("Error getting graphics context.\n");
1082 return rc;
1083 }
1084
1085 task_retval(0);
1086
1087 rc = demo_loop(gc, 400, 300);
1088 if (rc != EOK)
1089 return rc;
1090
1091 rc = gfx_context_delete(gc);
1092 if (rc != EOK)
1093 return rc;
1094
1095 display_window_destroy(window);
1096 display_close(display);
1097
1098 return EOK;
1099}
1100
1101static void wnd_close_event(void *arg)
1102{
1103 printf("Close event\n");
1104 quit = true;
1105}
1106
1107static void wnd_kbd_event(void *arg, kbd_event_t *event)
1108{
1109 printf("Keyboard event type=%d key=%d\n", event->type, event->key);
1110 if (event->type == KEY_PRESS)
1111 quit = true;
1112}
1113
1114static void uiwnd_close_event(ui_window_t *window, void *arg)
1115{
1116 printf("Close event\n");
1117 quit = true;
1118}
1119
1120static void uiwnd_kbd_event(ui_window_t *window, void *arg, kbd_event_t *event)
1121{
1122 printf("Keyboard event type=%d key=%d\n", event->type, event->key);
1123 if (event->type == KEY_PRESS)
1124 quit = true;
1125}
1126
1127static void print_syntax(void)
1128{
1129 printf("Syntax: gfxdemo [-d <display>] {console|display|ui}\n");
1130}
1131
1132int main(int argc, char *argv[])
1133{
1134 errno_t rc;
1135 const char *display_svc = DISPLAY_DEFAULT;
1136 const char *ui_display_spec = UI_DISPLAY_DEFAULT;
1137 int i;
1138
1139 i = 1;
1140 while (i < argc && argv[i][0] == '-') {
1141 if (str_cmp(argv[i], "-d") == 0) {
1142 ++i;
1143 if (i >= argc) {
1144 printf("Argument missing.\n");
1145 print_syntax();
1146 return 1;
1147 }
1148
1149 display_svc = ui_display_spec = argv[i++];
1150 } else {
1151 printf("Invalid option '%s'.\n", argv[i]);
1152 print_syntax();
1153 return 1;
1154 }
1155 }
1156
1157 if (i >= argc || str_cmp(argv[i], "display") == 0) {
1158 rc = demo_display(display_svc);
1159 if (rc != EOK)
1160 return 1;
1161 } else if (str_cmp(argv[i], "console") == 0) {
1162 rc = demo_console();
1163 if (rc != EOK)
1164 return 1;
1165 } else if (str_cmp(argv[i], "ui") == 0) {
1166 rc = demo_ui(ui_display_spec);
1167 if (rc != EOK)
1168 return 1;
1169 } else {
1170 print_syntax();
1171 return 1;
1172 }
1173}
1174
1175/** @}
1176 */
Note: See TracBrowser for help on using the repository browser.