121 #if defined ( PLD_png ) || defined ( PLD_jpeg ) || defined ( PLD_gif )
136 #if defined ( PLD_png )
137 "png:PNG file:0:gd:39:png\n"
139 #if defined ( PLD_jpeg )
140 "jpeg:JPEG file:0:gd:40:jpeg\n"
142 #if defined ( PLD_gif )
143 "gif:GIF file:0:gd:47:gif\n"
148 #ifdef PL_HAVE_FREETYPE
149 #define SMOOTH_LINES_OK
153 #ifdef PL_HAVE_FREETYPE
179 static void setcmap(
PLStream *pls );
180 static void plD_init_png_Dev(
PLStream *pls );
181 static void plD_gd_optimise(
PLStream *pls );
182 static void plD_black15_gd(
PLStream *pls );
183 static void plD_red15_gd(
PLStream *pls );
185 static void plD_init_gif_Dev(
PLStream *pls );
188 #ifdef PL_HAVE_FREETYPE
190 static void plD_pixel_gd(
PLStream *pls,
short x,
short y );
192 static void plD_set_pixel_gd(
PLStream *pls,
short x,
short y,
PLINT colour );
193 static void init_freetype_lv1(
PLStream *pls );
194 static void init_freetype_lv2(
PLStream *pls );
200 static int NCOLOURS = gdMaxColors;
210 #define use_experimental_hidden_line_hack
223 #ifndef max_number_of_grey_levels_used_in_text_smoothing
224 #define max_number_of_grey_levels_used_in_text_smoothing 64
229 #ifndef gdImagePalettePixel
230 #define gdImagePalettePixel( im, x, y ) ( im )->pixels[( y )][( x )]
234 int plToGdAlpha(
PLFLT a )
236 int tmp = (int) ( ( 1.0 - a ) * gdAlphaMax );
260 unsigned char TRY_BLENDED_ANTIALIASING;
265 unsigned char smooth;
270 void plD_line_png(
PLStream *,
short,
short,
short,
short );
271 void plD_polyline_png(
PLStream *,
short *,
short *,
PLINT );
287 #ifndef ENABLE_DYNDRIVERS
309 #ifndef ENABLE_DYNDRIVERS
331 #ifndef ENABLE_DYNDRIVERS
363 static int optimise = 0;
364 static int black15 = 0;
365 static int red15 = 0;
367 static int truecolour = 0;
368 static int palette = 0;
369 static int smooth_line = 0;
371 #ifdef PL_HAVE_FREETYPE
372 static int freetype = 1;
373 static int smooth_text = 1;
377 DrvOpt gd_options[] = { {
"optimise",
DRV_INT, &optimise,
"Optimise PNG palette when possible" },
378 {
"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\"" },
379 {
"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" },
381 {
"8bit",
DRV_INT, &palette,
"Palette (8 bit) mode" },
382 {
"24bit",
DRV_INT, &truecolour,
"Truecolor (24 bit) mode" },
383 {
"smoothlines",
DRV_INT, &smooth_line,
"Turn line Anti Aliasing on (1) or off (0)" },
385 #ifdef PL_HAVE_FREETYPE
386 {
"text",
DRV_INT, &freetype,
"Use driver text (FreeType)" },
387 {
"smooth",
DRV_INT, &smooth_text,
"Turn text smoothing on (1) or off (0)" },
389 { NULL,
DRV_INT, NULL, NULL } };
394 if ( pls->
dev != NULL )
395 free( (
void *) pls->
dev );
397 pls->
dev = calloc( 1, (
size_t)
sizeof ( png_Dev ) );
398 if ( pls->
dev == NULL )
399 plexit(
"plD_init_png_Dev: Out of memory." );
401 dev = (png_Dev *) pls->
dev;
410 dev->black15 = black15;
412 dev->optimise = optimise;
416 dev->palette = palette;
417 dev->truecolour = truecolour;
421 if ( ( dev->truecolour > 0 ) && ( dev->palette > 0 ) )
422 plwarn(
"Selecting both \"truecolor\" AND \"palette\" driver options is contradictory, so\nI will just use my best judgment.\n" );
423 else if ( dev->truecolour > 0 )
425 else if ( ( dev->truecolour == 0 ) && ( dev->palette == 0 ) && ( ( pls->
ncol1 + pls->
ncol0 ) > NCOLOURS ) )
430 if ( ( dev->palette == 0 ) && ( dev->optimise == 0 ) && ( smooth_line == 1 ) )
435 #ifdef PL_HAVE_FREETYPE
447 init_freetype_lv1( pls );
448 FT = (FT_Data *) pls->
FT;
449 FT->want_smooth_text = smooth_text > 0 ? 1 : 0;
450 if ( ( dev->optimise == 0 ) && ( dev->palette == 0 ) && ( smooth_text != 0 ) )
452 FT->BLENDED_ANTIALIASING = 1;
486 plD_init_png_Dev( pls );
487 dev = (png_Dev *) pls->
dev;
493 plspage( 0., 0., 800, 600, 0, 0 );
501 #ifdef use_experimental_hidden_line_hack
503 if ( dev->pngx > dev->pngy )
518 if ( pls->
xdpi <= 0 )
521 plspage( 4. * 25.4, 4. * 25.4, 0, 0, 0, 0 );
530 plP_setphy( 0, dev->scale * dev->pngx, 0, dev->scale * dev->pngy );
532 #ifdef PL_HAVE_FREETYPE
535 init_freetype_lv2( pls );
559 static int black15 = 0;
560 static int red15 = 0;
561 #ifdef PL_HAVE_FREETYPE
562 static int freetype = 1;
563 static int smooth_text = 0;
567 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\"" },
568 {
"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" },
569 #ifdef PL_HAVE_FREETYPE
570 {
"text",
DRV_INT, &freetype,
"Use driver text (FreeType)" },
571 {
"smooth",
DRV_INT, &smooth_text,
"Turn text smoothing on (1) or off (0)" },
573 { NULL,
DRV_INT, NULL, NULL } };
578 if ( pls->
dev != NULL )
579 free( (
void *) pls->
dev );
581 pls->
dev = calloc( 1, (
size_t)
sizeof ( png_Dev ) );
582 if ( pls->
dev == NULL )
583 plexit(
"plD_init_gif_Dev: Out of memory." );
585 dev = (png_Dev *) pls->
dev;
593 dev->black15 = black15;
600 #ifdef PL_HAVE_FREETYPE
606 init_freetype_lv1( pls );
607 FT = (FT_Data *) pls->
FT;
609 FT->want_smooth_text = smooth_text > 0 ? 1 : 0;
641 plD_init_gif_Dev( pls );
642 dev = (png_Dev *) pls->
dev;
648 plspage( 0., 0., 800, 600, 0, 0 );
656 #ifdef use_experimental_hidden_line_hack
658 if ( dev->pngx > dev->pngy )
673 if ( pls->
xdpi <= 0 )
676 plspage( 4. * 25.4, 4. * 25.4, 0, 0, 0, 0 );
685 plP_setphy( 0, dev->scale * dev->pngx, 0, dev->scale * dev->pngy );
687 #ifdef PL_HAVE_FREETYPE
690 init_freetype_lv2( pls );
705 plD_line_png(
PLStream *pls,
short x1a,
short y1a,
short x2a,
short y2a )
707 png_Dev *dev = (png_Dev *) pls->
dev;
708 int x1 = x1a / dev->scale, y1 = y1a / dev->scale, x2 = x2a / dev->scale, y2 = y2a / dev->scale;
712 #ifdef SMOOTH_LINES_OK
713 if ( dev->smooth == 1 )
715 gdImageSetAntiAliased( dev->im_out, dev->colour );
716 gdImageLine( dev->im_out, x1, y1, x2, y2, gdAntiAliased );
720 gdImageLine( dev->im_out, x1, y1, x2, y2, dev->colour );
723 gdImageLine( dev->im_out, x1, y1, x2, y2, dev->colour );
734 plD_polyline_png(
PLStream *pls,
short *xa,
short *ya,
PLINT npts )
738 for ( i = 0; i < npts - 1; i++ )
739 plD_line_png( pls, xa[i], ya[i], xa[i + 1], ya[i + 1] );
752 png_Dev *dev = (png_Dev *) pls->
dev;
755 gdPoint *points = NULL;
760 points = malloc( (
size_t) pls->
dev_npts * sizeof ( gdPoint ) );
762 for ( i = 0; i < pls->
dev_npts; i++ )
764 points[i].x = pls->
dev_x[i] / dev->scale;
765 points[i].y = dev->pngy - ( pls->
dev_y[i] / dev->scale );
768 #ifdef SMOOTH_LINES_OK
769 if ( dev->smooth == 1 )
771 gdImageSetAntiAliased( dev->im_out, dev->colour );
772 gdImageFilledPolygon( dev->im_out, points, pls->
dev_npts, gdAntiAliased );
776 gdImageFilledPolygon( dev->im_out, points, pls->
dev_npts, dev->colour );
779 gdImageFilledPolygon( dev->im_out, points, pls->
dev_npts, dev->colour );
794 int i, ncol1 = pls->
ncol1;
795 int ncol0 = pls->
ncol0, total_colours;
797 png_Dev *dev = (png_Dev *) pls->
dev;
798 PLFLT tmp_colour_pos;
805 if ( dev->im_out != NULL )
807 for ( i = 0; i < 256; i++ )
809 gdImageColorDeallocate( dev->im_out, i );
813 if ( ncol0 > NCOLOURS / 2 )
815 plwarn(
"Too many colours in cmap0." );
816 ncol0 = NCOLOURS / 2;
822 total_colours = ncol0 + ncol1;
824 if ( total_colours > NCOLOURS )
826 total_colours = NCOLOURS;
827 ncol1 = total_colours - ncol0;
831 plexit(
"Problem setting colourmap in PNG or JPEG driver." );
842 if ( ( ncol0 > 0 ) && ( dev->im_out != NULL ) )
844 for ( i = 0; i < ncol0; i++ )
847 gdImageColorAllocateAlpha( dev->im_out,
849 plToGdAlpha( pls->
cmap0[i].
a ) );
851 gdImageColorAllocate( dev->im_out,
861 if ( ( ncol1 > 0 ) && ( dev->im_out != NULL ) )
863 for ( i = 0; i < ncol1; i++ )
865 if ( ncol1 < pls->ncol1 )
875 tmp_colour_pos = i > 0 ? pls->
ncol1 * ( (
PLFLT) i / ncol1 ) : 0;
885 gdImageColorAllocateAlpha( dev->im_out,
886 cmap1col.
r, cmap1col.
g, cmap1col.
b,
887 plToGdAlpha( cmap1col.
a ) );
889 gdImageColorAllocate( dev->im_out,
890 cmap1col.
r, cmap1col.
g, cmap1col.
b );
908 png_Dev *dev = (png_Dev *) pls->
dev;
909 PLFLT tmp_colour_pos;
919 gdImageSetThickness( dev->im_out, pls->
width );
927 ( gdImageTrueColor( dev->im_out ) ) )
929 if ( ( dev->totcol < NCOLOURS ) ||
930 ( gdImageTrueColor( dev->im_out ) ) )
934 temp_col = gdImageColorAllocateAlpha( dev->im_out, pls->
curcolor.
r,
938 temp_col = gdImageColorAllocate( dev->im_out, pls->
curcolor.
r,
942 if ( gdImageTrueColor( dev->im_out ) )
943 dev->colour = temp_col;
946 dev->colour = dev->totcol;
953 dev->colour = pls->
icol0;
957 dev->colour = pls->
icol0;
960 if ( dev->totcol < NCOLOURS )
963 gdImageColorAllocateAlpha( dev->im_out, pls->
curcolor.
r,
967 gdImageColorAllocate( dev->im_out, pls->
curcolor.
r,
970 dev->colour = dev->totcol;
979 if ( !gdImageTrueColor( dev->im_out ) )
986 if ( dev->ncol1 < pls->
ncol1 )
989 dev->colour = pls->
ncol0 + (int) tmp_colour_pos;
1014 if ( ( dev->im_out != NULL ) && !gdImageTrueColor( dev->im_out ) )
1049 #ifdef PL_HAVE_FREETYPE
1051 plD_render_freetype_text( pls, (
EscText *) ptr );
1078 dev = (png_Dev *) pls->
dev;
1085 plD_black15_gd( pls );
1087 plD_red15_gd( pls );
1090 if ( ( ( ( ( dev->truecolour > 0 ) && ( dev->palette > 0 ) ) ||
1091 ( ( dev->truecolour == 0 ) && ( dev->palette == 0 ) ) ) &&
1093 ( ( ( dev->palette > 0 ) && ( dev->truecolour == 0 ) ) ) )
1105 dev->im_out = gdImageCreateTrueColor( pls->
xlength, pls->
ylength );
1121 if ( ( pls->
cmap0[0].
r != 0 ) || ( pls->
cmap0[0].
g != 0 ) ||
1122 ( pls->
cmap0[0].
b != 0 ) || ( pls->
cmap0[0].
a != 0.0 ) )
1124 gdImageFilledRectangle( dev->im_out, 0, 0, pls->
xlength - 1, pls->
ylength - 1,
1127 plToGdAlpha( pls->
cmap0[0].
a ) ) );
1148 #ifdef PL_HAVE_FREETYPE
1151 plD_FreeType_Destroy( pls );
1168 void plD_black15_gd(
PLStream *pls )
1170 if ( pls->
ncol0 > 15 )
1172 if ( ( pls->
cmap0[0].
r > 227 ) && ( pls->
cmap0[0].
g > 227 ) && ( pls->
cmap0[0].
b > 227 ) )
1210 char r = pls->
cmap0[1].
r;
1211 char g = pls->
cmap0[1].
g;
1212 char b = pls->
cmap0[1].
b;
1214 if ( pls->
ncol0 > 15 )
1255 void plD_gd_optimise(
PLStream *pls )
1257 png_Dev *dev = (png_Dev *) pls->
dev;
1261 bbuf = calloc( 256, (
size_t) 1 );
1263 plexit(
"plD_gd_optimise: Out of memory." );
1265 for ( i = 0; i < ( pls->
xlength - 1 ); i++ )
1267 for ( j = 0; j < ( pls->
ylength - 1 ); j++ )
1269 bbuf[gdImagePalettePixel( dev->im_out, i, j )] = 1;
1273 for ( i = 0; i < 256; i++ )
1276 gdImageColorDeallocate( dev->im_out, i );
1293 png_Dev *dev = (png_Dev *) pls->
dev;
1295 int png_compression;
1296 void *im_ptr = NULL;
1301 if ( dev->optimise )
1304 if ( ( ( ( ( dev->truecolour > 0 ) && ( dev->palette > 0 ) ) ||
1305 ( ( dev->truecolour == 0 ) && ( dev->palette == 0 ) ) ) &&
1307 ( ( ( dev->palette > 0 ) && ( dev->truecolour == 0 ) ) ) )
1310 plD_gd_optimise( pls );
1335 png_compression = ( png_compression > 9 ) ? ( png_compression / 10 ) : png_compression;
1336 im_ptr = gdImagePngPtrEx( dev->im_out, &im_size, png_compression );
1338 im_ptr = gdImagePngPtr( dev->im_out, &im_size );
1342 nwrite = fwrite( im_ptr,
sizeof (
char ), im_size, pls->
OutFile );
1343 if ( nwrite != im_size )
1344 plabort(
"gd driver: Error writing png file" );
1348 gdImageDestroy( dev->im_out );
1355 #ifdef PL_HAVE_FREETYPE
1364 void plD_pixel_gd(
PLStream *pls,
short x,
short y )
1366 png_Dev *dev = (png_Dev *) pls->
dev;
1368 gdImageSetPixel( dev->im_out, x, y, dev->colour );
1378 void plD_set_pixel_gd(
PLStream *pls,
short x,
short y,
PLINT colour )
1380 png_Dev *dev = (png_Dev *) pls->
dev;
1384 G = GetGValue( colour );
1385 R = GetRValue( colour );
1386 B = GetBValue( colour );
1388 Colour = gdImageColorResolve( dev->im_out, R, G, B );
1389 gdImageSetPixel( dev->im_out, x, y, Colour );
1402 png_Dev *dev = (png_Dev *) pls->
dev;
1404 unsigned char R, G, B;
1406 colour = gdImageGetTrueColorPixel( dev->im_out, x, y );
1408 R = gdTrueColorGetRed( colour );
1409 G = gdTrueColorGetGreen( colour );
1410 B = gdTrueColorGetBlue( colour );
1412 colour = RGB( R, G, B );
1426 static void init_freetype_lv1(
PLStream *pls )
1430 plD_FreeType_init( pls );
1432 FT = (FT_Data *) pls->
FT;
1433 FT->pixel = (plD_pixel_fp) plD_pixel_gd;
1434 FT->read_pixel = (plD_read_pixel_fp) plD_read_pixel_gd;
1435 FT->set_pixel = (plD_set_pixel_fp) plD_set_pixel_gd;
1463 static void init_freetype_lv2(
PLStream *pls )
1465 png_Dev *dev = (png_Dev *) pls->
dev;
1466 FT_Data *FT = (FT_Data *) pls->
FT;
1468 FT->scale = dev->scale;
1469 FT->ymax = dev->pngy;
1471 FT->smooth_text = 0;
1473 if ( ( FT->want_smooth_text == 1 ) && ( FT->BLENDED_ANTIALIASING == 0 ) )
1475 FT->ncol0_org = pls->
ncol0;
1476 FT->ncol0_xtra = NCOLOURS - ( pls->
ncol1 + pls->
ncol0 );
1477 FT->ncol0_width = FT->ncol0_xtra / ( pls->
ncol0 - 1 );
1478 if ( FT->ncol0_width > 4 )
1490 level_save = pls->
level;
1492 pl_set_extended_cmap0( pls, FT->ncol0_width, FT->ncol0_org );
1493 pls->
level = level_save;
1495 FT->smooth_text = 1;
1498 plwarn(
"Insufficient colour slots available in CMAP0 to do text smoothing." );
1500 else if ( ( FT->want_smooth_text == 1 ) && ( FT->BLENDED_ANTIALIASING == 1 ) )
1502 FT->smooth_text = 1;
1519 png_Dev *dev = (png_Dev *) pls->
dev;
1521 void *im_ptr = NULL;
1523 int jpeg_compression;
1531 jpeg_compression = 90;
1539 im_ptr = gdImageJpegPtr( dev->im_out, &im_size, jpeg_compression );
1542 nwrite = fwrite( im_ptr,
sizeof (
char ), im_size, pls->
OutFile );
1543 if ( nwrite != im_size )
1544 plabort(
"gd driver: Error writing png file" );
1548 gdImageDestroy( dev->im_out );
1565 png_Dev *dev = (png_Dev *) pls->
dev;
1567 void *im_ptr = NULL;
1576 im_ptr = gdImageGifPtr( dev->im_out, &im_size );
1579 nwrite = fwrite( im_ptr,
sizeof (
char ), im_size, pls->
OutFile );
1580 if ( nwrite != im_size )
1581 plabort(
"gd driver: Error writing png file" );
1585 gdImageDestroy( dev->im_out );