Support for g++-4.1.
[gf1.git] / drawgif.cxx
blob4094b074798e82da41529445c0fca528eea808bd
1 /*
2 ** $Id$
3 **
4 ** member-functions for the drawgif-class
5 */
6 /*
7 ** Copyright (C) 1998 Kurt Van den Branden
8 **
9 ** This program is free software; you can redistribute it and/or modify
10 ** it under the terms of the GNU General Public License as published by
11 ** the Free Software Foundation; either version 2 of the License, or
12 ** (at your option) any later version.
13 **
14 ** This program is distributed in the hope that it will be useful,
15 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ** GNU General Public License for more details.
18 **
19 ** You should have received a copy of the GNU General Public License
20 ** along with this program; if not, write to the Free Software
21 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #ifdef HAVEGD
26 #include <stdio.h>
27 #include <string.h>
28 #include <ctype.h>
29 #include "drawgif.h"
31 extern "C" {
32 #include <gd.h>
33 #include <gdfontg.h>
34 #include <gdfontl.h>
35 #include <gdfontmb.h>
36 #include <gdfonts.h>
37 #include <gdfontt.h>
40 #ifndef min
41 #define min(x,y) (x < y ? x : y)
42 #endif
44 #ifndef max
45 #define max(x,y) (x > y ? x : y)
46 #endif
48 #define round(x) (int)(x + 0.5)
49 #define MY_PI 3.14159
51 // x and y-position of each first point of a column
52 // based on a square of 2.5 by 2.5
53 double gif_rowbase[9][2] = {
54 {.384, 2}, // row a
55 {.6005, 2.125}, // row b
56 {.817, 2.25}, // row c
57 {1.0335, 2.375}, // row d
58 {1.25, 2.5}, // row e
59 {1.4665, 2.375}, // row f
60 {1.683, 2.25}, // row g
61 {1.8995, 2.125}, // row h
62 {2.116, 2}};// row i
64 /* lines on the board */
65 const position gif_linetable[21][2] = {
66 {{0, 4}, {5, 8}}, {{0, 3}, {6, 7}}, {{0, 2}, {7, 6}},
67 {{0, 1}, {8, 5}}, {{1, 1}, {8, 4}}, {{2, 1}, {8, 3}},
68 {{3, 1}, {8, 2}}, {{0, 2}, {5, 1}}, {{0, 3}, {6, 1}},
69 {{0, 4}, {7, 1}}, {{0, 5}, {8, 1}}, {{1, 6}, {8, 2}},
70 {{2, 7}, {8, 3}}, {{3, 8}, {8, 4}}, {{1, 6}, {1, 1}},
71 {{2, 7}, {2, 1}}, {{3, 8}, {3, 1}}, {{4, 9}, {4, 1}},
72 {{5, 8}, {5, 1}}, {{6, 7}, {6, 1}}, {{7, 6}, {7, 1}}
75 /* possible from-points */
76 const position gif_fromtable[24] = {
77 {0, 1}, {0, 2}, {0, 3}, {0, 4}, {0, 5}, {1, 6},
78 {2, 7}, {3, 8}, {4, 9}, {5, 8}, {6, 7}, {7, 6},
79 {8, 5}, {8, 4}, {8, 3}, {8, 2}, {8, 1}, {7, 1},
80 {6, 1}, {5, 1}, {4, 1}, {3, 1}, {2, 1}, {1, 1},
83 /* white hexagon */
84 const position gif_hexagon[7] = {
85 {1, 2}, {1, 5}, {4, 8}, {7, 5}, {7, 2}, {4, 2}, {1, 2}
89 drawgif::drawgif ()
91 filen = NULL;
92 size = 300;
93 colour = 1;
94 gipfb = NULL;
95 extratext = NULL;
97 return;
101 drawgif::~drawgif ()
103 char * ptr;
105 if (filen != NULL)
106 free (filen);
108 if (gipfb != NULL)
109 b_del (gipfb);
111 if (extratext != NULL)
113 while ((ptr = (char *) llrembynr (extratext, 1)) != NULL)
114 free (ptr);
116 free (extratext);
119 return;
123 void drawgif::filename (const char * fn)
125 if (filen != NULL)
126 free (filen);
128 filen = strdup (fn);
130 return;
134 void drawgif::gifboard (board * gb)
136 if (gipfb != NULL)
137 b_del (gipfb);
139 gipfb = b_copy (gb);
141 return;
145 void drawgif::addtext (const char * text)
147 char * tempstr,
148 * kar1,
149 * kar2;
151 if (extratext == NULL)
153 extratext = (listheader *) malloc (sizeof (listheader));
154 newlist (extratext);
157 tempstr = strdup (text);
158 kar1 = tempstr;
160 // split on '\n'
161 while ((kar2 = strchr (kar1, '\n')) != NULL)
163 kar2[0] = '\0';
164 pushll (extratext, strdup (kar1));
165 kar1 = kar2 + 1;
167 pushll (extratext, strdup (kar1));
169 free (tempstr);
171 return;
175 int drawgif::draw ()
177 int black,
178 white,
179 yellow,
180 lgray,
181 counter,
182 offset,
183 gray,
184 red,
185 notused,
186 texth,
187 pieceh,
188 poffset,
189 i, j;
190 gdImagePtr image;
191 FILE * imagefp;
192 FILE * fp;
193 double base8;
194 int diam,
195 x,y,
196 x1, y1, x2, y2,
198 diam2;
199 char tempstr[20];
200 gdFontPtr thefont = gdFontTiny;
201 gdPoint hexa[7];
202 listheader * extralist;
203 int extralines = 0,
204 maxchar;
205 char * strptr;
206 gdPoint rotarrow[7];
207 double sina,
208 cosa;
209 position * temppos;
211 /* choose font according to drawing-size */
212 if (size < 200)
213 thefont = gdFontTiny;
214 else if (size < 250)
215 thefont = gdFontSmall;
216 else if (size < 350)
217 thefont = gdFontMediumBold;
218 else if (size < 450)
219 thefont = gdFontLarge;
220 else
221 thefont = gdFontGiant;
224 ** find out how many extra lines have to be displayed
225 ** and split lines that are to long to fit
227 extralist = (listheader *) malloc (sizeof (listheader));
228 newlist (extralist);
229 maxchar = size / thefont->w - 2;
230 counter = 1;
231 while ((strptr = (char *) llitembynr (extratext, counter)) != NULL)
233 counter++;
234 extralines += splitline (extralist, strptr, maxchar);
237 /* create image */
238 base = size / 2.5;
239 image = gdImageCreate(size, size + thefont->h *
240 (extralines == 0 ? 0 : extralines + 1));
241 gdImageInterlace(image, 1);
243 /* all colors have been chosen to be the ones used by Netscape
244 when used in 256 color mode */
246 /* Allocate the color lgray (red, green and blue).
247 Since this is the first color in a new image, it will
248 be the background color. */
249 if (!colour)
251 white = gdImageColorAllocate(image, 255, 255, 255);
252 black = gdImageColorAllocate(image, 0, 0, 0);
254 /*lgray = white;*/
256 else
257 lgray = gdImageColorAllocate(image, 204, 204, 204);
259 /* Allocate the color black (red, green and blue). */
260 if (!colour)
262 yellow = white;
263 gray = black;
264 red = black;
266 else
268 white = gdImageColorAllocate(image, 255, 255, 255);
269 black = gdImageColorAllocate(image, 0, 0, 0);
270 yellow = gdImageColorAllocate(image, 255, 255, 204);
271 gray = gdImageColorAllocate (image, 153, 153, 153);
272 red = gdImageColorAllocate (image, 255, 0, 0);
275 /* the 'notused' color can be used for drawing the outline of a figure
276 you want to fill later */
277 notused = gdImageColorAllocate (image, 1, 1, 1);
279 /* draw rectangle around image */
280 gdImageRectangle (image, 0, 0, size-1, size-1, black);
282 /* draw hexagon */
283 for (i = 0; i < 6; i++)
285 pos2coor (&gif_hexagon[i], hexa[i].x, hexa[i].y);
287 gdImageFilledPolygon(image, hexa, 6, white);
289 /* draw from-points */
290 diam = round (base / 12);
291 for (i = 0; i < 24; i++)
293 pos2coor (&gif_fromtable[i], x, y);
294 gdImageArc(image,
295 x, y,
296 diam, diam,
297 0, 360, black);
298 gdImageFillToBorder(image,
299 x, y,
300 black, black);
303 /* draw lines */
304 for (i = 0 ; i < 21; i++)
306 pos2coor (&gif_linetable[i][0], x1, y1);
307 pos2coor (&gif_linetable[i][1], x2, y2);
308 gdImageLine (image,
309 x1, y1, x2, y2,
310 black);
313 /* draw pieces */
314 /* calculate size of piece */
315 diam = round (base / 6);
316 diam2 = round (base / 10);
318 temppos = (position *) malloc (sizeof (position));
320 for (i = 1; i < 8; i++)
321 for (j = 2; j <= b_colsize (i); j++)
323 posp_col (temppos) = i;
324 posp_row (temppos) = j;
326 if (b_ppiece (gipfb, temppos) != '.')
328 /* calculate position of center of the piece */
329 pos2coor (temppos, x, y);
331 gdImageArc (image, x, y, diam, diam, 0, 360, notused);
332 if ((b_ppiece (gipfb, temppos) == 'o') ||
333 (b_ppiece (gipfb, temppos) == 'O'))
335 gdImageFillToBorder (image, x, y, notused, yellow);
337 else
339 gdImageFillToBorder (image, x, y, notused, black);
341 gdImageArc (image, x, y, diam, diam, 0, 360, black);
343 if ((b_ppiece (gipfb, temppos) == 'X') ||
344 (b_ppiece (gipfb, temppos) == 'O'))
346 if (!colour)
348 if (b_ppiece (gipfb, temppos) == 'O')
349 gray = black;
350 else
351 gray = white;
354 gdImageArc (image, x, y, diam2, diam2, 0, 360, gray);
355 if (size >= 250)
356 gdImageArc (image, x, y, diam2-1, diam2-1, 0, 360,
357 gray);
362 free (temppos);
364 #if 0
365 /* draw arrows */
366 base8 = base / 8;
367 while ((arr = (arrowitem *) llrembynr (arrowlist, 1)) != NULL)
369 /* calculate position */
370 x = round (rowbase[arr->col][0] * base);
371 y = round ((rowbase[arr->col][1] - arr->row * .25) * base);
373 cosa = cos ((double) arr->angle * MY_PI / 180);
374 sina = sin ((double) arr->angle * MY_PI / 180);
375 for (i = 0; i < 8; i++)
376 { /* the 8th point is the center and used by the fill */
377 rotarrow[i].x = x +
378 round (base8 * (arrow[i][0] * cosa - arrow[i][1] * sina));
379 rotarrow[i].y = y -
380 round (base8 * (arrow[i][0] * sina + arrow[i][1] * cosa));
383 gdImagePolygon (image, rotarrow, 7, notused);
384 gdImageFillToBorder (image, rotarrow[7].x, rotarrow[7].y,
385 notused, red);
386 gdImagePolygon (image, rotarrow, 7, black);
388 free (arr);
390 free (arrowlist);
391 #endif
393 /* draw position-names */
394 for (i = 0; i < 9; i++)
396 sprintf (tempstr, "%c1", i+'a');
397 x = round (gif_rowbase[i][0] * base) - thefont->w;
398 y = round ((gif_rowbase[i][1] - .125) * base) - 3;
400 gdImageString(image, thefont, x, y, (unsigned char*)tempstr, black);
402 nr = (i < 5 ? i + 5 : 13 - i);
403 sprintf (tempstr, "%c%d", i+'a', nr);
404 y = size - round ((gif_rowbase[i][1] - .125) * base) - thefont->h + 3;
406 gdImageString(image, thefont, x, y, (unsigned char*)tempstr, black);
409 /* draw piles of available pieces */
410 pieceh = round (base / 30);
411 poffset = round (base / 20);
412 diam = round (base / 6);
413 texth = thefont->h;
415 /* white */
416 sprintf (tempstr, "white: %d", b_white (gipfb));
417 gdImageString (image, thefont, diam/4, size-texth*2-3, (unsigned char*)tempstr, black);
419 offset = size - texth*2 - 3;
420 for (i = 1; i <= b_white (gipfb); i++)
422 gdImageRectangle (image,
423 diam/2, offset - poffset * i,
424 round (diam * 1.5), offset - poffset * i + pieceh,
425 black);
426 gdImageFillToBorder (image, diam/2+1,
427 offset - poffset * i + 1,
428 black, yellow);
430 sprintf (tempstr, "lost : %d", b_white_lost (gipfb));
431 gdImageString (image, thefont, diam/4, size-texth-3, (unsigned char*)tempstr, black);
433 /* black */
434 sprintf (tempstr, "%d :black", b_black (gipfb));
435 gdImageString (image, thefont,
436 size - diam/4 - thefont->w * strlen (tempstr),
437 size-texth*2-3, (unsigned char*)tempstr, black);
439 offset = size - texth*2 - 3;
440 for (i = 1; i <= b_black (gipfb); i++)
442 gdImageRectangle (image,
443 round (size - diam * 1.5), offset - poffset * i,
444 size - diam/2, offset - poffset * i + pieceh,
445 black);
446 gdImageFillToBorder (image, size - diam/2 - 1,
447 offset - poffset * i + 1,
448 black, black);
450 sprintf (tempstr, "%d : lost", b_black_lost (gipfb));
451 gdImageString (image, thefont,
452 size - diam/4 - thefont->w * strlen (tempstr),
453 size-texth-3, (unsigned char*)tempstr, black);
456 ** draw gipf-logo
457 ** (if the file is available)
459 if ((imagefp = fopen ("small_logo.png", "rb")) != NULL)
461 gdImagePtr loadimage;
463 loadimage = gdImageCreateFromPng (imagefp);
464 fclose (imagefp);
465 if (loadimage != NULL)
467 gdImageCopy(image, loadimage, 1, 1, 0, 0,
468 loadimage->sx, loadimage->sy);
471 gdImageDestroy (loadimage);
475 /* draw extra lines of text */
476 if (extralines > 0)
478 gdImageFilledRectangle (image, 0, size, size-1,
479 size + thefont->h * (extralines + 1) - 1,
480 white);
481 gdImageRectangle (image, 0, size, size-1,
482 size + thefont->h * (extralines + 1) - 1,
483 black);
484 i = 0;
485 while ((strptr = (char *) llrembynr (extralist, 1)) != NULL)
487 gdImageString (image, thefont, thefont->w,
488 size + thefont->h / 2 + thefont->h * i,
489 (unsigned char*)strptr, black);
490 free (strptr);
491 i++;
494 free (extralist);
496 gdImageColorDeallocate(image, notused);
498 /* open file for output */
499 fp = fopen(filen, "wb");
500 /* Output the image to the disk file. */
501 gdImagePng(image, fp);
502 /* Close the file. */
503 fclose(fp);
505 /* Destroy the image in memory. */
506 gdImageDestroy(image);
509 return (1);
514 ** the 'string' will be copied and added to 'llist'
515 ** if 'string' is longer then 'maxchar', it will be splitted
516 ** into several strings and added to 'llist'
518 ** returns: nr of strings added to 'llist'
520 int drawgif::splitline (listheader * llist, char * string, int maxchar)
522 char * newstring,
523 * kar,
524 * kar2,
525 * tempstr,
526 savechar = 0;
527 int counter = 0;
529 tempstr = strdup (string);
530 kar = tempstr;
531 while (strlen(kar) > maxchar)
533 kar2 = kar + maxchar;
534 while ((kar2 > kar) && (!isspace ((int) kar2[0])))
536 kar2--;
538 if (kar2 == kar)
539 { /* string too long to be splitted, do the dirty split */
540 savechar = kar[maxchar];
541 kar2 = kar + maxchar;
543 kar2[0] = '\0';
544 newstring = (char *) malloc (strlen (kar) + 1);
545 strcpy (newstring, kar);
546 pushll (llist, (void *) newstring);
547 counter++;
549 if (savechar != 0)
551 kar[maxchar] = savechar;
552 savechar = 0;
553 kar = kar2;
555 else
557 kar = kar2 + 1;
561 /* last piece */
562 newstring = (char *) malloc (strlen (kar) + 1);
563 strcpy (newstring, kar);
564 pushll (llist, (void *) newstring);
565 counter++;
567 free (tempstr);
569 return (counter);
574 ** calculate coordinates starting from a board-position
576 void drawgif::pos2coor (const position *pos, int& x, int& y)
578 x = round (gif_rowbase[pos->col][0] * base);
579 y = round ((gif_rowbase[pos->col][1] - pos->row * .25) * base);
581 return;
584 #endif