Rename GP_Context -> GP_Pixmap
[gfxprim.git] / demos / c_simple / shapetest.c
blob71d82c85af6060783ca27696a969be0b67c2c484
1 /*****************************************************************************
2 * This file is part of gfxprim library. *
3 * *
4 * Gfxprim is free software; you can redistribute it and/or *
5 * modify it under the terms of the GNU Lesser General Public *
6 * License as published by the Free Software Foundation; either *
7 * version 2.1 of the License, or (at your option) any later version. *
8 * *
9 * Gfxprim is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
12 * Lesser General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU Lesser General Public *
15 * License along with gfxprim; if not, write to the Free Software *
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
17 * Boston, MA 02110-1301 USA *
18 * *
19 * Copyright (C) 2009-2010 Jiri "BlueBear" Dluhos *
20 * <jiri.bluebear.dluhos@gmail.com> *
21 * *
22 * Copyright (C) 2009-2013 Cyril Hrubis <metan@ucw.cz> *
23 * *
24 *****************************************************************************/
26 #include <stdio.h>
27 #include <stdlib.h>
29 #include <GP.h>
31 static GP_Pixmap *win;
32 static GP_Backend *backend;
34 /* Basic colors in display-specific format. */
35 static GP_Pixel black, white, yellow, green, red, gray, darkgray;
37 /* Radius of the shape being drawn */
38 static int xradius = 5;
39 static int yradius = 5;
41 /* Draw outline? 0=none, 1=before filling, 2=after filling */
42 static int outline = 0;
44 /* Fill the shape? */
45 static int fill = 1;
47 /* Show axes? */
48 static int show_axes = 1;
50 /* Shape to be drawn */
51 #define SHAPE_FIRST 1
52 #define SHAPE_TRIANGLE 1
53 #define SHAPE_CIRCLE 2
54 #define SHAPE_RING 3
55 #define SHAPE_ELLIPSE 4
56 #define SHAPE_RECTANGLE 5
57 #define SHAPE_TETRAGON 6
58 #define SHAPE_POLYGON 7
59 #define SHAPE_ARC 8
60 #define SHAPE_LAST 8
61 static int shape = SHAPE_FIRST;
63 /* Variants in coordinates, if applicable */
64 static int variant = 1;
66 /* center of drawing */
67 static int center_x;
68 static int center_y;
70 void draw_testing_triangle(int x, int y, int xradius, int yradius)
72 int x0, y0, x1, y1, x2, y2;
73 switch (variant) {
74 case 1:
75 x0 = x;
76 y0 = y - yradius;
77 x1 = x - xradius;
78 y1 = y;
79 x2 = x + xradius;
80 y2 = y + yradius;
81 break;
82 case 2:
83 x0 = x - xradius;
84 y0 = y - yradius;
85 x1 = x + xradius;
86 y1 = y;
87 x2 = x + xradius;
88 y2 = y + yradius;
89 break;
90 case 3:
91 x0 = x - xradius;
92 y0 = y - yradius;
93 x1 = x + xradius;
94 y1 = y + yradius;
95 x2 = x - xradius + xradius/8;
96 y2 = y;
97 break;
98 case 4:
99 default:
100 x0 = x;
101 y0 = y - yradius;
102 x1 = x + xradius;
103 y1 = y + yradius;
104 x2 = x - xradius;
105 y2 = y + yradius;
106 break;
109 /* draw the three vertices green; they should never be visible
110 * because the red triangle should cover them; if they are visible,
111 * it means we don't draw to the end */
112 GP_PutPixel(win, x0, y0, green);
113 GP_PutPixel(win, x1, y1, green);
114 GP_PutPixel(win, x2, y2, green);
116 if (outline == 1)
117 GP_Triangle(win, x0, y0, x1, y1, x2, y2, yellow);
119 if (fill)
120 GP_FillTriangle(win, x0, y0, x1, y1, x2, y2, red);
122 if (outline == 2)
123 GP_Triangle(win, x0, y0, x1, y1, x2, y2, white);
126 void draw_testing_circle(int x, int y, int xradius,
127 __attribute__((unused)) int yradius)
129 if (outline == 1)
130 GP_Circle(win, x, y, xradius, yellow);
132 if (fill)
133 GP_FillCircle(win, x, y, xradius, red);
135 if (outline == 2)
136 GP_Circle(win, x, y, xradius, white);
139 void draw_testing_ring(int x, int y, int xradius,
140 __attribute__((unused)) int yradius)
142 if (outline == 1)
143 GP_Ring(win, x, y, xradius, yradius, yellow);
145 if (fill)
146 GP_FillRing(win, x, y, xradius, yradius, red);
148 if (outline == 2)
149 GP_Ring(win, x, y, xradius, yradius, white);
152 void draw_testing_ellipse(int x, int y, int xradius, int yradius)
154 if (outline == 1)
155 GP_Ellipse(win, x, y, xradius, yradius, yellow);
157 if (fill)
158 GP_FillEllipse(win, x, y, xradius, yradius, red);
160 if (outline == 2)
161 GP_Ellipse(win, x, y, xradius, yradius, white);
164 void draw_testing_arc(int x, int y, int xradius, int yradius)
166 GP_ArcSegment(win, x, y, xradius, yradius, -1,
167 M_PI - M_PI/8.0, M_PI/4.0, red);
170 void draw_testing_rectangle(int x, int y, int xradius, int yradius)
172 int x0 = x - xradius, y0 = y - yradius;
173 int x1 = x + xradius, y1 = y + yradius;
175 if (outline == 1)
176 GP_Rect(win, x0, y0, x1, y1, yellow);
178 if (fill)
179 GP_FillRect(win, x0, y0, x1, y1, red);
181 if (outline == 2)
182 GP_Rect(win, x0, y0, x1, y1, white);
185 void draw_testing_tetragon(int x, int y, int xradius, int yradius)
187 int x0 = x - xradius, y0 = y - yradius;
188 int x1 = x + xradius, y1 = y;
189 int x2 = x + xradius, y2 = y + yradius/2;
190 int x3 = x, y3 = y + yradius;
192 if (outline == 1)
193 GP_Tetragon(win, x0, y0, x1, y1, x2, y2, x3, y3, yellow);
195 if (fill)
196 GP_FillTetragon(win, x0, y0, x1, y1, x2, y2, x3, y3, red);
198 if (outline == 2)
199 GP_Tetragon(win, x0, y0, x1, y1, x2, y2, x3, y3, white);
202 void draw_testing_polygon(int x, int y, int xradius, int yradius)
204 GP_Coord xy[14];
205 unsigned int edges = 7;
207 xy[0] = x + xradius;
208 xy[1] = y;
210 xy[2] = x + 3 * xradius / 4;
211 xy[3] = y + yradius / 4;
213 xy[4] = x + 3 * xradius / 4;
214 xy[5] = y + 3 * yradius / 4;
216 xy[6] = x + xradius / 4;
217 xy[7] = y + 3 * yradius / 4;
219 xy[8] = x;
220 xy[9] = y;
222 xy[10] = x - xradius;
223 xy[11] = y;
225 xy[12] = x - 3 * xradius / 4;
226 xy[13] = y - yradius / 4;
228 if (outline == 1)
229 GP_Polygon(win, edges, xy, yellow);
231 if (fill)
232 GP_FillPolygon(win, edges, xy, red);
234 if (outline == 2)
235 GP_Polygon(win, edges, xy, white);
238 void redraw_screen(void)
241 /* text style for the label */
242 GP_TextStyle style = {
243 .font = &GP_DefaultConsoleFont,
244 .pixel_xmul = 2,
245 .pixel_ymul = 1,
246 .pixel_xspace = 0,
247 .pixel_yspace = 1,
250 GP_Fill(win, black);
252 /* axes */
253 if (show_axes) {
254 int w, h;
256 w = GP_PixmapW(win);
257 h = GP_PixmapH(win);
259 GP_HLine(win, 0, w, center_y, gray);
260 GP_HLine(win, 0, w, center_y-yradius, darkgray);
261 GP_HLine(win, 0, w, center_y+yradius, darkgray);
262 GP_VLine(win, center_x, 0, h, gray);
263 GP_VLine(win, center_x-xradius, 0, h, darkgray);
264 GP_VLine(win, center_x+xradius, 0, h, darkgray);
267 /* the shape */
268 const char *title = NULL;
269 switch (shape) {
270 case SHAPE_TRIANGLE:
271 draw_testing_triangle(center_x, center_y, xradius, yradius);
272 title = "TRIANGLE";
273 break;
274 case SHAPE_CIRCLE:
275 draw_testing_circle(center_x, center_y, xradius, yradius);
276 title = "CIRCLE";
277 break;
278 case SHAPE_RING:
279 draw_testing_ring(center_x, center_y, xradius, yradius);
280 title = "RING";
281 break;
282 case SHAPE_ELLIPSE:
283 draw_testing_ellipse(center_x, center_y, xradius, yradius);
284 title = "ELLIPSE";
285 break;
286 case SHAPE_RECTANGLE:
287 draw_testing_rectangle(center_x, center_y, xradius, yradius);
288 title = "RECTANGLE";
289 break;
290 case SHAPE_TETRAGON:
291 draw_testing_tetragon(center_x, center_y, xradius, yradius);
292 title = "TETRAGON";
293 break;
294 case SHAPE_POLYGON:
295 draw_testing_polygon(center_x, center_y, xradius, yradius);
296 title = "POLYGON";
297 break;
298 case SHAPE_ARC:
299 draw_testing_arc(center_x, center_y, xradius, yradius);
300 title = "ARC";
301 break;
304 GP_Text(win, &style, 16, 16, GP_ALIGN_RIGHT|GP_VALIGN_BELOW,
305 white, black, title);
307 GP_BackendFlip(backend);
310 static void xradius_add(int xradius_add)
312 if (xradius + xradius_add > 1 &&
313 xradius + xradius_add < (int)GP_PixmapW(win))
314 xradius += xradius_add;
318 static void yradius_add(int yradius_add)
320 if (yradius + yradius_add > 1 &&
321 yradius + yradius_add < (int)GP_PixmapH(win))
322 yradius += yradius_add;
325 static void xcenter_add(int xcenter_add)
327 if (center_x + xcenter_add > 1 &&
328 center_x + xcenter_add < (int)GP_PixmapW(win)/2)
329 center_x += xcenter_add;
332 static void ycenter_add(int ycenter_add)
334 if (center_y + ycenter_add > 1 &&
335 center_y + ycenter_add < (int)GP_PixmapH(win)/2)
336 center_y += ycenter_add;
339 void event_loop(void)
341 int shift_pressed;
343 GP_Event ev;
345 for (;;) {
346 GP_BackendWaitEvent(backend, &ev);
348 //GP_EventDump(&ev);
350 shift_pressed = GP_EventGetKey(&ev, GP_KEY_LEFT_SHIFT) ||
351 GP_EventGetKey(&ev, GP_KEY_RIGHT_SHIFT);
353 switch (ev.type) {
354 case GP_EV_KEY:
355 if (ev.code != GP_EV_KEY_DOWN)
356 continue;
358 switch (ev.val.key.key) {
359 case GP_KEY_X:
360 win->x_swap = !win->x_swap;
361 break;
362 case GP_KEY_Y:
363 win->y_swap = !win->y_swap;
364 break;
365 case GP_KEY_R:
366 win->axes_swap = !win->axes_swap;
367 center_x = GP_PixmapW(win) / 2;
368 center_y = GP_PixmapH(win) / 2;
369 break;
370 case GP_KEY_F:
371 fill = !fill;
372 if (!fill && !outline)
373 outline = 1;
374 break;
375 case GP_KEY_O:
376 outline++;
377 if (outline == 3)
378 outline = 0;
379 if (!fill && outline == 0)
380 fill = 1;
381 break;
382 case GP_KEY_A:
383 show_axes = !show_axes;
384 break;
385 case GP_KEY_LEFT:
386 if (shift_pressed)
387 xcenter_add(-1);
388 else
389 xradius_add(-1);
390 break;
391 case GP_KEY_RIGHT:
392 if (shift_pressed)
393 xcenter_add(1);
394 else
395 xradius_add(1);
396 break;
397 case GP_KEY_UP:
398 if (shift_pressed)
399 ycenter_add(-1);
400 else
401 yradius_add(1);
402 break;
403 case GP_KEY_DOWN:
404 if (shift_pressed)
405 ycenter_add(1);
406 else
407 yradius_add(-1);
408 break;
409 case GP_KEY_SPACE:
410 shape++;
411 if (shape > SHAPE_LAST)
412 shape = SHAPE_FIRST;
413 break;
414 case GP_KEY_EQUAL:
415 if (xradius > yradius)
416 yradius = xradius;
417 else
418 xradius = yradius;
419 break;
420 case GP_KEY_1:
421 variant = 1;
422 break;
423 case GP_KEY_2:
424 variant = 2;
425 break;
426 case GP_KEY_3:
427 variant = 3;
428 break;
429 case GP_KEY_4:
430 variant = 4;
431 break;
432 case GP_KEY_PAGE_UP:
433 xradius_add(1);
434 yradius_add(1);
435 break;
436 case GP_KEY_PAGE_DOWN:
437 xradius_add(-1);
438 yradius_add(-1);
439 break;
440 case GP_KEY_ESC:
441 GP_BackendExit(backend);
442 exit(0);
443 break;
445 break;
446 case GP_EV_SYS:
447 switch(ev.code) {
448 case GP_EV_SYS_QUIT:
449 GP_BackendExit(backend);
450 exit(0);
451 break;
452 case GP_EV_SYS_RESIZE:
453 GP_BackendResizeAck(backend);
454 win = backend->pixmap;
455 center_x = GP_PixmapW(win) / 2;
456 center_y = GP_PixmapH(win) / 2;
457 break;
459 break;
462 redraw_screen();
466 void print_instructions(void)
468 printf("Use the following keys to control the test:\n");
469 printf(" Esc ................. exit\n");
470 printf(" Space ............... change shapes\n");
471 printf(" O ................... draw outlines (none/before/after fill)\n");
472 printf(" F ................... toggle filling\n");
473 printf(" A ................... show/hide axes\n");
474 printf(" X ................... mirror X\n");
475 printf(" Y ................... mirror Y\n");
476 printf(" R ................... reverse X and Y\n");
477 printf(" left/right .......... increase/decrease horizontal radius\n");
478 printf(" up/down ............. increase/decrease vertical radius\n");
479 printf(" shift + left/right .. increase/decrease horizontal center\n");
480 printf(" shift + up/down ..... increase/decrease vertical center\n");
481 printf(" PgUp/PgDn ........... increase/decrease both radii\n");
482 printf(" = ................... reset radii to the same value\n");
483 printf(" 1/2/3 ............... choose shape variant (if applicable)\n");
486 int main(int argc, char *argv[])
488 const char *backend_opts = "X11";
489 int opt;
491 while ((opt = getopt(argc, argv, "b:")) != -1) {
492 switch (opt) {
493 case 'b':
494 backend_opts = optarg;
495 break;
496 default:
497 fprintf(stderr, "Invalid paramter '%c'\n", opt);
501 backend = GP_BackendInit(backend_opts, "Shapetest");
503 if (backend == NULL) {
504 fprintf(stderr, "Failed to initalize backend '%s'\n",
505 backend_opts);
506 return 1;
509 win = backend->pixmap;
511 center_x = win->w / 2;
512 center_y = win->h / 2;
514 /* Load colors compatible with the display */
515 black = GP_RGBToPixmapPixel(0x00, 0x00, 0x00, win);
516 white = GP_RGBToPixmapPixel(0xff, 0xff, 0xff, win);
517 yellow = GP_RGBToPixmapPixel(0xff, 0xff, 0x00, win);
518 green = GP_RGBToPixmapPixel(0x00, 0xff, 0x00, win);
519 red = GP_RGBToPixmapPixel(0xff, 0x00, 0x00, win);
520 gray = GP_RGBToPixmapPixel(0xbe, 0xbe, 0xbe, win);
521 darkgray = GP_RGBToPixmapPixel(0x7f, 0x7f, 0x7f, win);
523 print_instructions();
524 redraw_screen();
525 event_loop();
527 return 0;