LCOV - code coverage report
Current view: top level - progs - mgd.cxx (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 1058 0
Test Date: 2025-11-11 10:26:08 Functions: 0.0 % 52 0

            Line data    Source code
       1              : /********************************************************************\
       2              : 
       3              :   Name:         mgd.c
       4              :   Created by:   Thomas Boutell (http://www.boutell.com/boutell/)
       5              :                 
       6              :                   with the help of 
       7              :                 
       8              :                 David Rowley <mgardi@watdscu.waterloo.edu>
       9              :                 David Koblas <koblas@netcom.com>
      10              : 
      11              :                   modified by 
      12              :                   
      13              :                 Stefan Ritt <Stefan.Ritt@psi.ch>
      14              : 
      15              :                   For further copywright notices see:
      16              : 
      17              :                 http://www.boutell.com/gd/
      18              : 
      19              :   Contents:     GD graphics library to create Web images
      20              : 
      21              :   $Id:$
      22              : 
      23              : \********************************************************************/
      24              : 
      25              : #include <stdio.h>
      26              : #include <math.h>
      27              : #include <string.h>
      28              : #include <stdlib.h>
      29              : #include <midas.h>
      30              : #include "mgd.h"
      31              : 
      32              : int gdFontGiantData[] = {
      33              :    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      34              :    0, 0, 0, 0, 0, 48, 120, 252, 510, 252, 120, 48, 0, 0, 0,
      35              :    0, 0, 0, 0, 0, 438, 204, 438, 204, 438, 204, 438, 0, 0, 0,
      36              :    0, 0, 0, 102, 102, 126, 102, 102, 0, 504, 96, 96, 96, 96, 0,
      37              :    0, 0, 0, 62, 6, 30, 6, 6, 0, 496, 48, 240, 48, 48, 0,
      38              :    0, 0, 0, 124, 70, 6, 70, 124, 0, 248, 408, 248, 408, 408, 0,
      39              :    0, 0, 0, 6, 6, 6, 6, 62, 0, 496, 48, 240, 48, 48, 0,
      40              :    0, 0, 0, 0, 0, 120, 204, 204, 120, 0, 0, 0, 0, 0, 0,
      41              :    0, 0, 48, 48, 48, 510, 510, 48, 48, 48, 0, 510, 510, 0, 0,
      42              :    0, 0, 0, 102, 110, 126, 118, 102, 0, 48, 48, 48, 48, 496, 0,
      43              :    0, 0, 0, 102, 102, 102, 60, 24, 0, 504, 96, 96, 96, 96, 0,
      44              :    48, 48, 48, 48, 48, 48, 48, 63, 63, 0, 0, 0, 0, 0, 0,
      45              :    0, 0, 0, 0, 0, 0, 0, 63, 63, 48, 48, 48, 48, 48, 48,
      46              :    0, 0, 0, 0, 0, 0, 0, 496, 496, 48, 48, 48, 48, 48, 48,
      47              :    48, 48, 48, 48, 48, 48, 48, 496, 496, 0, 0, 0, 0, 0, 0,
      48              :    48, 48, 48, 48, 48, 48, 48, 511, 511, 48, 48, 48, 48, 48, 48,
      49              :    0, 0, 0, 511, 511, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      50              :    0, 0, 0, 0, 0, 511, 511, 0, 0, 0, 0, 0, 0, 0, 0,
      51              :    0, 0, 0, 0, 0, 0, 0, 511, 511, 0, 0, 0, 0, 0, 0,
      52              :    0, 0, 0, 0, 0, 0, 0, 0, 0, 511, 511, 0, 0, 0, 0,
      53              :    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 511, 511, 0, 0,
      54              :    48, 48, 48, 48, 48, 48, 48, 496, 496, 48, 48, 48, 48, 48, 48,
      55              :    48, 48, 48, 48, 48, 48, 48, 63, 63, 48, 48, 48, 48, 48, 48,
      56              :    48, 48, 48, 48, 48, 48, 48, 511, 511, 0, 0, 0, 0, 0, 0,
      57              :    0, 0, 0, 0, 0, 0, 0, 511, 511, 48, 48, 48, 48, 48, 48,
      58              :    48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
      59              :    0, 0, 0, 448, 112, 28, 6, 28, 112, 448, 0, 510, 510, 0, 0,
      60              :    0, 0, 0, 14, 56, 224, 384, 224, 56, 14, 0, 510, 510, 0, 0,
      61              :    0, 0, 0, 0, 0, 510, 510, 200, 200, 200, 206, 206, 0, 0, 0,
      62              :    0, 0, 0, 384, 192, 510, 510, 48, 510, 510, 12, 6, 0, 0, 0,
      63              :    0, 0, 0, 240, 408, 24, 24, 252, 24, 24, 62, 506, 14, 0, 0,
      64              :    0, 0, 0, 0, 0, 0, 0, 48, 48, 0, 0, 0, 0, 0, 0,
      65              :    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      66              :    0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 0, 0, 0,
      67              :    0, 0, 216, 216, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      68              :    0, 0, 0, 108, 108, 254, 108, 108, 254, 108, 108, 0, 0, 0, 0,
      69              :    0, 0, 32, 248, 428, 44, 60, 248, 480, 416, 428, 248, 32, 0, 0,
      70              :    0, 0, 396, 222, 222, 108, 48, 48, 216, 492, 492, 198, 0, 0, 0,
      71              :    0, 0, 60, 102, 102, 102, 60, 102, 486, 198, 230, 444, 0, 0, 0,
      72              :    0, 0, 240, 112, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      73              :    0, 96, 48, 24, 24, 12, 12, 12, 12, 24, 24, 48, 96, 0, 0,
      74              :    0, 12, 24, 48, 48, 96, 96, 96, 96, 48, 48, 24, 12, 0, 0,
      75              :    0, 0, 0, 16, 214, 124, 56, 238, 56, 124, 214, 16, 0, 0, 0,
      76              :    0, 0, 0, 0, 48, 48, 48, 510, 48, 48, 48, 0, 0, 0, 0,
      77              :    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 56, 12, 0, 0,
      78              :    0, 0, 0, 0, 0, 0, 0, 510, 0, 0, 0, 0, 0, 0, 0,
      79              :    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 120, 48, 0, 0,
      80              :    0, 0, 384, 192, 192, 96, 48, 48, 24, 12, 12, 6, 0, 0, 0,
      81              :    0, 0, 120, 204, 390, 390, 390, 390, 390, 390, 204, 120, 0, 0, 0,
      82              :    0, 0, 48, 56, 60, 48, 48, 48, 48, 48, 48, 252, 0, 0, 0,
      83              :    0, 0, 252, 390, 390, 384, 192, 96, 56, 12, 6, 510, 0, 0, 0,
      84              :    0, 0, 510, 384, 192, 96, 240, 384, 384, 384, 390, 252, 0, 0, 0,
      85              :    0, 0, 192, 224, 240, 216, 204, 198, 510, 192, 192, 192, 0, 0, 0,
      86              :    0, 0, 510, 6, 6, 254, 398, 384, 384, 384, 390, 252, 0, 0, 0,
      87              :    0, 0, 248, 12, 6, 6, 254, 398, 390, 390, 390, 252, 0, 0, 0,
      88              :    0, 0, 510, 384, 384, 192, 96, 48, 24, 24, 12, 12, 0, 0, 0,
      89              :    0, 0, 252, 390, 390, 390, 252, 390, 390, 390, 390, 252, 0, 0, 0,
      90              :    0, 0, 252, 390, 390, 390, 454, 508, 384, 384, 192, 124, 0, 0, 0,
      91              :    0, 0, 0, 0, 0, 48, 120, 48, 0, 0, 48, 120, 48, 0, 0,
      92              :    0, 0, 0, 0, 0, 48, 120, 48, 0, 0, 120, 56, 12, 0, 0,
      93              :    0, 0, 192, 96, 48, 24, 12, 12, 24, 48, 96, 192, 0, 0, 0,
      94              :    0, 0, 0, 0, 0, 0, 510, 0, 0, 510, 0, 0, 0, 0, 0,
      95              :    0, 0, 12, 24, 48, 96, 192, 192, 96, 48, 24, 12, 0, 0, 0,
      96              :    0, 0, 252, 390, 390, 384, 192, 96, 48, 48, 0, 48, 0, 0, 0,
      97              :    0, 0, 252, 390, 390, 502, 414, 478, 502, 6, 6, 252, 0, 0, 0,
      98              :    0, 0, 48, 120, 204, 390, 390, 390, 510, 390, 390, 390, 0, 0, 0,
      99              :    0, 0, 254, 396, 396, 396, 252, 396, 396, 396, 396, 254, 0, 0, 0,
     100              :    0, 0, 252, 390, 6, 6, 6, 6, 6, 6, 390, 252, 0, 0, 0,
     101              :    0, 0, 254, 396, 396, 396, 396, 396, 396, 396, 396, 254, 0, 0, 0,
     102              :    0, 0, 510, 12, 12, 12, 124, 12, 12, 12, 12, 510, 0, 0, 0,
     103              :    0, 0, 510, 12, 12, 12, 124, 12, 12, 12, 12, 12, 0, 0, 0,
     104              :    0, 0, 252, 390, 6, 6, 6, 486, 390, 390, 390, 252, 0, 0, 0,
     105              :    0, 0, 390, 390, 390, 390, 510, 390, 390, 390, 390, 390, 0, 0, 0,
     106              :    0, 0, 252, 48, 48, 48, 48, 48, 48, 48, 48, 252, 0, 0, 0,
     107              :    0, 0, 496, 192, 192, 192, 192, 192, 192, 192, 198, 124, 0, 0, 0,
     108              :    0, 0, 390, 198, 102, 54, 30, 30, 54, 102, 198, 390, 0, 0, 0,
     109              :    0, 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 510, 0, 0, 0,
     110              :    0, 0, 390, 390, 462, 510, 510, 438, 438, 390, 390, 390, 0, 0, 0,
     111              :    0, 0, 390, 390, 398, 414, 438, 486, 454, 390, 390, 390, 0, 0, 0,
     112              :    0, 0, 252, 390, 390, 390, 390, 390, 390, 390, 390, 252, 0, 0, 0,
     113              :    0, 0, 254, 390, 390, 390, 254, 6, 6, 6, 6, 6, 0, 0, 0,
     114              :    0, 0, 252, 390, 390, 390, 390, 390, 390, 438, 486, 252, 384, 0, 0,
     115              :    0, 0, 254, 390, 390, 390, 254, 54, 102, 198, 390, 390, 0, 0, 0,
     116              :    0, 0, 252, 390, 6, 6, 252, 384, 384, 384, 390, 252, 0, 0, 0,
     117              :    0, 0, 510, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0,
     118              :    0, 0, 390, 390, 390, 390, 390, 390, 390, 390, 390, 252, 0, 0, 0,
     119              :    0, 0, 390, 390, 390, 204, 204, 204, 120, 120, 120, 48, 0, 0, 0,
     120              :    0, 0, 390, 390, 390, 390, 438, 438, 438, 438, 510, 204, 0, 0, 0,
     121              :    0, 0, 390, 390, 204, 120, 48, 48, 120, 204, 390, 390, 0, 0, 0,
     122              :    0, 0, 390, 390, 204, 120, 48, 48, 48, 48, 48, 48, 0, 0, 0,
     123              :    0, 0, 510, 384, 192, 96, 48, 24, 12, 6, 6, 510, 0, 0, 0,
     124              :    0, 0, 248, 24, 24, 24, 24, 24, 24, 24, 24, 248, 0, 0, 0,
     125              :    0, 0, 6, 12, 12, 24, 48, 48, 96, 192, 192, 384, 0, 0, 0,
     126              :    0, 0, 124, 96, 96, 96, 96, 96, 96, 96, 96, 124, 0, 0, 0,
     127              :    0, 0, 48, 120, 204, 390, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     128              :    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 511, 0, 0,
     129              :    0, 0, 60, 56, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     130              :    0, 0, 0, 0, 0, 252, 384, 384, 508, 390, 454, 508, 0, 0, 0,
     131              :    0, 0, 6, 6, 6, 254, 398, 390, 390, 390, 398, 254, 0, 0, 0,
     132              :    0, 0, 0, 0, 0, 252, 390, 6, 6, 6, 390, 252, 0, 0, 0,
     133              :    0, 0, 384, 384, 384, 508, 454, 390, 390, 390, 454, 508, 0, 0, 0,
     134              :    0, 0, 0, 0, 0, 252, 390, 390, 510, 6, 6, 252, 0, 0, 0,
     135              :    0, 0, 240, 408, 408, 24, 24, 126, 24, 24, 24, 24, 0, 0, 0,
     136              :    0, 0, 0, 0, 0, 508, 198, 198, 198, 124, 6, 252, 390, 390, 252,
     137              :    0, 0, 6, 6, 6, 254, 398, 390, 390, 390, 390, 390, 0, 0, 0,
     138              :    0, 0, 0, 48, 0, 56, 48, 48, 48, 48, 48, 252, 0, 0, 0,
     139              :    0, 0, 0, 192, 0, 240, 192, 192, 192, 192, 192, 198, 198, 198, 124,
     140              :    0, 0, 6, 6, 6, 390, 230, 62, 14, 62, 230, 390, 0, 0, 0,
     141              :    0, 0, 56, 48, 48, 48, 48, 48, 48, 48, 48, 252, 0, 0, 0,
     142              :    0, 0, 0, 0, 0, 254, 438, 438, 438, 438, 438, 390, 0, 0, 0,
     143              :    0, 0, 0, 0, 0, 254, 398, 390, 390, 390, 390, 390, 0, 0, 0,
     144              :    0, 0, 0, 0, 0, 252, 390, 390, 390, 390, 390, 252, 0, 0, 0,
     145              :    0, 0, 0, 0, 0, 254, 398, 390, 390, 390, 398, 254, 6, 6, 6,
     146              :    0, 0, 0, 0, 0, 508, 454, 390, 390, 390, 454, 508, 384, 384, 384,
     147              :    0, 0, 0, 0, 0, 246, 412, 396, 12, 12, 12, 12, 0, 0, 0,
     148              :    0, 0, 0, 0, 0, 252, 390, 6, 252, 384, 390, 252, 0, 0, 0,
     149              :    0, 0, 0, 24, 24, 254, 24, 24, 24, 24, 408, 240, 0, 0, 0,
     150              :    0, 0, 0, 0, 0, 198, 198, 198, 198, 198, 198, 508, 0, 0, 0,
     151              :    0, 0, 0, 0, 0, 390, 390, 204, 204, 120, 120, 48, 0, 0, 0,
     152              :    0, 0, 0, 0, 0, 390, 390, 438, 438, 438, 510, 204, 0, 0, 0,
     153              :    0, 0, 0, 0, 0, 390, 204, 120, 48, 120, 204, 390, 0, 0, 0,
     154              :    0, 0, 0, 0, 0, 198, 198, 198, 198, 198, 230, 252, 192, 198, 124,
     155              :    0, 0, 0, 0, 0, 510, 192, 96, 48, 24, 12, 510, 0, 0, 0,
     156              :    0, 0, 480, 48, 48, 96, 56, 56, 96, 48, 48, 480, 0, 0, 0,
     157              :    0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0,
     158              :    0, 0, 30, 48, 48, 24, 112, 112, 24, 48, 48, 30, 0, 0, 0,
     159              :    0, 0, 412, 438, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     160              :    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     161              : };
     162              : 
     163              : int gdFontMediumBoldData[] = {
     164              :    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     165              :    0, 0, 0, 0, 0, 12, 30, 63, 30, 12, 0, 0, 0,
     166              :    0, 0, 0, 51, 51, 12, 51, 51, 12, 51, 51, 0, 0,
     167              :    0, 27, 27, 31, 27, 27, 0, 60, 24, 24, 24, 24, 0,
     168              :    0, 15, 3, 7, 3, 3, 0, 60, 12, 28, 12, 12, 0,
     169              :    0, 14, 3, 3, 3, 14, 0, 28, 44, 28, 44, 44, 0,
     170              :    0, 3, 3, 3, 3, 15, 0, 60, 12, 28, 12, 12, 0,
     171              :    0, 0, 30, 51, 51, 30, 0, 0, 0, 0, 0, 0, 0,
     172              :    0, 0, 12, 12, 63, 63, 12, 12, 0, 63, 63, 0, 0,
     173              :    0, 51, 55, 63, 59, 51, 0, 12, 12, 12, 12, 60, 0,
     174              :    0, 51, 51, 18, 30, 12, 0, 60, 24, 24, 24, 24, 0,
     175              :    12, 12, 12, 12, 12, 12, 15, 15, 0, 0, 0, 0, 0,
     176              :    0, 0, 0, 0, 0, 0, 15, 15, 12, 12, 12, 12, 12,
     177              :    0, 0, 0, 0, 0, 0, 124, 124, 12, 12, 12, 12, 12,
     178              :    12, 12, 12, 12, 12, 12, 124, 124, 0, 0, 0, 0, 0,
     179              :    12, 12, 12, 12, 12, 12, 127, 127, 12, 12, 12, 12, 12,
     180              :    0, 0, 127, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     181              :    0, 0, 0, 0, 127, 127, 0, 0, 0, 0, 0, 0, 0,
     182              :    0, 0, 0, 0, 0, 0, 127, 127, 0, 0, 0, 0, 0,
     183              :    0, 0, 0, 0, 0, 0, 0, 0, 127, 127, 0, 0, 0,
     184              :    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 127, 0,
     185              :    12, 12, 12, 12, 12, 12, 124, 124, 12, 12, 12, 12, 12,
     186              :    12, 12, 12, 12, 12, 12, 15, 15, 12, 12, 12, 12, 12,
     187              :    12, 12, 12, 12, 12, 12, 127, 127, 0, 0, 0, 0, 0,
     188              :    0, 0, 0, 0, 0, 0, 127, 127, 12, 12, 12, 12, 12,
     189              :    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
     190              :    0, 0, 48, 24, 6, 3, 6, 24, 48, 63, 63, 0, 0,
     191              :    0, 0, 3, 6, 24, 48, 24, 6, 3, 63, 63, 0, 0,
     192              :    0, 0, 0, 0, 0, 63, 54, 54, 54, 55, 51, 0, 0,
     193              :    0, 0, 32, 48, 63, 63, 12, 63, 63, 3, 1, 0, 0,
     194              :    0, 0, 28, 54, 6, 6, 15, 6, 6, 54, 29, 0, 0,
     195              :    0, 0, 0, 0, 0, 0, 12, 12, 0, 0, 0, 0, 0,
     196              :    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     197              :    0, 0, 12, 12, 12, 12, 12, 12, 0, 12, 12, 0, 0,
     198              :    0, 0, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0,
     199              :    0, 0, 20, 20, 62, 62, 20, 62, 62, 20, 20, 0, 0,
     200              :    0, 0, 12, 30, 45, 13, 30, 44, 45, 30, 12, 0, 0,
     201              :    0, 0, 39, 53, 23, 24, 12, 6, 58, 43, 57, 0, 0,
     202              :    0, 0, 14, 27, 27, 27, 14, 43, 59, 27, 46, 0, 0,
     203              :    0, 0, 28, 28, 12, 6, 0, 0, 0, 0, 0, 0, 0,
     204              :    0, 0, 24, 12, 12, 6, 6, 6, 12, 12, 24, 0, 0,
     205              :    0, 0, 6, 12, 12, 24, 24, 24, 12, 12, 6, 0, 0,
     206              :    0, 0, 0, 0, 18, 12, 63, 63, 12, 18, 0, 0, 0,
     207              :    0, 0, 0, 0, 12, 12, 63, 63, 12, 12, 0, 0, 0,
     208              :    0, 0, 0, 0, 0, 0, 0, 0, 28, 28, 12, 6, 0,
     209              :    0, 0, 0, 0, 0, 0, 63, 63, 0, 0, 0, 0, 0,
     210              :    0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 30, 12, 0,
     211              :    0, 0, 48, 48, 24, 24, 12, 6, 6, 3, 3, 0, 0,
     212              :    0, 0, 12, 18, 51, 51, 51, 51, 51, 18, 12, 0, 0,
     213              :    0, 0, 12, 14, 13, 12, 12, 12, 12, 12, 63, 0, 0,
     214              :    0, 0, 30, 51, 51, 48, 28, 6, 3, 3, 63, 0, 0,
     215              :    0, 0, 30, 51, 48, 48, 28, 48, 48, 51, 30, 0, 0,
     216              :    0, 0, 48, 56, 60, 54, 51, 51, 63, 48, 48, 0, 0,
     217              :    0, 0, 63, 3, 3, 31, 51, 48, 48, 51, 30, 0, 0,
     218              :    0, 0, 30, 51, 3, 3, 31, 51, 51, 51, 30, 0, 0,
     219              :    0, 0, 63, 48, 48, 24, 24, 12, 12, 6, 6, 0, 0,
     220              :    0, 0, 30, 51, 51, 51, 30, 51, 51, 51, 30, 0, 0,
     221              :    0, 0, 30, 51, 51, 51, 62, 48, 48, 51, 30, 0, 0,
     222              :    0, 0, 0, 0, 12, 30, 12, 0, 0, 12, 30, 12, 0,
     223              :    0, 0, 0, 0, 12, 30, 12, 0, 28, 28, 12, 6, 0,
     224              :    0, 0, 48, 24, 12, 6, 3, 6, 12, 24, 48, 0, 0,
     225              :    0, 0, 0, 0, 63, 63, 0, 63, 63, 0, 0, 0, 0,
     226              :    0, 0, 3, 6, 12, 24, 48, 24, 12, 6, 3, 0, 0,
     227              :    0, 0, 30, 51, 51, 48, 28, 12, 0, 12, 12, 0, 0,
     228              :    0, 0, 30, 49, 49, 61, 53, 61, 1, 49, 30, 0, 0,
     229              :    0, 0, 30, 51, 51, 51, 63, 51, 51, 51, 51, 0, 0,
     230              :    0, 0, 31, 51, 51, 51, 31, 51, 51, 51, 31, 0, 0,
     231              :    0, 0, 30, 51, 3, 3, 3, 3, 3, 51, 30, 0, 0,
     232              :    0, 0, 31, 51, 51, 51, 51, 51, 51, 51, 31, 0, 0,
     233              :    0, 0, 63, 3, 3, 3, 31, 3, 3, 3, 63, 0, 0,
     234              :    0, 0, 63, 3, 3, 3, 31, 3, 3, 3, 3, 0, 0,
     235              :    0, 0, 30, 51, 3, 3, 59, 51, 51, 51, 62, 0, 0,
     236              :    0, 0, 51, 51, 51, 51, 63, 51, 51, 51, 51, 0, 0,
     237              :    0, 0, 63, 12, 12, 12, 12, 12, 12, 12, 63, 0, 0,
     238              :    0, 0, 48, 48, 48, 48, 48, 48, 48, 51, 30, 0, 0,
     239              :    0, 0, 35, 51, 27, 15, 7, 15, 27, 51, 35, 0, 0,
     240              :    0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 63, 0, 0,
     241              :    0, 0, 33, 51, 63, 63, 51, 51, 51, 51, 51, 0, 0,
     242              :    0, 0, 51, 51, 55, 55, 63, 59, 59, 51, 51, 0, 0,
     243              :    0, 0, 30, 51, 51, 51, 51, 51, 51, 51, 30, 0, 0,
     244              :    0, 0, 31, 51, 51, 51, 31, 3, 3, 3, 3, 0, 0,
     245              :    0, 0, 30, 51, 51, 51, 51, 51, 55, 59, 30, 48, 0,
     246              :    0, 0, 31, 51, 51, 51, 31, 15, 27, 51, 35, 0, 0,
     247              :    0, 0, 30, 51, 3, 3, 30, 48, 48, 51, 30, 0, 0,
     248              :    0, 0, 63, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0,
     249              :    0, 0, 51, 51, 51, 51, 51, 51, 51, 51, 30, 0, 0,
     250              :    0, 0, 51, 51, 51, 18, 18, 30, 12, 12, 12, 0, 0,
     251              :    0, 0, 51, 51, 51, 51, 51, 63, 63, 51, 33, 0, 0,
     252              :    0, 0, 33, 51, 18, 30, 12, 30, 18, 51, 33, 0, 0,
     253              :    0, 0, 51, 51, 30, 30, 12, 12, 12, 12, 12, 0, 0,
     254              :    0, 0, 63, 48, 48, 24, 12, 6, 3, 3, 63, 0, 0,
     255              :    0, 0, 30, 6, 6, 6, 6, 6, 6, 6, 30, 0, 0,
     256              :    0, 0, 3, 3, 6, 6, 12, 24, 24, 48, 48, 0, 0,
     257              :    0, 0, 30, 24, 24, 24, 24, 24, 24, 24, 30, 0, 0,
     258              :    0, 0, 12, 30, 51, 33, 0, 0, 0, 0, 0, 0, 0,
     259              :    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 63, 0,
     260              :    0, 0, 14, 14, 12, 24, 0, 0, 0, 0, 0, 0, 0,
     261              :    0, 0, 0, 0, 0, 30, 48, 62, 51, 51, 62, 0, 0,
     262              :    0, 0, 3, 3, 3, 31, 51, 51, 51, 51, 31, 0, 0,
     263              :    0, 0, 0, 0, 0, 30, 51, 3, 3, 51, 30, 0, 0,
     264              :    0, 0, 48, 48, 48, 62, 51, 51, 51, 51, 62, 0, 0,
     265              :    0, 0, 0, 0, 0, 30, 51, 63, 3, 51, 30, 0, 0,
     266              :    0, 0, 28, 54, 6, 6, 15, 6, 6, 6, 6, 0, 0,
     267              :    0, 0, 0, 0, 0, 46, 51, 51, 30, 3, 30, 51, 30,
     268              :    0, 0, 3, 3, 3, 31, 51, 51, 51, 51, 51, 0, 0,
     269              :    0, 0, 12, 12, 0, 14, 12, 12, 12, 12, 63, 0, 0,
     270              :    0, 0, 48, 48, 0, 48, 48, 48, 48, 48, 48, 51, 30,
     271              :    0, 0, 3, 3, 3, 51, 27, 15, 15, 27, 51, 0, 0,
     272              :    0, 0, 14, 12, 12, 12, 12, 12, 12, 12, 63, 0, 0,
     273              :    0, 0, 0, 0, 0, 27, 63, 63, 51, 51, 51, 0, 0,
     274              :    0, 0, 0, 0, 0, 31, 51, 51, 51, 51, 51, 0, 0,
     275              :    0, 0, 0, 0, 0, 30, 51, 51, 51, 51, 30, 0, 0,
     276              :    0, 0, 0, 0, 0, 31, 51, 51, 51, 31, 3, 3, 3,
     277              :    0, 0, 0, 0, 0, 62, 51, 51, 51, 62, 48, 48, 48,
     278              :    0, 0, 0, 0, 0, 31, 51, 3, 3, 3, 3, 0, 0,
     279              :    0, 0, 0, 0, 0, 30, 51, 6, 24, 51, 30, 0, 0,
     280              :    0, 0, 0, 3, 3, 15, 3, 3, 3, 51, 30, 0, 0,
     281              :    0, 0, 0, 0, 0, 51, 51, 51, 51, 51, 62, 0, 0,
     282              :    0, 0, 0, 0, 0, 51, 51, 51, 30, 30, 12, 0, 0,
     283              :    0, 0, 0, 0, 0, 51, 51, 51, 63, 63, 18, 0, 0,
     284              :    0, 0, 0, 0, 0, 51, 51, 30, 30, 51, 51, 0, 0,
     285              :    0, 0, 0, 0, 0, 51, 51, 51, 51, 62, 48, 51, 30,
     286              :    0, 0, 0, 0, 0, 63, 48, 24, 6, 3, 63, 0, 0,
     287              :    0, 0, 28, 6, 6, 12, 6, 12, 6, 6, 28, 0, 0,
     288              :    0, 0, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0,
     289              :    0, 0, 14, 24, 24, 12, 24, 12, 24, 24, 14, 0, 0,
     290              :    0, 0, 38, 63, 25, 0, 0, 0, 0, 0, 0, 0, 0,
     291              :    42, 20, 42, 20, 42, 20, 42, 20, 42, 20, 42, 20, 42,
     292              : };
     293              : 
     294              : int gdFontSmallData[] = {
     295              :    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     296              :    0, 0, 4, 4, 4, 4, 4, 0, 4, 0, 0, 0,
     297              :    0, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0,
     298              :    0, 0, 0, 10, 31, 10, 10, 31, 10, 0, 0, 0,
     299              :    0, 4, 14, 21, 5, 14, 20, 21, 14, 4, 0, 0,
     300              :    0, 0, 31, 19, 8, 4, 2, 25, 25, 0, 0, 0,
     301              :    0, 0, 2, 5, 5, 2, 21, 9, 22, 0, 0, 0,
     302              :    0, 6, 6, 3, 0, 0, 0, 0, 0, 0, 0, 0,
     303              :    0, 0, 16, 8, 4, 4, 4, 8, 16, 0, 0, 0,
     304              :    0, 0, 1, 2, 4, 4, 4, 2, 1, 0, 0, 0,
     305              :    0, 0, 4, 21, 14, 4, 14, 21, 4, 0, 0, 0,
     306              :    0, 0, 0, 4, 4, 31, 4, 4, 0, 0, 0, 0,
     307              :    0, 0, 0, 0, 0, 0, 0, 6, 6, 3, 0, 0,
     308              :    0, 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0,
     309              :    0, 0, 0, 0, 0, 0, 0, 6, 6, 0, 0, 0,
     310              :    0, 0, 0, 16, 8, 4, 2, 1, 0, 0, 0, 0,
     311              :    0, 0, 14, 17, 25, 21, 19, 17, 14, 0, 0, 0,
     312              :    0, 0, 4, 6, 4, 4, 4, 4, 14, 0, 0, 0,
     313              :    0, 0, 14, 17, 16, 8, 4, 2, 31, 0, 0, 0,
     314              :    0, 0, 14, 17, 16, 12, 16, 17, 14, 0, 0, 0,
     315              :    0, 0, 8, 12, 10, 9, 31, 8, 8, 0, 0, 0,
     316              :    0, 0, 31, 1, 15, 16, 16, 17, 14, 0, 0, 0,
     317              :    0, 0, 12, 2, 1, 15, 17, 17, 14, 0, 0, 0,
     318              :    0, 0, 31, 16, 8, 8, 4, 4, 4, 0, 0, 0,
     319              :    0, 0, 14, 17, 17, 14, 17, 17, 14, 0, 0, 0,
     320              :    0, 0, 14, 17, 17, 30, 16, 8, 6, 0, 0, 0,
     321              :    0, 0, 0, 0, 6, 6, 0, 6, 6, 0, 0, 0,
     322              :    0, 0, 0, 0, 6, 6, 0, 6, 6, 3, 0, 0,
     323              :    0, 0, 0, 8, 4, 2, 4, 8, 0, 0, 0, 0,
     324              :    0, 0, 0, 0, 31, 0, 31, 0, 0, 0, 0, 0,
     325              :    0, 0, 0, 2, 4, 8, 4, 2, 0, 0, 0, 0,
     326              :    0, 0, 14, 17, 8, 4, 4, 0, 4, 0, 0, 0,
     327              :    0, 0, 14, 17, 29, 21, 29, 1, 14, 0, 0, 0,
     328              :    0, 0, 14, 17, 17, 31, 17, 17, 17, 0, 0, 0,
     329              :    0, 0, 15, 17, 17, 15, 17, 17, 15, 0, 0, 0,
     330              :    0, 0, 14, 17, 1, 1, 1, 17, 14, 0, 0, 0,
     331              :    0, 0, 15, 18, 18, 18, 18, 18, 15, 0, 0, 0,
     332              :    0, 0, 31, 1, 1, 15, 1, 1, 31, 0, 0, 0,
     333              :    0, 0, 31, 1, 1, 15, 1, 1, 1, 0, 0, 0,
     334              :    0, 0, 14, 17, 1, 1, 25, 17, 14, 0, 0, 0,
     335              :    0, 0, 17, 17, 17, 31, 17, 17, 17, 0, 0, 0,
     336              :    0, 0, 14, 4, 4, 4, 4, 4, 14, 0, 0, 0,
     337              :    0, 0, 16, 16, 16, 16, 16, 17, 14, 0, 0, 0,
     338              :    0, 0, 17, 9, 5, 3, 5, 9, 17, 0, 0, 0,
     339              :    0, 0, 1, 1, 1, 1, 1, 1, 31, 0, 0, 0,
     340              :    0, 0, 17, 27, 21, 17, 17, 17, 17, 0, 0, 0,
     341              :    0, 0, 17, 17, 19, 21, 25, 17, 17, 0, 0, 0,
     342              :    0, 0, 14, 17, 17, 17, 17, 17, 14, 0, 0, 0,
     343              :    0, 0, 15, 17, 17, 15, 1, 1, 1, 0, 0, 0,
     344              :    0, 0, 14, 17, 17, 17, 21, 9, 22, 0, 0, 0,
     345              :    0, 0, 15, 17, 17, 15, 5, 9, 17, 0, 0, 0,
     346              :    0, 0, 14, 17, 1, 14, 16, 17, 14, 0, 0, 0,
     347              :    0, 0, 31, 4, 4, 4, 4, 4, 4, 0, 0, 0,
     348              :    0, 0, 17, 17, 17, 17, 17, 17, 14, 0, 0, 0,
     349              :    0, 0, 17, 17, 17, 17, 10, 10, 4, 0, 0, 0,
     350              :    0, 0, 17, 17, 17, 17, 21, 27, 17, 0, 0, 0,
     351              :    0, 0, 17, 17, 10, 4, 10, 17, 17, 0, 0, 0,
     352              :    0, 0, 17, 17, 10, 4, 4, 4, 4, 0, 0, 0,
     353              :    0, 0, 31, 16, 8, 31, 2, 1, 31, 0, 0, 0,
     354              :    0, 28, 4, 4, 4, 4, 4, 4, 4, 28, 0, 0,
     355              :    0, 0, 0, 1, 2, 4, 8, 16, 0, 0, 0, 0,
     356              :    0, 7, 4, 4, 4, 4, 4, 4, 4, 7, 0, 0,
     357              :    0, 4, 10, 17, 0, 0, 0, 0, 0, 0, 0, 0,
     358              :    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0,
     359              :    0, 12, 12, 24, 0, 0, 0, 0, 0, 0, 0, 0,
     360              :    0, 0, 0, 0, 14, 16, 30, 17, 30, 0, 0, 0,
     361              :    0, 0, 1, 1, 15, 17, 17, 17, 15, 0, 0, 0,
     362              :    0, 0, 0, 0, 14, 17, 1, 1, 30, 0, 0, 0,
     363              :    0, 0, 16, 16, 30, 17, 17, 17, 30, 0, 0, 0,
     364              :    0, 0, 0, 0, 14, 17, 15, 1, 14, 0, 0, 0,
     365              :    0, 0, 12, 18, 2, 7, 2, 2, 2, 0, 0, 0,
     366              :    0, 0, 0, 0, 14, 17, 17, 17, 30, 16, 14, 0,
     367              :    0, 0, 1, 1, 15, 17, 17, 17, 17, 0, 0, 0,
     368              :    0, 0, 0, 4, 0, 4, 4, 4, 4, 0, 0, 0,
     369              :    0, 0, 0, 16, 0, 16, 16, 16, 16, 17, 14, 0,
     370              :    0, 0, 1, 1, 17, 9, 7, 9, 17, 0, 0, 0,
     371              :    0, 0, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0,
     372              :    0, 0, 0, 0, 11, 21, 21, 21, 21, 0, 0, 0,
     373              :    0, 0, 0, 0, 13, 19, 17, 17, 17, 0, 0, 0,
     374              :    0, 0, 0, 0, 14, 17, 17, 17, 14, 0, 0, 0,
     375              :    0, 0, 0, 0, 15, 17, 17, 17, 15, 1, 1, 0,
     376              :    0, 0, 0, 0, 14, 17, 17, 17, 30, 16, 16, 0,
     377              :    0, 0, 0, 0, 13, 19, 1, 1, 1, 0, 0, 0,
     378              :    0, 0, 0, 0, 30, 1, 14, 16, 15, 0, 0, 0,
     379              :    0, 0, 4, 4, 31, 4, 4, 4, 24, 0, 0, 0,
     380              :    0, 0, 0, 0, 17, 17, 17, 17, 14, 0, 0, 0,
     381              :    0, 0, 0, 0, 17, 17, 17, 10, 4, 0, 0, 0,
     382              :    0, 0, 0, 0, 17, 17, 21, 21, 10, 0, 0, 0,
     383              :    0, 0, 0, 0, 17, 10, 4, 10, 17, 0, 0, 0,
     384              :    0, 0, 0, 0, 17, 17, 17, 10, 4, 2, 1, 0,
     385              :    0, 0, 0, 0, 31, 8, 14, 2, 31, 0, 0, 0,
     386              :    0, 16, 8, 8, 8, 4, 8, 8, 8, 16, 0, 0,
     387              :    0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0,
     388              :    0, 1, 2, 2, 2, 4, 2, 2, 2, 1, 0, 0,
     389              :    0, 22, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     390              :    0, 0, 1, 1, 15, 17, 17, 17, 15, 0, 0, 0,
     391              : };
     392              : 
     393              : gdFont gdFontGiantRep = {
     394              :    128, 0, 9, 15,
     395              :    gdFontGiantData
     396              : };
     397              : 
     398              : gdFont gdFontMediumBoldRep = {
     399              :    128, 0, 7, 13,
     400              :    gdFontMediumBoldData
     401              : };
     402              : 
     403              : gdFont gdFontSmallRep = {
     404              :    96, 32, 6, 12,
     405              :    gdFontSmallData
     406              : };
     407              : 
     408              : gdFontPtr gdFontMediumBold = &gdFontMediumBoldRep;
     409              : gdFontPtr gdFontGiant = &gdFontGiantRep;
     410              : gdFontPtr gdFontSmall = &gdFontSmallRep;
     411              : 
     412              : /*------------------------------------------------------------------*/
     413              : 
     414              : static void gdImageBrushApply(gdImagePtr im, int x, int y);
     415              : static void gdImageTileApply(gdImagePtr im, int x, int y);
     416              : 
     417            0 : gdImagePtr gdImageCreate(int sx, int sy)
     418              : {
     419              :    int i;
     420              :    gdImagePtr im;
     421            0 :    im = (gdImage *) M_MALLOC(sizeof(gdImage));
     422            0 :    im->pixels = (unsigned char **) M_MALLOC(sizeof(unsigned char *) * sx);
     423            0 :    im->polyInts = 0;
     424            0 :    im->polyAllocated = 0;
     425            0 :    im->brush = 0;
     426            0 :    im->tile = 0;
     427            0 :    im->style = 0;
     428            0 :    for (i = 0; (i < sx); i++) {
     429            0 :       im->pixels[i] = (unsigned char *) M_CALLOC(sy, sizeof(unsigned char));
     430              :    }
     431            0 :    im->sx = sx;
     432            0 :    im->sy = sy;
     433            0 :    im->colorsTotal = 0;
     434            0 :    im->transparent = (-1);
     435            0 :    im->interlace = 0;
     436            0 :    return im;
     437              : }
     438              : 
     439            0 : void gdImageDestroy(gdImagePtr im)
     440              : {
     441              :    int i;
     442            0 :    for (i = 0; (i < im->sx); i++) {
     443            0 :       M_FREE(im->pixels[i]);
     444              :    }
     445            0 :    M_FREE(im->pixels);
     446            0 :    if (im->polyInts) {
     447            0 :       M_FREE(im->polyInts);
     448              :    }
     449            0 :    if (im->style) {
     450            0 :       M_FREE(im->style);
     451              :    }
     452            0 :    M_FREE(im);
     453            0 : }
     454              : 
     455            0 : int gdImageColorClosest(gdImagePtr im, int r, int g, int b)
     456              : {
     457              :    int i;
     458              :    long rd, gd, bd;
     459            0 :    int ct = (-1);
     460            0 :    long mindist = 0;
     461            0 :    for (i = 0; (i < (im->colorsTotal)); i++) {
     462              :       long dist;
     463            0 :       if (im->open[i]) {
     464            0 :          continue;
     465              :       }
     466            0 :       rd = (im->red[i] - r);
     467            0 :       gd = (im->green[i] - g);
     468            0 :       bd = (im->blue[i] - b);
     469            0 :       dist = rd * rd + gd * gd + bd * bd;
     470            0 :       if ((i == 0) || (dist < mindist)) {
     471            0 :          mindist = dist;
     472            0 :          ct = i;
     473              :       }
     474              :    }
     475            0 :    return ct;
     476              : }
     477              : 
     478            0 : int gdImageColorExact(gdImagePtr im, int r, int g, int b)
     479              : {
     480              :    int i;
     481            0 :    for (i = 0; (i < (im->colorsTotal)); i++) {
     482            0 :       if (im->open[i]) {
     483            0 :          continue;
     484              :       }
     485            0 :       if ((im->red[i] == r) && (im->green[i] == g) && (im->blue[i] == b)) {
     486            0 :          return i;
     487              :       }
     488              :    }
     489            0 :    return -1;
     490              : }
     491              : 
     492            0 : int gdImageColorAllocate(gdImagePtr im, int r, int g, int b)
     493              : {
     494              :    int i;
     495            0 :    int ct = (-1);
     496              :    
     497              :    /* check if color exists already */
     498            0 :    for (i = 0; (i < (im->colorsTotal)); i++) {
     499            0 :       if (!im->open[i] &&
     500            0 :           im->red[i] == r &&
     501            0 :           im->green[i] == g &&
     502            0 :           im->blue[i] == b) {
     503            0 :          return i;
     504              :       }
     505              :    }
     506              :    
     507            0 :    for (i = 0; (i < (im->colorsTotal)); i++) {
     508            0 :       if (im->open[i]) {
     509            0 :          ct = i;
     510            0 :          break;
     511              :       }
     512              :    }
     513            0 :    if (ct == (-1)) {
     514            0 :       ct = im->colorsTotal;
     515            0 :       if (ct == gdMaxColors) {
     516            0 :          return -1;
     517              :       }
     518            0 :       im->colorsTotal++;
     519              :    }
     520            0 :    im->red[ct] = r;
     521            0 :    im->green[ct] = g;
     522            0 :    im->blue[ct] = b;
     523            0 :    im->open[ct] = 0;
     524            0 :    return ct;
     525              : }
     526              : 
     527            0 : void gdImageColorDeallocate(gdImagePtr im, int color)
     528              : {
     529              :    /* Mark it open. */
     530            0 :    im->open[color] = 1;
     531            0 : }
     532              : 
     533            0 : void gdImageColorTransparent(gdImagePtr im, int color)
     534              : {
     535            0 :    im->transparent = color;
     536            0 : }
     537              : 
     538            0 : void gdImageSetPixel(gdImagePtr im, int x, int y, int color)
     539              : {
     540              :    int p;
     541            0 :    switch (color) {
     542            0 :    case gdStyled:
     543            0 :       if (!im->style) {
     544              :          /* Refuse to draw if no style is set. */
     545            0 :          return;
     546              :       } else {
     547            0 :          p = im->style[im->stylePos++];
     548              :       }
     549            0 :       if (p != (gdTransparent)) {
     550            0 :          gdImageSetPixel(im, x, y, p);
     551              :       }
     552            0 :       im->stylePos = im->stylePos % im->styleLength;
     553            0 :       break;
     554            0 :    case gdStyledBrushed:
     555            0 :       if (!im->style) {
     556              :          /* Refuse to draw if no style is set. */
     557            0 :          return;
     558              :       }
     559            0 :       p = im->style[im->stylePos++];
     560            0 :       if ((p != gdTransparent) && (p != 0)) {
     561            0 :          gdImageSetPixel(im, x, y, gdBrushed);
     562              :       }
     563            0 :       im->stylePos = im->stylePos % im->styleLength;
     564            0 :       break;
     565            0 :    case gdBrushed:
     566            0 :       gdImageBrushApply(im, x, y);
     567            0 :       break;
     568            0 :    case gdTiled:
     569            0 :       gdImageTileApply(im, x, y);
     570            0 :       break;
     571            0 :    default:
     572            0 :       if (gdImageBoundsSafe(im, x, y)) {
     573            0 :          im->pixels[x][y] = color;
     574              :       }
     575            0 :       break;
     576              :    }
     577              : }
     578              : 
     579            0 : static void gdImageBrushApply(gdImagePtr im, int x, int y)
     580              : {
     581              :    int lx, ly;
     582              :    int hy;
     583              :    int hx;
     584              :    int x1, y1, x2, y2;
     585              :    int srcx, srcy;
     586            0 :    if (!im->brush) {
     587            0 :       return;
     588              :    }
     589            0 :    hy = gdImageSY(im->brush) / 2;
     590            0 :    y1 = y - hy;
     591            0 :    y2 = y1 + gdImageSY(im->brush);
     592            0 :    hx = gdImageSX(im->brush) / 2;
     593            0 :    x1 = x - hx;
     594            0 :    x2 = x1 + gdImageSX(im->brush);
     595            0 :    srcy = 0;
     596            0 :    for (ly = y1; (ly < y2); ly++) {
     597            0 :       srcx = 0;
     598            0 :       for (lx = x1; (lx < x2); lx++) {
     599              :          int p;
     600            0 :          p = gdImageGetPixel(im->brush, srcx, srcy);
     601              :          /* Allow for non-square brushes! */
     602            0 :          if (p != gdImageGetTransparent(im->brush)) {
     603            0 :             gdImageSetPixel(im, lx, ly, im->brushColorMap[p]);
     604              :          }
     605            0 :          srcx++;
     606              :       }
     607            0 :       srcy++;
     608              :    }
     609              : }
     610              : 
     611            0 : static void gdImageTileApply(gdImagePtr im, int x, int y)
     612              : {
     613              :    int srcx, srcy;
     614              :    int p;
     615            0 :    if (!im->tile) {
     616            0 :       return;
     617              :    }
     618            0 :    srcx = x % gdImageSX(im->tile);
     619            0 :    srcy = y % gdImageSY(im->tile);
     620            0 :    p = gdImageGetPixel(im->tile, srcx, srcy);
     621              :    /* Allow for transparency */
     622            0 :    if (p != gdImageGetTransparent(im->tile)) {
     623            0 :       gdImageSetPixel(im, x, y, im->tileColorMap[p]);
     624              :    }
     625              : }
     626              : 
     627            0 : int gdImageGetPixel(gdImagePtr im, int x, int y)
     628              : {
     629            0 :    if (gdImageBoundsSafe(im, x, y)) {
     630            0 :       return im->pixels[x][y];
     631              :    } else {
     632            0 :       return 0;
     633              :    }
     634              : }
     635              : 
     636              : /* Bresenham as presented in Foley & Van Dam */
     637              : 
     638            0 : void gdImageLine(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
     639              : {
     640              :    int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
     641            0 :    dx = abs(x2 - x1);
     642            0 :    dy = abs(y2 - y1);
     643            0 :    if (dy <= dx) {
     644            0 :       d = 2 * dy - dx;
     645            0 :       incr1 = 2 * dy;
     646            0 :       incr2 = 2 * (dy - dx);
     647            0 :       if (x1 > x2) {
     648            0 :          x = x2;
     649            0 :          y = y2;
     650            0 :          ydirflag = (-1);
     651            0 :          xend = x1;
     652              :       } else {
     653            0 :          x = x1;
     654            0 :          y = y1;
     655            0 :          ydirflag = 1;
     656            0 :          xend = x2;
     657              :       }
     658            0 :       gdImageSetPixel(im, x, y, color);
     659            0 :       if (((y2 - y1) * ydirflag) > 0) {
     660            0 :          while (x < xend) {
     661            0 :             x++;
     662            0 :             if (d < 0) {
     663            0 :                d += incr1;
     664              :             } else {
     665            0 :                y++;
     666            0 :                d += incr2;
     667              :             }
     668            0 :             gdImageSetPixel(im, x, y, color);
     669              :          }
     670              :       } else {
     671            0 :          while (x < xend) {
     672            0 :             x++;
     673            0 :             if (d < 0) {
     674            0 :                d += incr1;
     675              :             } else {
     676            0 :                y--;
     677            0 :                d += incr2;
     678              :             }
     679            0 :             gdImageSetPixel(im, x, y, color);
     680              :          }
     681              :       }
     682              :    } else {
     683            0 :       d = 2 * dx - dy;
     684            0 :       incr1 = 2 * dx;
     685            0 :       incr2 = 2 * (dx - dy);
     686            0 :       if (y1 > y2) {
     687            0 :          y = y2;
     688            0 :          x = x2;
     689            0 :          yend = y1;
     690            0 :          xdirflag = (-1);
     691              :       } else {
     692            0 :          y = y1;
     693            0 :          x = x1;
     694            0 :          yend = y2;
     695            0 :          xdirflag = 1;
     696              :       }
     697            0 :       gdImageSetPixel(im, x, y, color);
     698            0 :       if (((x2 - x1) * xdirflag) > 0) {
     699            0 :          while (y < yend) {
     700            0 :             y++;
     701            0 :             if (d < 0) {
     702            0 :                d += incr1;
     703              :             } else {
     704            0 :                x++;
     705            0 :                d += incr2;
     706              :             }
     707            0 :             gdImageSetPixel(im, x, y, color);
     708              :          }
     709              :       } else {
     710            0 :          while (y < yend) {
     711            0 :             y++;
     712            0 :             if (d < 0) {
     713            0 :                d += incr1;
     714              :             } else {
     715            0 :                x--;
     716            0 :                d += incr2;
     717              :             }
     718            0 :             gdImageSetPixel(im, x, y, color);
     719              :          }
     720              :       }
     721              :    }
     722            0 : }
     723              : 
     724              : /* As above, plus dashing */
     725              : 
     726              : #define dashedSet \
     727              :         { \
     728              :                 dashStep++; \
     729              :                 if (dashStep == gdDashSize) { \
     730              :                         dashStep = 0; \
     731              :                         on = !on; \
     732              :                 } \
     733              :                 if (on) { \
     734              :                         gdImageSetPixel(im, x, y, color); \
     735              :                 } \
     736              :         }
     737              : 
     738            0 : void gdImageDashedLine(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
     739              : {
     740              :    int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
     741            0 :    int dashStep = 0;
     742            0 :    int on = 1;
     743            0 :    dx = abs(x2 - x1);
     744            0 :    dy = abs(y2 - y1);
     745            0 :    if (dy <= dx) {
     746            0 :       d = 2 * dy - dx;
     747            0 :       incr1 = 2 * dy;
     748            0 :       incr2 = 2 * (dy - dx);
     749            0 :       if (x1 > x2) {
     750            0 :          x = x2;
     751            0 :          y = y2;
     752            0 :          ydirflag = (-1);
     753            0 :          xend = x1;
     754              :       } else {
     755            0 :          x = x1;
     756            0 :          y = y1;
     757            0 :          ydirflag = 1;
     758            0 :          xend = x2;
     759              :       }
     760            0 :       dashedSet;
     761            0 :       if (((y2 - y1) * ydirflag) > 0) {
     762            0 :          while (x < xend) {
     763            0 :             x++;
     764            0 :             if (d < 0) {
     765            0 :                d += incr1;
     766              :             } else {
     767            0 :                y++;
     768            0 :                d += incr2;
     769              :             }
     770            0 :             dashedSet;
     771              :          }
     772              :       } else {
     773            0 :          while (x < xend) {
     774            0 :             x++;
     775            0 :             if (d < 0) {
     776            0 :                d += incr1;
     777              :             } else {
     778            0 :                y--;
     779            0 :                d += incr2;
     780              :             }
     781            0 :             dashedSet;
     782              :          }
     783              :       }
     784              :    } else {
     785            0 :       d = 2 * dx - dy;
     786            0 :       incr1 = 2 * dx;
     787            0 :       incr2 = 2 * (dx - dy);
     788            0 :       if (y1 > y2) {
     789            0 :          y = y2;
     790            0 :          x = x2;
     791            0 :          yend = y1;
     792            0 :          xdirflag = (-1);
     793              :       } else {
     794            0 :          y = y1;
     795            0 :          x = x1;
     796            0 :          yend = y2;
     797            0 :          xdirflag = 1;
     798              :       }
     799            0 :       dashedSet;
     800            0 :       if (((x2 - x1) * xdirflag) > 0) {
     801            0 :          while (y < yend) {
     802            0 :             y++;
     803            0 :             if (d < 0) {
     804            0 :                d += incr1;
     805              :             } else {
     806            0 :                x++;
     807            0 :                d += incr2;
     808              :             }
     809            0 :             dashedSet;
     810              :          }
     811              :       } else {
     812            0 :          while (y < yend) {
     813            0 :             y++;
     814            0 :             if (d < 0) {
     815            0 :                d += incr1;
     816              :             } else {
     817            0 :                x--;
     818            0 :                d += incr2;
     819              :             }
     820            0 :             dashedSet;
     821              :          }
     822              :       }
     823              :    }
     824            0 : }
     825              : 
     826            0 : int gdImageBoundsSafe(gdImagePtr im, int x, int y)
     827              : {
     828            0 :    return (!(((y < 0) || (y >= im->sy)) || ((x < 0) || (x >= im->sx))));
     829              : }
     830              : 
     831            0 : void gdImageChar(gdImagePtr im, gdFontPtr f, int x, int y, int c, int color)
     832              : {
     833              :    int cx, cy;
     834              :    int px, py;
     835              :    int fline;
     836            0 :    cx = 0;
     837            0 :    cy = 0;
     838            0 :    if ((c < f->offset) || (c >= (f->offset + f->nchars))) {
     839            0 :       return;
     840              :    }
     841            0 :    fline = (c - f->offset) * f->h;
     842            0 :    for (py = y; (py < (y + f->h)); py++) {
     843            0 :       for (px = x; (px < (x + f->w)); px++) {
     844            0 :          if (f->data[fline + cy] & (1 << cx)) {
     845            0 :             gdImageSetPixel(im, px, py, color);
     846              :          }
     847            0 :          cx++;
     848              :       }
     849            0 :       cx = 0;
     850            0 :       cy++;
     851              :    }
     852              : }
     853              : 
     854            0 : void gdImageCharUp(gdImagePtr im, gdFontPtr f, int x, int y, char c, int color)
     855              : {
     856              :    int cx, cy;
     857              :    int px, py;
     858              :    int fline;
     859            0 :    cx = 0;
     860            0 :    cy = 0;
     861            0 :    if ((c < f->offset) || (c >= (f->offset + f->nchars))) {
     862            0 :       return;
     863              :    }
     864            0 :    fline = (c - f->offset) * f->h;
     865            0 :    for (py = y; (py > (y - f->w)); py--) {
     866            0 :       for (px = x; (px < (x + f->h)); px++) {
     867            0 :          if (f->data[fline + cy] & (1 << cx)) {
     868            0 :             gdImageSetPixel(im, px, py, color);
     869              :          }
     870            0 :          cy++;
     871              :       }
     872            0 :       cy = 0;
     873            0 :       cx++;
     874              :    }
     875              : }
     876              : 
     877            0 : void gdImageString(gdImagePtr im, gdFontPtr f, int x, int y, const char *s, int color)
     878              : {
     879              :    int i;
     880              :    int l;
     881            0 :    l = strlen(s);
     882            0 :    for (i = 0; (i < l); i++) {
     883            0 :       gdImageChar(im, f, x, y, s[i], color);
     884            0 :       x += f->w;
     885              :    }
     886            0 : }
     887              : 
     888            0 : void gdImageStringUp(gdImagePtr im, gdFontPtr f, int x, int y, const char *s, int color)
     889              : {
     890              :    int i;
     891              :    int l;
     892            0 :    l = strlen(s);
     893            0 :    for (i = 0; (i < l); i++) {
     894            0 :       gdImageCharUp(im, f, x, y, s[i], color);
     895            0 :       y -= f->w;
     896              :    }
     897            0 : }
     898              : 
     899            0 : void gdImageFillToBorder(gdImagePtr im, int x, int y, int border, int color)
     900              : {
     901              :    int lastBorder;
     902              :    /* Seek left */
     903              :    int leftLimit, rightLimit;
     904              :    int i;
     905            0 :    leftLimit = (-1);
     906            0 :    if (border < 0) {
     907              :       /* Refuse to fill to a non-solid border */
     908            0 :       return;
     909              :    }
     910            0 :    for (i = x; (i >= 0); i--) {
     911            0 :       if (gdImageGetPixel(im, i, y) == border) {
     912            0 :          break;
     913              :       }
     914            0 :       gdImageSetPixel(im, i, y, color);
     915            0 :       leftLimit = i;
     916              :    }
     917            0 :    if (leftLimit == (-1)) {
     918            0 :       return;
     919              :    }
     920              :    /* Seek right */
     921            0 :    rightLimit = x;
     922            0 :    for (i = (x + 1); (i < im->sx); i++) {
     923            0 :       if (gdImageGetPixel(im, i, y) == border) {
     924            0 :          break;
     925              :       }
     926            0 :       gdImageSetPixel(im, i, y, color);
     927            0 :       rightLimit = i;
     928              :    }
     929              :    /* Look at lines above and below and start paints */
     930              :    /* Above */
     931            0 :    if (y > 0) {
     932            0 :       lastBorder = 1;
     933            0 :       for (i = leftLimit; (i <= rightLimit); i++) {
     934              :          int c;
     935            0 :          c = gdImageGetPixel(im, i, y - 1);
     936            0 :          if (lastBorder) {
     937            0 :             if ((c != border) && (c != color)) {
     938            0 :                gdImageFillToBorder(im, i, y - 1, border, color);
     939            0 :                lastBorder = 0;
     940              :             }
     941            0 :          } else if ((c == border) || (c == color)) {
     942            0 :             lastBorder = 1;
     943              :          }
     944              :       }
     945              :    }
     946              :    /* Below */
     947            0 :    if (y < ((im->sy) - 1)) {
     948            0 :       lastBorder = 1;
     949            0 :       for (i = leftLimit; (i <= rightLimit); i++) {
     950              :          int c;
     951            0 :          c = gdImageGetPixel(im, i, y + 1);
     952            0 :          if (lastBorder) {
     953            0 :             if ((c != border) && (c != color)) {
     954            0 :                gdImageFillToBorder(im, i, y + 1, border, color);
     955            0 :                lastBorder = 0;
     956              :             }
     957            0 :          } else if ((c == border) || (c == color)) {
     958            0 :             lastBorder = 1;
     959              :          }
     960              :       }
     961              :    }
     962              : }
     963              : 
     964            0 : void gdImageFill(gdImagePtr im, int x, int y, int color)
     965              : {
     966              :    int lastBorder;
     967              :    int old;
     968              :    int leftLimit, rightLimit;
     969              :    int i;
     970            0 :    old = gdImageGetPixel(im, x, y);
     971            0 :    if (color == gdTiled) {
     972              :       /* Tile fill -- got to watch out! */
     973              :       int p, tileColor;
     974              :       int srcx, srcy;
     975            0 :       if (!im->tile) {
     976            0 :          return;
     977              :       }
     978              :       /* Refuse to flood-fill with a transparent pattern --
     979              :          I can't do it without allocating another image */
     980            0 :       if (gdImageGetTransparent(im->tile) != (-1)) {
     981            0 :          return;
     982              :       }
     983            0 :       srcx = x % gdImageSX(im->tile);
     984            0 :       srcy = y % gdImageSY(im->tile);
     985            0 :       p = gdImageGetPixel(im->tile, srcx, srcy);
     986            0 :       tileColor = im->tileColorMap[p];
     987            0 :       if (old == tileColor) {
     988              :          /* Nothing to be done */
     989            0 :          return;
     990              :       }
     991              :    } else {
     992            0 :       if (old == color) {
     993              :          /* Nothing to be done */
     994            0 :          return;
     995              :       }
     996              :    }
     997              :    /* Seek left */
     998            0 :    leftLimit = (-1);
     999            0 :    for (i = x; (i >= 0); i--) {
    1000            0 :       if (gdImageGetPixel(im, i, y) != old) {
    1001            0 :          break;
    1002              :       }
    1003            0 :       gdImageSetPixel(im, i, y, color);
    1004            0 :       leftLimit = i;
    1005              :    }
    1006            0 :    if (leftLimit == (-1)) {
    1007            0 :       return;
    1008              :    }
    1009              :    /* Seek right */
    1010            0 :    rightLimit = x;
    1011            0 :    for (i = (x + 1); (i < im->sx); i++) {
    1012            0 :       if (gdImageGetPixel(im, i, y) != old) {
    1013            0 :          break;
    1014              :       }
    1015            0 :       gdImageSetPixel(im, i, y, color);
    1016            0 :       rightLimit = i;
    1017              :    }
    1018              :    /* Look at lines above and below and start paints */
    1019              :    /* Above */
    1020            0 :    if (y > 0) {
    1021            0 :       lastBorder = 1;
    1022            0 :       for (i = leftLimit; (i <= rightLimit); i++) {
    1023              :          int c;
    1024            0 :          c = gdImageGetPixel(im, i, y - 1);
    1025            0 :          if (lastBorder) {
    1026            0 :             if (c == old) {
    1027            0 :                gdImageFill(im, i, y - 1, color);
    1028            0 :                lastBorder = 0;
    1029              :             }
    1030            0 :          } else if (c != old) {
    1031            0 :             lastBorder = 1;
    1032              :          }
    1033              :       }
    1034              :    }
    1035              :    /* Below */
    1036            0 :    if (y < ((im->sy) - 1)) {
    1037            0 :       lastBorder = 1;
    1038            0 :       for (i = leftLimit; (i <= rightLimit); i++) {
    1039              :          int c;
    1040            0 :          c = gdImageGetPixel(im, i, y + 1);
    1041            0 :          if (lastBorder) {
    1042            0 :             if (c == old) {
    1043            0 :                gdImageFill(im, i, y + 1, color);
    1044            0 :                lastBorder = 0;
    1045              :             }
    1046            0 :          } else if (c != old) {
    1047            0 :             lastBorder = 1;
    1048              :          }
    1049              :       }
    1050              :    }
    1051              : }
    1052              : 
    1053              : #ifdef TEST_CODE
    1054              : void gdImageDump(gdImagePtr im)
    1055              : {
    1056              :    int i, j;
    1057              :    for (i = 0; (i < im->sy); i++) {
    1058              :       for (j = 0; (j < im->sx); j++) {
    1059              :          printf("%d", im->pixels[j][i]);
    1060              :       }
    1061              :       printf("\n");
    1062              :    }
    1063              : }
    1064              : #endif
    1065              : 
    1066              : /* Code drawn from ppmtogif.c, from the pbmplus package
    1067              : **
    1068              : ** Based on GIFENCOD by David Rowley <mgardi@watdscu.waterloo.edu>. A
    1069              : ** Lempel-Zim compression based on "compress".
    1070              : **
    1071              : ** Modified by Marcel Wijkstra <wijkstra@fwi.uva.nl>
    1072              : **
    1073              : ** Copyright (C) 1989 by Jef Poskanzer.
    1074              : **
    1075              : ** Permission to use, copy, modify, and distribute this software and its
    1076              : ** documentation for any purpose and without fee is hereby granted, provided
    1077              : ** that the above copyright notice appear in all copies and that both that
    1078              : ** copyright notice and this permission notice appear in supporting
    1079              : ** documentation.  This software is provided "as is" without express or
    1080              : ** implied warranty.
    1081              : **
    1082              : ** The Graphics Interchange Format(c) is the Copyright property of
    1083              : ** CompuServe Incorporated.  GIF(sm) is a Service Mark property of
    1084              : ** CompuServe Incorporated.
    1085              : */
    1086              : 
    1087              : /*
    1088              :  * a code_int must be able to hold 2**GIFBITS values of type int, and also -1
    1089              :  */
    1090              : typedef int code_int;
    1091              : 
    1092              : #ifdef SIGNED_COMPARE_SLOW
    1093              : typedef unsigned long int count_int;
    1094              : typedef unsigned short int count_short;
    1095              : #else                           /*SIGNED_COMPARE_SLOW */
    1096              : typedef long int count_int;
    1097              : #endif                          /*SIGNED_COMPARE_SLOW */
    1098              : 
    1099              : static int colorstobpp(int colors);
    1100              : static void BumpPixel(void);
    1101              : static int GIFNextPixel(gdImagePtr im);
    1102              : static void GIFEncode(gdGifBuffer * buffer, int GWidth, int GHeight, int GInterlace,
    1103              :                       int Background, int Transparent, int BitsPerPixel, int *Red,
    1104              :                       int *Green, int *Blue, gdImagePtr im);
    1105              : static void Putword(int w, gdGifBuffer * buffer);
    1106              : static void compress(int init_bits, gdGifBuffer * buffer, gdImagePtr im);
    1107              : static void output(code_int code);
    1108              : static void cl_block(void);
    1109              : static void cl_hash(count_int hsize);
    1110              : static void char_init(void);
    1111              : static void char_out(int c);
    1112              : static void flush_char(void);
    1113              : /* Allows for reuse */
    1114              : static void init_statics(void);
    1115              : 
    1116              : static char gif_buffer[500000];
    1117              : 
    1118            0 : void gdImageGif(gdImagePtr im, gdGifBuffer * buffer)
    1119              : {
    1120              :    int interlace, transparent, BitsPerPixel;
    1121            0 :    interlace = im->interlace;
    1122            0 :    transparent = im->transparent;
    1123              : 
    1124              :    /* allocate buffer */
    1125            0 :    buffer->size = 0;
    1126            0 :    buffer->data = gif_buffer;
    1127              : 
    1128            0 :    BitsPerPixel = colorstobpp(im->colorsTotal);
    1129              :    /* Clear any old values in statics strewn through the GIF code */
    1130            0 :    init_statics();
    1131              :    /* All set, let's do it. */
    1132            0 :    GIFEncode(buffer, im->sx, im->sy, interlace, 0, transparent, BitsPerPixel,
    1133            0 :              im->red, im->green, im->blue, im);
    1134            0 : }
    1135              : 
    1136            0 : static int colorstobpp(int colors)
    1137              : {
    1138            0 :    int bpp = 0;
    1139              : 
    1140            0 :    if (colors <= 2)
    1141            0 :       bpp = 1;
    1142            0 :    else if (colors <= 4)
    1143            0 :       bpp = 2;
    1144            0 :    else if (colors <= 8)
    1145            0 :       bpp = 3;
    1146            0 :    else if (colors <= 16)
    1147            0 :       bpp = 4;
    1148            0 :    else if (colors <= 32)
    1149            0 :       bpp = 5;
    1150            0 :    else if (colors <= 64)
    1151            0 :       bpp = 6;
    1152            0 :    else if (colors <= 128)
    1153            0 :       bpp = 7;
    1154            0 :    else if (colors <= 256)
    1155            0 :       bpp = 8;
    1156            0 :    return bpp;
    1157              : }
    1158              : 
    1159              : /*****************************************************************************
    1160              :  *
    1161              :  * GIFENCODE.C    - GIF Image compression interface
    1162              :  *
    1163              :  * GIFEncode( FName, GHeight, GWidth, GInterlace, Background, Transparent,
    1164              :  *            BitsPerPixel, Red, Green, Blue, gdImagePtr )
    1165              :  *
    1166              :  *****************************************************************************/
    1167              : 
    1168              : #define TRUE 1
    1169              : #define FALSE 0
    1170              : 
    1171              : static int Width, Height;
    1172              : static int curx, cury;
    1173              : static long CountDown;
    1174              : static int Pass = 0;
    1175              : static int Interlace;
    1176              : 
    1177              : /*
    1178              :  * Bump the 'curx' and 'cury' to point to the next pixel
    1179              :  */
    1180            0 : static void BumpPixel(void)
    1181              : {
    1182              :    /*
    1183              :     * Bump the current X position
    1184              :     */
    1185            0 :    ++curx;
    1186              : 
    1187              :    /*
    1188              :     * If we are at the end of a scan line, set curx back to the beginning
    1189              :     * If we are interlaced, bump the cury to the appropriate spot,
    1190              :     * otherwise, just increment it.
    1191              :     */
    1192            0 :    if (curx == Width) {
    1193            0 :       curx = 0;
    1194              : 
    1195            0 :       if (!Interlace)
    1196            0 :          ++cury;
    1197              :       else {
    1198            0 :          switch (Pass) {
    1199              : 
    1200            0 :          case 0:
    1201            0 :             cury += 8;
    1202            0 :             if (cury >= Height) {
    1203            0 :                ++Pass;
    1204            0 :                cury = 4;
    1205              :             }
    1206            0 :             break;
    1207              : 
    1208            0 :          case 1:
    1209            0 :             cury += 8;
    1210            0 :             if (cury >= Height) {
    1211            0 :                ++Pass;
    1212            0 :                cury = 2;
    1213              :             }
    1214            0 :             break;
    1215              : 
    1216            0 :          case 2:
    1217            0 :             cury += 4;
    1218            0 :             if (cury >= Height) {
    1219            0 :                ++Pass;
    1220            0 :                cury = 1;
    1221              :             }
    1222            0 :             break;
    1223              : 
    1224            0 :          case 3:
    1225            0 :             cury += 2;
    1226            0 :             break;
    1227              :          }
    1228              :       }
    1229              :    }
    1230            0 : }
    1231              : 
    1232              : /*
    1233              :  * Return the next pixel from the image
    1234              :  */
    1235            0 : static int GIFNextPixel(gdImagePtr im)
    1236              : {
    1237              :    int r;
    1238              : 
    1239            0 :    if (CountDown == 0)
    1240            0 :       return EOF;
    1241              : 
    1242            0 :    --CountDown;
    1243              : 
    1244            0 :    r = gdImageGetPixel(im, curx, cury);
    1245              : 
    1246            0 :    BumpPixel();
    1247              : 
    1248            0 :    return r;
    1249              : }
    1250              : 
    1251              : /* public */
    1252              : 
    1253            0 : void bputc(int c, gdGifBuffer * buffer)
    1254              : {
    1255            0 :    buffer->data[buffer->size++] = (unsigned char) c;
    1256            0 : }
    1257              : 
    1258              : static void
    1259            0 : GIFEncode(gdGifBuffer * buffer, int GWidth, int GHeight, int GInterlace, int Background,
    1260              :           int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue,
    1261              :           gdImagePtr im)
    1262              : {
    1263              :    int B;
    1264              :    int RWidth, RHeight;
    1265              :    int LeftOfs, TopOfs;
    1266              :    int Resolution;
    1267              :    int ColorMapSize;
    1268              :    int InitCodeSize;
    1269              :    int i;
    1270              : 
    1271            0 :    Interlace = GInterlace;
    1272              : 
    1273            0 :    ColorMapSize = 1 << BitsPerPixel;
    1274              : 
    1275            0 :    RWidth = Width = GWidth;
    1276            0 :    RHeight = Height = GHeight;
    1277            0 :    LeftOfs = TopOfs = 0;
    1278              : 
    1279            0 :    Resolution = BitsPerPixel;
    1280              : 
    1281              :    /*
    1282              :     * Calculate number of bits we are expecting
    1283              :     */
    1284            0 :    CountDown = (long) Width *(long) Height;
    1285              : 
    1286              :    /*
    1287              :     * Indicate which pass we are on (if interlace)
    1288              :     */
    1289            0 :    Pass = 0;
    1290              : 
    1291              :    /*
    1292              :     * The initial code size
    1293              :     */
    1294            0 :    if (BitsPerPixel <= 1)
    1295            0 :       InitCodeSize = 2;
    1296              :    else
    1297            0 :       InitCodeSize = BitsPerPixel;
    1298              : 
    1299              :    /*
    1300              :     * Set up the current x and y position
    1301              :     */
    1302            0 :    curx = cury = 0;
    1303              : 
    1304              :    /*
    1305              :     * Write the Magic header
    1306              :     */
    1307            0 :    memcpy(buffer->data + buffer->size, Transparent < 0 ? "GIF87a" : "GIF89a", 6);
    1308            0 :    buffer->size += 6;
    1309              : 
    1310              :    /*
    1311              :     * Write out the screen width and height
    1312              :     */
    1313            0 :    Putword(RWidth, buffer);
    1314            0 :    Putword(RHeight, buffer);
    1315              : 
    1316              :    /*
    1317              :     * Indicate that there is a global color map
    1318              :     */
    1319            0 :    B = 0x80;                    /* Yes, there is a color map */
    1320              : 
    1321              :    /*
    1322              :     * OR in the resolution
    1323              :     */
    1324            0 :    B |= (Resolution - 1) << 5;
    1325              : 
    1326              :    /*
    1327              :     * OR in the Bits per Pixel
    1328              :     */
    1329            0 :    B |= (BitsPerPixel - 1);
    1330              : 
    1331              :    /*
    1332              :     * Write it out
    1333              :     */
    1334            0 :    bputc(B, buffer);
    1335              : 
    1336              :    /*
    1337              :     * Write out the Background color
    1338              :     */
    1339            0 :    bputc(Background, buffer);
    1340              : 
    1341              :    /*
    1342              :     * Byte of 0's (future expansion)
    1343              :     */
    1344            0 :    bputc(0, buffer);
    1345              : 
    1346              :    /*
    1347              :     * Write out the Global Color Map
    1348              :     */
    1349            0 :    for (i = 0; i < ColorMapSize; ++i) {
    1350            0 :       bputc(Red[i], buffer);
    1351            0 :       bputc(Green[i], buffer);
    1352            0 :       bputc(Blue[i], buffer);
    1353              :    }
    1354              : 
    1355              :    /*
    1356              :     * Write out extension for transparent color index, if necessary.
    1357              :     */
    1358            0 :    if (Transparent >= 0) {
    1359            0 :       bputc('!', buffer);
    1360            0 :       bputc(0xf9, buffer);
    1361            0 :       bputc(4, buffer);
    1362            0 :       bputc(1, buffer);
    1363            0 :       bputc(0, buffer);
    1364            0 :       bputc(0, buffer);
    1365            0 :       bputc((unsigned char) Transparent, buffer);
    1366            0 :       bputc(0, buffer);
    1367              :    }
    1368              : 
    1369              :    /*
    1370              :     * Write an Image separator
    1371              :     */
    1372            0 :    bputc(',', buffer);
    1373              : 
    1374              :    /*
    1375              :     * Write the Image header
    1376              :     */
    1377              : 
    1378            0 :    Putword(LeftOfs, buffer);
    1379            0 :    Putword(TopOfs, buffer);
    1380            0 :    Putword(Width, buffer);
    1381            0 :    Putword(Height, buffer);
    1382              : 
    1383              :    /*
    1384              :     * Write out whether or not the image is interlaced
    1385              :     */
    1386            0 :    if (Interlace)
    1387            0 :       bputc(0x40, buffer);
    1388              :    else
    1389            0 :       bputc(0x00, buffer);
    1390              : 
    1391              :    /*
    1392              :     * Write out the initial code size
    1393              :     */
    1394            0 :    bputc(InitCodeSize, buffer);
    1395              : 
    1396              :    /*
    1397              :     * Go and actually compress the data
    1398              :     */
    1399            0 :    compress(InitCodeSize + 1, buffer, im);
    1400              : 
    1401              :    /*
    1402              :     * Write out a Zero-length packet (to end the series)
    1403              :     */
    1404            0 :    bputc(0, buffer);
    1405              : 
    1406              :    /*
    1407              :     * Write the GIF file terminator
    1408              :     */
    1409            0 :    bputc(';', buffer);
    1410            0 : }
    1411              : 
    1412              : /*
    1413              :  * Write out a word to the GIF file
    1414              :  */
    1415            0 : static void Putword(int w, gdGifBuffer * buffer)
    1416              : {
    1417            0 :    buffer->data[buffer->size++] = (unsigned char) (w & 0xff);
    1418            0 :    buffer->data[buffer->size++] = (unsigned char) ((w / 256) & 0xff);
    1419            0 : }
    1420              : 
    1421              : 
    1422              : /***************************************************************************
    1423              :  *
    1424              :  *  GIFCOMPR.C       - GIF Image compression routines
    1425              :  *
    1426              :  *  Lempel-Ziv compression based on 'compress'.  GIF modifications by
    1427              :  *  David Rowley (mgardi@watdcsu.waterloo.edu)
    1428              :  *
    1429              :  ***************************************************************************/
    1430              : 
    1431              : /*
    1432              :  * General DEFINEs
    1433              :  */
    1434              : 
    1435              : #define GIFBITS    12
    1436              : 
    1437              : #define HSIZE  5003             /* 80% occupancy */
    1438              : 
    1439              : #ifdef NO_UCHAR
    1440              : typedef char char_type;
    1441              : #else                           /*NO_UCHAR */
    1442              : typedef unsigned char char_type;
    1443              : #endif                          /*NO_UCHAR */
    1444              : 
    1445              : /*
    1446              :  *
    1447              :  * GIF Image compression - modified 'compress'
    1448              :  *
    1449              :  * Based on: compress.c - File compression ala IEEE Computer, June 1984.
    1450              :  *
    1451              :  * By Authors:  Spencer W. Thomas       (decvax!harpo!utah-cs!utah-gr!thomas)
    1452              :  *              Jim McKie               (decvax!mcvax!jim)
    1453              :  *              Steve Davies            (decvax!vax135!petsd!peora!srd)
    1454              :  *              Ken Turkowski           (decvax!decwrl!turtlevax!ken)
    1455              :  *              James A. Woods          (decvax!ihnp4!ames!jaw)
    1456              :  *              Joe Orost               (decvax!vax135!petsd!joe)
    1457              :  *
    1458              :  */
    1459              : #include <ctype.h>
    1460              : 
    1461              : #define ARGVAL() (*++(*argv) || (--argc && *++argv))
    1462              : 
    1463              : static int n_bits;              /* number of bits/code */
    1464              : static int maxbits = GIFBITS;   /* user settable max # bits/code */
    1465              : static code_int maxcode;        /* maximum code, given n_bits */
    1466              : static code_int maxmaxcode = (code_int) 1 << GIFBITS;   /* should NEVER generate this code */
    1467              : #ifdef COMPATIBLE               /* But wrong! */
    1468              : # define MAXCODE(n_bits)        ((code_int) 1 << (n_bits) - 1)
    1469              : #else /*COMPATIBLE*/
    1470              : # define MAXCODE(n_bits)        (((code_int) 1 << (n_bits)) - 1)
    1471              : #endif /*COMPATIBLE*/
    1472              : static count_int htab[HSIZE];
    1473              : static unsigned short codetab[HSIZE];
    1474              : #define HashTabOf(i)       htab[i]
    1475              : #define CodeTabOf(i)    codetab[i]
    1476              : 
    1477              : static code_int hsize = HSIZE;  /* for dynamic table sizing */
    1478              : 
    1479              : /*
    1480              :  * To save much memory, we overlay the table used by compress() with those
    1481              :  * used by decompress().  The tab_prefix table is the same size and type
    1482              :  * as the codetab.  The tab_suffix table needs 2**GIFBITS characters.  We
    1483              :  * get this from the beginning of htab.  The output stack uses the rest
    1484              :  * of htab, and contains characters.  There is plenty of room for any
    1485              :  * possible stack (stack used to be 8000 characters).
    1486              :  */
    1487              : 
    1488              : #define tab_prefixof(i) CodeTabOf(i)
    1489              : #define tab_suffixof(i)        ((char_type*)(htab))[i]
    1490              : #define de_stack               ((char_type*)&tab_suffixof((code_int)1<<GIFBITS))
    1491              : 
    1492              : static code_int free_ent = 0;   /* first unused entry */
    1493              : 
    1494              : /*
    1495              :  * block compression parameters -- after all codes are used up,
    1496              :  * and compression rate changes, start over.
    1497              :  */
    1498              : static int clear_flg = 0;
    1499              : 
    1500              : static int offset;
    1501              : static long int in_count = 1;   /* length of input */
    1502              : static long int out_count = 0;  /* # of codes output (for debugging) */
    1503              : 
    1504              : /*
    1505              :  * compress stdin to stdout
    1506              :  *
    1507              :  * Algorithm:  use open addressing double hashing (no chaining) on the
    1508              :  * prefix code / next character combination.  We do a variant of Knuth's
    1509              :  * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
    1510              :  * secondary probe.  Here, the modular division first probe is gives way
    1511              :  * to a faster exclusive-or manipulation.  Also do block compression with
    1512              :  * an adaptive reset, whereby the code table is cleared when the compression
    1513              :  * ratio decreases, but after the table fills.  The variable-length output
    1514              :  * codes are re-sized at this point, and a special CLEAR code is generated
    1515              :  * for the decompressor.  Late addition:  construct the table according to
    1516              :  * file size for noticeable speed improvement on small files.  Please direct
    1517              :  * questions about this implementation to ames!jaw.
    1518              :  */
    1519              : 
    1520              : static int g_init_bits;
    1521              : static gdGifBuffer *g_outbuffer;
    1522              : 
    1523              : static int ClearCode;
    1524              : static int EOFCode;
    1525              : 
    1526            0 : static void compress(int init_bits, gdGifBuffer * buffer, gdImagePtr im)
    1527              : {
    1528              :    long fcode;
    1529              :    code_int i /* = 0 */ ;
    1530              :    int c;
    1531              :    code_int ent;
    1532              :    code_int disp;
    1533              :    code_int hsize_reg;
    1534              :    int hshift;
    1535              : 
    1536              :    /*
    1537              :     * Set up the globals:  g_init_bits - initial number of bits
    1538              :     *                      g_outbuffer   - pointer to output file
    1539              :     */
    1540            0 :    g_init_bits = init_bits;
    1541            0 :    g_outbuffer = buffer;
    1542              : 
    1543              :    /*
    1544              :     * Set up the necessary values
    1545              :     */
    1546            0 :    offset = 0;
    1547            0 :    out_count = 0;
    1548            0 :    clear_flg = 0;
    1549            0 :    in_count = 1;
    1550            0 :    maxcode = MAXCODE(n_bits = g_init_bits);
    1551              : 
    1552            0 :    ClearCode = (1 << (init_bits - 1));
    1553            0 :    EOFCode = ClearCode + 1;
    1554            0 :    free_ent = ClearCode + 2;
    1555              : 
    1556            0 :    char_init();
    1557              : 
    1558            0 :    ent = GIFNextPixel(im);
    1559              : 
    1560            0 :    hshift = 0;
    1561            0 :    for (fcode = (long) hsize; fcode < 65536L; fcode *= 2L)
    1562            0 :       ++hshift;
    1563            0 :    hshift = 8 - hshift;         /* set hash code range bound */
    1564              : 
    1565            0 :    hsize_reg = hsize;
    1566            0 :    cl_hash((count_int) hsize_reg);      /* clear hash table */
    1567              : 
    1568            0 :    output((code_int) ClearCode);
    1569              : 
    1570              : #ifdef SIGNED_COMPARE_SLOW
    1571              :    while ((c = GIFNextPixel(im)) != (unsigned) EOF) {
    1572              : #else                           /*SIGNED_COMPARE_SLOW */
    1573            0 :    while ((c = GIFNextPixel(im)) != EOF) {      /* } */
    1574              : #endif                          /*SIGNED_COMPARE_SLOW */
    1575              : 
    1576            0 :       ++in_count;
    1577              : 
    1578            0 :       fcode = (long) (((long) c << maxbits) + ent);
    1579            0 :       i = (((code_int) c << hshift) ^ ent);     /* xor hashing */
    1580              : 
    1581            0 :       if (HashTabOf(i) == fcode) {
    1582            0 :          ent = CodeTabOf(i);
    1583            0 :          continue;
    1584            0 :       } else if ((long) HashTabOf(i) < 0)       /* empty slot */
    1585            0 :          goto nomatch;
    1586            0 :       disp = hsize_reg - i;     /* secondary hash (after G. Knott) */
    1587            0 :       if (i == 0)
    1588            0 :          disp = 1;
    1589            0 :     probe:
    1590            0 :       if ((i -= disp) < 0)
    1591            0 :          i += hsize_reg;
    1592              : 
    1593            0 :       if (HashTabOf(i) == fcode) {
    1594            0 :          ent = CodeTabOf(i);
    1595            0 :          continue;
    1596              :       }
    1597            0 :       if ((long) HashTabOf(i) > 0)
    1598            0 :          goto probe;
    1599            0 :     nomatch:
    1600            0 :       output((code_int) ent);
    1601            0 :       ++out_count;
    1602            0 :       ent = c;
    1603              : #ifdef SIGNED_COMPARE_SLOW
    1604              :       if ((unsigned) free_ent < (unsigned) maxmaxcode) {
    1605              : #else                           /*SIGNED_COMPARE_SLOW */
    1606            0 :       if (free_ent < maxmaxcode) {      /* } */
    1607              : #endif                          /*SIGNED_COMPARE_SLOW */
    1608            0 :          CodeTabOf(i) = free_ent++;     /* code -> hashtable */
    1609            0 :          HashTabOf(i) = fcode;
    1610              :       } else
    1611            0 :          cl_block();
    1612              :    }
    1613              :    /*
    1614              :     * Put out the final code.
    1615              :     */
    1616            0 :    output((code_int) ent);
    1617            0 :    ++out_count;
    1618            0 :    output((code_int) EOFCode);
    1619            0 : }
    1620              : 
    1621              : /*****************************************************************
    1622              :  * TAG( output )
    1623              :  *
    1624              :  * Output the given code.
    1625              :  * Inputs:
    1626              :  *      code:   A n_bits-bit integer.  If == -1, then EOF.  This assumes
    1627              :  *              that n_bits =< (long)wordsize - 1.
    1628              :  * Outputs:
    1629              :  *      Outputs code to the file.
    1630              :  * Assumptions:
    1631              :  *      Chars are 8 bits long.
    1632              :  * Algorithm:
    1633              :  *      Maintain a GIFBITS character long buffer (so that 8 codes will
    1634              :  * fit in it exactly).  Use the VAX insv instruction to insert each
    1635              :  * code in turn.  When the buffer fills up empty it and start over.
    1636              :  */
    1637              : 
    1638              : static unsigned long cur_accum = 0;
    1639              : static int cur_bits = 0;
    1640              : 
    1641              : static unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
    1642              :    0x001F, 0x003F, 0x007F, 0x00FF,
    1643              :    0x01FF, 0x03FF, 0x07FF, 0x0FFF,
    1644              :    0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF
    1645              : };
    1646              : 
    1647            0 : static void output(code_int code)
    1648              : {
    1649            0 :    cur_accum &= masks[cur_bits];
    1650              : 
    1651            0 :    if (cur_bits > 0)
    1652            0 :       cur_accum |= ((long) code << cur_bits);
    1653              :    else
    1654            0 :       cur_accum = code;
    1655              : 
    1656            0 :    cur_bits += n_bits;
    1657              : 
    1658            0 :    while (cur_bits >= 8) {
    1659            0 :       char_out((unsigned int) (cur_accum & 0xff));
    1660            0 :       cur_accum >>= 8;
    1661            0 :       cur_bits -= 8;
    1662              :    }
    1663              : 
    1664              :    /*
    1665              :     * If the next entry is going to be too big for the code size,
    1666              :     * then increase it, if possible.
    1667              :     */
    1668            0 :    if (free_ent > maxcode || clear_flg) {
    1669              : 
    1670            0 :       if (clear_flg) {
    1671              : 
    1672            0 :          maxcode = MAXCODE(n_bits = g_init_bits);
    1673            0 :          clear_flg = 0;
    1674              : 
    1675              :       } else {
    1676              : 
    1677            0 :          ++n_bits;
    1678            0 :          if (n_bits == maxbits)
    1679            0 :             maxcode = maxmaxcode;
    1680              :          else
    1681            0 :             maxcode = MAXCODE(n_bits);
    1682              :       }
    1683              :    }
    1684              : 
    1685            0 :    if (code == EOFCode) {
    1686              :       /*
    1687              :        * At EOF, write the rest of the buffer.
    1688              :        */
    1689            0 :       while (cur_bits > 0) {
    1690            0 :          char_out((unsigned int) (cur_accum & 0xff));
    1691            0 :          cur_accum >>= 8;
    1692            0 :          cur_bits -= 8;
    1693              :       }
    1694              : 
    1695            0 :       flush_char();
    1696              : 
    1697              :    }
    1698            0 : }
    1699              : 
    1700              : /*
    1701              :  * Clear out the hash table
    1702              :  */
    1703            0 : static void cl_block(void)
    1704              : {                               /* table clear for block compress */
    1705              : 
    1706            0 :    cl_hash((count_int) hsize);
    1707            0 :    free_ent = ClearCode + 2;
    1708            0 :    clear_flg = 1;
    1709              : 
    1710            0 :    output((code_int) ClearCode);
    1711            0 : }
    1712              : 
    1713            0 : static void cl_hash(count_int hsize)
    1714              : {                               /* reset code table */
    1715              :   
    1716            0 :    count_int *htab_p = htab + hsize;
    1717              : 
    1718              :    long i;
    1719            0 :    long m1 = -1;
    1720              : 
    1721            0 :    i = hsize - 16;
    1722              :    do {                         /* might use Sys V memset(3) here */
    1723            0 :       *(htab_p - 16) = m1;
    1724            0 :       *(htab_p - 15) = m1;
    1725            0 :       *(htab_p - 14) = m1;
    1726            0 :       *(htab_p - 13) = m1;
    1727            0 :       *(htab_p - 12) = m1;
    1728            0 :       *(htab_p - 11) = m1;
    1729            0 :       *(htab_p - 10) = m1;
    1730            0 :       *(htab_p - 9) = m1;
    1731            0 :       *(htab_p - 8) = m1;
    1732            0 :       *(htab_p - 7) = m1;
    1733            0 :       *(htab_p - 6) = m1;
    1734            0 :       *(htab_p - 5) = m1;
    1735            0 :       *(htab_p - 4) = m1;
    1736            0 :       *(htab_p - 3) = m1;
    1737            0 :       *(htab_p - 2) = m1;
    1738            0 :       *(htab_p - 1) = m1;
    1739            0 :       htab_p -= 16;
    1740            0 :    } while ((i -= 16) >= 0);
    1741              : 
    1742            0 :    for (i += 16; i > 0; --i)
    1743            0 :       *--htab_p = m1;
    1744            0 : }
    1745              : 
    1746              : /******************************************************************************
    1747              :  *
    1748              :  * GIF Specific routines
    1749              :  *
    1750              :  ******************************************************************************/
    1751              : 
    1752              : /*
    1753              :  * Number of characters so far in this 'packet'
    1754              :  */
    1755              : static int a_count;
    1756              : 
    1757              : /*
    1758              :  * Set up the 'byte output' routine
    1759              :  */
    1760            0 : static void char_init(void)
    1761              : {
    1762            0 :    a_count = 0;
    1763            0 : }
    1764              : 
    1765              : /*
    1766              :  * Define the storage for the packet accumulator
    1767              :  */
    1768              : static char accum[256];
    1769              : 
    1770              : /*
    1771              :  * Add a character to the end of the current packet, and if it is 254
    1772              :  * characters, flush the packet to disk.
    1773              :  */
    1774            0 : static void char_out(int c)
    1775              : {
    1776            0 :    accum[a_count++] = c;
    1777            0 :    if (a_count >= 254)
    1778            0 :       flush_char();
    1779            0 : }
    1780              : 
    1781              : /*
    1782              :  * Flush the packet to disk, and reset the accumulator
    1783              :  */
    1784            0 : static void flush_char(void)
    1785              : {
    1786            0 :    if (a_count > 0) {
    1787            0 :       bputc(a_count, g_outbuffer);
    1788            0 :       memcpy(g_outbuffer->data + g_outbuffer->size, accum, a_count);
    1789            0 :       g_outbuffer->size += a_count;
    1790            0 :       a_count = 0;
    1791              :    }
    1792            0 : }
    1793              : 
    1794            0 : static void init_statics(void)
    1795              : {
    1796              :    /* Some of these are properly initialized later. What I'm doing
    1797              :       here is making sure code that depends on C's initialization
    1798              :       of statics doesn't break when the code gets called more
    1799              :       than once. */
    1800            0 :    Width = 0;
    1801            0 :    Height = 0;
    1802            0 :    curx = 0;
    1803            0 :    cury = 0;
    1804            0 :    CountDown = 0;
    1805            0 :    Pass = 0;
    1806            0 :    Interlace = 0;
    1807            0 :    a_count = 0;
    1808            0 :    cur_accum = 0;
    1809            0 :    cur_bits = 0;
    1810            0 :    g_init_bits = 0;
    1811            0 :    g_outbuffer = 0;
    1812            0 :    ClearCode = 0;
    1813            0 :    EOFCode = 0;
    1814            0 :    free_ent = 0;
    1815            0 :    clear_flg = 0;
    1816            0 :    offset = 0;
    1817            0 :    in_count = 1;
    1818            0 :    out_count = 0;
    1819            0 :    hsize = HSIZE;
    1820            0 :    n_bits = 0;
    1821            0 :    maxbits = GIFBITS;
    1822            0 :    maxcode = 0;
    1823            0 :    maxmaxcode = (code_int) 1 << GIFBITS;
    1824            0 : }
    1825              : 
    1826              : 
    1827              : /* +-------------------------------------------------------------------+ */
    1828              : /* | Copyright 1990, 1991, 1993, David Koblas.  (koblas@netcom.com)    | */
    1829              : /* |   Permission to use, copy, modify, and distribute this software   | */
    1830              : /* |   and its documentation for any purpose and without fee is hereby | */
    1831              : /* |   granted, provided that the above copyright notice appear in all | */
    1832              : /* |   copies and that both that copyright notice and this permission  | */
    1833              : /* |   notice appear in supporting documentation.  This software is    | */
    1834              : /* |   provided "as is" without express or implied warranty.           | */
    1835              : /* +-------------------------------------------------------------------+ */
    1836              : 
    1837              : 
    1838              : #define        MAXCOLORMAPSIZE         256
    1839              : 
    1840              : #define        TRUE    1
    1841              : #define        FALSE   0
    1842              : 
    1843              : #define CM_RED         0
    1844              : #define CM_GREEN       1
    1845              : #define CM_BLUE                2
    1846              : 
    1847              : #define        MAX_LWZ_BITS            12
    1848              : 
    1849              : #define INTERLACE              0x40
    1850              : #define LOCALCOLORMAP  0x80
    1851              : #define BitSet(byte, bit)      (((byte) & (bit)) == (bit))
    1852              : 
    1853              : #define        ReadOK(file,buffer,len) (fread(buffer, len, 1, file) != 0)
    1854              : 
    1855              : #define LM_to_uint(a,b)                        (((b)<<8)|(a))
    1856              : 
    1857              : /* We may eventually want to use this information, but def it out for now */
    1858              : #if 0
    1859              : static struct {
    1860              :    unsigned int Width;
    1861              :    unsigned int Height;
    1862              :    unsigned char ColorMap[3][MAXCOLORMAPSIZE];
    1863              :    unsigned int BitPixel;
    1864              :    unsigned int ColorResolution;
    1865              :    unsigned int Background;
    1866              :    unsigned int AspectRatio;
    1867              : } GifScreen;
    1868              : #endif
    1869              : 
    1870              : static struct {
    1871              :    int transparent;
    1872              :    int delayTime;
    1873              :    int inputFlag;
    1874              :    int disposal;
    1875              : } Gif89 = {
    1876              : -1, -1, -1, 0};
    1877              : 
    1878              : static int ReadColorMap(FILE * fd, int number, unsigned char (*buffer)[256]);
    1879              : static int DoExtension(FILE * fd, int label, int *Transparent);
    1880              : static int GetDataBlock(FILE * fd, unsigned char *buf);
    1881              : static int GetCode(FILE * fd, int code_size, int flag);
    1882              : static int LWZReadByte(FILE * fd, int flag, int input_code_size);
    1883              : static void ReadImage(gdImagePtr im, FILE * fd, int len, int height,
    1884              :                       unsigned char (*cmap)[256], int interlace, int ignore);
    1885              : 
    1886              : int ZeroDataBlock;
    1887              : 
    1888            0 : gdImagePtr gdImageCreateFromGif(FILE * fd)
    1889              : {
    1890              :    int imageNumber;
    1891              :    int BitPixel;
    1892              :    //int ColorResolution;
    1893              :    //int Background;
    1894              :    //int AspectRatio;
    1895            0 :    int Transparent = (-1);
    1896              :    unsigned char buf[16];
    1897              :    unsigned char c;
    1898              :    unsigned char ColorMap[3][MAXCOLORMAPSIZE];
    1899              :    unsigned char localColorMap[3][MAXCOLORMAPSIZE];
    1900              :    int imw, imh;
    1901              :    int useGlobalColormap;
    1902              :    int bitPixel;
    1903            0 :    int imageCount = 0;
    1904              :    char version[4];
    1905            0 :    gdImagePtr im = 0;
    1906            0 :    ZeroDataBlock = FALSE;
    1907              : 
    1908            0 :    imageNumber = 1;
    1909            0 :    if (!ReadOK(fd, buf, 6)) {
    1910            0 :       return 0;
    1911              :    }
    1912            0 :    if (strncmp((char *) buf, "GIF", 3) != 0) {
    1913            0 :       return 0;
    1914              :    }
    1915            0 :    strncpy(version, (char *) buf + 3, 3);
    1916            0 :    version[3] = '\0';
    1917              : 
    1918            0 :    if ((strcmp(version, "87a") != 0) && (strcmp(version, "89a") != 0)) {
    1919            0 :       return 0;
    1920              :    }
    1921            0 :    if (!ReadOK(fd, buf, 7)) {
    1922            0 :       return 0;
    1923              :    }
    1924            0 :    BitPixel = 2 << (buf[4] & 0x07);
    1925              :    //ColorResolution = (int) (((buf[4] & 0x70) >> 3) + 1);
    1926              :    //Background = buf[5];
    1927              :    //AspectRatio = buf[6];
    1928              : 
    1929            0 :    if (BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */
    1930            0 :       if (ReadColorMap(fd, BitPixel, ColorMap)) {
    1931            0 :          return 0;
    1932              :       }
    1933              :    }
    1934              :    for (;;) {
    1935            0 :       if (!ReadOK(fd, &c, 1)) {
    1936            0 :          return 0;
    1937              :       }
    1938            0 :       if (c == ';') {           /* GIF terminator */
    1939              :          int i;
    1940            0 :          if (imageCount < imageNumber) {
    1941            0 :             return 0;
    1942              :          }
    1943              :          /* Terminator before any image was declared! */
    1944            0 :          if (!im) {
    1945            0 :             return 0;
    1946              :          }
    1947              :          /* Check for open colors at the end, so
    1948              :             we can reduce colorsTotal and ultimately
    1949              :             BitsPerPixel */
    1950            0 :          for (i = ((im->colorsTotal - 1)); (i >= 0); i--) {
    1951            0 :             if (im->open[i]) {
    1952            0 :                im->colorsTotal--;
    1953              :             } else {
    1954            0 :                break;
    1955              :             }
    1956              :          }
    1957            0 :          return im;
    1958              :       }
    1959              : 
    1960            0 :       if (c == '!') {           /* Extension */
    1961            0 :          if (!ReadOK(fd, &c, 1)) {
    1962            0 :             return 0;
    1963              :          }
    1964            0 :          DoExtension(fd, c, &Transparent);
    1965            0 :          continue;
    1966              :       }
    1967              : 
    1968            0 :       if (c != ',') {           /* Not a valid start character */
    1969            0 :          continue;
    1970              :       }
    1971              : 
    1972            0 :       ++imageCount;
    1973              : 
    1974            0 :       if (!ReadOK(fd, buf, 9)) {
    1975            0 :          return 0;
    1976              :       }
    1977              : 
    1978            0 :       useGlobalColormap = !BitSet(buf[8], LOCALCOLORMAP);
    1979              : 
    1980            0 :       bitPixel = 1 << ((buf[8] & 0x07) + 1);
    1981              : 
    1982            0 :       imw = LM_to_uint(buf[4], buf[5]);
    1983            0 :       imh = LM_to_uint(buf[6], buf[7]);
    1984            0 :       if (!(im = gdImageCreate(imw, imh))) {
    1985            0 :          return 0;
    1986              :       }
    1987            0 :       im->interlace = BitSet(buf[8], INTERLACE);
    1988            0 :       if (!useGlobalColormap) {
    1989            0 :          if (ReadColorMap(fd, bitPixel, localColorMap)) {
    1990            0 :             return 0;
    1991              :          }
    1992            0 :          ReadImage(im, fd, imw, imh, localColorMap,
    1993            0 :                    BitSet(buf[8], INTERLACE), imageCount != imageNumber);
    1994              :       } else {
    1995            0 :          ReadImage(im, fd, imw, imh,
    1996            0 :                    ColorMap, BitSet(buf[8], INTERLACE), imageCount != imageNumber);
    1997              :       }
    1998            0 :       if (Transparent != (-1)) {
    1999            0 :          gdImageColorTransparent(im, Transparent);
    2000              :       }
    2001            0 :    }
    2002              : }
    2003              : 
    2004            0 : static int ReadColorMap(FILE * fd, int number, unsigned char (*buffer)[256])
    2005              : {
    2006              :    int i;
    2007              :    unsigned char rgb[3];
    2008              : 
    2009              : 
    2010            0 :    for (i = 0; i < number; ++i) {
    2011            0 :       if (!ReadOK(fd, rgb, sizeof(rgb))) {
    2012            0 :          return TRUE;
    2013              :       }
    2014            0 :       buffer[CM_RED][i] = rgb[0];
    2015            0 :       buffer[CM_GREEN][i] = rgb[1];
    2016            0 :       buffer[CM_BLUE][i] = rgb[2];
    2017              :    }
    2018              : 
    2019              : 
    2020            0 :    return FALSE;
    2021              : }
    2022              : 
    2023            0 : static int DoExtension(FILE * fd, int label, int *Transparent)
    2024              : {
    2025              :    static unsigned char buf[256];
    2026              : 
    2027            0 :    switch (label) {
    2028            0 :    case 0xf9:                  /* Graphic Control Extension */
    2029            0 :       (void) GetDataBlock(fd, (unsigned char *) buf);
    2030            0 :       Gif89.disposal = (buf[0] >> 2) & 0x7;
    2031            0 :       Gif89.inputFlag = (buf[0] >> 1) & 0x1;
    2032            0 :       Gif89.delayTime = LM_to_uint(buf[1], buf[2]);
    2033            0 :       if ((buf[0] & 0x1) != 0)
    2034            0 :          *Transparent = buf[3];
    2035              : 
    2036            0 :       while (GetDataBlock(fd, (unsigned char *) buf) != 0);
    2037            0 :       return FALSE;
    2038            0 :    default:
    2039            0 :       break;
    2040              :    }
    2041            0 :    while (GetDataBlock(fd, (unsigned char *) buf) != 0);
    2042              : 
    2043            0 :    return FALSE;
    2044              : }
    2045              : 
    2046            0 : static int GetDataBlock(FILE * fd, unsigned char *buf)
    2047              : {
    2048              :    unsigned char count;
    2049              : 
    2050            0 :    if (!ReadOK(fd, &count, 1)) {
    2051            0 :       return -1;
    2052              :    }
    2053              : 
    2054            0 :    ZeroDataBlock = count == 0;
    2055              : 
    2056            0 :    if ((count != 0) && (!ReadOK(fd, buf, count))) {
    2057            0 :       return -1;
    2058              :    }
    2059              : 
    2060            0 :    return count;
    2061              : }
    2062              : 
    2063            0 : static int GetCode(FILE * fd, int code_size, int flag)
    2064              : {
    2065              :    static unsigned char buf[280];
    2066              :    static int curbit, lastbit, done, last_byte;
    2067              :    int i, j, ret;
    2068              :    unsigned char count;
    2069              : 
    2070            0 :    if (flag) {
    2071            0 :       curbit = 0;
    2072            0 :       lastbit = 0;
    2073            0 :       done = FALSE;
    2074            0 :       return 0;
    2075              :    }
    2076              : 
    2077            0 :    if ((curbit + code_size) >= lastbit) {
    2078            0 :       if (done) {
    2079            0 :          if (curbit >= lastbit) {
    2080              :             /* Oh well */
    2081              :          }
    2082            0 :          return -1;
    2083              :       }
    2084            0 :       buf[0] = buf[last_byte - 2];
    2085            0 :       buf[1] = buf[last_byte - 1];
    2086              : 
    2087            0 :       if ((count = GetDataBlock(fd, &buf[2])) == 0)
    2088            0 :          done = TRUE;
    2089              : 
    2090            0 :       last_byte = 2 + count;
    2091            0 :       curbit = (curbit - lastbit) + 16;
    2092            0 :       lastbit = (2 + count) * 8;
    2093              :    }
    2094              : 
    2095            0 :    ret = 0;
    2096            0 :    for (i = curbit, j = 0; j < code_size; ++i, ++j)
    2097            0 :       ret |= ((buf[i / 8] & (1 << (i % 8))) != 0) << j;
    2098              : 
    2099            0 :    curbit += code_size;
    2100              : 
    2101            0 :    return ret;
    2102              : }
    2103              : 
    2104            0 : static int LWZReadByte(FILE * fd, int flag, int input_code_size)
    2105              : {
    2106              :    static int fresh = FALSE;
    2107              :    int code, incode;
    2108              :    static int code_size, set_code_size;
    2109              :    static int max_code, max_code_size;
    2110              :    static int firstcode, oldcode;
    2111              :    static int clear_code, end_code;
    2112              :    static int table[2][(1 << MAX_LWZ_BITS)];
    2113              :    static int stack[(1 << (MAX_LWZ_BITS)) * 2], *sp;
    2114              :    int i;
    2115              : 
    2116            0 :    if (flag) {
    2117            0 :       set_code_size = input_code_size;
    2118            0 :       code_size = set_code_size + 1;
    2119            0 :       clear_code = 1 << set_code_size;
    2120            0 :       end_code = clear_code + 1;
    2121            0 :       max_code_size = 2 * clear_code;
    2122            0 :       max_code = clear_code + 2;
    2123              : 
    2124            0 :       GetCode(fd, 0, TRUE);
    2125              : 
    2126            0 :       fresh = TRUE;
    2127              : 
    2128            0 :       for (i = 0; i < clear_code; ++i) {
    2129            0 :          table[0][i] = 0;
    2130            0 :          table[1][i] = i;
    2131              :       }
    2132            0 :       for (; i < (1 << MAX_LWZ_BITS); ++i)
    2133            0 :          table[0][i] = table[1][0] = 0;
    2134              : 
    2135            0 :       sp = stack;
    2136              : 
    2137            0 :       return 0;
    2138            0 :    } else if (fresh) {
    2139            0 :       fresh = FALSE;
    2140              :       do {
    2141            0 :          firstcode = oldcode = GetCode(fd, code_size, FALSE);
    2142            0 :       } while (firstcode == clear_code);
    2143            0 :       return firstcode;
    2144              :    }
    2145              : 
    2146            0 :    if (sp > stack)
    2147            0 :       return *--sp;
    2148              : 
    2149            0 :    while ((code = GetCode(fd, code_size, FALSE)) >= 0) {
    2150            0 :       if (code == clear_code) {
    2151            0 :          for (i = 0; i < clear_code; ++i) {
    2152            0 :             table[0][i] = 0;
    2153            0 :             table[1][i] = i;
    2154              :          }
    2155            0 :          for (; i < (1 << MAX_LWZ_BITS); ++i)
    2156            0 :             table[0][i] = table[1][i] = 0;
    2157            0 :          code_size = set_code_size + 1;
    2158            0 :          max_code_size = 2 * clear_code;
    2159            0 :          max_code = clear_code + 2;
    2160            0 :          sp = stack;
    2161            0 :          firstcode = oldcode = GetCode(fd, code_size, FALSE);
    2162            0 :          return firstcode;
    2163            0 :       } else if (code == end_code) {
    2164              :          int count;
    2165              :          unsigned char buf[260];
    2166              : 
    2167            0 :          if (ZeroDataBlock)
    2168            0 :             return -2;
    2169              : 
    2170            0 :          while ((count = GetDataBlock(fd, buf)) > 0);
    2171              : 
    2172            0 :          if (count != 0)
    2173            0 :             return -2;
    2174              :       }
    2175              : 
    2176            0 :       incode = code;
    2177              : 
    2178            0 :       if (code >= max_code) {
    2179            0 :          *sp++ = firstcode;
    2180            0 :          code = oldcode;
    2181              :       }
    2182              : 
    2183            0 :       while (code >= clear_code) {
    2184            0 :          *sp++ = table[1][code];
    2185            0 :          if (code == table[0][code]) {
    2186              :             /* Oh well */
    2187              :          }
    2188            0 :          code = table[0][code];
    2189              :       }
    2190              : 
    2191            0 :       *sp++ = firstcode = table[1][code];
    2192              : 
    2193            0 :       if ((code = max_code) < (1 << MAX_LWZ_BITS)) {
    2194            0 :          table[0][code] = oldcode;
    2195            0 :          table[1][code] = firstcode;
    2196            0 :          ++max_code;
    2197            0 :          if ((max_code >= max_code_size) && (max_code_size < (1 << MAX_LWZ_BITS))) {
    2198            0 :             max_code_size *= 2;
    2199            0 :             ++code_size;
    2200              :          }
    2201              :       }
    2202              : 
    2203            0 :       oldcode = incode;
    2204              : 
    2205            0 :       if (sp > stack)
    2206            0 :          return *--sp;
    2207              :    }
    2208            0 :    return code;
    2209              : }
    2210              : 
    2211              : static void
    2212            0 : ReadImage(gdImagePtr im, FILE * fd, int len, int height, unsigned char (*cmap)[256],
    2213              :           int interlace, int ignore)
    2214              : {
    2215              :    unsigned char c;
    2216              :    int v;
    2217            0 :    int xpos = 0, ypos = 0, pass = 0;
    2218              :    int i;
    2219              :    /* Stash the color map into the image */
    2220            0 :    for (i = 0; (i < gdMaxColors); i++) {
    2221            0 :       im->red[i] = cmap[CM_RED][i];
    2222            0 :       im->green[i] = cmap[CM_GREEN][i];
    2223            0 :       im->blue[i] = cmap[CM_BLUE][i];
    2224            0 :       im->open[i] = 1;
    2225              :    }
    2226              :    /* Many (perhaps most) of these colors will remain marked open. */
    2227            0 :    im->colorsTotal = gdMaxColors;
    2228              :    /*
    2229              :     **  Initialize the Compression routines
    2230              :     */
    2231            0 :    if (!ReadOK(fd, &c, 1)) {
    2232            0 :       return;
    2233              :    }
    2234            0 :    if (LWZReadByte(fd, TRUE, c) < 0) {
    2235            0 :       return;
    2236              :    }
    2237              : 
    2238              :    /*
    2239              :     **  If this is an "uninteresting picture" ignore it.
    2240              :     */
    2241            0 :    if (ignore) {
    2242            0 :       while (LWZReadByte(fd, FALSE, c) >= 0);
    2243            0 :       return;
    2244              :    }
    2245              : 
    2246            0 :    while ((v = LWZReadByte(fd, FALSE, c)) >= 0) {
    2247              :       /* This how we recognize which colors are actually used. */
    2248            0 :       if (im->open[v]) {
    2249            0 :          im->open[v] = 0;
    2250              :       }
    2251            0 :       gdImageSetPixel(im, xpos, ypos, v);
    2252            0 :       ++xpos;
    2253            0 :       if (xpos == len) {
    2254            0 :          xpos = 0;
    2255            0 :          if (interlace) {
    2256            0 :             switch (pass) {
    2257            0 :             case 0:
    2258              :             case 1:
    2259            0 :                ypos += 8;
    2260            0 :                break;
    2261            0 :             case 2:
    2262            0 :                ypos += 4;
    2263            0 :                break;
    2264            0 :             case 3:
    2265            0 :                ypos += 2;
    2266            0 :                break;
    2267              :             }
    2268              : 
    2269            0 :             if (ypos >= height) {
    2270            0 :                ++pass;
    2271            0 :                switch (pass) {
    2272            0 :                case 1:
    2273            0 :                   ypos = 4;
    2274            0 :                   break;
    2275            0 :                case 2:
    2276            0 :                   ypos = 2;
    2277            0 :                   break;
    2278            0 :                case 3:
    2279            0 :                   ypos = 1;
    2280            0 :                   break;
    2281            0 :                default:
    2282            0 :                   goto fini;
    2283              :                }
    2284              :             }
    2285              :          } else {
    2286            0 :             ++ypos;
    2287              :          }
    2288              :       }
    2289            0 :       if (ypos >= height)
    2290            0 :          break;
    2291              :    }
    2292              : 
    2293            0 :  fini:
    2294            0 :    if (LWZReadByte(fd, FALSE, c) >= 0) {
    2295              :       /* Ignore extra */
    2296              :    }
    2297              : }
    2298              : 
    2299            0 : void gdImageRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
    2300              : {
    2301            0 :    gdImageLine(im, x1, y1, x2, y1, color);
    2302            0 :    gdImageLine(im, x1, y2, x2, y2, color);
    2303            0 :    gdImageLine(im, x1, y1, x1, y2, color);
    2304            0 :    gdImageLine(im, x2, y1, x2, y2, color);
    2305            0 : }
    2306              : 
    2307            0 : void gdImageFilledRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
    2308              : {
    2309              :    int x, y;
    2310            0 :    for (y = y1; (y <= y2); y++) {
    2311            0 :       for (x = x1; (x <= x2); x++) {
    2312            0 :          gdImageSetPixel(im, x, y, color);
    2313              :       }
    2314              :    }
    2315            0 : }
    2316              : 
    2317            0 : void gdImageCopy(gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY,
    2318              :                  int w, int h)
    2319              : {
    2320              :    int c;
    2321              :    int x, y;
    2322              :    int tox, toy;
    2323              :    int i;
    2324              :    int colorMap[gdMaxColors];
    2325            0 :    for (i = 0; (i < gdMaxColors); i++) {
    2326            0 :       colorMap[i] = (-1);
    2327              :    }
    2328            0 :    toy = dstY;
    2329            0 :    for (y = srcY; (y < (srcY + h)); y++) {
    2330            0 :       tox = dstX;
    2331            0 :       for (x = srcX; (x < (srcX + w)); x++) {
    2332              :          int nc;
    2333            0 :          c = gdImageGetPixel(src, x, y);
    2334              :          /* Added 7/24/95: support transparent copies */
    2335            0 :          if (gdImageGetTransparent(src) == c) {
    2336            0 :             tox++;
    2337            0 :             continue;
    2338              :          }
    2339              :          /* Have we established a mapping for this color? */
    2340            0 :          if (colorMap[c] == (-1)) {
    2341              :             /* If it's the same image, mapping is trivial */
    2342            0 :             if (dst == src) {
    2343            0 :                nc = c;
    2344              :             } else {
    2345              :                /* First look for an exact match */
    2346            0 :                nc = gdImageColorExact(dst, src->red[c], src->green[c], src->blue[c]);
    2347              :             }
    2348            0 :             if (nc == (-1)) {
    2349              :                /* No, so try to allocate it */
    2350            0 :                nc = gdImageColorAllocate(dst, src->red[c], src->green[c], src->blue[c]);
    2351              :                /* If we're out of colors, go for the
    2352              :                   closest color */
    2353            0 :                if (nc == (-1)) {
    2354            0 :                   nc = gdImageColorClosest(dst, src->red[c], src->green[c], src->blue[c]);
    2355              :                }
    2356              :             }
    2357            0 :             colorMap[c] = nc;
    2358              :          }
    2359            0 :          gdImageSetPixel(dst, tox, toy, colorMap[c]);
    2360            0 :          tox++;
    2361              :       }
    2362            0 :       toy++;
    2363              :    }
    2364            0 : }
    2365              : 
    2366            0 : void gdImageCopyResized(gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX,
    2367              :                         int srcY, int dstW, int dstH, int srcW, int srcH)
    2368              : {
    2369              :    int c;
    2370              :    int x, y;
    2371              :    int tox, toy;
    2372              :    int ydest;
    2373              :    int i;
    2374              :    int colorMap[gdMaxColors];
    2375              :    /* Stretch vectors */
    2376              :    int *stx;
    2377              :    int *sty;
    2378              :    /* We only need to use floating point to determine the correct
    2379              :       stretch vector for one line's worth. */
    2380              :    double accum;
    2381            0 :    stx = (int *) M_MALLOC(sizeof(int) * srcW);
    2382            0 :    sty = (int *) M_MALLOC(sizeof(int) * srcH);
    2383            0 :    accum = 0;
    2384            0 :    for (i = 0; (i < srcW); i++) {
    2385              :       int got;
    2386            0 :       accum += (double) dstW / (double) srcW;
    2387            0 :       got = (int) floor(accum);
    2388            0 :       stx[i] = got;
    2389            0 :       accum -= got;
    2390              :    }
    2391            0 :    accum = 0;
    2392            0 :    for (i = 0; (i < srcH); i++) {
    2393              :       int got;
    2394            0 :       accum += (double) dstH / (double) srcH;
    2395            0 :       got = (int) floor(accum);
    2396            0 :       sty[i] = got;
    2397            0 :       accum -= got;
    2398              :    }
    2399            0 :    for (i = 0; (i < gdMaxColors); i++) {
    2400            0 :       colorMap[i] = (-1);
    2401              :    }
    2402            0 :    toy = dstY;
    2403            0 :    for (y = srcY; (y < (srcY + srcH)); y++) {
    2404            0 :       for (ydest = 0; (ydest < sty[y - srcY]); ydest++) {
    2405            0 :          tox = dstX;
    2406            0 :          for (x = srcX; (x < (srcX + srcW)); x++) {
    2407              :             int nc;
    2408            0 :             if (!stx[x - srcX]) {
    2409            0 :                continue;
    2410              :             }
    2411            0 :             c = gdImageGetPixel(src, x, y);
    2412              :             /* Added 7/24/95: support transparent copies */
    2413            0 :             if (gdImageGetTransparent(src) == c) {
    2414            0 :                tox += stx[x - srcX];
    2415            0 :                continue;
    2416              :             }
    2417              :             /* Have we established a mapping for this color? */
    2418            0 :             if (colorMap[c] == (-1)) {
    2419              :                /* If it's the same image, mapping is trivial */
    2420            0 :                if (dst == src) {
    2421            0 :                   nc = c;
    2422              :                } else {
    2423              :                   /* First look for an exact match */
    2424            0 :                   nc = gdImageColorExact(dst, src->red[c], src->green[c], src->blue[c]);
    2425              :                }
    2426            0 :                if (nc == (-1)) {
    2427              :                   /* No, so try to allocate it */
    2428            0 :                   nc = gdImageColorAllocate(dst,
    2429              :                                             src->red[c], src->green[c], src->blue[c]);
    2430              :                   /* If we're out of colors, go for the
    2431              :                      closest color */
    2432            0 :                   if (nc == (-1)) {
    2433            0 :                      nc = gdImageColorClosest(dst,
    2434              :                                               src->red[c], src->green[c], src->blue[c]);
    2435              :                   }
    2436              :                }
    2437            0 :                colorMap[c] = nc;
    2438              :             }
    2439            0 :             for (i = 0; (i < stx[x - srcX]); i++) {
    2440            0 :                gdImageSetPixel(dst, tox, toy, colorMap[c]);
    2441            0 :                tox++;
    2442              :             }
    2443              :          }
    2444            0 :          toy++;
    2445              :       }
    2446              :    }
    2447            0 :    M_FREE(stx);
    2448            0 :    M_FREE(sty);
    2449            0 : }
    2450              : 
    2451            0 : void gdImagePolygon(gdImagePtr im, gdPointPtr p, int n, int c)
    2452              : {
    2453              :    int i;
    2454              :    int lx, ly;
    2455            0 :    if (!n) {
    2456            0 :       return;
    2457              :    }
    2458            0 :    lx = p->x;
    2459            0 :    ly = p->y;
    2460            0 :    gdImageLine(im, lx, ly, p[n - 1].x, p[n - 1].y, c);
    2461            0 :    for (i = 1; (i < n); i++) {
    2462            0 :       p++;
    2463            0 :       gdImageLine(im, lx, ly, p->x, p->y, c);
    2464            0 :       lx = p->x;
    2465            0 :       ly = p->y;
    2466              :    }
    2467              : }
    2468              : 
    2469              : int gdCompareInt(const void *a, const void *b);
    2470              : 
    2471            0 : void gdImageFilledPolygon(gdImagePtr im, gdPointPtr p, int n, int c)
    2472              : {
    2473              :    int i;
    2474              :    int y;
    2475              :    int y1, y2;
    2476              :    int ints;
    2477            0 :    if (!n) {
    2478            0 :       return;
    2479              :    }
    2480            0 :    if (!im->polyAllocated) {
    2481            0 :       im->polyInts = (int *) M_MALLOC(sizeof(int) * n);
    2482            0 :       im->polyAllocated = n;
    2483              :    }
    2484            0 :    if (im->polyAllocated < n) {
    2485            0 :       while (im->polyAllocated < n) {
    2486            0 :          im->polyAllocated *= 2;
    2487              :       }
    2488            0 :       im->polyInts = (int *) realloc(im->polyInts, sizeof(int) * im->polyAllocated);
    2489              :    }
    2490            0 :    y1 = p[0].y;
    2491            0 :    y2 = p[0].y;
    2492            0 :    for (i = 1; (i < n); i++) {
    2493            0 :       if (p[i].y < y1) {
    2494            0 :          y1 = p[i].y;
    2495              :       }
    2496            0 :       if (p[i].y > y2) {
    2497            0 :          y2 = p[i].y;
    2498              :       }
    2499              :    }
    2500            0 :    for (y = y1; (y <= y2); y++) {
    2501            0 :       int interLast = 0;
    2502            0 :       int dirLast = 0;
    2503            0 :       int interFirst = 1;
    2504            0 :       ints = 0;
    2505            0 :       for (i = 0; (i <= n); i++) {
    2506              :          int x1, x2;
    2507              :          int y1, y2;
    2508              :          int dir;
    2509              :          int ind1, ind2;
    2510            0 :          int lastInd1 = 0;
    2511            0 :          if ((i == n) || (!i)) {
    2512            0 :             ind1 = n - 1;
    2513            0 :             ind2 = 0;
    2514              :          } else {
    2515            0 :             ind1 = i - 1;
    2516            0 :             ind2 = i;
    2517              :          }
    2518            0 :          y1 = p[ind1].y;
    2519            0 :          y2 = p[ind2].y;
    2520            0 :          if (y1 < y2) {
    2521            0 :             y1 = p[ind1].y;
    2522            0 :             y2 = p[ind2].y;
    2523            0 :             x1 = p[ind1].x;
    2524            0 :             x2 = p[ind2].x;
    2525            0 :             dir = -1;
    2526            0 :          } else if (y1 > y2) {
    2527            0 :             y2 = p[ind1].y;
    2528            0 :             y1 = p[ind2].y;
    2529            0 :             x2 = p[ind1].x;
    2530            0 :             x1 = p[ind2].x;
    2531            0 :             dir = 1;
    2532              :          } else {
    2533              :             /* Horizontal; just draw it */
    2534            0 :             gdImageLine(im, p[ind1].x, y1, p[ind2].x, y1, c);
    2535            0 :             continue;
    2536              :          }
    2537            0 :          if ((y >= y1) && (y <= y2)) {
    2538            0 :             int inter = (y - y1) * (x2 - x1) / (y2 - y1) + x1;
    2539              :             /* Only count intersections once
    2540              :                except at maxima and minima. Also, 
    2541              :                if two consecutive intersections are
    2542              :                endpoints of the same horizontal line
    2543              :                that is not at a maxima or minima,   
    2544              :                discard the leftmost of the two. */
    2545            0 :             if (!interFirst) {
    2546            0 :                if ((p[ind1].y == p[lastInd1].y) && (p[ind1].x != p[lastInd1].x)) {
    2547            0 :                   if (dir == dirLast) {
    2548            0 :                      if (inter > interLast) {
    2549              :                         /* Replace the old one */
    2550            0 :                         im->polyInts[ints] = inter;
    2551              :                      } else {
    2552              :                         /* Discard this one */
    2553              :                      }
    2554            0 :                      continue;
    2555              :                   }
    2556              :                }
    2557            0 :                if (inter == interLast) {
    2558            0 :                   if (dir == dirLast) {
    2559            0 :                      continue;
    2560              :                   }
    2561              :                }
    2562              :             }
    2563            0 :             if (i > 0) {
    2564            0 :                im->polyInts[ints++] = inter;
    2565              :             }
    2566            0 :             lastInd1 = i;
    2567            0 :             dirLast = dir;
    2568            0 :             interLast = inter;
    2569            0 :             interFirst = 0;
    2570              :          }
    2571              :       }
    2572            0 :       qsort(im->polyInts, ints, sizeof(int), gdCompareInt);
    2573            0 :       for (i = 0; (i < (ints - 1)); i += 2) {
    2574            0 :          gdImageLine(im, im->polyInts[i], y, im->polyInts[i + 1], y, c);
    2575              :       }
    2576              :    }
    2577              : }
    2578              : 
    2579            0 : int gdCompareInt(const void *a, const void *b)
    2580              : {
    2581            0 :    return (*(const int *) a) - (*(const int *) b);
    2582              : }
    2583              : 
    2584            0 : void gdImageSetStyle(gdImagePtr im, int *style, int noOfPixels)
    2585              : {
    2586            0 :    if (im->style) {
    2587            0 :       M_FREE(im->style);
    2588              :    }
    2589            0 :    im->style = (int *)
    2590            0 :        M_MALLOC(sizeof(int) * noOfPixels);
    2591            0 :    memcpy(im->style, style, sizeof(int) * noOfPixels);
    2592            0 :    im->styleLength = noOfPixels;
    2593            0 :    im->stylePos = 0;
    2594            0 : }
    2595              : 
    2596            0 : void gdImageSetBrush(gdImagePtr im, gdImagePtr brush)
    2597              : {
    2598              :    int i;
    2599            0 :    im->brush = brush;
    2600            0 :    for (i = 0; (i < gdImageColorsTotal(brush)); i++) {
    2601              :       int index;
    2602            0 :       index = gdImageColorExact(im,
    2603              :                                 gdImageRed(brush, i),
    2604              :                                 gdImageGreen(brush, i), gdImageBlue(brush, i));
    2605            0 :       if (index == (-1)) {
    2606            0 :          index = gdImageColorAllocate(im,
    2607              :                                       gdImageRed(brush, i),
    2608              :                                       gdImageGreen(brush, i), gdImageBlue(brush, i));
    2609            0 :          if (index == (-1)) {
    2610            0 :             index = gdImageColorClosest(im,
    2611              :                                         gdImageRed(brush, i),
    2612              :                                         gdImageGreen(brush, i), gdImageBlue(brush, i));
    2613              :          }
    2614              :       }
    2615            0 :       im->brushColorMap[i] = index;
    2616              :    }
    2617            0 : }
    2618              : 
    2619            0 : void gdImageInterlace(gdImagePtr im, int interlaceArg)
    2620              : {
    2621            0 :    im->interlace = interlaceArg;
    2622            0 : }
        

Generated by: LCOV version 2.0-1