source: mainline/uspace/app/gfxdemo/gfxdemo.c@ 901b302

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

Add text abbreviation screen to GFX Demo

  • Property mode set to 100644
File size: 24.4 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;
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 text abbreviation demo on a graphic context.
804 *
805 * @param gc Graphic context
806 * @param w Width
807 * @param h Height
808 */
809static errno_t demo_text_abbr(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
810{
811 gfx_color_t *color = NULL;
812 gfx_rect_t rect;
813 gfx_coord2_t pos;
814 gfx_text_fmt_t fmt;
815 int i;
816 errno_t rc;
817
818 if (quit)
819 return EOK;
820
821 rc = demo_begin(gc, w, h, "Text abbreviation");
822 if (rc != EOK)
823 goto error;
824
825 for (i = 0; i < 11; i++) {
826
827 rc = gfx_color_new_rgb_i16(0, 0, 0x8000, &color);
828 if (rc != EOK)
829 goto error;
830
831 rc = gfx_set_color(gc, color);
832 if (rc != EOK)
833 goto error;
834
835 rect.p0.x = w / 20;
836 rect.p0.y = (2 + 2 * i) * h / 25;
837 rect.p1.x = w - w / 20 - w * i / 12;
838 rect.p1.y = (3 + 2 * i) * h / 25;
839
840 rc = gfx_fill_rect(gc, &rect);
841 if (rc != EOK)
842 goto error;
843
844 gfx_color_delete(color);
845
846 if (demo_is_text(w, h)) {
847 rc = gfx_color_new_ega(0x1f, &color);
848 if (rc != EOK)
849 goto error;
850 } else {
851 rc = gfx_color_new_rgb_i16(0xffff, 0xffff, 0xffff,
852 &color);
853 if (rc != EOK)
854 goto error;
855 }
856
857 gfx_text_fmt_init(&fmt);
858 fmt.font = font;
859 fmt.color = color;
860 fmt.abbreviate = true;
861 fmt.width = rect.p1.x - rect.p0.x;
862
863 pos.x = rect.p0.x;
864 pos.y = rect.p0.y;
865 rc = gfx_puttext(&pos, &fmt,
866 "The quick brow fox jumps over the lazy dog!");
867 if (rc != EOK) {
868 printf("Error rendering text.\n");
869 goto error;
870 }
871 }
872
873 for (i = 0; i < 10; i++) {
874 fibril_usleep(500 * 1000);
875 if (quit)
876 break;
877 }
878
879 return EOK;
880error:
881 return rc;
882}
883
884/** Run clipping demo on a graphic context.
885 *
886 * @param gc Graphic context
887 * @param w Width
888 * @param h Height
889 */
890static errno_t demo_clip(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
891{
892 gfx_bitmap_t *bitmap;
893 gfx_color_t *color;
894 gfx_bitmap_params_t params;
895 int i, j;
896 gfx_coord2_t offs;
897 gfx_rect_t rect;
898 errno_t rc;
899
900 if (quit)
901 return EOK;
902
903 rc = demo_begin(gc, w, h, "Clipping demonstration");
904 if (rc != EOK)
905 return rc;
906
907 gfx_bitmap_params_init(&params);
908 params.rect.p0.x = 0;
909 params.rect.p0.y = 0;
910 params.rect.p1.x = 40;
911 params.rect.p1.y = 20;
912
913 rc = gfx_bitmap_create(gc, &params, NULL, &bitmap);
914 if (rc != EOK)
915 return rc;
916
917 rc = bitmap_moire(bitmap, 40, 20);
918 if (rc != EOK)
919 goto error;
920
921 for (j = 0; j < 10; j++) {
922 rect.p0.x = w / 8;
923 rect.p0.y = h / 8;
924 rect.p1.x = w * 7 / 8;
925 rect.p1.y = h * 3 / 8;
926
927 rc = gfx_set_clip_rect(gc, &rect);
928 if (rc != EOK)
929 return rc;
930
931 rc = gfx_color_new_rgb_i16(rand() % 0x10000, rand() % 0x10000,
932 rand() % 0x10000, &color);
933 if (rc != EOK)
934 return rc;
935
936 rc = gfx_set_color(gc, color);
937 if (rc != EOK)
938 return rc;
939
940 for (i = 0; i < 10; i++) {
941 rect.p0.x = rand() % (w - 1);
942 rect.p0.y = rand() % (h - 1);
943 rect.p1.x = rect.p0.x + rand() % (w - 1 - rect.p0.x);
944 rect.p1.y = rect.p0.y + rand() % (h - 1 - rect.p0.y);
945
946 rc = gfx_fill_rect(gc, &rect);
947 if (rc != EOK)
948 return rc;
949 }
950
951 gfx_color_delete(color);
952
953 rect.p0.x = w / 8;
954 rect.p0.y = h * 5 / 8;
955 rect.p1.x = w * 7 / 8;
956 rect.p1.y = h * 7 / 8;
957
958 rc = gfx_set_clip_rect(gc, &rect);
959 if (rc != EOK)
960 return rc;
961
962 for (i = 0; i < 10; i++) {
963 offs.x = rand() % (w - 40);
964 offs.y = rand() % (h - 20);
965
966 rc = gfx_bitmap_render(bitmap, NULL, &offs);
967 if (rc != EOK)
968 goto error;
969 }
970
971 fibril_usleep(500 * 1000);
972
973 if (quit)
974 break;
975 }
976
977 (void) gfx_set_clip_rect(gc, NULL);
978 gfx_bitmap_destroy(bitmap);
979 return EOK;
980error:
981 (void) gfx_set_clip_rect(gc, NULL);
982 gfx_bitmap_destroy(bitmap);
983 return rc;
984}
985
986/** Run demo loop on a graphic context.
987 *
988 * @param gc Graphic context
989 * @param w Width
990 * @param h Height
991 */
992static errno_t demo_loop(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
993{
994 errno_t rc;
995
996 (void) demo_font_init(gc, w, h);
997
998 while (!quit) {
999 rc = demo_rects(gc, w, h);
1000 if (rc != EOK)
1001 goto error;
1002
1003 rc = demo_bitmap(gc, w, h);
1004 if (rc != EOK)
1005 goto error;
1006
1007 rc = demo_bitmap2(gc, w, h);
1008 if (rc != EOK)
1009 goto error;
1010
1011 rc = demo_bitmap_kc(gc, w, h);
1012 if (rc != EOK)
1013 goto error;
1014
1015 rc = demo_text(gc, w, h);
1016 if (rc != EOK)
1017 goto error;
1018
1019 rc = demo_text_abbr(gc, w, h);
1020 if (rc != EOK)
1021 goto error;
1022
1023 rc = demo_clip(gc, w, h);
1024 if (rc != EOK)
1025 goto error;
1026 }
1027
1028 demo_font_fini();
1029 return EOK;
1030error:
1031 demo_font_fini();
1032 return rc;
1033}
1034
1035/** Run demo on console. */
1036static errno_t demo_console(void)
1037{
1038 console_ctrl_t *con = NULL;
1039 console_gc_t *cgc = NULL;
1040 gfx_context_t *gc;
1041 errno_t rc;
1042
1043 printf("Init console..\n");
1044 con = console_init(stdin, stdout);
1045 if (con == NULL)
1046 return EIO;
1047
1048 printf("Create console GC\n");
1049 rc = console_gc_create(con, stdout, &cgc);
1050 if (rc != EOK)
1051 return rc;
1052
1053 gc = console_gc_get_ctx(cgc);
1054
1055 rc = demo_loop(gc, 80, 25);
1056 if (rc != EOK)
1057 return rc;
1058
1059 rc = console_gc_delete(cgc);
1060 if (rc != EOK)
1061 return rc;
1062
1063 return EOK;
1064}
1065
1066/** Run demo on UI. */
1067static errno_t demo_ui(const char *display_spec)
1068{
1069 ui_t *ui = NULL;
1070 ui_wnd_params_t params;
1071 ui_window_t *window = NULL;
1072 gfx_context_t *gc;
1073 gfx_rect_t rect;
1074 gfx_rect_t wrect;
1075 gfx_coord2_t off;
1076 errno_t rc;
1077
1078 printf("Init UI..\n");
1079
1080 rc = ui_create(display_spec, &ui);
1081 if (rc != EOK) {
1082 printf("Error initializing UI (%s)\n", display_spec);
1083 goto error;
1084 }
1085
1086 rect.p0.x = 0;
1087 rect.p0.y = 0;
1088 rect.p1.x = 400;
1089 rect.p1.y = 300;
1090
1091 ui_wnd_params_init(&params);
1092 params.caption = "GFX Demo";
1093
1094 /*
1095 * Compute window rectangle such that application area corresponds
1096 * to rect
1097 */
1098 ui_wdecor_rect_from_app(params.style, &rect, &wrect);
1099 off = wrect.p0;
1100 gfx_rect_rtranslate(&off, &wrect, &params.rect);
1101
1102 rc = ui_window_create(ui, &params, &window);
1103 if (rc != EOK) {
1104 printf("Error creating window.\n");
1105 goto error;
1106 }
1107
1108 ui_window_set_cb(window, &ui_window_cb, NULL);
1109
1110 rc = ui_window_get_app_gc(window, &gc);
1111 if (rc != EOK) {
1112 printf("Error creating graphic context.\n");
1113 goto error;
1114 }
1115
1116 task_retval(0);
1117
1118 rc = demo_loop(gc, rect.p1.x, rect.p1.y);
1119 if (rc != EOK)
1120 goto error;
1121
1122 ui_window_destroy(window);
1123 ui_destroy(ui);
1124
1125 return EOK;
1126error:
1127 if (window != NULL)
1128 ui_window_destroy(window);
1129 if (ui != NULL)
1130 ui_destroy(ui);
1131 return rc;
1132}
1133
1134/** Run demo on display server. */
1135static errno_t demo_display(const char *display_svc)
1136{
1137 display_t *display = NULL;
1138 gfx_context_t *gc;
1139 display_wnd_params_t params;
1140 display_window_t *window = NULL;
1141 errno_t rc;
1142
1143 printf("Init display..\n");
1144
1145 rc = display_open(display_svc, &display);
1146 if (rc != EOK) {
1147 printf("Error opening display.\n");
1148 return rc;
1149 }
1150
1151 display_wnd_params_init(&params);
1152 params.rect.p0.x = 0;
1153 params.rect.p0.y = 0;
1154 params.rect.p1.x = 400;
1155 params.rect.p1.y = 300;
1156 params.caption = "GFX Demo";
1157
1158 rc = display_window_create(display, &params, &wnd_cb, NULL, &window);
1159 if (rc != EOK) {
1160 printf("Error creating window.\n");
1161 return rc;
1162 }
1163
1164 rc = display_window_get_gc(window, &gc);
1165 if (rc != EOK) {
1166 printf("Error getting graphics context.\n");
1167 return rc;
1168 }
1169
1170 task_retval(0);
1171
1172 rc = demo_loop(gc, 400, 300);
1173 if (rc != EOK)
1174 return rc;
1175
1176 rc = gfx_context_delete(gc);
1177 if (rc != EOK)
1178 return rc;
1179
1180 display_window_destroy(window);
1181 display_close(display);
1182
1183 return EOK;
1184}
1185
1186static void wnd_close_event(void *arg)
1187{
1188 printf("Close event\n");
1189 quit = true;
1190}
1191
1192static void wnd_kbd_event(void *arg, kbd_event_t *event)
1193{
1194 printf("Keyboard event type=%d key=%d\n", event->type, event->key);
1195 if (event->type == KEY_PRESS)
1196 quit = true;
1197}
1198
1199static void uiwnd_close_event(ui_window_t *window, void *arg)
1200{
1201 printf("Close event\n");
1202 quit = true;
1203}
1204
1205static void uiwnd_kbd_event(ui_window_t *window, void *arg, kbd_event_t *event)
1206{
1207 printf("Keyboard event type=%d key=%d\n", event->type, event->key);
1208 if (event->type == KEY_PRESS)
1209 quit = true;
1210}
1211
1212static void print_syntax(void)
1213{
1214 printf("Syntax: gfxdemo [-d <display>] {console|display|ui}\n");
1215}
1216
1217int main(int argc, char *argv[])
1218{
1219 errno_t rc;
1220 const char *display_svc = DISPLAY_DEFAULT;
1221 const char *ui_display_spec = UI_DISPLAY_DEFAULT;
1222 int i;
1223
1224 i = 1;
1225 while (i < argc && argv[i][0] == '-') {
1226 if (str_cmp(argv[i], "-d") == 0) {
1227 ++i;
1228 if (i >= argc) {
1229 printf("Argument missing.\n");
1230 print_syntax();
1231 return 1;
1232 }
1233
1234 display_svc = ui_display_spec = argv[i++];
1235 } else {
1236 printf("Invalid option '%s'.\n", argv[i]);
1237 print_syntax();
1238 return 1;
1239 }
1240 }
1241
1242 if (i >= argc || str_cmp(argv[i], "display") == 0) {
1243 rc = demo_display(display_svc);
1244 if (rc != EOK)
1245 return 1;
1246 } else if (str_cmp(argv[i], "console") == 0) {
1247 rc = demo_console();
1248 if (rc != EOK)
1249 return 1;
1250 } else if (str_cmp(argv[i], "ui") == 0) {
1251 rc = demo_ui(ui_display_spec);
1252 if (rc != EOK)
1253 return 1;
1254 } else {
1255 print_syntax();
1256 return 1;
1257 }
1258}
1259
1260/** @}
1261 */
Note: See TracBrowser for help on using the repository browser.