00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119 #include "plDevs.h"
00120
00121 #if defined ( PLD_png ) || defined ( PLD_jpeg ) || defined ( PLD_gif )
00122
00123 #include "plplotP.h"
00124 #include "drivers.h"
00125
00126 #include <gd.h>
00127
00128
00129
00130
00131
00132
00133
00134
00135 PLDLLIMPEXP_DRIVER const char* plD_DEVICE_INFO_gd =
00136 #if defined ( PLD_png )
00137 "png:PNG file:0:gd:39:png\n"
00138 #endif
00139 #if defined ( PLD_jpeg )
00140 "jpeg:JPEG file:0:gd:40:jpeg\n"
00141 #endif
00142 #if defined ( PLD_gif )
00143 "gif:GIF file:0:gd:47:gif\n"
00144 #endif
00145 ;
00146
00147 #if GD2_VERS >= 2
00148 #ifdef HAVE_FREETYPE
00149 #define SMOOTH_LINES_OK
00150 #endif
00151 #endif
00152
00153 #ifdef HAVE_FREETYPE
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172 #include "plfreetype.h"
00173
00174 #endif
00175
00176
00177
00178 static void fill_polygon( PLStream *pls );
00179 static void setcmap( PLStream *pls );
00180 static void plD_init_png_Dev( PLStream *pls );
00181 static void plD_gd_optimise( PLStream *pls );
00182 static void plD_black15_gd( PLStream *pls );
00183 static void plD_red15_gd( PLStream *pls );
00184 #ifdef PLD_gif
00185 static void plD_init_gif_Dev( PLStream *pls );
00186 #endif
00187
00188 #ifdef HAVE_FREETYPE
00189
00190 static void plD_pixel_gd( PLStream *pls, short x, short y );
00191 static PLINT plD_read_pixel_gd( PLStream *pls, short x, short y );
00192 static void plD_set_pixel_gd( PLStream *pls, short x, short y, PLINT colour );
00193 static void init_freetype_lv1( PLStream *pls );
00194 static void init_freetype_lv2( PLStream *pls );
00195
00196 #endif
00197
00198
00199
00200 static int NCOLOURS = gdMaxColors;
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210 #define use_experimental_hidden_line_hack
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 #ifndef max_number_of_grey_levels_used_in_text_smoothing
00224 #define max_number_of_grey_levels_used_in_text_smoothing 64
00225 #endif
00226
00227
00228
00229 #ifndef gdImagePalettePixel
00230 #define gdImagePalettePixel( im, x, y ) ( im )->pixels[( y )][( x )]
00231 #endif
00232
00233 #if GD2_VERS >= 2
00234 int plToGdAlpha( PLFLT a )
00235 {
00236 int tmp = (int) ( ( 1.0 - a ) * gdAlphaMax );
00237 return tmp;
00238 }
00239 #endif
00240
00241
00242
00243 typedef struct
00244 {
00245 gdImagePtr im_out;
00246 PLINT pngx;
00247 PLINT pngy;
00248
00249 int colour;
00250 int totcol;
00251 int ncol1;
00252
00253 PLFLT scale;
00254
00255
00256 int optimise;
00257 int black15;
00258 int red15;
00259
00260 unsigned char TRY_BLENDED_ANTIALIASING;
00261
00262 #if GD2_VERS >= 2
00263 int truecolour;
00264 int palette;
00265 unsigned char smooth;
00266 #endif
00267 } png_Dev;
00268
00269 void plD_init_png( PLStream * );
00270 void plD_line_png( PLStream *, short, short, short, short );
00271 void plD_polyline_png( PLStream *, short *, short *, PLINT );
00272 void plD_eop_png( PLStream * );
00273 void plD_eop_jpeg( PLStream * );
00274 void plD_bop_png( PLStream * );
00275 void plD_tidy_png( PLStream * );
00276 void plD_state_png( PLStream *, PLINT );
00277 void plD_esc_png( PLStream *, PLINT, void * );
00278 #ifdef PLD_gif
00279 void plD_init_gif( PLStream * );
00280 void plD_eop_gif( PLStream * );
00281 #endif
00282
00283 #ifdef PLD_png
00284
00285 void plD_dispatch_init_png( PLDispatchTable *pdt )
00286 {
00287 #ifndef ENABLE_DYNDRIVERS
00288 pdt->pl_MenuStr = "PNG file";
00289 pdt->pl_DevName = "png";
00290 #endif
00291 pdt->pl_type = plDevType_FileOriented;
00292 pdt->pl_seq = 39;
00293 pdt->pl_init = (plD_init_fp) plD_init_png;
00294 pdt->pl_line = (plD_line_fp) plD_line_png;
00295 pdt->pl_polyline = (plD_polyline_fp) plD_polyline_png;
00296 pdt->pl_eop = (plD_eop_fp) plD_eop_png;
00297 pdt->pl_bop = (plD_bop_fp) plD_bop_png;
00298 pdt->pl_tidy = (plD_tidy_fp) plD_tidy_png;
00299 pdt->pl_state = (plD_state_fp) plD_state_png;
00300 pdt->pl_esc = (plD_esc_fp) plD_esc_png;
00301 }
00302
00303 #endif
00304
00305 #ifdef PLD_jpeg
00306
00307 void plD_dispatch_init_jpeg( PLDispatchTable *pdt )
00308 {
00309 #ifndef ENABLE_DYNDRIVERS
00310 pdt->pl_MenuStr = "JPEG File";
00311 pdt->pl_DevName = "jpeg";
00312 #endif
00313 pdt->pl_type = plDevType_FileOriented;
00314 pdt->pl_seq = 40;
00315 pdt->pl_init = (plD_init_fp) plD_init_png;
00316 pdt->pl_line = (plD_line_fp) plD_line_png;
00317 pdt->pl_polyline = (plD_polyline_fp) plD_polyline_png;
00318 pdt->pl_eop = (plD_eop_fp) plD_eop_jpeg;
00319 pdt->pl_bop = (plD_bop_fp) plD_bop_png;
00320 pdt->pl_tidy = (plD_tidy_fp) plD_tidy_png;
00321 pdt->pl_state = (plD_state_fp) plD_state_png;
00322 pdt->pl_esc = (plD_esc_fp) plD_esc_png;
00323 }
00324 #endif
00325
00326
00327 #ifdef PLD_gif
00328
00329 void plD_dispatch_init_gif( PLDispatchTable *pdt )
00330 {
00331 #ifndef ENABLE_DYNDRIVERS
00332 pdt->pl_MenuStr = "GIF File";
00333 pdt->pl_DevName = "gif";
00334 #endif
00335 pdt->pl_type = plDevType_FileOriented;
00336 pdt->pl_seq = 47;
00337 pdt->pl_init = (plD_init_fp) plD_init_gif;
00338 pdt->pl_line = (plD_line_fp) plD_line_png;
00339 pdt->pl_polyline = (plD_polyline_fp) plD_polyline_png;
00340 pdt->pl_eop = (plD_eop_fp) plD_eop_gif;
00341 pdt->pl_bop = (plD_bop_fp) plD_bop_png;
00342 pdt->pl_tidy = (plD_tidy_fp) plD_tidy_png;
00343 pdt->pl_state = (plD_state_fp) plD_state_png;
00344 pdt->pl_esc = (plD_esc_fp) plD_esc_png;
00345 }
00346 #endif
00347
00348
00349
00350
00351
00352
00353
00354 static void
00355 plD_init_png_Dev( PLStream *pls )
00356 {
00357 png_Dev *dev;
00358
00359
00360
00361
00362
00363 static int optimise = 0;
00364 static int black15 = 0;
00365 static int red15 = 0;
00366 #if GD2_VERS >= 2
00367 static int truecolour = 0;
00368 static int palette = 0;
00369 static int smooth_line = 0;
00370 #endif
00371 #ifdef HAVE_FREETYPE
00372 static int freetype = 1;
00373 static int smooth_text = 1;
00374 FT_Data *FT;
00375 #endif
00376
00377 DrvOpt gd_options[] = { { "optimise", DRV_INT, &optimise, "Optimise PNG palette when possible" },
00378 { "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\"" },
00379 { "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" },
00380 #if GD2_VERS >= 2
00381 { "8bit", DRV_INT, &palette, "Palette (8 bit) mode" },
00382 { "24bit", DRV_INT, &truecolour, "Truecolor (24 bit) mode" },
00383 { "smoothlines", DRV_INT, &smooth_line, "Turn line Anti Aliasing on (1) or off (0)" },
00384 #endif
00385 #ifdef HAVE_FREETYPE
00386 { "text", DRV_INT, &freetype, "Use driver text (FreeType)" },
00387 { "smooth", DRV_INT, &smooth_text, "Turn text smoothing on (1) or off (0)" },
00388 #endif
00389 { NULL, DRV_INT, NULL, NULL } };
00390
00391
00392
00393
00394 if ( pls->dev != NULL )
00395 free( (void *) pls->dev );
00396
00397 pls->dev = calloc( 1, (size_t) sizeof ( png_Dev ) );
00398 if ( pls->dev == NULL )
00399 plexit( "plD_init_png_Dev: Out of memory." );
00400
00401 dev = (png_Dev *) pls->dev;
00402
00403 dev->colour = 1;
00404
00405
00406
00407
00408 plParseDrvOpts( gd_options );
00409
00410 dev->black15 = black15;
00411 dev->red15 = red15;
00412 dev->optimise = optimise;
00413
00414 #if GD2_VERS >= 2
00415
00416 dev->palette = palette;
00417 dev->truecolour = truecolour;
00418
00419
00420
00421 if ( ( dev->truecolour > 0 ) && ( dev->palette > 0 ) )
00422 plwarn( "Selecting both \"truecolor\" AND \"palette\" driver options is contradictory, so\nI will just use my best judgment.\n" );
00423 else if ( dev->truecolour > 0 )
00424 NCOLOURS = 16777216;
00425 else if ( ( dev->truecolour == 0 ) && ( dev->palette == 0 ) && ( ( pls->ncol1 + pls->ncol0 ) > NCOLOURS ) )
00426 {
00427 NCOLOURS = 16777216;
00428 }
00429
00430 if ( ( dev->palette == 0 ) && ( dev->optimise == 0 ) && ( smooth_line == 1 ) )
00431 dev->smooth = 1;
00432
00433 #endif
00434
00435 #ifdef HAVE_FREETYPE
00436 if ( freetype )
00437 {
00438 pls->dev_text = 1;
00439 pls->dev_unicode = 1;
00440
00441
00442
00443
00444
00445
00446
00447 init_freetype_lv1( pls );
00448 FT = (FT_Data *) pls->FT;
00449 FT->want_smooth_text = smooth_text > 0 ? 1 : 0;
00450 if ( ( dev->optimise == 0 ) && ( dev->palette == 0 ) && ( smooth_text != 0 ) )
00451 {
00452 FT->BLENDED_ANTIALIASING = 1;
00453 dev->truecolour = 1;
00454 }
00455 }
00456
00457 #endif
00458 }
00459
00460
00461
00462
00463
00464
00465
00466 void plD_init_png( PLStream *pls )
00467 {
00468 png_Dev *dev = NULL;
00469
00470 pls->termin = 0;
00471 pls->icol0 = 1;
00472 pls->bytecnt = 0;
00473 pls->page = 0;
00474 pls->dev_fill0 = 1;
00475
00476 if ( !pls->colorset )
00477 pls->color = 1;
00478
00479
00480 plFamInit( pls );
00481
00482
00483 plOpenFile( pls );
00484
00485
00486 plD_init_png_Dev( pls );
00487 dev = (png_Dev *) pls->dev;
00488
00489 if ( pls->xlength <= 0 || pls->ylength <= 0 )
00490 {
00491
00492
00493 plspage( 0., 0., 800, 600, 0, 0 );
00494 }
00495
00496 pls->graphx = GRAPHICS_MODE;
00497
00498 dev->pngx = pls->xlength - 1;
00499 dev->pngy = pls->ylength - 1;
00500
00501 #ifdef use_experimental_hidden_line_hack
00502
00503 if ( dev->pngx > dev->pngy )
00504 {
00505 dev->scale = (PLFLT) ( PIXELS_X - 1 ) / (PLFLT) dev->pngx;
00506 }
00507 else
00508 {
00509 dev->scale = (PLFLT) PIXELS_Y / (PLFLT) dev->pngy;
00510 }
00511 #else
00512
00513 dev->scale = 1.;
00514
00515 #endif
00516
00517
00518 if ( pls->xdpi <= 0 )
00519 {
00520
00521 plspage( 4. * 25.4, 4. * 25.4, 0, 0, 0, 0 );
00522 }
00523 else
00524 {
00525 pls->ydpi = pls->xdpi;
00526 }
00527
00528 plP_setpxl( dev->scale * pls->xdpi / 25.4, dev->scale * pls->ydpi / 25.4 );
00529
00530 plP_setphy( 0, dev->scale * dev->pngx, 0, dev->scale * dev->pngy );
00531
00532 #ifdef HAVE_FREETYPE
00533 if ( pls->dev_text )
00534 {
00535 init_freetype_lv2( pls );
00536 }
00537 #endif
00538 }
00539
00540
00541 #ifdef PLD_gif
00542
00543
00544
00545
00546
00547
00548
00549
00550 static void
00551 plD_init_gif_Dev( PLStream *pls )
00552 {
00553 png_Dev *dev;
00554
00555
00556
00557
00558
00559 static int black15 = 0;
00560 static int red15 = 0;
00561 #ifdef HAVE_FREETYPE
00562 static int freetype = 1;
00563 static int smooth_text = 0;
00564 FT_Data *FT;
00565 #endif
00566
00567 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\"" },
00568 { "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" },
00569 #ifdef HAVE_FREETYPE
00570 { "text", DRV_INT, &freetype, "Use driver text (FreeType)" },
00571 { "smooth", DRV_INT, &smooth_text, "Turn text smoothing on (1) or off (0)" },
00572 #endif
00573 { NULL, DRV_INT, NULL, NULL } };
00574
00575
00576
00577
00578 if ( pls->dev != NULL )
00579 free( (void *) pls->dev );
00580
00581 pls->dev = calloc( 1, (size_t) sizeof ( png_Dev ) );
00582 if ( pls->dev == NULL )
00583 plexit( "plD_init_gif_Dev: Out of memory." );
00584
00585 dev = (png_Dev *) pls->dev;
00586
00587 dev->colour = 1;
00588
00589
00590
00591 plParseDrvOpts( gd_options );
00592
00593 dev->black15 = black15;
00594 dev->red15 = red15;
00595
00596 dev->optimise = 0;
00597 dev->palette = 1;
00598 dev->truecolour = 0;
00599
00600 #ifdef HAVE_FREETYPE
00601 if ( freetype )
00602 {
00603 pls->dev_text = 1;
00604 pls->dev_unicode = 1;
00605
00606 init_freetype_lv1( pls );
00607 FT = (FT_Data *) pls->FT;
00608
00609 FT->want_smooth_text = smooth_text > 0 ? 1 : 0;
00610 }
00611
00612 #endif
00613 }
00614
00615
00616
00617
00618
00619
00620
00621 void plD_init_gif( PLStream *pls )
00622 {
00623 png_Dev *dev = NULL;
00624
00625 pls->termin = 0;
00626 pls->icol0 = 1;
00627 pls->bytecnt = 0;
00628 pls->page = 0;
00629 pls->dev_fill0 = 1;
00630
00631 if ( !pls->colorset )
00632 pls->color = 1;
00633
00634
00635 plFamInit( pls );
00636
00637
00638 plOpenFile( pls );
00639
00640
00641 plD_init_gif_Dev( pls );
00642 dev = (png_Dev *) pls->dev;
00643
00644 if ( pls->xlength <= 0 || pls->ylength <= 0 )
00645 {
00646
00647
00648 plspage( 0., 0., 800, 600, 0, 0 );
00649 }
00650
00651 pls->graphx = GRAPHICS_MODE;
00652
00653 dev->pngx = pls->xlength - 1;
00654 dev->pngy = pls->ylength - 1;
00655
00656 #ifdef use_experimental_hidden_line_hack
00657
00658 if ( dev->pngx > dev->pngy )
00659 {
00660 dev->scale = (PLFLT) ( PIXELS_X - 1 ) / (PLFLT) dev->pngx;
00661 }
00662 else
00663 {
00664 dev->scale = (PLFLT) PIXELS_Y / (PLFLT) dev->pngy;
00665 }
00666 #else
00667
00668 dev->scale = 1.;
00669
00670 #endif
00671
00672
00673 if ( pls->xdpi <= 0 )
00674 {
00675
00676 plspage( 4. * 25.4, 4. * 25.4, 0, 0, 0, 0 );
00677 }
00678 else
00679 {
00680 pls->ydpi = pls->xdpi;
00681 }
00682
00683 plP_setpxl( dev->scale * pls->xdpi / 25.4, dev->scale * pls->ydpi / 25.4 );
00684
00685 plP_setphy( 0, dev->scale * dev->pngx, 0, dev->scale * dev->pngy );
00686
00687 #ifdef HAVE_FREETYPE
00688 if ( pls->dev_text )
00689 {
00690 init_freetype_lv2( pls );
00691 }
00692 #endif
00693 }
00694
00695 #endif
00696
00697
00698
00699
00700
00701
00702
00703
00704 void
00705 plD_line_png( PLStream *pls, short x1a, short y1a, short x2a, short y2a )
00706 {
00707 png_Dev *dev = (png_Dev *) pls->dev;
00708 int x1 = x1a / dev->scale, y1 = y1a / dev->scale, x2 = x2a / dev->scale, y2 = y2a / dev->scale;
00709 y1 = dev->pngy - y1;
00710 y2 = dev->pngy - y2;
00711
00712 #ifdef SMOOTH_LINES_OK
00713 if ( dev->smooth == 1 )
00714 {
00715 gdImageSetAntiAliased( dev->im_out, dev->colour );
00716 gdImageLine( dev->im_out, x1, y1, x2, y2, gdAntiAliased );
00717 }
00718 else
00719 {
00720 gdImageLine( dev->im_out, x1, y1, x2, y2, dev->colour );
00721 }
00722 #else
00723 gdImageLine( dev->im_out, x1, y1, x2, y2, dev->colour );
00724 #endif
00725 }
00726
00727
00728
00729
00730
00731
00732
00733 void
00734 plD_polyline_png( PLStream *pls, short *xa, short *ya, PLINT npts )
00735 {
00736 PLINT i;
00737
00738 for ( i = 0; i < npts - 1; i++ )
00739 plD_line_png( pls, xa[i], ya[i], xa[i + 1], ya[i + 1] );
00740 }
00741
00742
00743
00744
00745
00746
00747
00748
00749 static void
00750 fill_polygon( PLStream *pls )
00751 {
00752 png_Dev *dev = (png_Dev *) pls->dev;
00753
00754 int i;
00755 gdPoint *points = NULL;
00756
00757 if ( pls->dev_npts < 1 )
00758 return;
00759
00760 points = malloc( (size_t) pls->dev_npts * sizeof ( gdPoint ) );
00761
00762 for ( i = 0; i < pls->dev_npts; i++ )
00763 {
00764 points[i].x = pls->dev_x[i] / dev->scale;
00765 points[i].y = dev->pngy - ( pls->dev_y[i] / dev->scale );
00766 }
00767
00768 #ifdef SMOOTH_LINES_OK
00769 if ( dev->smooth == 1 )
00770 {
00771 gdImageSetAntiAliased( dev->im_out, dev->colour );
00772 gdImageFilledPolygon( dev->im_out, points, pls->dev_npts, gdAntiAliased );
00773 }
00774 else
00775 {
00776 gdImageFilledPolygon( dev->im_out, points, pls->dev_npts, dev->colour );
00777 }
00778 #else
00779 gdImageFilledPolygon( dev->im_out, points, pls->dev_npts, dev->colour );
00780 #endif
00781
00782 free( points );
00783 }
00784
00785
00786
00787
00788
00789
00790
00791 static void
00792 setcmap( PLStream *pls )
00793 {
00794 int i, ncol1 = pls->ncol1;
00795 int ncol0 = pls->ncol0, total_colours;
00796 PLColor cmap1col;
00797 png_Dev *dev = (png_Dev *) pls->dev;
00798 PLFLT tmp_colour_pos;
00799
00800
00801
00802
00803
00804
00805 if ( dev->im_out != NULL )
00806 {
00807 for ( i = 0; i < 256; i++ )
00808 {
00809 gdImageColorDeallocate( dev->im_out, i );
00810 }
00811 }
00812
00813 if ( ncol0 > NCOLOURS / 2 )
00814 {
00815 plwarn( "Too many colours in cmap0." );
00816 ncol0 = NCOLOURS / 2;
00817 pls->ncol0 = ncol0;
00818 }
00819
00820 dev->totcol = 0;
00821
00822 total_colours = ncol0 + ncol1;
00823
00824 if ( total_colours > NCOLOURS )
00825 {
00826 total_colours = NCOLOURS;
00827 ncol1 = total_colours - ncol0;
00828
00829 if ( ncol1 <= 0 )
00830 {
00831 plexit( "Problem setting colourmap in PNG or JPEG driver." );
00832 }
00833 }
00834
00835 dev->ncol1 = ncol1;
00836
00837
00838
00839
00840
00841
00842 if ( ( ncol0 > 0 ) && ( dev->im_out != NULL ) )
00843 {
00844 for ( i = 0; i < ncol0; i++ )
00845 {
00846 #if GD2_VERS >= 2
00847 gdImageColorAllocateAlpha( dev->im_out,
00848 pls->cmap0[i].r, pls->cmap0[i].g, pls->cmap0[i].b,
00849 plToGdAlpha( pls->cmap0[i].a ) );
00850 #else
00851 gdImageColorAllocate( dev->im_out,
00852 pls->cmap0[i].r, pls->cmap0[i].g, pls->cmap0[i].b );
00853 #endif
00854 ++dev->totcol;
00855 }
00856 }
00857
00858
00859
00860
00861 if ( ( ncol1 > 0 ) && ( dev->im_out != NULL ) )
00862 {
00863 for ( i = 0; i < ncol1; i++ )
00864 {
00865 if ( ncol1 < pls->ncol1 )
00866 {
00867
00868
00869
00870
00871
00872
00873
00874
00875 tmp_colour_pos = i > 0 ? pls->ncol1 * ( (PLFLT) i / ncol1 ) : 0;
00876 plcol_interp( pls, &cmap1col, (int) tmp_colour_pos, pls->ncol1 );
00877 }
00878 else
00879 {
00880 plcol_interp( pls, &cmap1col, i, ncol1 );
00881 }
00882
00883
00884 #if GD2_VERS >= 2
00885 gdImageColorAllocateAlpha( dev->im_out,
00886 cmap1col.r, cmap1col.g, cmap1col.b,
00887 plToGdAlpha( cmap1col.a ) );
00888 #else
00889 gdImageColorAllocate( dev->im_out,
00890 cmap1col.r, cmap1col.g, cmap1col.b );
00891 #endif
00892
00893 ++dev->totcol;
00894 }
00895 }
00896 }
00897
00898
00899
00900
00901
00902
00903
00904
00905 void
00906 plD_state_png( PLStream *pls, PLINT op )
00907 {
00908 png_Dev *dev = (png_Dev *) pls->dev;
00909 PLFLT tmp_colour_pos;
00910 #if GD2_VERS >= 2
00911 long temp_col;
00912 #endif
00913
00914
00915 switch ( op )
00916 {
00917 #if GD2_VERS >= 2
00918 case PLSTATE_WIDTH:
00919 gdImageSetThickness( dev->im_out, pls->width );
00920 break;
00921 #endif
00922
00923 case PLSTATE_COLOR0:
00924 #if GD2_VERS >= 2
00925
00926 if ( ( pls->icol0 == PL_RGB_COLOR ) ||
00927 ( gdImageTrueColor( dev->im_out ) ) )
00928 {
00929 if ( ( dev->totcol < NCOLOURS ) ||
00930 ( gdImageTrueColor( dev->im_out ) ) )
00931 {
00932
00933 #if GD2_VERS >= 2
00934 temp_col = gdImageColorAllocateAlpha( dev->im_out, pls->curcolor.r,
00935 pls->curcolor.g, pls->curcolor.b,
00936 plToGdAlpha( pls->curcolor.a ) );
00937 #else
00938 temp_col = gdImageColorAllocate( dev->im_out, pls->curcolor.r,
00939 pls->curcolor.g, pls->curcolor.b );
00940 #endif
00941
00942 if ( gdImageTrueColor( dev->im_out ) )
00943 dev->colour = temp_col;
00944 else
00945 {
00946 dev->colour = dev->totcol;
00947 dev->totcol++;
00948 }
00949 }
00950 }
00951 else
00952 {
00953 dev->colour = pls->icol0;
00954 }
00955
00956 #else
00957 dev->colour = pls->icol0;
00958 if ( dev->colour == PL_RGB_COLOR )
00959 {
00960 if ( dev->totcol < NCOLOURS )
00961 {
00962 #if GD2_VERS >= 2
00963 gdImageColorAllocateAlpha( dev->im_out, pls->curcolor.r,
00964 pls->curcolor.g, pls->curcolor.b,
00965 plToGdAlpha( pls->curcolor.a ) );
00966 #else
00967 gdImageColorAllocate( dev->im_out, pls->curcolor.r,
00968 pls->curcolor.g, pls->curcolor.b );
00969 #endif
00970 dev->colour = dev->totcol;
00971 }
00972 }
00973 #endif
00974 break;
00975
00976 case PLSTATE_COLOR1:
00977
00978 #if GD2_VERS >= 2
00979 if ( !gdImageTrueColor( dev->im_out ) )
00980 {
00981 #endif
00982
00983
00984
00985
00986 if ( dev->ncol1 < pls->ncol1 )
00987 {
00988 tmp_colour_pos = dev->ncol1 * ( (PLFLT) pls->icol1 / ( pls->ncol1 > 0 ? pls->ncol1 : 1 ) );
00989 dev->colour = pls->ncol0 + (int) tmp_colour_pos;
00990 }
00991 else
00992 dev->colour = pls->ncol0 + pls->icol1;
00993 #if GD2_VERS >= 2
00994 }
00995 else
00996 {
00997 #if GD2_VERS >= 2
00998 dev->colour = gdTrueColorAlpha( pls->curcolor.r, pls->curcolor.g,
00999 pls->curcolor.b,
01000 plToGdAlpha( pls->curcolor.a ) );
01001 #else
01002 dev->colour = gdTrueColor( pls->curcolor.r, pls->curcolor.g,
01003 pls->curcolor.b );
01004 #endif
01005 }
01006 #endif
01007 break;
01008
01009
01010 case PLSTATE_CMAP0:
01011 case PLSTATE_CMAP1:
01012
01013 #if GD2_VERS >= 2
01014 if ( ( dev->im_out != NULL ) && !gdImageTrueColor( dev->im_out ) )
01015 {
01016 #endif
01017
01018
01019
01020
01021
01022
01023 if ( pls->color )
01024 setcmap( pls );
01025
01026 #if GD2_VERS >= 2
01027 }
01028 #endif
01029
01030 break;
01031 }
01032 }
01033
01034
01035
01036
01037
01038
01039
01040
01041 void plD_esc_png( PLStream *pls, PLINT op, void *ptr )
01042 {
01043 switch ( op )
01044 {
01045 case PLESC_FILL:
01046 fill_polygon( pls );
01047 break;
01048
01049 #ifdef HAVE_FREETYPE
01050 case PLESC_HAS_TEXT:
01051 plD_render_freetype_text( pls, (EscText *) ptr );
01052 break;
01053 #endif
01054 }
01055 }
01056
01057
01058
01059
01060
01061
01062
01063
01064 void plD_bop_png( PLStream *pls )
01065 {
01066 png_Dev *dev;
01067
01068 plGetFam( pls );
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078 dev = (png_Dev *) pls->dev;
01079
01080 pls->famadv = 1;
01081
01082 pls->page++;
01083
01084 if ( dev->black15 )
01085 plD_black15_gd( pls );
01086 if ( dev->red15 )
01087 plD_red15_gd( pls );
01088
01089 #if GD2_VERS >= 2
01090 if ( ( ( ( ( dev->truecolour > 0 ) && ( dev->palette > 0 ) ) ||
01091 ( ( dev->truecolour == 0 ) && ( dev->palette == 0 ) ) ) &&
01092 ( ( pls->ncol1 + pls->ncol0 ) <= 256 ) ) ||
01093 ( ( ( dev->palette > 0 ) && ( dev->truecolour == 0 ) ) ) )
01094 {
01095 #endif
01096
01097 dev->im_out = gdImageCreate( pls->xlength, pls->ylength );
01098
01099 setcmap( pls );
01100
01101 #if GD2_VERS >= 2
01102 }
01103 else
01104 {
01105 dev->im_out = gdImageCreateTrueColor( pls->xlength, pls->ylength );
01106 plP_state( PLSTATE_COLOR0 );
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121 if ( ( pls->cmap0[0].r != 0 ) || ( pls->cmap0[0].g != 0 ) ||
01122 ( pls->cmap0[0].b != 0 ) || ( pls->cmap0[0].a != 0.0 ) )
01123 {
01124 gdImageFilledRectangle( dev->im_out, 0, 0, pls->xlength - 1, pls->ylength - 1,
01125 gdTrueColorAlpha( pls->cmap0[0].r, pls->cmap0[0].g,
01126 pls->cmap0[0].b,
01127 plToGdAlpha( pls->cmap0[0].a ) ) );
01128 }
01129 }
01130
01131
01132
01133
01134
01135 plD_state_png( pls, PLSTATE_WIDTH );
01136
01137 #endif
01138 }
01139
01140
01141
01142
01143
01144
01145
01146 void plD_tidy_png( PLStream *pls )
01147 {
01148 #ifdef HAVE_FREETYPE
01149 if ( pls->dev_text )
01150 {
01151 plD_FreeType_Destroy( pls );
01152 }
01153 #endif
01154
01155 plCloseFile( pls );
01156 free_mem( pls->dev );
01157 }
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168 void plD_black15_gd( PLStream *pls )
01169 {
01170 if ( pls->ncol0 > 15 )
01171 {
01172 if ( ( pls->cmap0[0].r > 227 ) && ( pls->cmap0[0].g > 227 ) && ( pls->cmap0[0].b > 227 ) )
01173 {
01174 pls->cmap0[15].r = 0;
01175 pls->cmap0[15].g = 0;
01176 pls->cmap0[15].b = 0;
01177 }
01178 }
01179 }
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208 void plD_red15_gd( PLStream *pls )
01209 {
01210 char r = pls->cmap0[1].r;
01211 char g = pls->cmap0[1].g;
01212 char b = pls->cmap0[1].b;
01213
01214 if ( pls->ncol0 > 15 )
01215 {
01216 pls->cmap0[1].r = pls->cmap0[15].r;
01217 pls->cmap0[1].g = pls->cmap0[15].r;
01218 pls->cmap0[1].b = pls->cmap0[15].r;
01219
01220 pls->cmap0[15].r = r;
01221 pls->cmap0[15].g = g;
01222 pls->cmap0[15].b = b;
01223 }
01224 }
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255 void plD_gd_optimise( PLStream *pls )
01256 {
01257 png_Dev *dev = (png_Dev *) pls->dev;
01258 int i, j;
01259 char *bbuf;
01260
01261 bbuf = calloc( 256, (size_t) 1 );
01262 if ( bbuf == NULL )
01263 plexit( "plD_gd_optimise: Out of memory." );
01264
01265 for ( i = 0; i < ( pls->xlength - 1 ); i++ )
01266 {
01267 for ( j = 0; j < ( pls->ylength - 1 ); j++ )
01268 {
01269 bbuf[gdImagePalettePixel( dev->im_out, i, j )] = 1;
01270 }
01271 }
01272
01273 for ( i = 0; i < 256; i++ )
01274 {
01275 if ( bbuf[i] == 0 )
01276 gdImageColorDeallocate( dev->im_out, i );
01277 }
01278
01279 free( bbuf );
01280 }
01281
01282
01283 #ifdef PLD_png
01284
01285
01286
01287
01288
01289
01290
01291 void plD_eop_png( PLStream *pls )
01292 {
01293 png_Dev *dev = (png_Dev *) pls->dev;
01294 int im_size = 0;
01295 int png_compression;
01296 void *im_ptr = NULL;
01297 size_t nwrite;
01298
01299 if ( pls->family || pls->page == 1 )
01300 {
01301 if ( dev->optimise )
01302 {
01303 #if GD2_VERS >= 2
01304 if ( ( ( ( ( dev->truecolour > 0 ) && ( dev->palette > 0 ) ) ||
01305 ( ( dev->truecolour == 0 ) && ( dev->palette == 0 ) ) ) &&
01306 ( ( pls->ncol1 + pls->ncol0 ) <= 256 ) ) ||
01307 ( ( ( dev->palette > 0 ) && ( dev->truecolour == 0 ) ) ) )
01308 {
01309 #endif
01310 plD_gd_optimise( pls );
01311
01312 #if GD2_VERS >= 2
01313 }
01314 #endif
01315 }
01316
01317
01318
01319
01320
01321
01322 #if GD2_VERS >= 2
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334 png_compression = ( ( pls->dev_compression <= 0 ) || ( pls->dev_compression > 99 ) ) ? 90 : pls->dev_compression;
01335 png_compression = ( png_compression > 9 ) ? ( png_compression / 10 ) : png_compression;
01336 im_ptr = gdImagePngPtrEx( dev->im_out, &im_size, png_compression );
01337 #else
01338 im_ptr = gdImagePngPtr( dev->im_out, &im_size );
01339 #endif
01340 if ( im_ptr )
01341 {
01342 nwrite = fwrite( im_ptr, sizeof ( char ), im_size, pls->OutFile );
01343 if ( nwrite != im_size )
01344 plabort( "gd driver: Error writing png file" );
01345 gdFree( im_ptr );
01346 }
01347
01348 gdImageDestroy( dev->im_out );
01349 dev->im_out = NULL;
01350 }
01351 }
01352
01353 #endif
01354
01355 #ifdef HAVE_FREETYPE
01356
01357
01358
01359
01360
01361
01362
01363
01364 void plD_pixel_gd( PLStream *pls, short x, short y )
01365 {
01366 png_Dev *dev = (png_Dev *) pls->dev;
01367
01368 gdImageSetPixel( dev->im_out, x, y, dev->colour );
01369 }
01370
01371
01372
01373
01374
01375
01376
01377
01378 void plD_set_pixel_gd( PLStream *pls, short x, short y, PLINT colour )
01379 {
01380 png_Dev *dev = (png_Dev *) pls->dev;
01381 int R, G, B;
01382 int Colour;
01383
01384 G = GetGValue( colour );
01385 R = GetRValue( colour );
01386 B = GetBValue( colour );
01387
01388 Colour = gdImageColorResolve( dev->im_out, R, G, B );
01389 gdImageSetPixel( dev->im_out, x, y, Colour );
01390 }
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400 PLINT plD_read_pixel_gd( PLStream *pls, short x, short y )
01401 {
01402 png_Dev *dev = (png_Dev *) pls->dev;
01403 PLINT colour;
01404 unsigned char R, G, B;
01405
01406 colour = gdImageGetTrueColorPixel( dev->im_out, x, y );
01407
01408 R = gdTrueColorGetRed( colour );
01409 G = gdTrueColorGetGreen( colour );
01410 B = gdTrueColorGetBlue( colour );
01411
01412 colour = RGB( R, G, B );
01413 return ( colour );
01414 }
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426 static void init_freetype_lv1( PLStream *pls )
01427 {
01428 FT_Data *FT;
01429
01430 plD_FreeType_init( pls );
01431
01432 FT = (FT_Data *) pls->FT;
01433 FT->pixel = (plD_pixel_fp) plD_pixel_gd;
01434 FT->read_pixel = (plD_read_pixel_fp) plD_read_pixel_gd;
01435 FT->set_pixel = (plD_set_pixel_fp) plD_set_pixel_gd;
01436 }
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463 static void init_freetype_lv2( PLStream *pls )
01464 {
01465 png_Dev *dev = (png_Dev *) pls->dev;
01466 FT_Data *FT = (FT_Data *) pls->FT;
01467
01468 FT->scale = dev->scale;
01469 FT->ymax = dev->pngy;
01470 FT->invert_y = 1;
01471 FT->smooth_text = 0;
01472
01473 if ( ( FT->want_smooth_text == 1 ) && ( FT->BLENDED_ANTIALIASING == 0 ) )
01474 {
01475 FT->ncol0_org = pls->ncol0;
01476 FT->ncol0_xtra = NCOLOURS - ( pls->ncol1 + pls->ncol0 );
01477 FT->ncol0_width = FT->ncol0_xtra / ( pls->ncol0 - 1 );
01478 if ( FT->ncol0_width > 4 )
01479 {
01480 if ( FT->ncol0_width > max_number_of_grey_levels_used_in_text_smoothing )
01481 FT->ncol0_width = max_number_of_grey_levels_used_in_text_smoothing;
01482 plscmap0n( FT->ncol0_org + ( FT->ncol0_width * pls->ncol0 ) );
01483
01484
01485
01486
01487
01488 {
01489 PLINT level_save;
01490 level_save = pls->level;
01491 pls->level = 0;
01492 pl_set_extended_cmap0( pls, FT->ncol0_width, FT->ncol0_org );
01493 pls->level = level_save;
01494 }
01495 FT->smooth_text = 1;
01496 }
01497 else
01498 plwarn( "Insufficient colour slots available in CMAP0 to do text smoothing." );
01499 }
01500 else if ( ( FT->want_smooth_text == 1 ) && ( FT->BLENDED_ANTIALIASING == 1 ) )
01501 {
01502 FT->smooth_text = 1;
01503 }
01504 }
01505
01506 #endif
01507
01508
01509 #ifdef PLD_jpeg
01510
01511
01512
01513
01514
01515
01516
01517 void plD_eop_jpeg( PLStream *pls )
01518 {
01519 png_Dev *dev = (png_Dev *) pls->dev;
01520 int im_size = 0;
01521 void *im_ptr = NULL;
01522 size_t nwrite;
01523 int jpeg_compression;
01524
01525 if ( pls->family || pls->page == 1 )
01526 {
01527
01528
01529
01530 if ( ( pls->dev_compression <= 0 ) || ( pls->dev_compression > 99 ) )
01531 jpeg_compression = 90;
01532 else
01533 jpeg_compression = pls->dev_compression;
01534
01535
01536
01537
01538
01539 im_ptr = gdImageJpegPtr( dev->im_out, &im_size, jpeg_compression );
01540 if ( im_ptr )
01541 {
01542 nwrite = fwrite( im_ptr, sizeof ( char ), im_size, pls->OutFile );
01543 if ( nwrite != im_size )
01544 plabort( "gd driver: Error writing png file" );
01545 gdFree( im_ptr );
01546 }
01547
01548 gdImageDestroy( dev->im_out );
01549 dev->im_out = NULL;
01550 }
01551 }
01552
01553 #endif
01554
01555 #ifdef PLD_gif
01556
01557
01558
01559
01560
01561
01562
01563 void plD_eop_gif( PLStream *pls )
01564 {
01565 png_Dev *dev = (png_Dev *) pls->dev;
01566 int im_size = 0;
01567 void *im_ptr = NULL;
01568 size_t nwrite;
01569
01570 if ( pls->family || pls->page == 1 )
01571 {
01572
01573
01574
01575
01576 im_ptr = gdImageGifPtr( dev->im_out, &im_size );
01577 if ( im_ptr )
01578 {
01579 nwrite = fwrite( im_ptr, sizeof ( char ), im_size, pls->OutFile );
01580 if ( nwrite != im_size )
01581 plabort( "gd driver: Error writing png file" );
01582 gdFree( im_ptr );
01583 }
01584
01585 gdImageDestroy( dev->im_out );
01586 dev->im_out = NULL;
01587 }
01588 }
01589
01590 #endif
01591
01592
01593
01594
01595
01596 #else
01597 int
01598 pldummy_png()
01599 {
01600 return 0;
01601 }
01602
01603 #endif // PNG