source: mainline/uspace/app/gfxdemo/gfxdemo.c@ 400a16d

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

Clarify right/bottom-aligned text position and fix off-by-ones

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