119 #if defined ( PLD_png ) || defined ( PLD_jpeg ) || defined ( PLD_gif )
134 #if defined ( PLD_png )
135 "png:PNG file:0:gd:39:png\n"
137 #if defined ( PLD_jpeg )
138 "jpeg:JPEG file:0:gd:40:jpeg\n"
140 #if defined ( PLD_gif )
141 "gif:GIF file:0:gd:47:gif\n"
146 #ifdef PL_HAVE_FREETYPE
147 #define SMOOTH_LINES_OK
151 #ifdef PL_HAVE_FREETYPE
177 static void setcmap(
PLStream *pls );
178 static void plD_init_png_Dev(
PLStream *pls );
179 static void plD_gd_optimise(
PLStream *pls );
180 static void plD_black15_gd(
PLStream *pls );
181 static void plD_red15_gd(
PLStream *pls );
183 static void plD_init_gif_Dev(
PLStream *pls );
186 #ifdef PL_HAVE_FREETYPE
188 static void plD_pixel_gd(
PLStream *pls,
short x,
short y );
189 static PLINT plD_read_pixel_gd(
PLStream *pls,
short x,
short y );
190 static void plD_set_pixel_gd(
PLStream *pls,
short x,
short y,
PLINT colour );
191 static void init_freetype_lv1(
PLStream *pls );
192 static void init_freetype_lv2(
PLStream *pls );
198 static int NCOLOURS = gdMaxColors;
208 #define use_experimental_hidden_line_hack
221 #ifndef max_number_of_grey_levels_used_in_text_smoothing
222 #define max_number_of_grey_levels_used_in_text_smoothing 64
227 #ifndef gdImagePalettePixel
228 #define gdImagePalettePixel( im, x, y ) ( im )->pixels[( y )][( x )]
232 int plToGdAlpha(
PLFLT a )
234 int tmp = (int) ( ( 1.0 - a ) * gdAlphaMax );
258 unsigned char TRY_BLENDED_ANTIALIASING;
263 unsigned char smooth;
268 void plD_line_png(
PLStream *,
short,
short,
short,
short );
269 void plD_polyline_png(
PLStream *,
short *,
short *,
PLINT );
285 #ifndef ENABLE_DYNDRIVERS
307 #ifndef ENABLE_DYNDRIVERS
329 #ifndef ENABLE_DYNDRIVERS
361 static int optimise = 0;
362 static int black15 = 0;
363 static int red15 = 0;
365 static int truecolour = 0;
366 static int palette = 0;
367 static int smooth_line = 0;
369 #ifdef PL_HAVE_FREETYPE
370 static int freetype = 1;
371 static int smooth_text = 1;
375 DrvOpt gd_options[] = { {
"optimise",
DRV_INT, &optimise,
"Optimise PNG palette when possible" },
376 {
"def_black15",
DRV_INT, &black15,
"Define idx 15 as black. If the background is \"whiteish\" (from \"-bg\" option), force index 15 (traditionally white) to be \"black\"" },
377 {
"swp_red15",
DRV_INT, &red15,
"Swap index 1 (usually red) and 1 (usually white); always done after \"black15\"; quite useful for quick changes to web pages" },
379 {
"8bit",
DRV_INT, &palette,
"Palette (8 bit) mode" },
380 {
"24bit",
DRV_INT, &truecolour,
"Truecolor (24 bit) mode" },
381 {
"smoothlines",
DRV_INT, &smooth_line,
"Turn line Anti Aliasing on (1) or off (0)" },
383 #ifdef PL_HAVE_FREETYPE
384 {
"text",
DRV_INT, &freetype,
"Use driver text (FreeType)" },
385 {
"smooth",
DRV_INT, &smooth_text,
"Turn text smoothing on (1) or off (0)" },
387 { NULL,
DRV_INT, NULL, NULL } };
392 if ( pls->
dev != NULL )
393 free( (
void *) pls->
dev );
395 pls->
dev = calloc( 1, (
size_t)
sizeof ( png_Dev ) );
396 if ( pls->
dev == NULL )
397 plexit(
"plD_init_png_Dev: Out of memory." );
399 dev = (png_Dev *) pls->
dev;
408 dev->black15 = black15;
410 dev->optimise = optimise;
414 dev->palette = palette;
415 dev->truecolour = truecolour;
419 if ( ( dev->truecolour > 0 ) && ( dev->palette > 0 ) )
420 plwarn(
"Selecting both \"truecolor\" AND \"palette\" driver options is contradictory, so\nI will just use my best judgment.\n" );
421 else if ( dev->truecolour > 0 )
423 else if ( ( dev->truecolour == 0 ) && ( dev->palette == 0 ) && ( ( pls->
ncol1 + pls->
ncol0 ) > NCOLOURS ) )
428 if ( ( dev->palette == 0 ) && ( dev->optimise == 0 ) && ( smooth_line == 1 ) )
433 #ifdef PL_HAVE_FREETYPE
445 init_freetype_lv1( pls );
446 FT = (FT_Data *) pls->
FT;
447 FT->want_smooth_text = smooth_text > 0 ? 1 : 0;
448 if ( ( dev->optimise == 0 ) && ( dev->palette == 0 ) && ( smooth_text != 0 ) )
450 FT->BLENDED_ANTIALIASING = 1;
484 plD_init_png_Dev( pls );
485 dev = (png_Dev *) pls->
dev;
491 plspage( 0., 0., 800, 600, 0, 0 );
499 #ifdef use_experimental_hidden_line_hack
501 if ( dev->pngx > dev->pngy )
516 if ( pls->
xdpi <= 0 )
519 plspage( 4. * 25.4, 4. * 25.4, 0, 0, 0, 0 );
528 plP_setphy( 0, dev->scale * dev->pngx, 0, dev->scale * dev->pngy );
530 #ifdef PL_HAVE_FREETYPE
533 init_freetype_lv2( pls );
557 static int black15 = 0;
558 static int red15 = 0;
559 #ifdef PL_HAVE_FREETYPE
560 static int freetype = 1;
561 static int smooth_text = 0;
565 DrvOpt gd_options[] = { {
"def_black15",
DRV_INT, &black15,
"Define idx 15 as black. If the background is \"whiteish\" (from \"-bg\" option), force index 15 (traditionally white) to be \"black\"" },
566 {
"swp_red15",
DRV_INT, &red15,
"Swap index 1 (usually red) and 1 (usually white); always done after \"black15\"; quite useful for quick changes to web pages" },
567 #ifdef PL_HAVE_FREETYPE
568 {
"text",
DRV_INT, &freetype,
"Use driver text (FreeType)" },
569 {
"smooth",
DRV_INT, &smooth_text,
"Turn text smoothing on (1) or off (0)" },
571 { NULL,
DRV_INT, NULL, NULL } };
576 if ( pls->
dev != NULL )
577 free( (
void *) pls->
dev );
579 pls->
dev = calloc( 1, (
size_t)
sizeof ( png_Dev ) );
580 if ( pls->
dev == NULL )
581 plexit(
"plD_init_gif_Dev: Out of memory." );
583 dev = (png_Dev *) pls->
dev;
591 dev->black15 = black15;
598 #ifdef PL_HAVE_FREETYPE
604 init_freetype_lv1( pls );
605 FT = (FT_Data *) pls->
FT;
607 FT->want_smooth_text = smooth_text > 0 ? 1 : 0;
639 plD_init_gif_Dev( pls );
640 dev = (png_Dev *) pls->
dev;
646 plspage( 0., 0., 800, 600, 0, 0 );
654 #ifdef use_experimental_hidden_line_hack
656 if ( dev->pngx > dev->pngy )
671 if ( pls->
xdpi <= 0 )
674 plspage( 4. * 25.4, 4. * 25.4, 0, 0, 0, 0 );
683 plP_setphy( 0, dev->scale * dev->pngx, 0, dev->scale * dev->pngy );
685 #ifdef PL_HAVE_FREETYPE
688 init_freetype_lv2( pls );
703 plD_line_png(
PLStream *pls,
short x1a,
short y1a,
short x2a,
short y2a )
705 png_Dev *dev = (png_Dev *) pls->
dev;
706 int x1 = x1a / dev->scale, y1 = y1a / dev->scale, x2 = x2a / dev->scale, y2 = y2a / dev->scale;
710 #ifdef SMOOTH_LINES_OK
711 if ( dev->smooth == 1 )
713 gdImageSetAntiAliased( dev->im_out, dev->colour );
714 gdImageLine( dev->im_out, x1, y1, x2, y2, gdAntiAliased );
718 gdImageLine( dev->im_out, x1, y1, x2, y2, dev->colour );
721 gdImageLine( dev->im_out, x1, y1, x2, y2, dev->colour );
732 plD_polyline_png(
PLStream *pls,
short *xa,
short *ya,
PLINT npts )
736 for ( i = 0; i < npts - 1; i++ )
737 plD_line_png( pls, xa[i], ya[i], xa[i + 1], ya[i + 1] );
750 png_Dev *dev = (png_Dev *) pls->
dev;
753 gdPoint *points = NULL;
758 points = malloc( (
size_t) pls->
dev_npts * sizeof ( gdPoint ) );
760 for ( i = 0; i < pls->
dev_npts; i++ )
762 points[i].x = pls->
dev_x[i] / dev->scale;
763 points[i].y = dev->pngy - ( pls->
dev_y[i] / dev->scale );
766 #ifdef SMOOTH_LINES_OK
767 if ( dev->smooth == 1 )
769 gdImageSetAntiAliased( dev->im_out, dev->colour );
770 gdImageFilledPolygon( dev->im_out, points, pls->
dev_npts, gdAntiAliased );
774 gdImageFilledPolygon( dev->im_out, points, pls->
dev_npts, dev->colour );
777 gdImageFilledPolygon( dev->im_out, points, pls->
dev_npts, dev->colour );
792 int i, ncol1 = pls->
ncol1;
793 int ncol0 = pls->
ncol0, total_colours;
795 png_Dev *dev = (png_Dev *) pls->
dev;
796 PLFLT tmp_colour_pos;
803 if ( dev->im_out != NULL )
805 for ( i = 0; i < 256; i++ )
807 gdImageColorDeallocate( dev->im_out, i );
811 if ( ncol0 > NCOLOURS / 2 )
813 plwarn(
"Too many colours in cmap0." );
814 ncol0 = NCOLOURS / 2;
820 total_colours = ncol0 + ncol1;
822 if ( total_colours > NCOLOURS )
824 total_colours = NCOLOURS;
825 ncol1 = total_colours - ncol0;
829 plexit(
"Problem setting colourmap in PNG or JPEG driver." );
840 if ( ( ncol0 > 0 ) && ( dev->im_out != NULL ) )
842 for ( i = 0; i < ncol0; i++ )
845 gdImageColorAllocateAlpha( dev->im_out,
847 plToGdAlpha( pls->
cmap0[i].
a ) );
849 gdImageColorAllocate( dev->im_out,
859 if ( ( ncol1 > 0 ) && ( dev->im_out != NULL ) )
861 for ( i = 0; i < ncol1; i++ )
863 if ( ncol1 < pls->ncol1 )
873 tmp_colour_pos = i > 0 ? pls->
ncol1 * ( (
PLFLT) i / ncol1 ) : 0;
883 gdImageColorAllocateAlpha( dev->im_out,
884 cmap1col.
r, cmap1col.
g, cmap1col.
b,
885 plToGdAlpha( cmap1col.
a ) );
887 gdImageColorAllocate( dev->im_out,
888 cmap1col.
r, cmap1col.
g, cmap1col.
b );
906 png_Dev *dev = (png_Dev *) pls->
dev;
907 PLFLT tmp_colour_pos;
917 gdImageSetThickness( dev->im_out, pls->
width );
925 ( gdImageTrueColor( dev->im_out ) ) )
927 if ( ( dev->totcol < NCOLOURS ) ||
928 ( gdImageTrueColor( dev->im_out ) ) )
932 temp_col = gdImageColorAllocateAlpha( dev->im_out, pls->
curcolor.
r,
936 temp_col = gdImageColorAllocate( dev->im_out, pls->
curcolor.
r,
940 if ( gdImageTrueColor( dev->im_out ) )
941 dev->colour = temp_col;
944 dev->colour = dev->totcol;
951 dev->colour = pls->
icol0;
955 dev->colour = pls->
icol0;
958 if ( dev->totcol < NCOLOURS )
961 gdImageColorAllocateAlpha( dev->im_out, pls->
curcolor.
r,
965 gdImageColorAllocate( dev->im_out, pls->
curcolor.
r,
968 dev->colour = dev->totcol;
977 if ( !gdImageTrueColor( dev->im_out ) )
984 if ( dev->ncol1 < pls->
ncol1 )
987 dev->colour = pls->
ncol0 + (int) tmp_colour_pos;
1012 if ( ( dev->im_out != NULL ) && !gdImageTrueColor( dev->im_out ) )
1047 #ifdef PL_HAVE_FREETYPE
1049 plD_render_freetype_text( pls, (
EscText *) ptr );
1076 dev = (png_Dev *) pls->
dev;
1083 plD_black15_gd( pls );
1085 plD_red15_gd( pls );
1088 if ( ( ( ( ( dev->truecolour > 0 ) && ( dev->palette > 0 ) ) ||
1089 ( ( dev->truecolour == 0 ) && ( dev->palette == 0 ) ) ) &&
1091 ( ( ( dev->palette > 0 ) && ( dev->truecolour == 0 ) ) ) )
1103 dev->im_out = gdImageCreateTrueColor( pls->
xlength, pls->
ylength );
1119 if ( ( pls->
cmap0[0].
r != 0 ) || ( pls->
cmap0[0].
g != 0 ) ||
1120 ( pls->
cmap0[0].
b != 0 ) || ( pls->
cmap0[0].
a != 0.0 ) )
1122 gdImageFilledRectangle( dev->im_out, 0, 0, pls->
xlength - 1, pls->
ylength - 1,
1125 plToGdAlpha( pls->
cmap0[0].
a ) ) );
1146 #ifdef PL_HAVE_FREETYPE
1149 plD_FreeType_Destroy( pls );
1166 void plD_black15_gd(
PLStream *pls )
1168 if ( pls->
ncol0 > 15 )
1170 if ( ( pls->
cmap0[0].
r > 227 ) && ( pls->
cmap0[0].
g > 227 ) && ( pls->
cmap0[0].
b > 227 ) )
1208 char r = pls->
cmap0[1].
r;
1209 char g = pls->
cmap0[1].
g;
1210 char b = pls->
cmap0[1].
b;
1212 if ( pls->
ncol0 > 15 )
1253 void plD_gd_optimise(
PLStream *pls )
1255 png_Dev *dev = (png_Dev *) pls->
dev;
1259 bbuf = calloc( 256, (
size_t) 1 );
1261 plexit(
"plD_gd_optimise: Out of memory." );
1263 for ( i = 0; i < ( pls->
xlength - 1 ); i++ )
1265 for ( j = 0; j < ( pls->
ylength - 1 ); j++ )
1267 bbuf[gdImagePalettePixel( dev->im_out, i, j )] = 1;
1271 for ( i = 0; i < 256; i++ )
1274 gdImageColorDeallocate( dev->im_out, i );
1291 png_Dev *dev = (png_Dev *) pls->
dev;
1293 int png_compression;
1294 void *im_ptr = NULL;
1299 if ( dev->optimise )
1302 if ( ( ( ( ( dev->truecolour > 0 ) && ( dev->palette > 0 ) ) ||
1303 ( ( dev->truecolour == 0 ) && ( dev->palette == 0 ) ) ) &&
1305 ( ( ( dev->palette > 0 ) && ( dev->truecolour == 0 ) ) ) )
1308 plD_gd_optimise( pls );
1333 png_compression = ( png_compression > 9 ) ? ( png_compression / 10 ) : png_compression;
1334 im_ptr = gdImagePngPtrEx( dev->im_out, &im_size, png_compression );
1336 im_ptr = gdImagePngPtr( dev->im_out, &im_size );
1340 nwrite = fwrite( im_ptr,
sizeof (
char ), im_size, pls->
OutFile );
1341 if ( nwrite != im_size )
1342 plabort(
"gd driver: Error writing png file" );
1346 gdImageDestroy( dev->im_out );
1353 #ifdef PL_HAVE_FREETYPE
1362 void plD_pixel_gd(
PLStream *pls,
short x,
short y )
1364 png_Dev *dev = (png_Dev *) pls->
dev;
1366 gdImageSetPixel( dev->im_out, x, y, dev->colour );
1376 void plD_set_pixel_gd(
PLStream *pls,
short x,
short y,
PLINT colour )
1378 png_Dev *dev = (png_Dev *) pls->
dev;
1382 G = GetGValue( colour );
1383 R = GetRValue( colour );
1384 B = GetBValue( colour );
1386 Colour = gdImageColorResolve( dev->im_out, R, G, B );
1387 gdImageSetPixel( dev->im_out, x, y, Colour );
1400 png_Dev *dev = (png_Dev *) pls->
dev;
1402 unsigned char R, G, B;
1404 colour = gdImageGetTrueColorPixel( dev->im_out, x, y );
1406 R = gdTrueColorGetRed( colour );
1407 G = gdTrueColorGetGreen( colour );
1408 B = gdTrueColorGetBlue( colour );
1410 colour = RGB( R, G, B );
1424 static void init_freetype_lv1(
PLStream *pls )
1428 plD_FreeType_init( pls );
1430 FT = (FT_Data *) pls->
FT;
1431 FT->pixel = (plD_pixel_fp) plD_pixel_gd;
1432 FT->read_pixel = (plD_read_pixel_fp) plD_read_pixel_gd;
1433 FT->set_pixel = (plD_set_pixel_fp) plD_set_pixel_gd;
1461 static void init_freetype_lv2(
PLStream *pls )
1463 png_Dev *dev = (png_Dev *) pls->
dev;
1464 FT_Data *FT = (FT_Data *) pls->
FT;
1466 FT->scale = dev->scale;
1467 FT->ymax = dev->pngy;
1469 FT->smooth_text = 0;
1471 if ( ( FT->want_smooth_text == 1 ) && ( FT->BLENDED_ANTIALIASING == 0 ) )
1473 FT->ncol0_org = pls->
ncol0;
1474 FT->ncol0_xtra = NCOLOURS - ( pls->
ncol1 + pls->
ncol0 );
1475 FT->ncol0_width = FT->ncol0_xtra / ( pls->
ncol0 - 1 );
1476 if ( FT->ncol0_width > 4 )
1478 if ( FT->ncol0_width > max_number_of_grey_levels_used_in_text_smoothing )
1479 FT->ncol0_width = max_number_of_grey_levels_used_in_text_smoothing;
1488 level_save = pls->
level;
1490 pl_set_extended_cmap0( pls, FT->ncol0_width, FT->ncol0_org );
1491 pls->
level = level_save;
1493 FT->smooth_text = 1;
1496 plwarn(
"Insufficient colour slots available in CMAP0 to do text smoothing." );
1498 else if ( ( FT->want_smooth_text == 1 ) && ( FT->BLENDED_ANTIALIASING == 1 ) )
1500 FT->smooth_text = 1;
1517 png_Dev *dev = (png_Dev *) pls->
dev;
1519 void *im_ptr = NULL;
1521 int jpeg_compression;
1529 jpeg_compression = 90;
1537 im_ptr = gdImageJpegPtr( dev->im_out, &im_size, jpeg_compression );
1540 nwrite = fwrite( im_ptr,
sizeof (
char ), im_size, pls->
OutFile );
1541 if ( nwrite != im_size )
1542 plabort(
"gd driver: Error writing png file" );
1546 gdImageDestroy( dev->im_out );
1563 png_Dev *dev = (png_Dev *) pls->
dev;
1565 void *im_ptr = NULL;
1574 im_ptr = gdImageGifPtr( dev->im_out, &im_size );
1577 nwrite = fwrite( im_ptr,
sizeof (
char ), im_size, pls->
OutFile );
1578 if ( nwrite != im_size )
1579 plabort(
"gd driver: Error writing png file" );
1583 gdImageDestroy( dev->im_out );