mgd.c

Go to the documentation of this file.
00001 /********************************************************************\
00002 
00003   Name:         mgd.c
00004   Created by:   Thomas Boutell (http://www.boutell.com/boutell/)
00005                 
00006                   with the help of 
00007                 
00008                 David Rowley <mgardi@watdscu.waterloo.edu>
00009                 David Koblas <koblas@netcom.com>
00010 
00011                   modified by 
00012                   
00013                 Stefan Ritt <Stefan.Ritt@psi.ch>
00014 
00015                   For further copywright notices see:
00016 
00017                 http://www.boutell.com/gd/
00018 
00019   Contents:     GD graphics library to create Web images
00020 
00021   $Id: mgd.c 2753 2005-10-07 14:55:31Z ritt $
00022 
00023 \********************************************************************/
00024 
00025 #include <stdio.h>
00026 #include <math.h>
00027 #include <string.h>
00028 #include <stdlib.h>
00029 #include <midas.h>
00030 #include "mgd.h"
00031 
00032 int gdFontGiantData[] = {
00033    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00034    0, 0, 0, 0, 0, 48, 120, 252, 510, 252, 120, 48, 0, 0, 0,
00035    0, 0, 0, 0, 0, 438, 204, 438, 204, 438, 204, 438, 0, 0, 0,
00036    0, 0, 0, 102, 102, 126, 102, 102, 0, 504, 96, 96, 96, 96, 0,
00037    0, 0, 0, 62, 6, 30, 6, 6, 0, 496, 48, 240, 48, 48, 0,
00038    0, 0, 0, 124, 70, 6, 70, 124, 0, 248, 408, 248, 408, 408, 0,
00039    0, 0, 0, 6, 6, 6, 6, 62, 0, 496, 48, 240, 48, 48, 0,
00040    0, 0, 0, 0, 0, 120, 204, 204, 120, 0, 0, 0, 0, 0, 0,
00041    0, 0, 48, 48, 48, 510, 510, 48, 48, 48, 0, 510, 510, 0, 0,
00042    0, 0, 0, 102, 110, 126, 118, 102, 0, 48, 48, 48, 48, 496, 0,
00043    0, 0, 0, 102, 102, 102, 60, 24, 0, 504, 96, 96, 96, 96, 0,
00044    48, 48, 48, 48, 48, 48, 48, 63, 63, 0, 0, 0, 0, 0, 0,
00045    0, 0, 0, 0, 0, 0, 0, 63, 63, 48, 48, 48, 48, 48, 48,
00046    0, 0, 0, 0, 0, 0, 0, 496, 496, 48, 48, 48, 48, 48, 48,
00047    48, 48, 48, 48, 48, 48, 48, 496, 496, 0, 0, 0, 0, 0, 0,
00048    48, 48, 48, 48, 48, 48, 48, 511, 511, 48, 48, 48, 48, 48, 48,
00049    0, 0, 0, 511, 511, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00050    0, 0, 0, 0, 0, 511, 511, 0, 0, 0, 0, 0, 0, 0, 0,
00051    0, 0, 0, 0, 0, 0, 0, 511, 511, 0, 0, 0, 0, 0, 0,
00052    0, 0, 0, 0, 0, 0, 0, 0, 0, 511, 511, 0, 0, 0, 0,
00053    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 511, 511, 0, 0,
00054    48, 48, 48, 48, 48, 48, 48, 496, 496, 48, 48, 48, 48, 48, 48,
00055    48, 48, 48, 48, 48, 48, 48, 63, 63, 48, 48, 48, 48, 48, 48,
00056    48, 48, 48, 48, 48, 48, 48, 511, 511, 0, 0, 0, 0, 0, 0,
00057    0, 0, 0, 0, 0, 0, 0, 511, 511, 48, 48, 48, 48, 48, 48,
00058    48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
00059    0, 0, 0, 448, 112, 28, 6, 28, 112, 448, 0, 510, 510, 0, 0,
00060    0, 0, 0, 14, 56, 224, 384, 224, 56, 14, 0, 510, 510, 0, 0,
00061    0, 0, 0, 0, 0, 510, 510, 200, 200, 200, 206, 206, 0, 0, 0,
00062    0, 0, 0, 384, 192, 510, 510, 48, 510, 510, 12, 6, 0, 0, 0,
00063    0, 0, 0, 240, 408, 24, 24, 252, 24, 24, 62, 506, 14, 0, 0,
00064    0, 0, 0, 0, 0, 0, 0, 48, 48, 0, 0, 0, 0, 0, 0,
00065    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00066    0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 0, 0, 0,
00067    0, 0, 216, 216, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00068    0, 0, 0, 108, 108, 254, 108, 108, 254, 108, 108, 0, 0, 0, 0,
00069    0, 0, 32, 248, 428, 44, 60, 248, 480, 416, 428, 248, 32, 0, 0,
00070    0, 0, 396, 222, 222, 108, 48, 48, 216, 492, 492, 198, 0, 0, 0,
00071    0, 0, 60, 102, 102, 102, 60, 102, 486, 198, 230, 444, 0, 0, 0,
00072    0, 0, 240, 112, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00073    0, 96, 48, 24, 24, 12, 12, 12, 12, 24, 24, 48, 96, 0, 0,
00074    0, 12, 24, 48, 48, 96, 96, 96, 96, 48, 48, 24, 12, 0, 0,
00075    0, 0, 0, 16, 214, 124, 56, 238, 56, 124, 214, 16, 0, 0, 0,
00076    0, 0, 0, 0, 48, 48, 48, 510, 48, 48, 48, 0, 0, 0, 0,
00077    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 56, 12, 0, 0,
00078    0, 0, 0, 0, 0, 0, 0, 510, 0, 0, 0, 0, 0, 0, 0,
00079    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 120, 48, 0, 0,
00080    0, 0, 384, 192, 192, 96, 48, 48, 24, 12, 12, 6, 0, 0, 0,
00081    0, 0, 120, 204, 390, 390, 390, 390, 390, 390, 204, 120, 0, 0, 0,
00082    0, 0, 48, 56, 60, 48, 48, 48, 48, 48, 48, 252, 0, 0, 0,
00083    0, 0, 252, 390, 390, 384, 192, 96, 56, 12, 6, 510, 0, 0, 0,
00084    0, 0, 510, 384, 192, 96, 240, 384, 384, 384, 390, 252, 0, 0, 0,
00085    0, 0, 192, 224, 240, 216, 204, 198, 510, 192, 192, 192, 0, 0, 0,
00086    0, 0, 510, 6, 6, 254, 398, 384, 384, 384, 390, 252, 0, 0, 0,
00087    0, 0, 248, 12, 6, 6, 254, 398, 390, 390, 390, 252, 0, 0, 0,
00088    0, 0, 510, 384, 384, 192, 96, 48, 24, 24, 12, 12, 0, 0, 0,
00089    0, 0, 252, 390, 390, 390, 252, 390, 390, 390, 390, 252, 0, 0, 0,
00090    0, 0, 252, 390, 390, 390, 454, 508, 384, 384, 192, 124, 0, 0, 0,
00091    0, 0, 0, 0, 0, 48, 120, 48, 0, 0, 48, 120, 48, 0, 0,
00092    0, 0, 0, 0, 0, 48, 120, 48, 0, 0, 120, 56, 12, 0, 0,
00093    0, 0, 192, 96, 48, 24, 12, 12, 24, 48, 96, 192, 0, 0, 0,
00094    0, 0, 0, 0, 0, 0, 510, 0, 0, 510, 0, 0, 0, 0, 0,
00095    0, 0, 12, 24, 48, 96, 192, 192, 96, 48, 24, 12, 0, 0, 0,
00096    0, 0, 252, 390, 390, 384, 192, 96, 48, 48, 0, 48, 0, 0, 0,
00097    0, 0, 252, 390, 390, 502, 414, 478, 502, 6, 6, 252, 0, 0, 0,
00098    0, 0, 48, 120, 204, 390, 390, 390, 510, 390, 390, 390, 0, 0, 0,
00099    0, 0, 254, 396, 396, 396, 252, 396, 396, 396, 396, 254, 0, 0, 0,
00100    0, 0, 252, 390, 6, 6, 6, 6, 6, 6, 390, 252, 0, 0, 0,
00101    0, 0, 254, 396, 396, 396, 396, 396, 396, 396, 396, 254, 0, 0, 0,
00102    0, 0, 510, 12, 12, 12, 124, 12, 12, 12, 12, 510, 0, 0, 0,
00103    0, 0, 510, 12, 12, 12, 124, 12, 12, 12, 12, 12, 0, 0, 0,
00104    0, 0, 252, 390, 6, 6, 6, 486, 390, 390, 390, 252, 0, 0, 0,
00105    0, 0, 390, 390, 390, 390, 510, 390, 390, 390, 390, 390, 0, 0, 0,
00106    0, 0, 252, 48, 48, 48, 48, 48, 48, 48, 48, 252, 0, 0, 0,
00107    0, 0, 496, 192, 192, 192, 192, 192, 192, 192, 198, 124, 0, 0, 0,
00108    0, 0, 390, 198, 102, 54, 30, 30, 54, 102, 198, 390, 0, 0, 0,
00109    0, 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 510, 0, 0, 0,
00110    0, 0, 390, 390, 462, 510, 510, 438, 438, 390, 390, 390, 0, 0, 0,
00111    0, 0, 390, 390, 398, 414, 438, 486, 454, 390, 390, 390, 0, 0, 0,
00112    0, 0, 252, 390, 390, 390, 390, 390, 390, 390, 390, 252, 0, 0, 0,
00113    0, 0, 254, 390, 390, 390, 254, 6, 6, 6, 6, 6, 0, 0, 0,
00114    0, 0, 252, 390, 390, 390, 390, 390, 390, 438, 486, 252, 384, 0, 0,
00115    0, 0, 254, 390, 390, 390, 254, 54, 102, 198, 390, 390, 0, 0, 0,
00116    0, 0, 252, 390, 6, 6, 252, 384, 384, 384, 390, 252, 0, 0, 0,
00117    0, 0, 510, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0,
00118    0, 0, 390, 390, 390, 390, 390, 390, 390, 390, 390, 252, 0, 0, 0,
00119    0, 0, 390, 390, 390, 204, 204, 204, 120, 120, 120, 48, 0, 0, 0,
00120    0, 0, 390, 390, 390, 390, 438, 438, 438, 438, 510, 204, 0, 0, 0,
00121    0, 0, 390, 390, 204, 120, 48, 48, 120, 204, 390, 390, 0, 0, 0,
00122    0, 0, 390, 390, 204, 120, 48, 48, 48, 48, 48, 48, 0, 0, 0,
00123    0, 0, 510, 384, 192, 96, 48, 24, 12, 6, 6, 510, 0, 0, 0,
00124    0, 0, 248, 24, 24, 24, 24, 24, 24, 24, 24, 248, 0, 0, 0,
00125    0, 0, 6, 12, 12, 24, 48, 48, 96, 192, 192, 384, 0, 0, 0,
00126    0, 0, 124, 96, 96, 96, 96, 96, 96, 96, 96, 124, 0, 0, 0,
00127    0, 0, 48, 120, 204, 390, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00128    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 511, 0, 0,
00129    0, 0, 60, 56, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00130    0, 0, 0, 0, 0, 252, 384, 384, 508, 390, 454, 508, 0, 0, 0,
00131    0, 0, 6, 6, 6, 254, 398, 390, 390, 390, 398, 254, 0, 0, 0,
00132    0, 0, 0, 0, 0, 252, 390, 6, 6, 6, 390, 252, 0, 0, 0,
00133    0, 0, 384, 384, 384, 508, 454, 390, 390, 390, 454, 508, 0, 0, 0,
00134    0, 0, 0, 0, 0, 252, 390, 390, 510, 6, 6, 252, 0, 0, 0,
00135    0, 0, 240, 408, 408, 24, 24, 126, 24, 24, 24, 24, 0, 0, 0,
00136    0, 0, 0, 0, 0, 508, 198, 198, 198, 124, 6, 252, 390, 390, 252,
00137    0, 0, 6, 6, 6, 254, 398, 390, 390, 390, 390, 390, 0, 0, 0,
00138    0, 0, 0, 48, 0, 56, 48, 48, 48, 48, 48, 252, 0, 0, 0,
00139    0, 0, 0, 192, 0, 240, 192, 192, 192, 192, 192, 198, 198, 198, 124,
00140    0, 0, 6, 6, 6, 390, 230, 62, 14, 62, 230, 390, 0, 0, 0,
00141    0, 0, 56, 48, 48, 48, 48, 48, 48, 48, 48, 252, 0, 0, 0,
00142    0, 0, 0, 0, 0, 254, 438, 438, 438, 438, 438, 390, 0, 0, 0,
00143    0, 0, 0, 0, 0, 254, 398, 390, 390, 390, 390, 390, 0, 0, 0,
00144    0, 0, 0, 0, 0, 252, 390, 390, 390, 390, 390, 252, 0, 0, 0,
00145    0, 0, 0, 0, 0, 254, 398, 390, 390, 390, 398, 254, 6, 6, 6,
00146    0, 0, 0, 0, 0, 508, 454, 390, 390, 390, 454, 508, 384, 384, 384,
00147    0, 0, 0, 0, 0, 246, 412, 396, 12, 12, 12, 12, 0, 0, 0,
00148    0, 0, 0, 0, 0, 252, 390, 6, 252, 384, 390, 252, 0, 0, 0,
00149    0, 0, 0, 24, 24, 254, 24, 24, 24, 24, 408, 240, 0, 0, 0,
00150    0, 0, 0, 0, 0, 198, 198, 198, 198, 198, 198, 508, 0, 0, 0,
00151    0, 0, 0, 0, 0, 390, 390, 204, 204, 120, 120, 48, 0, 0, 0,
00152    0, 0, 0, 0, 0, 390, 390, 438, 438, 438, 510, 204, 0, 0, 0,
00153    0, 0, 0, 0, 0, 390, 204, 120, 48, 120, 204, 390, 0, 0, 0,
00154    0, 0, 0, 0, 0, 198, 198, 198, 198, 198, 230, 252, 192, 198, 124,
00155    0, 0, 0, 0, 0, 510, 192, 96, 48, 24, 12, 510, 0, 0, 0,
00156    0, 0, 480, 48, 48, 96, 56, 56, 96, 48, 48, 480, 0, 0, 0,
00157    0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0,
00158    0, 0, 30, 48, 48, 24, 112, 112, 24, 48, 48, 30, 0, 0, 0,
00159    0, 0, 412, 438, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00160    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00161 };
00162 
00163 int gdFontMediumBoldData[] = {
00164    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00165    0, 0, 0, 0, 0, 12, 30, 63, 30, 12, 0, 0, 0,
00166    0, 0, 0, 51, 51, 12, 51, 51, 12, 51, 51, 0, 0,
00167    0, 27, 27, 31, 27, 27, 0, 60, 24, 24, 24, 24, 0,
00168    0, 15, 3, 7, 3, 3, 0, 60, 12, 28, 12, 12, 0,
00169    0, 14, 3, 3, 3, 14, 0, 28, 44, 28, 44, 44, 0,
00170    0, 3, 3, 3, 3, 15, 0, 60, 12, 28, 12, 12, 0,
00171    0, 0, 30, 51, 51, 30, 0, 0, 0, 0, 0, 0, 0,
00172    0, 0, 12, 12, 63, 63, 12, 12, 0, 63, 63, 0, 0,
00173    0, 51, 55, 63, 59, 51, 0, 12, 12, 12, 12, 60, 0,
00174    0, 51, 51, 18, 30, 12, 0, 60, 24, 24, 24, 24, 0,
00175    12, 12, 12, 12, 12, 12, 15, 15, 0, 0, 0, 0, 0,
00176    0, 0, 0, 0, 0, 0, 15, 15, 12, 12, 12, 12, 12,
00177    0, 0, 0, 0, 0, 0, 124, 124, 12, 12, 12, 12, 12,
00178    12, 12, 12, 12, 12, 12, 124, 124, 0, 0, 0, 0, 0,
00179    12, 12, 12, 12, 12, 12, 127, 127, 12, 12, 12, 12, 12,
00180    0, 0, 127, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00181    0, 0, 0, 0, 127, 127, 0, 0, 0, 0, 0, 0, 0,
00182    0, 0, 0, 0, 0, 0, 127, 127, 0, 0, 0, 0, 0,
00183    0, 0, 0, 0, 0, 0, 0, 0, 127, 127, 0, 0, 0,
00184    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 127, 0,
00185    12, 12, 12, 12, 12, 12, 124, 124, 12, 12, 12, 12, 12,
00186    12, 12, 12, 12, 12, 12, 15, 15, 12, 12, 12, 12, 12,
00187    12, 12, 12, 12, 12, 12, 127, 127, 0, 0, 0, 0, 0,
00188    0, 0, 0, 0, 0, 0, 127, 127, 12, 12, 12, 12, 12,
00189    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
00190    0, 0, 48, 24, 6, 3, 6, 24, 48, 63, 63, 0, 0,
00191    0, 0, 3, 6, 24, 48, 24, 6, 3, 63, 63, 0, 0,
00192    0, 0, 0, 0, 0, 63, 54, 54, 54, 55, 51, 0, 0,
00193    0, 0, 32, 48, 63, 63, 12, 63, 63, 3, 1, 0, 0,
00194    0, 0, 28, 54, 6, 6, 15, 6, 6, 54, 29, 0, 0,
00195    0, 0, 0, 0, 0, 0, 12, 12, 0, 0, 0, 0, 0,
00196    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00197    0, 0, 12, 12, 12, 12, 12, 12, 0, 12, 12, 0, 0,
00198    0, 0, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0,
00199    0, 0, 20, 20, 62, 62, 20, 62, 62, 20, 20, 0, 0,
00200    0, 0, 12, 30, 45, 13, 30, 44, 45, 30, 12, 0, 0,
00201    0, 0, 39, 53, 23, 24, 12, 6, 58, 43, 57, 0, 0,
00202    0, 0, 14, 27, 27, 27, 14, 43, 59, 27, 46, 0, 0,
00203    0, 0, 28, 28, 12, 6, 0, 0, 0, 0, 0, 0, 0,
00204    0, 0, 24, 12, 12, 6, 6, 6, 12, 12, 24, 0, 0,
00205    0, 0, 6, 12, 12, 24, 24, 24, 12, 12, 6, 0, 0,
00206    0, 0, 0, 0, 18, 12, 63, 63, 12, 18, 0, 0, 0,
00207    0, 0, 0, 0, 12, 12, 63, 63, 12, 12, 0, 0, 0,
00208    0, 0, 0, 0, 0, 0, 0, 0, 28, 28, 12, 6, 0,
00209    0, 0, 0, 0, 0, 0, 63, 63, 0, 0, 0, 0, 0,
00210    0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 30, 12, 0,
00211    0, 0, 48, 48, 24, 24, 12, 6, 6, 3, 3, 0, 0,
00212    0, 0, 12, 18, 51, 51, 51, 51, 51, 18, 12, 0, 0,
00213    0, 0, 12, 14, 13, 12, 12, 12, 12, 12, 63, 0, 0,
00214    0, 0, 30, 51, 51, 48, 28, 6, 3, 3, 63, 0, 0,
00215    0, 0, 30, 51, 48, 48, 28, 48, 48, 51, 30, 0, 0,
00216    0, 0, 48, 56, 60, 54, 51, 51, 63, 48, 48, 0, 0,
00217    0, 0, 63, 3, 3, 31, 51, 48, 48, 51, 30, 0, 0,
00218    0, 0, 30, 51, 3, 3, 31, 51, 51, 51, 30, 0, 0,
00219    0, 0, 63, 48, 48, 24, 24, 12, 12, 6, 6, 0, 0,
00220    0, 0, 30, 51, 51, 51, 30, 51, 51, 51, 30, 0, 0,
00221    0, 0, 30, 51, 51, 51, 62, 48, 48, 51, 30, 0, 0,
00222    0, 0, 0, 0, 12, 30, 12, 0, 0, 12, 30, 12, 0,
00223    0, 0, 0, 0, 12, 30, 12, 0, 28, 28, 12, 6, 0,
00224    0, 0, 48, 24, 12, 6, 3, 6, 12, 24, 48, 0, 0,
00225    0, 0, 0, 0, 63, 63, 0, 63, 63, 0, 0, 0, 0,
00226    0, 0, 3, 6, 12, 24, 48, 24, 12, 6, 3, 0, 0,
00227    0, 0, 30, 51, 51, 48, 28, 12, 0, 12, 12, 0, 0,
00228    0, 0, 30, 49, 49, 61, 53, 61, 1, 49, 30, 0, 0,
00229    0, 0, 30, 51, 51, 51, 63, 51, 51, 51, 51, 0, 0,
00230    0, 0, 31, 51, 51, 51, 31, 51, 51, 51, 31, 0, 0,
00231    0, 0, 30, 51, 3, 3, 3, 3, 3, 51, 30, 0, 0,
00232    0, 0, 31, 51, 51, 51, 51, 51, 51, 51, 31, 0, 0,
00233    0, 0, 63, 3, 3, 3, 31, 3, 3, 3, 63, 0, 0,
00234    0, 0, 63, 3, 3, 3, 31, 3, 3, 3, 3, 0, 0,
00235    0, 0, 30, 51, 3, 3, 59, 51, 51, 51, 62, 0, 0,
00236    0, 0, 51, 51, 51, 51, 63, 51, 51, 51, 51, 0, 0,
00237    0, 0, 63, 12, 12, 12, 12, 12, 12, 12, 63, 0, 0,
00238    0, 0, 48, 48, 48, 48, 48, 48, 48, 51, 30, 0, 0,
00239    0, 0, 35, 51, 27, 15, 7, 15, 27, 51, 35, 0, 0,
00240    0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 63, 0, 0,
00241    0, 0, 33, 51, 63, 63, 51, 51, 51, 51, 51, 0, 0,
00242    0, 0, 51, 51, 55, 55, 63, 59, 59, 51, 51, 0, 0,
00243    0, 0, 30, 51, 51, 51, 51, 51, 51, 51, 30, 0, 0,
00244    0, 0, 31, 51, 51, 51, 31, 3, 3, 3, 3, 0, 0,
00245    0, 0, 30, 51, 51, 51, 51, 51, 55, 59, 30, 48, 0,
00246    0, 0, 31, 51, 51, 51, 31, 15, 27, 51, 35, 0, 0,
00247    0, 0, 30, 51, 3, 3, 30, 48, 48, 51, 30, 0, 0,
00248    0, 0, 63, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0,
00249    0, 0, 51, 51, 51, 51, 51, 51, 51, 51, 30, 0, 0,
00250    0, 0, 51, 51, 51, 18, 18, 30, 12, 12, 12, 0, 0,
00251    0, 0, 51, 51, 51, 51, 51, 63, 63, 51, 33, 0, 0,
00252    0, 0, 33, 51, 18, 30, 12, 30, 18, 51, 33, 0, 0,
00253    0, 0, 51, 51, 30, 30, 12, 12, 12, 12, 12, 0, 0,
00254    0, 0, 63, 48, 48, 24, 12, 6, 3, 3, 63, 0, 0,
00255    0, 0, 30, 6, 6, 6, 6, 6, 6, 6, 30, 0, 0,
00256    0, 0, 3, 3, 6, 6, 12, 24, 24, 48, 48, 0, 0,
00257    0, 0, 30, 24, 24, 24, 24, 24, 24, 24, 30, 0, 0,
00258    0, 0, 12, 30, 51, 33, 0, 0, 0, 0, 0, 0, 0,
00259    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 63, 0,
00260    0, 0, 14, 14, 12, 24, 0, 0, 0, 0, 0, 0, 0,
00261    0, 0, 0, 0, 0, 30, 48, 62, 51, 51, 62, 0, 0,
00262    0, 0, 3, 3, 3, 31, 51, 51, 51, 51, 31, 0, 0,
00263    0, 0, 0, 0, 0, 30, 51, 3, 3, 51, 30, 0, 0,
00264    0, 0, 48, 48, 48, 62, 51, 51, 51, 51, 62, 0, 0,
00265    0, 0, 0, 0, 0, 30, 51, 63, 3, 51, 30, 0, 0,
00266    0, 0, 28, 54, 6, 6, 15, 6, 6, 6, 6, 0, 0,
00267    0, 0, 0, 0, 0, 46, 51, 51, 30, 3, 30, 51, 30,
00268    0, 0, 3, 3, 3, 31, 51, 51, 51, 51, 51, 0, 0,
00269    0, 0, 12, 12, 0, 14, 12, 12, 12, 12, 63, 0, 0,
00270    0, 0, 48, 48, 0, 48, 48, 48, 48, 48, 48, 51, 30,
00271    0, 0, 3, 3, 3, 51, 27, 15, 15, 27, 51, 0, 0,
00272    0, 0, 14, 12, 12, 12, 12, 12, 12, 12, 63, 0, 0,
00273    0, 0, 0, 0, 0, 27, 63, 63, 51, 51, 51, 0, 0,
00274    0, 0, 0, 0, 0, 31, 51, 51, 51, 51, 51, 0, 0,
00275    0, 0, 0, 0, 0, 30, 51, 51, 51, 51, 30, 0, 0,
00276    0, 0, 0, 0, 0, 31, 51, 51, 51, 31, 3, 3, 3,
00277    0, 0, 0, 0, 0, 62, 51, 51, 51, 62, 48, 48, 48,
00278    0, 0, 0, 0, 0, 31, 51, 3, 3, 3, 3, 0, 0,
00279    0, 0, 0, 0, 0, 30, 51, 6, 24, 51, 30, 0, 0,
00280    0, 0, 0, 3, 3, 15, 3, 3, 3, 51, 30, 0, 0,
00281    0, 0, 0, 0, 0, 51, 51, 51, 51, 51, 62, 0, 0,
00282    0, 0, 0, 0, 0, 51, 51, 51, 30, 30, 12, 0, 0,
00283    0, 0, 0, 0, 0, 51, 51, 51, 63, 63, 18, 0, 0,
00284    0, 0, 0, 0, 0, 51, 51, 30, 30, 51, 51, 0, 0,
00285    0, 0, 0, 0, 0, 51, 51, 51, 51, 62, 48, 51, 30,
00286    0, 0, 0, 0, 0, 63, 48, 24, 6, 3, 63, 0, 0,
00287    0, 0, 28, 6, 6, 12, 6, 12, 6, 6, 28, 0, 0,
00288    0, 0, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0,
00289    0, 0, 14, 24, 24, 12, 24, 12, 24, 24, 14, 0, 0,
00290    0, 0, 38, 63, 25, 0, 0, 0, 0, 0, 0, 0, 0,
00291    42, 20, 42, 20, 42, 20, 42, 20, 42, 20, 42, 20, 42,
00292 };
00293 
00294 int gdFontSmallData[] = {
00295    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00296    0, 0, 4, 4, 4, 4, 4, 0, 4, 0, 0, 0,
00297    0, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0,
00298    0, 0, 0, 10, 31, 10, 10, 31, 10, 0, 0, 0,
00299    0, 4, 14, 21, 5, 14, 20, 21, 14, 4, 0, 0,
00300    0, 0, 31, 19, 8, 4, 2, 25, 25, 0, 0, 0,
00301    0, 0, 2, 5, 5, 2, 21, 9, 22, 0, 0, 0,
00302    0, 6, 6, 3, 0, 0, 0, 0, 0, 0, 0, 0,
00303    0, 0, 16, 8, 4, 4, 4, 8, 16, 0, 0, 0,
00304    0, 0, 1, 2, 4, 4, 4, 2, 1, 0, 0, 0,
00305    0, 0, 4, 21, 14, 4, 14, 21, 4, 0, 0, 0,
00306    0, 0, 0, 4, 4, 31, 4, 4, 0, 0, 0, 0,
00307    0, 0, 0, 0, 0, 0, 0, 6, 6, 3, 0, 0,
00308    0, 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0,
00309    0, 0, 0, 0, 0, 0, 0, 6, 6, 0, 0, 0,
00310    0, 0, 0, 16, 8, 4, 2, 1, 0, 0, 0, 0,
00311    0, 0, 14, 17, 25, 21, 19, 17, 14, 0, 0, 0,
00312    0, 0, 4, 6, 4, 4, 4, 4, 14, 0, 0, 0,
00313    0, 0, 14, 17, 16, 8, 4, 2, 31, 0, 0, 0,
00314    0, 0, 14, 17, 16, 12, 16, 17, 14, 0, 0, 0,
00315    0, 0, 8, 12, 10, 9, 31, 8, 8, 0, 0, 0,
00316    0, 0, 31, 1, 15, 16, 16, 17, 14, 0, 0, 0,
00317    0, 0, 12, 2, 1, 15, 17, 17, 14, 0, 0, 0,
00318    0, 0, 31, 16, 8, 8, 4, 4, 4, 0, 0, 0,
00319    0, 0, 14, 17, 17, 14, 17, 17, 14, 0, 0, 0,
00320    0, 0, 14, 17, 17, 30, 16, 8, 6, 0, 0, 0,
00321    0, 0, 0, 0, 6, 6, 0, 6, 6, 0, 0, 0,
00322    0, 0, 0, 0, 6, 6, 0, 6, 6, 3, 0, 0,
00323    0, 0, 0, 8, 4, 2, 4, 8, 0, 0, 0, 0,
00324    0, 0, 0, 0, 31, 0, 31, 0, 0, 0, 0, 0,
00325    0, 0, 0, 2, 4, 8, 4, 2, 0, 0, 0, 0,
00326    0, 0, 14, 17, 8, 4, 4, 0, 4, 0, 0, 0,
00327    0, 0, 14, 17, 29, 21, 29, 1, 14, 0, 0, 0,
00328    0, 0, 14, 17, 17, 31, 17, 17, 17, 0, 0, 0,
00329    0, 0, 15, 17, 17, 15, 17, 17, 15, 0, 0, 0,
00330    0, 0, 14, 17, 1, 1, 1, 17, 14, 0, 0, 0,
00331    0, 0, 15, 18, 18, 18, 18, 18, 15, 0, 0, 0,
00332    0, 0, 31, 1, 1, 15, 1, 1, 31, 0, 0, 0,
00333    0, 0, 31, 1, 1, 15, 1, 1, 1, 0, 0, 0,
00334    0, 0, 14, 17, 1, 1, 25, 17, 14, 0, 0, 0,
00335    0, 0, 17, 17, 17, 31, 17, 17, 17, 0, 0, 0,
00336    0, 0, 14, 4, 4, 4, 4, 4, 14, 0, 0, 0,
00337    0, 0, 16, 16, 16, 16, 16, 17, 14, 0, 0, 0,
00338    0, 0, 17, 9, 5, 3, 5, 9, 17, 0, 0, 0,
00339    0, 0, 1, 1, 1, 1, 1, 1, 31, 0, 0, 0,
00340    0, 0, 17, 27, 21, 17, 17, 17, 17, 0, 0, 0,
00341    0, 0, 17, 17, 19, 21, 25, 17, 17, 0, 0, 0,
00342    0, 0, 14, 17, 17, 17, 17, 17, 14, 0, 0, 0,
00343    0, 0, 15, 17, 17, 15, 1, 1, 1, 0, 0, 0,
00344    0, 0, 14, 17, 17, 17, 21, 9, 22, 0, 0, 0,
00345    0, 0, 15, 17, 17, 15, 5, 9, 17, 0, 0, 0,
00346    0, 0, 14, 17, 1, 14, 16, 17, 14, 0, 0, 0,
00347    0, 0, 31, 4, 4, 4, 4, 4, 4, 0, 0, 0,
00348    0, 0, 17, 17, 17, 17, 17, 17, 14, 0, 0, 0,
00349    0, 0, 17, 17, 17, 17, 10, 10, 4, 0, 0, 0,
00350    0, 0, 17, 17, 17, 17, 21, 27, 17, 0, 0, 0,
00351    0, 0, 17, 17, 10, 4, 10, 17, 17, 0, 0, 0,
00352    0, 0, 17, 17, 10, 4, 4, 4, 4, 0, 0, 0,
00353    0, 0, 31, 16, 8, 31, 2, 1, 31, 0, 0, 0,
00354    0, 28, 4, 4, 4, 4, 4, 4, 4, 28, 0, 0,
00355    0, 0, 0, 1, 2, 4, 8, 16, 0, 0, 0, 0,
00356    0, 7, 4, 4, 4, 4, 4, 4, 4, 7, 0, 0,
00357    0, 4, 10, 17, 0, 0, 0, 0, 0, 0, 0, 0,
00358    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0,
00359    0, 12, 12, 24, 0, 0, 0, 0, 0, 0, 0, 0,
00360    0, 0, 0, 0, 14, 16, 30, 17, 30, 0, 0, 0,
00361    0, 0, 1, 1, 15, 17, 17, 17, 15, 0, 0, 0,
00362    0, 0, 0, 0, 14, 17, 1, 1, 30, 0, 0, 0,
00363    0, 0, 16, 16, 30, 17, 17, 17, 30, 0, 0, 0,
00364    0, 0, 0, 0, 14, 17, 15, 1, 14, 0, 0, 0,
00365    0, 0, 12, 18, 2, 7, 2, 2, 2, 0, 0, 0,
00366    0, 0, 0, 0, 14, 17, 17, 17, 30, 16, 14, 0,
00367    0, 0, 1, 1, 15, 17, 17, 17, 17, 0, 0, 0,
00368    0, 0, 0, 4, 0, 4, 4, 4, 4, 0, 0, 0,
00369    0, 0, 0, 16, 0, 16, 16, 16, 16, 17, 14, 0,
00370    0, 0, 1, 1, 17, 9, 7, 9, 17, 0, 0, 0,
00371    0, 0, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0,
00372    0, 0, 0, 0, 11, 21, 21, 21, 21, 0, 0, 0,
00373    0, 0, 0, 0, 13, 19, 17, 17, 17, 0, 0, 0,
00374    0, 0, 0, 0, 14, 17, 17, 17, 14, 0, 0, 0,
00375    0, 0, 0, 0, 15, 17, 17, 17, 15, 1, 1, 0,
00376    0, 0, 0, 0, 14, 17, 17, 17, 30, 16, 16, 0,
00377    0, 0, 0, 0, 13, 19, 1, 1, 1, 0, 0, 0,
00378    0, 0, 0, 0, 30, 1, 14, 16, 15, 0, 0, 0,
00379    0, 0, 4, 4, 31, 4, 4, 4, 24, 0, 0, 0,
00380    0, 0, 0, 0, 17, 17, 17, 17, 14, 0, 0, 0,
00381    0, 0, 0, 0, 17, 17, 17, 10, 4, 0, 0, 0,
00382    0, 0, 0, 0, 17, 17, 21, 21, 10, 0, 0, 0,
00383    0, 0, 0, 0, 17, 10, 4, 10, 17, 0, 0, 0,
00384    0, 0, 0, 0, 17, 17, 17, 10, 4, 2, 1, 0,
00385    0, 0, 0, 0, 31, 8, 14, 2, 31, 0, 0, 0,
00386    0, 16, 8, 8, 8, 4, 8, 8, 8, 16, 0, 0,
00387    0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0,
00388    0, 1, 2, 2, 2, 4, 2, 2, 2, 1, 0, 0,
00389    0, 22, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00390    0, 0, 1, 1, 15, 17, 17, 17, 15, 0, 0, 0,
00391 };
00392 
00393 gdFont gdFontGiantRep = {
00394    128, 0, 9, 15,
00395    gdFontGiantData
00396 };
00397 
00398 gdFont gdFontMediumBoldRep = {
00399    128, 0, 7, 13,
00400    gdFontMediumBoldData
00401 };
00402 
00403 gdFont gdFontSmallRep = {
00404    96, 32, 6, 12,
00405    gdFontSmallData
00406 };
00407 
00408 gdFontPtr gdFontMediumBold = &gdFontMediumBoldRep;
00409 gdFontPtr gdFontGiant = &gdFontGiantRep;
00410 gdFontPtr gdFontSmall = &gdFontSmallRep;
00411 
00412 /*------------------------------------------------------------------*/
00413 
00414 static void gdImageBrushApply(gdImagePtr im, int x, int y);
00415 static void gdImageTileApply(gdImagePtr im, int x, int y);
00416 
00417 gdImagePtr gdImageCreate(int sx, int sy)
00418 {
00419    int i;
00420    gdImagePtr im;
00421    im = (gdImage *) M_MALLOC(sizeof(gdImage));
00422    im->pixels = (unsigned char **) M_MALLOC(sizeof(unsigned char *) * sx);
00423    im->polyInts = 0;
00424    im->polyAllocated = 0;
00425    im->brush = 0;
00426    im->tile = 0;
00427    im->style = 0;
00428    for (i = 0; (i < sx); i++) {
00429       im->pixels[i] = (unsigned char *) M_CALLOC(sy, sizeof(unsigned char));
00430    }
00431    im->sx = sx;
00432    im->sy = sy;
00433    im->colorsTotal = 0;
00434    im->transparent = (-1);
00435    im->interlace = 0;
00436    return im;
00437 }
00438 
00439 void gdImageDestroy(gdImagePtr im)
00440 {
00441    int i;
00442    for (i = 0; (i < im->sx); i++) {
00443       M_FREE(im->pixels[i]);
00444    }
00445    M_FREE(im->pixels);
00446    if (im->polyInts) {
00447       M_FREE(im->polyInts);
00448    }
00449    if (im->style) {
00450       M_FREE(im->style);
00451    }
00452    M_FREE(im);
00453 }
00454 
00455 int gdImageColorClosest(gdImagePtr im, int r, int g, int b)
00456 {
00457    int i;
00458    long rd, gd, bd;
00459    int ct = (-1);
00460    long mindist = 0;
00461    for (i = 0; (i < (im->colorsTotal)); i++) {
00462       long dist;
00463       if (im->open[i]) {
00464          continue;
00465       }
00466       rd = (im->red[i] - r);
00467       gd = (im->green[i] - g);
00468       bd = (im->blue[i] - b);
00469       dist = rd * rd + gd * gd + bd * bd;
00470       if ((i == 0) || (dist < mindist)) {
00471          mindist = dist;
00472          ct = i;
00473       }
00474    }
00475    return ct;
00476 }
00477 
00478 int gdImageColorExact(gdImagePtr im, int r, int g, int b)
00479 {
00480    int i;
00481    for (i = 0; (i < (im->colorsTotal)); i++) {
00482       if (im->open[i]) {
00483          continue;
00484       }
00485       if ((im->red[i] == r) && (im->green[i] == g) && (im->blue[i] == b)) {
00486          return i;
00487       }
00488    }
00489    return -1;
00490 }
00491 
00492 int gdImageColorAllocate(gdImagePtr im, int r, int g, int b)
00493 {
00494    int i;
00495    int ct = (-1);
00496    
00497    /* check if color exists already */
00498    for (i = 0; (i < (im->colorsTotal)); i++) {
00499       if (!im->open[i] &&
00500           im->red[i] == r &&
00501           im->green[i] == g &&
00502           im->blue[i] == b) {
00503          return i;
00504       }
00505    }
00506    
00507    for (i = 0; (i < (im->colorsTotal)); i++) {
00508       if (im->open[i]) {
00509          ct = i;
00510          break;
00511       }
00512    }
00513    if (ct == (-1)) {
00514       ct = im->colorsTotal;
00515       if (ct == gdMaxColors) {
00516          return -1;
00517       }
00518       im->colorsTotal++;
00519    }
00520    im->red[ct] = r;
00521    im->green[ct] = g;
00522    im->blue[ct] = b;
00523    im->open[ct] = 0;
00524    return ct;
00525 }
00526 
00527 void gdImageColorDeallocate(gdImagePtr im, int color)
00528 {
00529    /* Mark it open. */
00530    im->open[color] = 1;
00531 }
00532 
00533 void gdImageColorTransparent(gdImagePtr im, int color)
00534 {
00535    im->transparent = color;
00536 }
00537 
00538 void gdImageSetPixel(gdImagePtr im, int x, int y, int color)
00539 {
00540    int p;
00541    switch (color) {
00542    case gdStyled:
00543       if (!im->style) {
00544          /* Refuse to draw if no style is set. */
00545          return;
00546       } else {
00547          p = im->style[im->stylePos++];
00548       }
00549       if (p != (gdTransparent)) {
00550          gdImageSetPixel(im, x, y, p);
00551       }
00552       im->stylePos = im->stylePos % im->styleLength;
00553       break;
00554    case gdStyledBrushed:
00555       if (!im->style) {
00556          /* Refuse to draw if no style is set. */
00557          return;
00558       }
00559       p = im->style[im->stylePos++];
00560       if ((p != gdTransparent) && (p != 0)) {
00561          gdImageSetPixel(im, x, y, gdBrushed);
00562       }
00563       im->stylePos = im->stylePos % im->styleLength;
00564       break;
00565    case gdBrushed:
00566       gdImageBrushApply(im, x, y);
00567       break;
00568    case gdTiled:
00569       gdImageTileApply(im, x, y);
00570       break;
00571    default:
00572       if (gdImageBoundsSafe(im, x, y)) {
00573          im->pixels[x][y] = color;
00574       }
00575       break;
00576    }
00577 }
00578 
00579 static void gdImageBrushApply(gdImagePtr im, int x, int y)
00580 {
00581    int lx, ly;
00582    int hy;
00583    int hx;
00584    int x1, y1, x2, y2;
00585    int srcx, srcy;
00586    if (!im->brush) {
00587       return;
00588    }
00589    hy = gdImageSY(im->brush) / 2;
00590    y1 = y - hy;
00591    y2 = y1 + gdImageSY(im->brush);
00592    hx = gdImageSX(im->brush) / 2;
00593    x1 = x - hx;
00594    x2 = x1 + gdImageSX(im->brush);
00595    srcy = 0;
00596    for (ly = y1; (ly < y2); ly++) {
00597       srcx = 0;
00598       for (lx = x1; (lx < x2); lx++) {
00599          int p;
00600          p = gdImageGetPixel(im->brush, srcx, srcy);
00601          /* Allow for non-square brushes! */
00602          if (p != gdImageGetTransparent(im->brush)) {
00603             gdImageSetPixel(im, lx, ly, im->brushColorMap[p]);
00604          }
00605          srcx++;
00606       }
00607       srcy++;
00608    }
00609 }
00610 
00611 static void gdImageTileApply(gdImagePtr im, int x, int y)
00612 {
00613    int srcx, srcy;
00614    int p;
00615    if (!im->tile) {
00616       return;
00617    }
00618    srcx = x % gdImageSX(im->tile);
00619    srcy = y % gdImageSY(im->tile);
00620    p = gdImageGetPixel(im->tile, srcx, srcy);
00621    /* Allow for transparency */
00622    if (p != gdImageGetTransparent(im->tile)) {
00623       gdImageSetPixel(im, x, y, im->tileColorMap[p]);
00624    }
00625 }
00626 
00627 int gdImageGetPixel(gdImagePtr im, int x, int y)
00628 {
00629    if (gdImageBoundsSafe(im, x, y)) {
00630       return im->pixels[x][y];
00631    } else {
00632       return 0;
00633    }
00634 }
00635 
00636 /* Bresenham as presented in Foley & Van Dam */
00637 
00638 void gdImageLine(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
00639 {
00640    int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
00641    dx = abs(x2 - x1);
00642    dy = abs(y2 - y1);
00643    if (dy <= dx) {
00644       d = 2 * dy - dx;
00645       incr1 = 2 * dy;
00646       incr2 = 2 * (dy - dx);
00647       if (x1 > x2) {
00648          x = x2;
00649          y = y2;
00650          ydirflag = (-1);
00651          xend = x1;
00652       } else {
00653          x = x1;
00654          y = y1;
00655          ydirflag = 1;
00656          xend = x2;
00657       }
00658       gdImageSetPixel(im, x, y, color);
00659       if (((y2 - y1) * ydirflag) > 0) {
00660          while (x < xend) {
00661             x++;
00662             if (d < 0) {
00663                d += incr1;
00664             } else {
00665                y++;
00666                d += incr2;
00667             }
00668             gdImageSetPixel(im, x, y, color);
00669          }
00670       } else {
00671          while (x < xend) {
00672             x++;
00673             if (d < 0) {
00674                d += incr1;
00675             } else {
00676                y--;
00677                d += incr2;
00678             }
00679             gdImageSetPixel(im, x, y, color);
00680          }
00681       }
00682    } else {
00683       d = 2 * dx - dy;
00684       incr1 = 2 * dx;
00685       incr2 = 2 * (dx - dy);
00686       if (y1 > y2) {
00687          y = y2;
00688          x = x2;
00689          yend = y1;
00690          xdirflag = (-1);
00691       } else {
00692          y = y1;
00693          x = x1;
00694          yend = y2;
00695          xdirflag = 1;
00696       }
00697       gdImageSetPixel(im, x, y, color);
00698       if (((x2 - x1) * xdirflag) > 0) {
00699          while (y < yend) {
00700             y++;
00701             if (d < 0) {
00702                d += incr1;
00703             } else {
00704                x++;
00705                d += incr2;
00706             }
00707             gdImageSetPixel(im, x, y, color);
00708          }
00709       } else {
00710          while (y < yend) {
00711             y++;
00712             if (d < 0) {
00713                d += incr1;
00714             } else {
00715                x--;
00716                d += incr2;
00717             }
00718             gdImageSetPixel(im, x, y, color);
00719          }
00720       }
00721    }
00722 }
00723 
00724 /* As above, plus dashing */
00725 
00726 #define dashedSet \
00727         { \
00728                 dashStep++; \
00729                 if (dashStep == gdDashSize) { \
00730                         dashStep = 0; \
00731                         on = !on; \
00732                 } \
00733                 if (on) { \
00734                         gdImageSetPixel(im, x, y, color); \
00735                 } \
00736         }
00737 
00738 void gdImageDashedLine(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
00739 {
00740    int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
00741    int dashStep = 0;
00742    int on = 1;
00743    dx = abs(x2 - x1);
00744    dy = abs(y2 - y1);
00745    if (dy <= dx) {
00746       d = 2 * dy - dx;
00747       incr1 = 2 * dy;
00748       incr2 = 2 * (dy - dx);
00749       if (x1 > x2) {
00750          x = x2;
00751          y = y2;
00752          ydirflag = (-1);
00753          xend = x1;
00754       } else {
00755          x = x1;
00756          y = y1;
00757          ydirflag = 1;
00758          xend = x2;
00759       }
00760       dashedSet;
00761       if (((y2 - y1) * ydirflag) > 0) {
00762          while (x < xend) {
00763             x++;
00764             if (d < 0) {
00765                d += incr1;
00766             } else {
00767                y++;
00768                d += incr2;
00769             }
00770             dashedSet;
00771          }
00772       } else {
00773          while (x < xend) {
00774             x++;
00775             if (d < 0) {
00776                d += incr1;
00777             } else {
00778                y--;
00779                d += incr2;
00780             }
00781             dashedSet;
00782          }
00783       }
00784    } else {
00785       d = 2 * dx - dy;
00786       incr1 = 2 * dx;
00787       incr2 = 2 * (dx - dy);
00788       if (y1 > y2) {
00789          y = y2;
00790          x = x2;
00791          yend = y1;
00792          xdirflag = (-1);
00793       } else {
00794          y = y1;
00795          x = x1;
00796          yend = y2;
00797          xdirflag = 1;
00798       }
00799       dashedSet;
00800       if (((x2 - x1) * xdirflag) > 0) {
00801          while (y < yend) {
00802             y++;
00803             if (d < 0) {
00804                d += incr1;
00805             } else {
00806                x++;
00807                d += incr2;
00808             }
00809             dashedSet;
00810          }
00811       } else {
00812          while (y < yend) {
00813             y++;
00814             if (d < 0) {
00815                d += incr1;
00816             } else {
00817                x--;
00818                d += incr2;
00819             }
00820             dashedSet;
00821          }
00822       }
00823    }
00824 }
00825 
00826 int gdImageBoundsSafe(gdImagePtr im, int x, int y)
00827 {
00828    return (!(((y < 0) || (y >= im->sy)) || ((x < 0) || (x >= im->sx))));
00829 }
00830 
00831 void gdImageChar(gdImagePtr im, gdFontPtr f, int x, int y, int c, int color)
00832 {
00833    int cx, cy;
00834    int px, py;
00835    int fline;
00836    cx = 0;
00837    cy = 0;
00838    if ((c < f->offset) || (c >= (f->offset + f->nchars))) {
00839       return;
00840    }
00841    fline = (c - f->offset) * f->h;
00842    for (py = y; (py < (y + f->h)); py++) {
00843       for (px = x; (px < (x + f->w)); px++) {
00844          if (f->data[fline + cy] & (1 << cx)) {
00845             gdImageSetPixel(im, px, py, color);
00846          }
00847          cx++;
00848       }
00849       cx = 0;
00850       cy++;
00851    }
00852 }
00853 
00854 void gdImageCharUp(gdImagePtr im, gdFontPtr f, int x, int y, char c, int color)
00855 {
00856    int cx, cy;
00857    int px, py;
00858    int fline;
00859    cx = 0;
00860    cy = 0;
00861    if ((c < f->offset) || (c >= (f->offset + f->nchars))) {
00862       return;
00863    }
00864    fline = (c - f->offset) * f->h;
00865    for (py = y; (py > (y - f->w)); py--) {
00866       for (px = x; (px < (x + f->h)); px++) {
00867          if (f->data[fline + cy] & (1 << cx)) {
00868             gdImageSetPixel(im, px, py, color);
00869          }
00870          cy++;
00871       }
00872       cy = 0;
00873       cx++;
00874    }
00875 }
00876 
00877 void gdImageString(gdImagePtr im, gdFontPtr f, int x, int y, char *s, int color)
00878 {
00879    int i;
00880    int l;
00881    l = strlen(s);
00882    for (i = 0; (i < l); i++) {
00883       gdImageChar(im, f, x, y, s[i], color);
00884       x += f->w;
00885    }
00886 }
00887 
00888 void gdImageStringUp(gdImagePtr im, gdFontPtr f, int x, int y, char *s, int color)
00889 {
00890    int i;
00891    int l;
00892    l = strlen(s);
00893    for (i = 0; (i < l); i++) {
00894       gdImageCharUp(im, f, x, y, s[i], color);
00895       y -= f->w;
00896    }
00897 }
00898 
00899 void gdImageFillToBorder(gdImagePtr im, int x, int y, int border, int color)
00900 {
00901    int lastBorder;
00902    /* Seek left */
00903    int leftLimit, rightLimit;
00904    int i;
00905    leftLimit = (-1);
00906    if (border < 0) {
00907       /* Refuse to fill to a non-solid border */
00908       return;
00909    }
00910    for (i = x; (i >= 0); i--) {
00911       if (gdImageGetPixel(im, i, y) == border) {
00912          break;
00913       }
00914       gdImageSetPixel(im, i, y, color);
00915       leftLimit = i;
00916    }
00917    if (leftLimit == (-1)) {
00918       return;
00919    }
00920    /* Seek right */
00921    rightLimit = x;
00922    for (i = (x + 1); (i < im->sx); i++) {
00923       if (gdImageGetPixel(im, i, y) == border) {
00924          break;
00925       }
00926       gdImageSetPixel(im, i, y, color);
00927       rightLimit = i;
00928    }
00929    /* Look at lines above and below and start paints */
00930    /* Above */
00931    if (y > 0) {
00932       lastBorder = 1;
00933       for (i = leftLimit; (i <= rightLimit); i++) {
00934          int c;
00935          c = gdImageGetPixel(im, i, y - 1);
00936          if (lastBorder) {
00937             if ((c != border) && (c != color)) {
00938                gdImageFillToBorder(im, i, y - 1, border, color);
00939                lastBorder = 0;
00940             }
00941          } else if ((c == border) || (c == color)) {
00942             lastBorder = 1;
00943          }
00944       }
00945    }
00946    /* Below */
00947    if (y < ((im->sy) - 1)) {
00948       lastBorder = 1;
00949       for (i = leftLimit; (i <= rightLimit); i++) {
00950          int c;
00951          c = gdImageGetPixel(im, i, y + 1);
00952          if (lastBorder) {
00953             if ((c != border) && (c != color)) {
00954                gdImageFillToBorder(im, i, y + 1, border, color);
00955                lastBorder = 0;
00956             }
00957          } else if ((c == border) || (c == color)) {
00958             lastBorder = 1;
00959          }
00960       }
00961    }
00962 }
00963 
00964 void gdImageFill(gdImagePtr im, int x, int y, int color)
00965 {
00966    int lastBorder;
00967    int old;
00968    int leftLimit, rightLimit;
00969    int i;
00970    old = gdImageGetPixel(im, x, y);
00971    if (color == gdTiled) {
00972       /* Tile fill -- got to watch out! */
00973       int p, tileColor;
00974       int srcx, srcy;
00975       if (!im->tile) {
00976          return;
00977       }
00978       /* Refuse to flood-fill with a transparent pattern --
00979          I can't do it without allocating another image */
00980       if (gdImageGetTransparent(im->tile) != (-1)) {
00981          return;
00982       }
00983       srcx = x % gdImageSX(im->tile);
00984       srcy = y % gdImageSY(im->tile);
00985       p = gdImageGetPixel(im->tile, srcx, srcy);
00986       tileColor = im->tileColorMap[p];
00987       if (old == tileColor) {
00988          /* Nothing to be done */
00989          return;
00990       }
00991    } else {
00992       if (old == color) {
00993          /* Nothing to be done */
00994          return;
00995       }
00996    }
00997    /* Seek left */
00998    leftLimit = (-1);
00999    for (i = x; (i >= 0); i--) {
01000       if (gdImageGetPixel(im, i, y) != old) {
01001          break;
01002       }
01003       gdImageSetPixel(im, i, y, color);
01004       leftLimit = i;
01005    }
01006    if (leftLimit == (-1)) {
01007       return;
01008    }
01009    /* Seek right */
01010    rightLimit = x;
01011    for (i = (x + 1); (i < im->sx); i++) {
01012       if (gdImageGetPixel(im, i, y) != old) {
01013          break;
01014       }
01015       gdImageSetPixel(im, i, y, color);
01016       rightLimit = i;
01017    }
01018    /* Look at lines above and below and start paints */
01019    /* Above */
01020    if (y > 0) {
01021       lastBorder = 1;
01022       for (i = leftLimit; (i <= rightLimit); i++) {
01023          int c;
01024          c = gdImageGetPixel(im, i, y - 1);
01025          if (lastBorder) {
01026             if (c == old) {
01027                gdImageFill(im, i, y - 1, color);
01028                lastBorder = 0;
01029             }
01030          } else if (c != old) {
01031             lastBorder = 1;
01032          }
01033       }
01034    }
01035    /* Below */
01036    if (y < ((im->sy) - 1)) {
01037       lastBorder = 1;
01038       for (i = leftLimit; (i <= rightLimit); i++) {
01039          int c;
01040          c = gdImageGetPixel(im, i, y + 1);
01041          if (lastBorder) {
01042             if (c == old) {
01043                gdImageFill(im, i, y + 1, color);
01044                lastBorder = 0;
01045             }
01046          } else if (c != old) {
01047             lastBorder = 1;
01048          }
01049       }
01050    }
01051 }
01052 
01053 #ifdef TEST_CODE
01054 void gdImageDump(gdImagePtr im)
01055 {
01056    int i, j;
01057    for (i = 0; (i < im->sy); i++) {
01058       for (j = 0; (j < im->sx); j++) {
01059          printf("%d", im->pixels[j][i]);
01060       }
01061       printf("\n");
01062    }
01063 }
01064 #endif
01065 
01066 /* Code drawn from ppmtogif.c, from the pbmplus package
01067 **
01068 ** Based on GIFENCOD by David Rowley <mgardi@watdscu.waterloo.edu>. A
01069 ** Lempel-Zim compression based on "compress".
01070 **
01071 ** Modified by Marcel Wijkstra <wijkstra@fwi.uva.nl>
01072 **
01073 ** Copyright (C) 1989 by Jef Poskanzer.
01074 **
01075 ** Permission to use, copy, modify, and distribute this software and its
01076 ** documentation for any purpose and without fee is hereby granted, provided
01077 ** that the above copyright notice appear in all copies and that both that
01078 ** copyright notice and this permission notice appear in supporting
01079 ** documentation.  This software is provided "as is" without express or
01080 ** implied warranty.
01081 **
01082 ** The Graphics Interchange Format(c) is the Copyright property of
01083 ** CompuServe Incorporated.  GIF(sm) is a Service Mark property of
01084 ** CompuServe Incorporated.
01085 */
01086 
01087 /*
01088  * a code_int must be able to hold 2**GIFBITS values of type int, and also -1
01089  */
01090 typedef int code_int;
01091 
01092 #ifdef SIGNED_COMPARE_SLOW
01093 typedef unsigned long int count_int;
01094 typedef unsigned short int count_short;
01095 #else                           /*SIGNED_COMPARE_SLOW */
01096 typedef long int count_int;
01097 #endif                          /*SIGNED_COMPARE_SLOW */
01098 
01099 static int colorstobpp(int colors);
01100 static void BumpPixel(void);
01101 static int GIFNextPixel(gdImagePtr im);
01102 static void GIFEncode(gdGifBuffer * buffer, int GWidth, int GHeight, int GInterlace,
01103                       int Background, int Transparent, int BitsPerPixel, int *Red,
01104                       int *Green, int *Blue, gdImagePtr im);
01105 static void Putword(int w, gdGifBuffer * buffer);
01106 static void compress(int init_bits, gdGifBuffer * buffer, gdImagePtr im);
01107 static void output(code_int code);
01108 static void cl_block(void);
01109 static void cl_hash(register count_int hsize);
01110 static void char_init(void);
01111 static void char_out(int c);
01112 static void flush_char(void);
01113 /* Allows for reuse */
01114 static void init_statics(void);
01115 
01116 char gif_buffer[500000];
01117 
01118 void gdImageGif(gdImagePtr im, gdGifBuffer * buffer)
01119 {
01120    int interlace, transparent, BitsPerPixel;
01121    interlace = im->interlace;
01122    transparent = im->transparent;
01123 
01124    /* allocate buffer */
01125    buffer->size = 0;
01126    buffer->data = gif_buffer;
01127 
01128    BitsPerPixel = colorstobpp(im->colorsTotal);
01129    /* Clear any old values in statics strewn through the GIF code */
01130    init_statics();
01131    /* All set, let's do it. */
01132    GIFEncode(buffer, im->sx, im->sy, interlace, 0, transparent, BitsPerPixel,
01133              im->red, im->green, im->blue, im);
01134 }
01135 
01136 static int colorstobpp(int colors)
01137 {
01138    int bpp = 0;
01139 
01140    if (colors <= 2)
01141       bpp = 1;
01142    else if (colors <= 4)
01143       bpp = 2;
01144    else if (colors <= 8)
01145       bpp = 3;
01146    else if (colors <= 16)
01147       bpp = 4;
01148    else if (colors <= 32)
01149       bpp = 5;
01150    else if (colors <= 64)
01151       bpp = 6;
01152    else if (colors <= 128)
01153       bpp = 7;
01154    else if (colors <= 256)
01155       bpp = 8;
01156    return bpp;
01157 }
01158 
01159 /*****************************************************************************
01160  *
01161  * GIFENCODE.C    - GIF Image compression interface
01162  *
01163  * GIFEncode( FName, GHeight, GWidth, GInterlace, Background, Transparent,
01164  *            BitsPerPixel, Red, Green, Blue, gdImagePtr )
01165  *
01166  *****************************************************************************/
01167 
01168 #define TRUE 1
01169 #define FALSE 0
01170 
01171 static int Width, Height;
01172 static int curx, cury;
01173 static long CountDown;
01174 static int Pass = 0;
01175 static int Interlace;
01176 
01177 /*
01178  * Bump the 'curx' and 'cury' to point to the next pixel
01179  */
01180 static void BumpPixel(void)
01181 {
01182    /*
01183     * Bump the current X position
01184     */
01185    ++curx;
01186 
01187    /*
01188     * If we are at the end of a scan line, set curx back to the beginning
01189     * If we are interlaced, bump the cury to the appropriate spot,
01190     * otherwise, just increment it.
01191     */
01192    if (curx == Width) {
01193       curx = 0;
01194 
01195       if (!Interlace)
01196          ++cury;
01197       else {
01198          switch (Pass) {
01199 
01200          case 0:
01201             cury += 8;
01202             if (cury >= Height) {
01203                ++Pass;
01204                cury = 4;
01205             }
01206             break;
01207 
01208          case 1:
01209             cury += 8;
01210             if (cury >= Height) {
01211                ++Pass;
01212                cury = 2;
01213             }
01214             break;
01215 
01216          case 2:
01217             cury += 4;
01218             if (cury >= Height) {
01219                ++Pass;
01220                cury = 1;
01221             }
01222             break;
01223 
01224          case 3:
01225             cury += 2;
01226             break;
01227          }
01228       }
01229    }
01230 }
01231 
01232 /*
01233  * Return the next pixel from the image
01234  */
01235 static int GIFNextPixel(gdImagePtr im)
01236 {
01237    int r;
01238 
01239    if (CountDown == 0)
01240       return EOF;
01241 
01242    --CountDown;
01243 
01244    r = gdImageGetPixel(im, curx, cury);
01245 
01246    BumpPixel();
01247 
01248    return r;
01249 }
01250 
01251 /* public */
01252 
01253 void bputc(int c, gdGifBuffer * buffer)
01254 {
01255    buffer->data[buffer->size++] = (unsigned char) c;
01256 }
01257 
01258 static void
01259 GIFEncode(gdGifBuffer * buffer, int GWidth, int GHeight, int GInterlace, int Background,
01260           int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue,
01261           gdImagePtr im)
01262 {
01263    int B;
01264    int RWidth, RHeight;
01265    int LeftOfs, TopOfs;
01266    int Resolution;
01267    int ColorMapSize;
01268    int InitCodeSize;
01269    int i;
01270 
01271    Interlace = GInterlace;
01272 
01273    ColorMapSize = 1 << BitsPerPixel;
01274 
01275    RWidth = Width = GWidth;
01276    RHeight = Height = GHeight;
01277    LeftOfs = TopOfs = 0;
01278 
01279    Resolution = BitsPerPixel;
01280 
01281    /*
01282     * Calculate number of bits we are expecting
01283     */
01284    CountDown = (long) Width *(long) Height;
01285 
01286    /*
01287     * Indicate which pass we are on (if interlace)
01288     */
01289    Pass = 0;
01290 
01291    /*
01292     * The initial code size
01293     */
01294    if (BitsPerPixel <= 1)
01295       InitCodeSize = 2;
01296    else
01297       InitCodeSize = BitsPerPixel;
01298 
01299    /*
01300     * Set up the current x and y position
01301     */
01302    curx = cury = 0;
01303 
01304    /*
01305     * Write the Magic header
01306     */
01307    memcpy(buffer->data + buffer->size, Transparent < 0 ? "GIF87a" : "GIF89a", 6);
01308    buffer->size += 6;
01309 
01310    /*
01311     * Write out the screen width and height
01312     */
01313    Putword(RWidth, buffer);
01314    Putword(RHeight, buffer);
01315 
01316    /*
01317     * Indicate that there is a global colour map
01318     */
01319    B = 0x80;                    /* Yes, there is a color map */
01320 
01321    /*
01322     * OR in the resolution
01323     */
01324    B |= (Resolution - 1) << 5;
01325 
01326    /*
01327     * OR in the Bits per Pixel
01328     */
01329    B |= (BitsPerPixel - 1);
01330 
01331    /*
01332     * Write it out
01333     */
01334    bputc(B, buffer);
01335 
01336    /*
01337     * Write out the Background colour
01338     */
01339    bputc(Background, buffer);
01340 
01341    /*
01342     * Byte of 0's (future expansion)
01343     */
01344    bputc(0, buffer);
01345 
01346    /*
01347     * Write out the Global Colour Map
01348     */
01349    for (i = 0; i < ColorMapSize; ++i) {
01350       bputc(Red[i], buffer);
01351       bputc(Green[i], buffer);
01352       bputc(Blue[i], buffer);
01353    }
01354 
01355    /*
01356     * Write out extension for transparent colour index, if necessary.
01357     */
01358    if (Transparent >= 0) {
01359       bputc('!', buffer);
01360       bputc(0xf9, buffer);
01361       bputc(4, buffer);
01362       bputc(1, buffer);
01363       bputc(0, buffer);
01364       bputc(0, buffer);
01365       bputc((unsigned char) Transparent, buffer);
01366       bputc(0, buffer);
01367    }
01368 
01369    /*
01370     * Write an Image separator
01371     */
01372    bputc(',', buffer);
01373 
01374    /*
01375     * Write the Image header
01376     */
01377 
01378    Putword(LeftOfs, buffer);
01379    Putword(TopOfs, buffer);
01380    Putword(Width, buffer);
01381    Putword(Height, buffer);
01382 
01383    /*
01384     * Write out whether or not the image is interlaced
01385     */
01386    if (Interlace)
01387       bputc(0x40, buffer);
01388    else
01389       bputc(0x00, buffer);
01390 
01391    /*
01392     * Write out the initial code size
01393     */
01394    bputc(InitCodeSize, buffer);
01395 
01396    /*
01397     * Go and actually compress the data
01398     */
01399    compress(InitCodeSize + 1, buffer, im);
01400 
01401    /*
01402     * Write out a Zero-length packet (to end the series)
01403     */
01404    bputc(0, buffer);
01405 
01406    /*
01407     * Write the GIF file terminator
01408     */
01409    bputc(';', buffer);
01410 }
01411 
01412 /*
01413  * Write out a word to the GIF file
01414  */
01415 static void Putword(int w, gdGifBuffer * buffer)
01416 {
01417    buffer->data[buffer->size++] = (unsigned char) (w & 0xff);
01418    buffer->data[buffer->size++] = (unsigned char) ((w / 256) & 0xff);
01419 }
01420 
01421 
01422 /***************************************************************************
01423  *
01424  *  GIFCOMPR.C       - GIF Image compression routines
01425  *
01426  *  Lempel-Ziv compression based on 'compress'.  GIF modifications by
01427  *  David Rowley (mgardi@watdcsu.waterloo.edu)
01428  *
01429  ***************************************************************************/
01430 
01431 /*
01432  * General DEFINEs
01433  */
01434 
01435 #define GIFBITS    12
01436 
01437 #define HSIZE  5003             /* 80% occupancy */
01438 
01439 #ifdef NO_UCHAR
01440 typedef char char_type;
01441 #else                           /*NO_UCHAR */
01442 typedef unsigned char char_type;
01443 #endif                          /*NO_UCHAR */
01444 
01445 /*
01446  *
01447  * GIF Image compression - modified 'compress'
01448  *
01449  * Based on: compress.c - File compression ala IEEE Computer, June 1984.
01450  *
01451  * By Authors:  Spencer W. Thomas       (decvax!harpo!utah-cs!utah-gr!thomas)
01452  *              Jim McKie               (decvax!mcvax!jim)
01453  *              Steve Davies            (decvax!vax135!petsd!peora!srd)
01454  *              Ken Turkowski           (decvax!decwrl!turtlevax!ken)
01455  *              James A. Woods          (decvax!ihnp4!ames!jaw)
01456  *              Joe Orost               (decvax!vax135!petsd!joe)
01457  *
01458  */
01459 #include <ctype.h>
01460 
01461 #define ARGVAL() (*++(*argv) || (--argc && *++argv))
01462 
01463 static int n_bits;              /* number of bits/code */
01464 static int maxbits = GIFBITS;   /* user settable max # bits/code */
01465 static code_int maxcode;        /* maximum code, given n_bits */
01466 static code_int maxmaxcode = (code_int) 1 << GIFBITS;   /* should NEVER generate this code */
01467 #ifdef COMPATIBLE               /* But wrong! */
01468 # define MAXCODE(n_bits)        ((code_int) 1 << (n_bits) - 1)
01469 #else /*COMPATIBLE*/
01470 # define MAXCODE(n_bits)        (((code_int) 1 << (n_bits)) - 1)
01471 #endif /*COMPATIBLE*/
01472 static count_int htab[HSIZE];
01473 static unsigned short codetab[HSIZE];
01474 #define HashTabOf(i)       htab[i]
01475 #define CodeTabOf(i)    codetab[i]
01476 
01477 static code_int hsize = HSIZE;  /* for dynamic table sizing */
01478 
01479 /*
01480  * To save much memory, we overlay the table used by compress() with those
01481  * used by decompress().  The tab_prefix table is the same size and type
01482  * as the codetab.  The tab_suffix table needs 2**GIFBITS characters.  We
01483  * get this from the beginning of htab.  The output stack uses the rest
01484  * of htab, and contains characters.  There is plenty of room for any
01485  * possible stack (stack used to be 8000 characters).
01486  */
01487 
01488 #define tab_prefixof(i) CodeTabOf(i)
01489 #define tab_suffixof(i)        ((char_type*)(htab))[i]
01490 #define de_stack               ((char_type*)&tab_suffixof((code_int)1<<GIFBITS))
01491 
01492 static code_int free_ent = 0;   /* first unused entry */
01493 
01494 /*
01495  * block compression parameters -- after all codes are used up,
01496  * and compression rate changes, start over.
01497  */
01498 static int clear_flg = 0;
01499 
01500 static int offset;
01501 static long int in_count = 1;   /* length of input */
01502 static long int out_count = 0;  /* # of codes output (for debugging) */
01503 
01504 /*
01505  * compress stdin to stdout
01506  *
01507  * Algorithm:  use open addressing double hashing (no chaining) on the
01508  * prefix code / next character combination.  We do a variant of Knuth's
01509  * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
01510  * secondary probe.  Here, the modular division first probe is gives way
01511  * to a faster exclusive-or manipulation.  Also do block compression with
01512  * an adaptive reset, whereby the code table is cleared when the compression
01513  * ratio decreases, but after the table fills.  The variable-length output
01514  * codes are re-sized at this point, and a special CLEAR code is generated
01515  * for the decompressor.  Late addition:  construct the table according to
01516  * file size for noticeable speed improvement on small files.  Please direct
01517  * questions about this implementation to ames!jaw.
01518  */
01519 
01520 static int g_init_bits;
01521 static gdGifBuffer *g_outbuffer;
01522 
01523 static int ClearCode;
01524 static int EOFCode;
01525 
01526 static void compress(int init_bits, gdGifBuffer * buffer, gdImagePtr im)
01527 {
01528    register long fcode;
01529    register code_int i /* = 0 */ ;
01530    register int c;
01531    register code_int ent;
01532    register code_int disp;
01533    register code_int hsize_reg;
01534    register int hshift;
01535 
01536    /*
01537     * Set up the globals:  g_init_bits - initial number of bits
01538     *                      g_outbuffer   - pointer to output file
01539     */
01540    g_init_bits = init_bits;
01541    g_outbuffer = buffer;
01542 
01543    /*
01544     * Set up the necessary values
01545     */
01546    offset = 0;
01547    out_count = 0;
01548    clear_flg = 0;
01549    in_count = 1;
01550    maxcode = MAXCODE(n_bits = g_init_bits);
01551 
01552    ClearCode = (1 << (init_bits - 1));
01553    EOFCode = ClearCode + 1;
01554    free_ent = ClearCode + 2;
01555 
01556    char_init();
01557 
01558    ent = GIFNextPixel(im);
01559 
01560    hshift = 0;
01561    for (fcode = (long) hsize; fcode < 65536L; fcode *= 2L)
01562       ++hshift;
01563    hshift = 8 - hshift;         /* set hash code range bound */
01564 
01565    hsize_reg = hsize;
01566    cl_hash((count_int) hsize_reg);      /* clear hash table */
01567 
01568    output((code_int) ClearCode);
01569 
01570 #ifdef SIGNED_COMPARE_SLOW
01571    while ((c = GIFNextPixel(im)) != (unsigned) EOF) {
01572 #else                           /*SIGNED_COMPARE_SLOW */
01573    while ((c = GIFNextPixel(im)) != EOF) {      /* } */
01574 #endif                          /*SIGNED_COMPARE_SLOW */
01575 
01576       ++in_count;
01577 
01578       fcode = (long) (((long) c << maxbits) + ent);
01579       i = (((code_int) c << hshift) ^ ent);     /* xor hashing */
01580 
01581       if (HashTabOf(i) == fcode) {
01582          ent = CodeTabOf(i);
01583          continue;
01584       } else if ((long) HashTabOf(i) < 0)       /* empty slot */
01585          goto nomatch;
01586       disp = hsize_reg - i;     /* secondary hash (after G. Knott) */
01587       if (i == 0)
01588          disp = 1;
01589     probe:
01590       if ((i -= disp) < 0)
01591          i += hsize_reg;
01592 
01593       if (HashTabOf(i) == fcode) {
01594          ent = CodeTabOf(i);
01595          continue;
01596       }
01597       if ((long) HashTabOf(i) > 0)
01598          goto probe;
01599     nomatch:
01600       output((code_int) ent);
01601       ++out_count;
01602       ent = c;
01603 #ifdef SIGNED_COMPARE_SLOW
01604       if ((unsigned) free_ent < (unsigned) maxmaxcode) {
01605 #else                           /*SIGNED_COMPARE_SLOW */
01606       if (free_ent < maxmaxcode) {      /* } */
01607 #endif                          /*SIGNED_COMPARE_SLOW */
01608          CodeTabOf(i) = free_ent++;     /* code -> hashtable */
01609          HashTabOf(i) = fcode;
01610       } else
01611          cl_block();
01612    }
01613    /*
01614     * Put out the final code.
01615     */
01616    output((code_int) ent);
01617    ++out_count;
01618    output((code_int) EOFCode);
01619 }
01620 
01621 /*****************************************************************
01622  * TAG( output )
01623  *
01624  * Output the given code.
01625  * Inputs:
01626  *      code:   A n_bits-bit integer.  If == -1, then EOF.  This assumes
01627  *              that n_bits =< (long)wordsize - 1.
01628  * Outputs:
01629  *      Outputs code to the file.
01630  * Assumptions:
01631  *      Chars are 8 bits long.
01632  * Algorithm:
01633  *      Maintain a GIFBITS character long buffer (so that 8 codes will
01634  * fit in it exactly).  Use the VAX insv instruction to insert each
01635  * code in turn.  When the buffer fills up empty it and start over.
01636  */
01637 
01638 static unsigned long cur_accum = 0;
01639 static int cur_bits = 0;
01640 
01641 static unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
01642    0x001F, 0x003F, 0x007F, 0x00FF,
01643    0x01FF, 0x03FF, 0x07FF, 0x0FFF,
01644    0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF
01645 };
01646 
01647 static void output(code_int code)
01648 {
01649    cur_accum &= masks[cur_bits];
01650 
01651    if (cur_bits > 0)
01652       cur_accum |= ((long) code << cur_bits);
01653    else
01654       cur_accum = code;
01655 
01656    cur_bits += n_bits;
01657 
01658    while (cur_bits >= 8) {
01659       char_out((unsigned int) (cur_accum & 0xff));
01660       cur_accum >>= 8;
01661       cur_bits -= 8;
01662    }
01663 
01664    /*
01665     * If the next entry is going to be too big for the code size,
01666     * then increase it, if possible.
01667     */
01668    if (free_ent > maxcode || clear_flg) {
01669 
01670       if (clear_flg) {
01671 
01672          maxcode = MAXCODE(n_bits = g_init_bits);
01673          clear_flg = 0;
01674 
01675       } else {
01676 
01677          ++n_bits;
01678          if (n_bits == maxbits)
01679             maxcode = maxmaxcode;
01680          else
01681             maxcode = MAXCODE(n_bits);
01682       }
01683    }
01684 
01685    if (code == EOFCode) {
01686       /*
01687        * At EOF, write the rest of the buffer.
01688        */
01689       while (cur_bits > 0) {
01690          char_out((unsigned int) (cur_accum & 0xff));
01691          cur_accum >>= 8;
01692          cur_bits -= 8;
01693       }
01694 
01695       flush_char();
01696 
01697    }
01698 }
01699 
01700 /*
01701  * Clear out the hash table
01702  */
01703 static void cl_block(void)
01704 {                               /* table clear for block compress */
01705 
01706    cl_hash((count_int) hsize);
01707    free_ent = ClearCode + 2;
01708    clear_flg = 1;
01709 
01710    output((code_int) ClearCode);
01711 }
01712 
01713 static void cl_hash(register count_int hsize)
01714 {                               /* reset code table */
01715 
01716    register count_int *htab_p = htab + hsize;
01717 
01718    register long i;
01719    register long m1 = -1;
01720 
01721    i = hsize - 16;
01722    do {                         /* might use Sys V memset(3) here */
01723       *(htab_p - 16) = m1;
01724       *(htab_p - 15) = m1;
01725       *(htab_p - 14) = m1;
01726       *(htab_p - 13) = m1;
01727       *(htab_p - 12) = m1;
01728       *(htab_p - 11) = m1;
01729       *(htab_p - 10) = m1;
01730       *(htab_p - 9) = m1;
01731       *(htab_p - 8) = m1;
01732       *(htab_p - 7) = m1;
01733       *(htab_p - 6) = m1;
01734       *(htab_p - 5) = m1;
01735       *(htab_p - 4) = m1;
01736       *(htab_p - 3) = m1;
01737       *(htab_p - 2) = m1;
01738       *(htab_p - 1) = m1;
01739       htab_p -= 16;
01740    } while ((i -= 16) >= 0);
01741 
01742    for (i += 16; i > 0; --i)
01743       *--htab_p = m1;
01744 }
01745 
01746 /******************************************************************************
01747  *
01748  * GIF Specific routines
01749  *
01750  ******************************************************************************/
01751 
01752 /*
01753  * Number of characters so far in this 'packet'
01754  */
01755 static int a_count;
01756 
01757 /*
01758  * Set up the 'byte output' routine
01759  */
01760 static void char_init(void)
01761 {
01762    a_count = 0;
01763 }
01764 
01765 /*
01766  * Define the storage for the packet accumulator
01767  */
01768 static char accum[256];
01769 
01770 /*
01771  * Add a character to the end of the current packet, and if it is 254
01772  * characters, flush the packet to disk.
01773  */
01774 static void char_out(int c)
01775 {
01776    accum[a_count++] = c;
01777    if (a_count >= 254)
01778       flush_char();
01779 }
01780 
01781 /*
01782  * Flush the packet to disk, and reset the accumulator
01783  */
01784 static void flush_char(void)
01785 {
01786    if (a_count > 0) {
01787       bputc(a_count, g_outbuffer);
01788       memcpy(g_outbuffer->data + g_outbuffer->size, accum, a_count);
01789       g_outbuffer->size += a_count;
01790       a_count = 0;
01791    }
01792 }
01793 
01794 static void init_statics(void)
01795 {
01796    /* Some of these are properly initialized later. What I'm doing
01797       here is making sure code that depends on C's initialization
01798       of statics doesn't break when the code gets called more
01799       than once. */
01800    Width = 0;
01801    Height = 0;
01802    curx = 0;
01803    cury = 0;
01804    CountDown = 0;
01805    Pass = 0;
01806    Interlace = 0;
01807    a_count = 0;
01808    cur_accum = 0;
01809    cur_bits = 0;
01810    g_init_bits = 0;
01811    g_outbuffer = 0;
01812    ClearCode = 0;
01813    EOFCode = 0;
01814    free_ent = 0;
01815    clear_flg = 0;
01816    offset = 0;
01817    in_count = 1;
01818    out_count = 0;
01819    hsize = HSIZE;
01820    n_bits = 0;
01821    maxbits = GIFBITS;
01822    maxcode = 0;
01823    maxmaxcode = (code_int) 1 << GIFBITS;
01824 }
01825 
01826 
01827 /* +-------------------------------------------------------------------+ */
01828 /* | Copyright 1990, 1991, 1993, David Koblas.  (koblas@netcom.com)    | */
01829 /* |   Permission to use, copy, modify, and distribute this software   | */
01830 /* |   and its documentation for any purpose and without fee is hereby | */
01831 /* |   granted, provided that the above copyright notice appear in all | */
01832 /* |   copies and that both that copyright notice and this permission  | */
01833 /* |   notice appear in supporting documentation.  This software is    | */
01834 /* |   provided "as is" without express or implied warranty.           | */
01835 /* +-------------------------------------------------------------------+ */
01836 
01837 
01838 #define        MAXCOLORMAPSIZE         256
01839 
01840 #define        TRUE    1
01841 #define        FALSE   0
01842 
01843 #define CM_RED         0
01844 #define CM_GREEN       1
01845 #define CM_BLUE                2
01846 
01847 #define        MAX_LWZ_BITS            12
01848 
01849 #define INTERLACE              0x40
01850 #define LOCALCOLORMAP  0x80
01851 #define BitSet(byte, bit)      (((byte) & (bit)) == (bit))
01852 
01853 #define        ReadOK(file,buffer,len) (fread(buffer, len, 1, file) != 0)
01854 
01855 #define LM_to_uint(a,b)                        (((b)<<8)|(a))
01856 
01857 /* We may eventually want to use this information, but def it out for now */
01858 #if 0
01859 static struct {
01860    unsigned int Width;
01861    unsigned int Height;
01862    unsigned char ColorMap[3][MAXCOLORMAPSIZE];
01863    unsigned int BitPixel;
01864    unsigned int ColorResolution;
01865    unsigned int Background;
01866    unsigned int AspectRatio;
01867 } GifScreen;
01868 #endif
01869 
01870 static struct {
01871    int transparent;
01872    int delayTime;
01873    int inputFlag;
01874    int disposal;
01875 } Gif89 = {
01876 -1, -1, -1, 0};
01877 
01878 static int ReadColorMap(FILE * fd, int number, unsigned char (*buffer)[256]);
01879 static int DoExtension(FILE * fd, int label, int *Transparent);
01880 static int GetDataBlock(FILE * fd, unsigned char *buf);
01881 static int GetCode(FILE * fd, int code_size, int flag);
01882 static int LWZReadByte(FILE * fd, int flag, int input_code_size);
01883 static void ReadImage(gdImagePtr im, FILE * fd, int len, int height,
01884                       unsigned char (*cmap)[256], int interlace, int ignore);
01885 
01886 int ZeroDataBlock;
01887 
01888 gdImagePtr gdImageCreateFromGif(FILE * fd)
01889 {
01890    int imageNumber;
01891    int BitPixel;
01892    int ColorResolution;
01893    int Background;
01894    int AspectRatio;
01895    int Transparent = (-1);
01896    unsigned char buf[16];
01897    unsigned char c;
01898    unsigned char ColorMap[3][MAXCOLORMAPSIZE];
01899    unsigned char localColorMap[3][MAXCOLORMAPSIZE];
01900    int imw, imh;
01901    int useGlobalColormap;
01902    int bitPixel;
01903    int imageCount = 0;
01904    char version[4];
01905    gdImagePtr im = 0;
01906    ZeroDataBlock = FALSE;
01907 
01908    imageNumber = 1;
01909    if (!ReadOK(fd, buf, 6)) {
01910       return 0;
01911    }
01912    if (strncmp((char *) buf, "GIF", 3) != 0) {
01913       return 0;
01914    }
01915    strncpy(version, (char *) buf + 3, 3);
01916    version[3] = '\0';
01917 
01918    if ((strcmp(version, "87a") != 0) && (strcmp(version, "89a") != 0)) {
01919       return 0;
01920    }
01921    if (!ReadOK(fd, buf, 7)) {
01922       return 0;
01923    }
01924    BitPixel = 2 << (buf[4] & 0x07);
01925    ColorResolution = (int) (((buf[4] & 0x70) >> 3) + 1);
01926    Background = buf[5];
01927    AspectRatio = buf[6];
01928 
01929    if (BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */
01930       if (ReadColorMap(fd, BitPixel, ColorMap)) {
01931          return 0;
01932       }
01933    }
01934    for (;;) {
01935       if (!ReadOK(fd, &c, 1)) {
01936          return 0;
01937       }
01938       if (c == ';') {           /* GIF terminator */
01939          int i;
01940          if (imageCount < imageNumber) {
01941             return 0;
01942          }
01943          /* Terminator before any image was declared! */
01944          if (!im) {
01945             return 0;
01946          }
01947          /* Check for open colors at the end, so
01948             we can reduce colorsTotal and ultimately
01949             BitsPerPixel */
01950          for (i = ((im->colorsTotal - 1)); (i >= 0); i--) {
01951             if (im->open[i]) {
01952                im->colorsTotal--;
01953             } else {
01954                break;
01955             }
01956          }
01957          return im;
01958       }
01959 
01960       if (c == '!') {           /* Extension */
01961          if (!ReadOK(fd, &c, 1)) {
01962             return 0;
01963          }
01964          DoExtension(fd, c, &Transparent);
01965          continue;
01966       }
01967 
01968       if (c != ',') {           /* Not a valid start character */
01969          continue;
01970       }
01971 
01972       ++imageCount;
01973 
01974       if (!ReadOK(fd, buf, 9)) {
01975          return 0;
01976       }
01977 
01978       useGlobalColormap = !BitSet(buf[8], LOCALCOLORMAP);
01979 
01980       bitPixel = 1 << ((buf[8] & 0x07) + 1);
01981 
01982       imw = LM_to_uint(buf[4], buf[5]);
01983       imh = LM_to_uint(buf[6], buf[7]);
01984       if (!(im = gdImageCreate(imw, imh))) {
01985          return 0;
01986       }
01987       im->interlace = BitSet(buf[8], INTERLACE);
01988       if (!useGlobalColormap) {
01989          if (ReadColorMap(fd, bitPixel, localColorMap)) {
01990             return 0;
01991          }
01992          ReadImage(im, fd, imw, imh, localColorMap,
01993                    BitSet(buf[8], INTERLACE), imageCount != imageNumber);
01994       } else {
01995          ReadImage(im, fd, imw, imh,
01996                    ColorMap, BitSet(buf[8], INTERLACE), imageCount != imageNumber);
01997       }
01998       if (Transparent != (-1)) {
01999          gdImageColorTransparent(im, Transparent);
02000       }
02001    }
02002 }
02003 
02004 static int ReadColorMap(FILE * fd, int number, unsigned char (*buffer)[256])
02005 {
02006    int i;
02007    unsigned char rgb[3];
02008 
02009 
02010    for (i = 0; i < number; ++i) {
02011       if (!ReadOK(fd, rgb, sizeof(rgb))) {
02012          return TRUE;
02013       }
02014       buffer[CM_RED][i] = rgb[0];
02015       buffer[CM_GREEN][i] = rgb[1];
02016       buffer[CM_BLUE][i] = rgb[2];
02017    }
02018 
02019 
02020    return FALSE;
02021 }
02022 
02023 static int DoExtension(FILE * fd, int label, int *Transparent)
02024 {
02025    static unsigned char buf[256];
02026 
02027    switch (label) {
02028    case 0xf9:                  /* Graphic Control Extension */
02029       (void) GetDataBlock(fd, (unsigned char *) buf);
02030       Gif89.disposal = (buf[0] >> 2) & 0x7;
02031       Gif89.inputFlag = (buf[0] >> 1) & 0x1;
02032       Gif89.delayTime = LM_to_uint(buf[1], buf[2]);
02033       if ((buf[0] & 0x1) != 0)
02034          *Transparent = buf[3];
02035 
02036       while (GetDataBlock(fd, (unsigned char *) buf) != 0);
02037       return FALSE;
02038    default:
02039       break;
02040    }
02041    while (GetDataBlock(fd, (unsigned char *) buf) != 0);
02042 
02043    return FALSE;
02044 }
02045 
02046 static int GetDataBlock(FILE * fd, unsigned char *buf)
02047 {
02048    unsigned char count;
02049 
02050    if (!ReadOK(fd, &count, 1)) {
02051       return -1;
02052    }
02053 
02054    ZeroDataBlock = count == 0;
02055 
02056    if ((count != 0) && (!ReadOK(fd, buf, count))) {
02057       return -1;
02058    }
02059 
02060    return count;
02061 }
02062 
02063 static int GetCode(FILE * fd, int code_size, int flag)
02064 {
02065    static unsigned char buf[280];
02066    static int curbit, lastbit, done, last_byte;
02067    int i, j, ret;
02068    unsigned char count;
02069 
02070    if (flag) {
02071       curbit = 0;
02072       lastbit = 0;
02073       done = FALSE;
02074       return 0;
02075    }
02076 
02077    if ((curbit + code_size) >= lastbit) {
02078       if (done) {
02079          if (curbit >= lastbit) {
02080             /* Oh well */
02081          }
02082          return -1;
02083       }
02084       buf[0] = buf[last_byte - 2];
02085       buf[1] = buf[last_byte - 1];
02086 
02087       if ((count = GetDataBlock(fd, &buf[2])) == 0)
02088          done = TRUE;
02089 
02090       last_byte = 2 + count;
02091       curbit = (curbit - lastbit) + 16;
02092       lastbit = (2 + count) * 8;
02093    }
02094 
02095    ret = 0;
02096    for (i = curbit, j = 0; j < code_size; ++i, ++j)
02097       ret |= ((buf[i / 8] & (1 << (i % 8))) != 0) << j;
02098 
02099    curbit += code_size;
02100 
02101    return ret;
02102 }
02103 
02104 static int LWZReadByte(FILE * fd, int flag, int input_code_size)
02105 {
02106    static int fresh = FALSE;
02107    int code, incode;
02108    static int code_size, set_code_size;
02109    static int max_code, max_code_size;
02110    static int firstcode, oldcode;
02111    static int clear_code, end_code;
02112    static int table[2][(1 << MAX_LWZ_BITS)];
02113    static int stack[(1 << (MAX_LWZ_BITS)) * 2], *sp;
02114    register int i;
02115 
02116    if (flag) {
02117       set_code_size = input_code_size;
02118       code_size = set_code_size + 1;
02119       clear_code = 1 << set_code_size;
02120       end_code = clear_code + 1;
02121       max_code_size = 2 * clear_code;
02122       max_code = clear_code + 2;
02123 
02124       GetCode(fd, 0, TRUE);
02125 
02126       fresh = TRUE;
02127 
02128       for (i = 0; i < clear_code; ++i) {
02129          table[0][i] = 0;
02130          table[1][i] = i;
02131       }
02132       for (; i < (1 << MAX_LWZ_BITS); ++i)
02133          table[0][i] = table[1][0] = 0;
02134 
02135       sp = stack;
02136 
02137       return 0;
02138    } else if (fresh) {
02139       fresh = FALSE;
02140       do {
02141          firstcode = oldcode = GetCode(fd, code_size, FALSE);
02142       } while (firstcode == clear_code);
02143       return firstcode;
02144    }
02145 
02146    if (sp > stack)
02147       return *--sp;
02148 
02149    while ((code = GetCode(fd, code_size, FALSE)) >= 0) {
02150       if (code == clear_code) {
02151          for (i = 0; i < clear_code; ++i) {
02152             table[0][i] = 0;
02153             table[1][i] = i;
02154          }
02155          for (; i < (1 << MAX_LWZ_BITS); ++i)
02156             table[0][i] = table[1][i] = 0;
02157          code_size = set_code_size + 1;
02158          max_code_size = 2 * clear_code;
02159          max_code = clear_code + 2;
02160          sp = stack;
02161          firstcode = oldcode = GetCode(fd, code_size, FALSE);
02162          return firstcode;
02163       } else if (code == end_code) {
02164          int count;
02165          unsigned char buf[260];
02166 
02167          if (ZeroDataBlock)
02168             return -2;
02169 
02170          while ((count = GetDataBlock(fd, buf)) > 0);
02171 
02172          if (count != 0)
02173             return -2;
02174       }
02175 
02176       incode = code;
02177 
02178       if (code >= max_code) {
02179          *sp++ = firstcode;
02180          code = oldcode;
02181       }
02182 
02183       while (code >= clear_code) {
02184          *sp++ = table[1][code];
02185          if (code == table[0][code]) {
02186             /* Oh well */
02187          }
02188          code = table[0][code];
02189       }
02190 
02191       *sp++ = firstcode = table[1][code];
02192 
02193       if ((code = max_code) < (1 << MAX_LWZ_BITS)) {
02194          table[0][code] = oldcode;
02195          table[1][code] = firstcode;
02196          ++max_code;
02197          if ((max_code >= max_code_size) && (max_code_size < (1 << MAX_LWZ_BITS))) {
02198             max_code_size *= 2;
02199             ++code_size;
02200          }
02201       }
02202 
02203       oldcode = incode;
02204 
02205       if (sp > stack)
02206          return *--sp;
02207    }
02208    return code;
02209 }
02210 
02211 static void
02212 ReadImage(gdImagePtr im, FILE * fd, int len, int height, unsigned char (*cmap)[256],
02213           int interlace, int ignore)
02214 {
02215    unsigned char c;
02216    int v;
02217    int xpos = 0, ypos = 0, pass = 0;
02218    int i;
02219    /* Stash the color map into the image */
02220    for (i = 0; (i < gdMaxColors); i++) {
02221       im->red[i] = cmap[CM_RED][i];
02222       im->green[i] = cmap[CM_GREEN][i];
02223       im->blue[i] = cmap[CM_BLUE][i];
02224       im->open[i] = 1;
02225    }
02226    /* Many (perhaps most) of these colors will remain marked open. */
02227    im->colorsTotal = gdMaxColors;
02228    /*
02229     **  Initialize the Compression routines
02230     */
02231    if (!ReadOK(fd, &c, 1)) {
02232       return;
02233    }
02234    if (LWZReadByte(fd, TRUE, c) < 0) {
02235       return;
02236    }
02237 
02238    /*
02239     **  If this is an "uninteresting picture" ignore it.
02240     */
02241    if (ignore) {
02242       while (LWZReadByte(fd, FALSE, c) >= 0);
02243       return;
02244    }
02245 
02246    while ((v = LWZReadByte(fd, FALSE, c)) >= 0) {
02247       /* This how we recognize which colors are actually used. */
02248       if (im->open[v]) {
02249          im->open[v] = 0;
02250       }
02251       gdImageSetPixel(im, xpos, ypos, v);
02252       ++xpos;
02253       if (xpos == len) {
02254          xpos = 0;
02255          if (interlace) {
02256             switch (pass) {
02257             case 0:
02258             case 1:
02259                ypos += 8;
02260                break;
02261             case 2:
02262                ypos += 4;
02263                break;
02264             case 3:
02265                ypos += 2;
02266                break;
02267             }
02268 
02269             if (ypos >= height) {
02270                ++pass;
02271                switch (pass) {
02272                case 1:
02273                   ypos = 4;
02274                   break;
02275                case 2:
02276                   ypos = 2;
02277                   break;
02278                case 3:
02279                   ypos = 1;
02280                   break;
02281                default:
02282                   goto fini;
02283                }
02284             }
02285          } else {
02286             ++ypos;
02287          }
02288       }
02289       if (ypos >= height)
02290          break;
02291    }
02292 
02293  fini:
02294    if (LWZReadByte(fd, FALSE, c) >= 0) {
02295       /* Ignore extra */
02296    }
02297 }
02298 
02299 void gdImageRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
02300 {
02301    gdImageLine(im, x1, y1, x2, y1, color);
02302    gdImageLine(im, x1, y2, x2, y2, color);
02303    gdImageLine(im, x1, y1, x1, y2, color);
02304    gdImageLine(im, x2, y1, x2, y2, color);
02305 }
02306 
02307 void gdImageFilledRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
02308 {
02309    int x, y;
02310    for (y = y1; (y <= y2); y++) {
02311       for (x = x1; (x <= x2); x++) {
02312          gdImageSetPixel(im, x, y, color);
02313       }
02314    }
02315 }
02316 
02317 void gdImageCopy(gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY,
02318                  int w, int h)
02319 {
02320    int c;
02321    int x, y;
02322    int tox, toy;
02323    int i;
02324    int colorMap[gdMaxColors];
02325    for (i = 0; (i < gdMaxColors); i++) {
02326       colorMap[i] = (-1);
02327    }
02328    toy = dstY;
02329    for (y = srcY; (y < (srcY + h)); y++) {
02330       tox = dstX;
02331       for (x = srcX; (x < (srcX + w)); x++) {
02332          int nc;
02333          c = gdImageGetPixel(src, x, y);
02334          /* Added 7/24/95: support transparent copies */
02335          if (gdImageGetTransparent(src) == c) {
02336             tox++;
02337             continue;
02338          }
02339          /* Have we established a mapping for this color? */
02340          if (colorMap[c] == (-1)) {
02341             /* If it's the same image, mapping is trivial */
02342             if (dst == src) {
02343                nc = c;
02344             } else {
02345                /* First look for an exact match */
02346                nc = gdImageColorExact(dst, src->red[c], src->green[c], src->blue[c]);
02347             }
02348             if (nc == (-1)) {
02349                /* No, so try to allocate it */
02350                nc = gdImageColorAllocate(dst, src->red[c], src->green[c], src->blue[c]);
02351                /* If we're out of colors, go for the
02352                   closest color */
02353                if (nc == (-1)) {
02354                   nc = gdImageColorClosest(dst, src->red[c], src->green[c], src->blue[c]);
02355                }
02356             }
02357             colorMap[c] = nc;
02358          }
02359          gdImageSetPixel(dst, tox, toy, colorMap[c]);
02360          tox++;
02361       }
02362       toy++;
02363    }
02364 }
02365 
02366 void gdImageCopyResized(gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX,
02367                         int srcY, int dstW, int dstH, int srcW, int srcH)
02368 {
02369    int c;
02370    int x, y;
02371    int tox, toy;
02372    int ydest;
02373    int i;
02374    int colorMap[gdMaxColors];
02375    /* Stretch vectors */
02376    int *stx;
02377    int *sty;
02378    /* We only need to use floating point to determine the correct
02379       stretch vector for one line's worth. */
02380    double accum;
02381    stx = (int *) M_MALLOC(sizeof(int) * srcW);
02382    sty = (int *) M_MALLOC(sizeof(int) * srcH);
02383    accum = 0;
02384    for (i = 0; (i < srcW); i++) {
02385       int got;
02386       accum += (double) dstW / (double) srcW;
02387       got = (int) floor(accum);
02388       stx[i] = got;
02389       accum -= got;
02390    }
02391    accum = 0;
02392    for (i = 0; (i < srcH); i++) {
02393       int got;
02394       accum += (double) dstH / (double) srcH;
02395       got = (int) floor(accum);
02396       sty[i] = got;
02397       accum -= got;
02398    }
02399    for (i = 0; (i < gdMaxColors); i++) {
02400       colorMap[i] = (-1);
02401    }
02402    toy = dstY;
02403    for (y = srcY; (y < (srcY + srcH)); y++) {
02404       for (ydest = 0; (ydest < sty[y - srcY]); ydest++) {
02405          tox = dstX;
02406          for (x = srcX; (x < (srcX + srcW)); x++) {
02407             int nc;
02408             if (!stx[x - srcX]) {
02409                continue;
02410             }
02411             c = gdImageGetPixel(src, x, y);
02412             /* Added 7/24/95: support transparent copies */
02413             if (gdImageGetTransparent(src) == c) {
02414                tox += stx[x - srcX];
02415                continue;
02416             }
02417             /* Have we established a mapping for this color? */
02418             if (colorMap[c] == (-1)) {
02419                /* If it's the same image, mapping is trivial */
02420                if (dst == src) {
02421                   nc = c;
02422                } else {
02423                   /* First look for an exact match */
02424                   nc = gdImageColorExact(dst, src->red[c], src->green[c], src->blue[c]);
02425                }
02426                if (nc == (-1)) {
02427                   /* No, so try to allocate it */
02428                   nc = gdImageColorAllocate(dst,
02429                                             src->red[c], src->green[c], src->blue[c]);
02430                   /* If we're out of colors, go for the
02431                      closest color */
02432                   if (nc == (-1)) {
02433                      nc = gdImageColorClosest(dst,
02434                                               src->red[c], src->green[c], src->blue[c]);
02435                   }
02436                }
02437                colorMap[c] = nc;
02438             }
02439             for (i = 0; (i < stx[x - srcX]); i++) {
02440                gdImageSetPixel(dst, tox, toy, colorMap[c]);
02441                tox++;
02442             }
02443          }
02444          toy++;
02445       }
02446    }
02447    M_FREE(stx);
02448    M_FREE(sty);
02449 }
02450 
02451 void gdImagePolygon(gdImagePtr im, gdPointPtr p, int n, int c)
02452 {
02453    int i;
02454    int lx, ly;
02455    if (!n) {
02456       return;
02457    }
02458    lx = p->x;
02459    ly = p->y;
02460    gdImageLine(im, lx, ly, p[n - 1].x, p[n - 1].y, c);
02461    for (i = 1; (i < n); i++) {
02462       p++;
02463       gdImageLine(im, lx, ly, p->x, p->y, c);
02464       lx = p->x;
02465       ly = p->y;
02466    }
02467 }
02468 
02469 int gdCompareInt(const void *a, const void *b);
02470 
02471 void gdImageFilledPolygon(gdImagePtr im, gdPointPtr p, int n, int c)
02472 {
02473    int i;
02474    int y;
02475    int y1, y2;
02476    int ints;
02477    if (!n) {
02478       return;
02479    }
02480    if (!im->polyAllocated) {
02481       im->polyInts = (int *) M_MALLOC(sizeof(int) * n);
02482       im->polyAllocated = n;
02483    }
02484    if (im->polyAllocated < n) {
02485       while (im->polyAllocated < n) {
02486          im->polyAllocated *= 2;
02487       }
02488       im->polyInts = (int *) realloc(im->polyInts, sizeof(int) * im->polyAllocated);
02489    }
02490    y1 = p[0].y;
02491    y2 = p[0].y;
02492    for (i = 1; (i < n); i++) {
02493       if (p[i].y < y1) {
02494          y1 = p[i].y;
02495       }
02496       if (p[i].y > y2) {
02497          y2 = p[i].y;
02498       }
02499    }
02500    for (y = y1; (y <= y2); y++) {
02501       int interLast = 0;
02502       int dirLast = 0;
02503       int interFirst = 1;
02504       ints = 0;
02505       for (i = 0; (i <= n); i++) {
02506          int x1, x2;
02507          int y1, y2;
02508          int dir;
02509          int ind1, ind2;
02510          int lastInd1 = 0;
02511          if ((i == n) || (!i)) {
02512             ind1 = n - 1;
02513             ind2 = 0;
02514          } else {
02515             ind1 = i - 1;
02516             ind2 = i;
02517          }
02518          y1 = p[ind1].y;
02519          y2 = p[ind2].y;
02520          if (y1 < y2) {
02521             y1 = p[ind1].y;
02522             y2 = p[ind2].y;
02523             x1 = p[ind1].x;
02524             x2 = p[ind2].x;
02525             dir = -1;
02526          } else if (y1 > y2) {
02527             y2 = p[ind1].y;
02528             y1 = p[ind2].y;
02529             x2 = p[ind1].x;
02530             x1 = p[ind2].x;
02531             dir = 1;
02532          } else {
02533             /* Horizontal; just draw it */
02534             gdImageLine(im, p[ind1].x, y1, p[ind2].x, y1, c);
02535             continue;
02536          }
02537          if ((y >= y1) && (y <= y2)) {
02538             int inter = (y - y1) * (x2 - x1) / (y2 - y1) + x1;
02539             /* Only count intersections once
02540                except at maxima and minima. Also, 
02541                if two consecutive intersections are
02542                endpoints of the same horizontal line
02543                that is not at a maxima or minima,   
02544                discard the leftmost of the two. */
02545             if (!interFirst) {
02546                if ((p[ind1].y == p[lastInd1].y) && (p[ind1].x != p[lastInd1].x)) {
02547                   if (dir == dirLast) {
02548                      if (inter > interLast) {
02549                         /* Replace the old one */
02550                         im->polyInts[ints] = inter;
02551                      } else {
02552                         /* Discard this one */
02553                      }
02554                      continue;
02555                   }
02556                }
02557                if (inter == interLast) {
02558                   if (dir == dirLast) {
02559                      continue;
02560                   }
02561                }
02562             }
02563             if (i > 0) {
02564                im->polyInts[ints++] = inter;
02565             }
02566             lastInd1 = i;
02567             dirLast = dir;
02568             interLast = inter;
02569             interFirst = 0;
02570          }
02571       }
02572       qsort(im->polyInts, ints, sizeof(int), gdCompareInt);
02573       for (i = 0; (i < (ints - 1)); i += 2) {
02574          gdImageLine(im, im->polyInts[i], y, im->polyInts[i + 1], y, c);
02575       }
02576    }
02577 }
02578 
02579 int gdCompareInt(const void *a, const void *b)
02580 {
02581    return (*(const int *) a) - (*(const int *) b);
02582 }
02583 
02584 void gdImageSetStyle(gdImagePtr im, int *style, int noOfPixels)
02585 {
02586    if (im->style) {
02587       M_FREE(im->style);
02588    }
02589    im->style = (int *)
02590        M_MALLOC(sizeof(int) * noOfPixels);
02591    memcpy(im->style, style, sizeof(int) * noOfPixels);
02592    im->styleLength = noOfPixels;
02593    im->stylePos = 0;
02594 }
02595 
02596 void gdImageSetBrush(gdImagePtr im, gdImagePtr brush)
02597 {
02598    int i;
02599    im->brush = brush;
02600    for (i = 0; (i < gdImageColorsTotal(brush)); i++) {
02601       int index;
02602       index = gdImageColorExact(im,
02603                                 gdImageRed(brush, i),
02604                                 gdImageGreen(brush, i), gdImageBlue(brush, i));
02605       if (index == (-1)) {
02606          index = gdImageColorAllocate(im,
02607                                       gdImageRed(brush, i),
02608                                       gdImageGreen(brush, i), gdImageBlue(brush, i));
02609          if (index == (-1)) {
02610             index = gdImageColorClosest(im,
02611                                         gdImageRed(brush, i),
02612                                         gdImageGreen(brush, i), gdImageBlue(brush, i));
02613          }
02614       }
02615       im->brushColorMap[i] = index;
02616    }
02617 }
02618 
02619 void gdImageInterlace(gdImagePtr im, int interlaceArg)
02620 {
02621    im->interlace = interlaceArg;
02622 }

Midas DOC Version 3.0.0 ---- PSI Stefan Ritt ----
Contributions: Pierre-Andre Amaudruz - Sergio Ballestrero - Suzannah Daviel - Doxygen - Peter Green - Qing Gu - Greg Hackman - Gertjan Hofman - Paul Knowles - Exaos Lee - Rudi Meier - Glenn Moloney - Dave Morris - John M O'Donnell - Konstantin Olchanski - Renee Poutissou - Tamsen Schurman - Andreas Suter - Jan M.Wouters - Piotr Adam Zolnierczuk