4 ** member-functions for the drawgif-class
7 ** Copyright (C) 1998 Kurt Van den Branden
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.
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.
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.
41 #define min(x,y) (x < y ? x : y)
45 #define max(x,y) (x > y ? x : y)
48 #define round(x) (int)(x + 0.5)
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] = {
55 {.6005, 2.125}, // row b
56 {.817, 2.25}, // row c
57 {1.0335, 2.375}, // row d
59 {1.4665, 2.375}, // row f
60 {1.683, 2.25}, // row g
61 {1.8995, 2.125}, // row h
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},
84 const position gif_hexagon
[7] = {
85 {1, 2}, {1, 5}, {4, 8}, {7, 5}, {7, 2}, {4, 2}, {1, 2}
111 if (extratext
!= NULL
)
113 while ((ptr
= (char *) llrembynr (extratext
, 1)) != NULL
)
123 void drawgif::filename (const char * fn
)
134 void drawgif::gifboard (board
* gb
)
145 void drawgif::addtext (const char * text
)
151 if (extratext
== NULL
)
153 extratext
= (listheader
*) malloc (sizeof (listheader
));
157 tempstr
= strdup (text
);
161 while ((kar2
= strchr (kar1
, '\n')) != NULL
)
164 pushll (extratext
, strdup (kar1
));
167 pushll (extratext
, strdup (kar1
));
200 gdFontPtr thefont
= gdFontTiny
;
202 listheader
* extralist
;
211 /* choose font according to drawing-size */
213 thefont
= gdFontTiny
;
215 thefont
= gdFontSmall
;
217 thefont
= gdFontMediumBold
;
219 thefont
= gdFontLarge
;
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
));
229 maxchar
= size
/ thefont
->w
- 2;
231 while ((strptr
= (char *) llitembynr (extratext
, counter
)) != NULL
)
234 extralines
+= splitline (extralist
, strptr
, maxchar
);
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. */
251 white
= gdImageColorAllocate(image
, 255, 255, 255);
252 black
= gdImageColorAllocate(image
, 0, 0, 0);
257 lgray
= gdImageColorAllocate(image
, 204, 204, 204);
259 /* Allocate the color black (red, green and blue). */
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
);
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
);
298 gdImageFillToBorder(image
,
304 for (i
= 0 ; i
< 21; i
++)
306 pos2coor (&gif_linetable
[i
][0], x1
, y1
);
307 pos2coor (&gif_linetable
[i
][1], x2
, y2
);
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
);
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'))
348 if (b_ppiece (gipfb
, temppos
) == 'O')
354 gdImageArc (image
, x
, y
, diam2
, diam2
, 0, 360, gray
);
356 gdImageArc (image
, x
, y
, diam2
-1, diam2
-1, 0, 360,
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 */
378 round (base8
* (arrow
[i
][0] * cosa
- arrow
[i
][1] * sina
));
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
,
386 gdImagePolygon (image
, rotarrow
, 7, black
);
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);
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
,
426 gdImageFillToBorder (image
, diam
/2+1,
427 offset
- poffset
* i
+ 1,
430 sprintf (tempstr
, "lost : %d", b_white_lost (gipfb
));
431 gdImageString (image
, thefont
, diam
/4, size
-texth
-3, (unsigned char*)tempstr
, 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
,
446 gdImageFillToBorder (image
, size
- diam
/2 - 1,
447 offset
- poffset
* i
+ 1,
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
);
457 ** (if the file is available)
459 if ((imagefp
= fopen ("small_logo.png", "rb")) != NULL
)
461 gdImagePtr loadimage
;
463 loadimage
= gdImageCreateFromPng (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 */
478 gdImageFilledRectangle (image
, 0, size
, size
-1,
479 size
+ thefont
->h
* (extralines
+ 1) - 1,
481 gdImageRectangle (image
, 0, size
, size
-1,
482 size
+ thefont
->h
* (extralines
+ 1) - 1,
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
);
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. */
505 /* Destroy the image in memory. */
506 gdImageDestroy(image
);
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
)
529 tempstr
= strdup (string
);
531 while (strlen(kar
) > maxchar
)
533 kar2
= kar
+ maxchar
;
534 while ((kar2
> kar
) && (!isspace ((int) kar2
[0])))
539 { /* string too long to be splitted, do the dirty split */
540 savechar
= kar
[maxchar
];
541 kar2
= kar
+ maxchar
;
544 newstring
= (char *) malloc (strlen (kar
) + 1);
545 strcpy (newstring
, kar
);
546 pushll (llist
, (void *) newstring
);
551 kar
[maxchar
] = savechar
;
562 newstring
= (char *) malloc (strlen (kar
) + 1);
563 strcpy (newstring
, kar
);
564 pushll (llist
, (void *) newstring
);
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
);