diff options
author | Peter Breitenlohner <peb@mppmu.mpg.de> | 2008-05-14 15:56:03 +0000 |
---|---|---|
committer | Peter Breitenlohner <peb@mppmu.mpg.de> | 2008-05-14 15:56:03 +0000 |
commit | a1c768e64b0301a6e6a7a186048a79b6d0fb6d78 (patch) | |
tree | 07c9046a51de431c66e21914c423c73e9d62f00c /Build/source/texk/dvipng/special.c | |
parent | 6f0a0723e2f1a5fdbb91158be02f8794f704d278 (diff) |
dvipng-1.10
git-svn-id: svn://tug.org/texlive/trunk@8139 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/dvipng/special.c')
-rw-r--r-- | Build/source/texk/dvipng/special.c | 695 |
1 files changed, 438 insertions, 257 deletions
diff --git a/Build/source/texk/dvipng/special.c b/Build/source/texk/dvipng/special.c index e93e6d5d772..9fc47a373b3 100644 --- a/Build/source/texk/dvipng/special.c +++ b/Build/source/texk/dvipng/special.c @@ -4,35 +4,135 @@ Part of the dvipng distribution - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA. + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/>. - Copyright (C) 2002-2006 Jan-Åke Larsson + Copyright (C) 2002-2008 Jan-Åke Larsson ************************************************************************/ #include "dvipng.h" -#include <fcntl.h> -#if HAVE_ALLOCA_H -# include <alloca.h> -#endif #define SKIPSPACES(s) while(s && *s==' ' && *s!='\0') s++ +/* PostScript can come as a string (headers and raw specials) or + a memory-mapped file (headers and included EPS figures). */ + +struct pscode { + struct pscode* next; + char* special; /* complete special */ + char* code; /* PS string, null if a file */ + char* filename; /* file name, null if a string */ + char* postcode; /* post PS string */ + struct filemmap fmmap; /* file mmap */ +}; + +struct pscode* psheaderp=NULL; /* static, DVI-specific header list */ + +void PSCodeInit(struct pscode *entry, char *special) +{ + entry->next=NULL; + entry->special=special; + entry->code=NULL; + entry->filename=NULL; + entry->postcode=NULL; + entry->fmmap.data=NULL; + if (special==NULL) + return; + if (strncmp(special,"header=",7)==0) + entry->filename=special+7; + else if (strncmp(special,"ps:: plotfile ",14)==0) + entry->filename=special+14; + else if (special[0]=='"' || special[0]=='!') + entry->code=special+1; + else if (strncmp(special,"ps::[begin]",11)==0) + entry->code=special+11; + else if (strncmp(special,"ps::[end]",9)==0) + entry->code=special+9; + else if (strncmp(special,"ps::",4)==0) + entry->code=special+4; + else if (strncmp(special,"ps:",3)==0) + entry->code=special+3; + else + entry->code=special; +#ifdef DEBUG + if (entry->code!=NULL) + DEBUG_PRINT(DEBUG_GS,(" '%s'",entry->code)); + if (entry->filename!=NULL) + DEBUG_PRINT(DEBUG_GS,(" {%s}",entry->filename)); + if (entry->postcode!=NULL) + DEBUG_PRINT(DEBUG_GS,(" '%s'",entry->postcode)); +#endif +} + + + +void ClearPSHeaders(void) +{ + struct pscode *temp=psheaderp; + + while(temp!=NULL) { + psheaderp=psheaderp->next; + if (temp->fmmap.data!=NULL) + UnMmapFile(&(temp->fmmap)); + free(temp); + temp=psheaderp; + } +} + +void writepscode(struct pscode* pscodep, FILE* psstream) +{ + while (pscodep!=NULL) { + if (pscodep->code!=NULL) { + fputs(pscodep->code,psstream); + putc('\n',psstream); + DEBUG_PRINT(DEBUG_GS,("\n PS CODE:\t%s",pscodep->code)); + } + if (pscodep->filename!=NULL && pscodep->fmmap.data==NULL) { + char* filepath= + kpse_find_file(pscodep->filename,kpse_tex_ps_header_format,false); + if (filepath==NULL) { + Warning("Cannot find PostScript file %s, ignored", pscodep->filename); + page_flags |= PAGE_GAVE_WARN; + } else if (MmapFile(filepath,&(pscodep->fmmap))) { + Warning("PostScript file %s unusable, ignored", pscodep->filename); + page_flags |= PAGE_GAVE_WARN; + } + } + if (pscodep->fmmap.data!=NULL) { + unsigned char* position; + + DEBUG_PRINT(DEBUG_GS,("\n PS FILE:\t%s",pscodep->filename)); + position=(unsigned char*)pscodep->fmmap.data; + while(position + < (unsigned char*)pscodep->fmmap.data + pscodep->fmmap.size) { + putc(*position,psstream); + position++; + } + } + if (pscodep->postcode!=NULL) { + fputs(pscodep->postcode,psstream); + putc('\n',psstream); + DEBUG_PRINT(DEBUG_GS,("\n PS POST CODE:\t%s",pscodep->postcode)); + } + pscodep=pscodep->next; + } +} + + gdImagePtr -ps2png(FILE *psfilestream, char *device, int hresolution, int vresolution, +ps2png(struct pscode* pscodep, char *device, int hresolution, int vresolution, int llx, int lly, int urx, int ury, int bgred, int bggreen, int bgblue) { #ifndef MIKTEX @@ -54,7 +154,6 @@ ps2png(FILE *psfilestream, char *device, int hresolution, int vresolution, gdImagePtr psimage=NULL; static bool showpage=false; - fseek(psfilestream,0,SEEK_SET); sprintf(resolution, "-r%dx%d",hresolution,vresolution); /* Future extension for \rotatebox status=sprintf(devicesize, "-g%dx%d", @@ -68,8 +167,8 @@ ps2png(FILE *psfilestream, char *device, int hresolution, int vresolution, GS_PATH, device, resolution, /*devicesize,*/ "-dBATCH", "-dNOPAUSE", "-q", "-sOutputFile=-", "-dTextAlphaBits=4", "-dGraphicsAlphaBits=4", - (flags & NO_GSSAFER) ? "-": "-dSAFER", - (flags & NO_GSSAFER) ? "": "- ")); + (option_flags & NO_GSSAFER) ? "-": "-dSAFER", + (option_flags & NO_GSSAFER) ? "": "- ")); #ifndef MIKTEX if (pipe(downpipe) || pipe(uppipe)) return(NULL); /* Ready to fork */ @@ -84,8 +183,8 @@ ps2png(FILE *psfilestream, char *device, int hresolution, int vresolution, execlp(GS_PATH, GS_PATH, device, resolution, /*devicesize,*/ "-dBATCH", "-dNOPAUSE", "-q", "-sOutputFile=-", "-dTextAlphaBits=4", "-dGraphicsAlphaBits=4", - (flags & NO_GSSAFER) ? "-": "-dSAFER", - (flags & NO_GSSAFER) ? NULL: "-", + (option_flags & NO_GSSAFER) ? "-": "-dSAFER", + (option_flags & NO_GSSAFER) ? NULL: "-", NULL); _exit (EXIT_FAILURE); } @@ -93,6 +192,7 @@ ps2png(FILE *psfilestream, char *device, int hresolution, int vresolution, close(downpipe[0]); psstream=fdopen(downpipe[1],"wb"); + /* fclose(psstream); psstream=fopen("test.ps","wb"); */ if (psstream == NULL) close(downpipe[1]); close(uppipe[1]); @@ -108,8 +208,8 @@ ps2png(FILE *psfilestream, char *device, int hresolution, int vresolution, szGsPath, device, resolution, /*devicesize,*/ "-dBATCH", "-dNOPAUSE", "-q", "-sOutputFile=-", "-dTextAlphaBits=4", "-dGraphicsAlphaBits=4", - (flags & NO_GSSAFER) ? "-": "-dSAFER", - (flags & NO_GSSAFER) ? "": "-"); + (option_flags & NO_GSSAFER) ? "-": "-dSAFER", + (option_flags & NO_GSSAFER) ? "": "-"); if (! miktex_start_process_3(szCommandLine, &pi, INVALID_HANDLE_VALUE, &hPsStream, &hPngStream, &hStdErr, 0)) { Warning("Ghostscript could not be started"); @@ -130,7 +230,7 @@ ps2png(FILE *psfilestream, char *device, int hresolution, int vresolution, } #endif if (psstream) { - int pschar; + writepscode(psheaderp,psstream); DEBUG_PRINT(DEBUG_GS,("\n PS CODE:\t<</PageSize[%d %d]/PageOffset[%d %d[1 1 dtransform exch]{0 ge{neg}if exch}forall]>>setpagedevice", urx - llx, ury - lly,llx,lly)); fprintf(psstream, "<</PageSize[%d %d]/PageOffset[%d %d[1 1 dtransform exch]{0 ge{neg}if exch}forall]>>setpagedevice\n", @@ -141,12 +241,7 @@ ps2png(FILE *psfilestream, char *device, int hresolution, int vresolution, fprintf(psstream, "gsave %f %f %f setrgbcolor clippath fill grestore", bgred/255.0, bggreen/255.0, bgblue/255.0); } - DEBUG_PRINT(DEBUG_GS,("\n PS DATA:\t...")); - pschar=getc(psfilestream); - while(pschar!=EOF) { - putc(pschar,psstream); - pschar=getc(psfilestream); - } + writepscode(pscodep,psstream); if (showpage) { DEBUG_PRINT(DEBUG_GS,("\n PS CODE:\tshowpage")); fprintf(psstream, " showpage "); @@ -165,7 +260,8 @@ ps2png(FILE *psfilestream, char *device, int hresolution, int vresolution, if (!showpage) { showpage=true; DEBUG_PRINT(DEBUG_GS,("(will try adding \"showpage\") ")); - psimage=ps2png(psfilestream, device, hresolution, vresolution, llx, lly, urx, ury, + psimage=ps2png(pscodep, + device, hresolution, vresolution, llx, lly, urx, ury, bgred,bggreen,bgblue); showpage=false; } @@ -178,132 +274,140 @@ ps2png(FILE *psfilestream, char *device, int hresolution, int vresolution, return psimage; } - -gdImagePtr readcache(char* psname) +gdImagePtr +rescale(gdImagePtr psimage, int pngwidth, int pngheight) { - char *cachename = NULL, *cachefile, *separator; - gdImagePtr cacheimage=NULL; - - cachename = alloca(sizeof(char)*(strlen(psname+5))); - if (cachename==NULL) - Fatal("cannot allocate space for cached image filename"); - strcpy(cachename,psname); - separator = strrchr(cachename,'.'); - if (separator!=NULL) - *separator='\0'; - strcat(cachename,".png"); - - cachefile = kpse_find_file(cachename,kpse_pict_format,0); - if (cachefile!=NULL) { - FILE* cachefilep = fopen(cachefile,"rb"); - - if (cachefilep!=NULL) { - DEBUG_PRINT(DEBUG_DVI,("\n READING CACHED IMAGE \t%s", cachefile)); - cacheimage = gdImageCreateFromPng(cachefilep); - fclose(cachefilep); - } - free(cachefile); + gdImagePtr scaledimage=psimage; + /* Rescale unless correct size */ + if (psimage!=NULL + && gdImageSX(psimage)!=pngwidth + && gdImageSY(psimage)!=pngheight) { + DEBUG_PRINT(DEBUG_DVI, + ("\n RESCALE INCLUDED BITMAP \t(%d,%d) -> (%d,%d)", + gdImageSX(psimage),gdImageSY(psimage), + pngwidth,pngheight)); +#ifdef HAVE_GDIMAGECREATETRUECOLOR + scaledimage=gdImageCreateTrueColor(pngwidth,pngheight); + gdImageCopyResampled(scaledimage,psimage,0,0,0,0, + pngwidth,pngheight, + gdImageSX(psimage),gdImageSY(psimage)); +#else + scaledimage=gdImageCreate(pngwidth,pngheight); + gdImageCopyResized(scaledimage,psimage,0,0,0,0, + pngwidth,pngheight, + gdImageSX(psimage),gdImageSY(psimage)); +#endif + gdImageDestroy(psimage); } - return(cacheimage); + return(scaledimage); } -void storecache(char* psname, gdImagePtr psimage) -{ - char *cachename = NULL, *separator; - - cachename = alloca(sizeof(char)*(strlen(psname+5))); - if (cachename==NULL) - Fatal("cannot allocate space for cached image filename"); - strcpy(cachename,psname); - separator = strrchr(cachename,'.'); - if (separator!=NULL) - *separator='\0'; - strcat(cachename,".png"); - - if (psimage != NULL) { - FILE* cachefilep = fopen(cachename,"wb"); - if (cachefilep!=NULL) { - gdImagePng(psimage,cachefilep); - fclose(cachefilep); - } else - Warning("Unable to cache %s as PNG", psname ); +void newpsheader(char* special) { + struct pscode* tmp; + char* txt; + + if (strncmp(special,"! /pgfH",7)==0) { + SetSpecial("header=tex.pro",0,0); + SetSpecial("header=special.pro",0,0); + SetSpecial("! TeXDict begin",0,0); } + if (psheaderp==NULL) { + if ((tmp=psheaderp=malloc(sizeof(struct pscode)))==NULL) + Fatal("cannot allocate space for PostScript header struct"); + } else { + tmp=psheaderp; + /* No duplicates. This still misses pre=..., because we still + change that. To be fixed */ + while(tmp->next!=NULL) { + tmp=tmp->next; + if (strcmp(tmp->special,special)==0) + return; + } + if ((tmp->next=malloc(sizeof(struct pscode)))==NULL) + Fatal("cannot allocate space for PostScript header struct"); + tmp=tmp->next; + } + DEBUG_PRINT(DEBUG_GS,("\n PS HEADER ")); + if ((txt=malloc(strlen(special)+1))==NULL) + Fatal("cannot malloc space for PostScript header"); + strcpy(txt,special); + PSCodeInit(tmp,txt); } - - -/*-->SetSpecial*/ /*********************************************************************/ /**************************** SetSpecial ***************************/ /*********************************************************************/ -void SetSpecial(char * special, int32_t length, int32_t hh, int32_t vv) -/* interpret a \special command, made up of keyword=value pairs */ +void SetSpecial(char * special, int32_t hh, int32_t vv) +/* interpret a \special command, made up of keyword=value pairs, + * or !header or ps:literal_PostScript + */ { - char *buffer; - - DEBUG_PRINT(DEBUG_DVI,(" '%.*s'",length,special)); - - buffer = alloca(sizeof(char)*(length+1)); - if (buffer==NULL) - Fatal("cannot allocate space for special string"); - - strncpy(buffer,special,length); - buffer[length]='\0'; - - SKIPSPACES(buffer); + DEBUG_PRINT(DEBUG_DVI,(" '%s'",special)); + SKIPSPACES(special); /********************** Color specials ***********************/ - if (strncmp(buffer,"background ",11)==0) { - background(buffer+11); + if (strncmp(special,"background ",11)==0) { + background(special+11); return; } - if (strncmp(buffer,"color ",6)==0) { - buffer+=6; - SKIPSPACES(buffer); - if (strncmp(buffer,"push ",5)==0) { - pushcolor(buffer+5); + if (strncmp(special,"color ",6)==0) { + special+=6; + SKIPSPACES(special); + if (strncmp(special,"push ",5)==0) { + pushcolor(special+5); } else { - if (strcmp(buffer,"pop")==0) + if (strcmp(special,"pop")==0) popcolor(); else - resetcolorstack(buffer); + resetcolorstack(special); } return; } /******************* Image inclusion ********************/ - if (strncmp(buffer,"PSfile=",7)==0) { /* PSfile */ - char* psname = buffer+7,*psfile; + + /* Needed tests for regression: PNG, GIF, JPEG and EPS inclusion, + * for different gd versions */ + + if (strncmp(special,"PSfile=",7)==0) { /* PSfile */ + char* psname = special+7; int llx=0,lly=0,urx=0,ury=0,rwi=0,rhi=0; bool clip=false; int hresolution,vresolution; int pngheight,pngwidth; - /* Remove quotation marks around filename */ + /* Remove quotation marks around filename. If no quotation marks, + use first word as filename */ if (*psname=='"') { - char* tmp; psname++; - tmp=strrchr(psname,'"'); - if (tmp!=NULL) { - *tmp='\0'; - buffer=tmp+1; - } else - buffer=NULL; + special=strrchr(psname,'"'); + } else { + special=strchr(psname,' '); + } + if (special!=NULL) { + *special='\0'; + special++; } - TEMPSTR(psfile,kpse_find_file(psname,kpse_pict_format,0)); /* Retrieve parameters */ - SKIPSPACES(buffer); - while(buffer && *buffer) { - if (strncmp(buffer,"llx=",4)==0) llx = strtol(buffer+4,&buffer,10); - else if (strncmp(buffer,"lly=",4)==0) lly = strtol(buffer+4,&buffer,10); - else if (strncmp(buffer,"urx=",4)==0) urx = strtol(buffer+4,&buffer,10); - else if (strncmp(buffer,"ury=",4)==0) ury = strtol(buffer+4,&buffer,10); - else if (strncmp(buffer,"rwi=",4)==0) rwi = strtol(buffer+4,&buffer,10); - else if (strncmp(buffer,"rhi=",4)==0) rhi = strtol(buffer+4,&buffer,10); - else if (strncmp(buffer,"clip",4)==0) {clip = true; buffer=buffer+4;} - while (*buffer && *buffer!=' ') buffer++; - SKIPSPACES(buffer); + SKIPSPACES(special); + while(special && *special) { + if (strncmp(special,"llx=",4)==0) + llx = strtol(special+4,&special,10); + else if (strncmp(special,"lly=",4)==0) + lly = strtol(special+4,&special,10); + else if (strncmp(special,"urx=",4)==0) + urx = strtol(special+4,&special,10); + else if (strncmp(special,"ury=",4)==0) + ury = strtol(special+4,&special,10); + else if (strncmp(special,"rwi=",4)==0) + rwi = strtol(special+4,&special,10); + else if (strncmp(special,"rhi=",4)==0) + rhi = strtol(special+4,&special,10); + else if (strncmp(special,"clip",4)==0) + {clip = true; special=special+4;} + while (*special && *special!=' ') special++; + SKIPSPACES(special); } /* Calculate resolution, and use our base resolution as a fallback. */ @@ -326,143 +430,114 @@ void SetSpecial(char * special, int32_t length, int32_t hh, int32_t vv) pngheight = (dpi*(ury-lly)+71)/72; } if (page_imagep != NULL) { /* Draw into image */ - char *psfile; + struct pscode image; gdImagePtr psimage=NULL; +#ifndef HAVE_GDIMAGECREATEFROMPNGPTR FILE* psstream; +#endif - TEMPSTR(psfile,kpse_find_file(psname,kpse_pict_format,0)); - if (psfile == NULL) { - Warning("Image file %s not found, image will be left blank", psname ); - flags |= PAGE_GAVE_WARN; - return; - } - /* Test access permission even for EPS files */ - psstream=fopen(psfile,"rb"); - if (psstream == NULL) { - Warning("Cannot access image file %s, image will be left blank", - psname ); - flags |= PAGE_GAVE_WARN; + TEMPSTR(image.filename,kpse_find_file(psname,kpse_pict_format,0)); + if (MmapFile(image.filename,&(image.fmmap)) || image.fmmap.size==0) { + Warning("Image file %s unusable, image will be left blank", + image.filename); + page_flags |= PAGE_GAVE_WARN; return; } Message(BE_NONQUIET," <%s",psname); - switch (getc(psstream)) { + switch ((unsigned char)*image.fmmap.data) { case 0x89: /* PNG magic: "\211PNG\r\n\032\n" */ - DEBUG_PRINT(DEBUG_DVI,("\n INCLUDE PNG \t%s",psfile)); - fseek(psstream,0,SEEK_SET); + DEBUG_PRINT(DEBUG_DVI,("\n INCLUDE PNG \t%s",image.filename)); +#ifdef HAVE_GDIMAGECREATEFROMPNGPTR + psimage=gdImageCreateFromPngPtr(image.fmmap.size,image.fmmap.data); +#else + psstream=fopen(image.filename,"rb"); psimage=gdImageCreateFromPng(psstream); + fclose(psstream); +#endif + psimage=rescale(psimage,pngwidth,pngheight); break; case 'G': /* GIF magic: "GIF87" or "GIF89" */ - DEBUG_PRINT(DEBUG_DVI,("\n INCLUDE GIF \t%s",psfile)); + DEBUG_PRINT(DEBUG_DVI,("\n INCLUDE GIF \t%s",image.filename)); #ifdef HAVE_GDIMAGEGIF - fseek(psstream,0,SEEK_SET); - psimage=gdImageCreateFromGif(psstream); + psimage=rescale(gdImageCreateFromGifPtr(image.fmmap.size, + image.fmmap.data), + pngwidth,pngheight); #else DEBUG_PRINT(DEBUG_DVI,(" (NO GIF DECODER)")); #endif break; case 0xff: /* JPEG magic: 0xffd8 */ - DEBUG_PRINT(DEBUG_DVI,("\n INCLUDE JPEG \t%s",psfile)); -#ifdef HAVE_GDIMAGEJPEG - fseek(psstream,0,SEEK_SET); + DEBUG_PRINT(DEBUG_DVI,("\n INCLUDE JPEG \t%s",image.filename)); +#ifdef HAVE_GDIMAGECREATEFROMJPEG +#ifdef HAVE_GDIMAGECREATEFROMPNGPTR + psimage=gdImageCreateFromJpegPtr(image.fmmap.size,image.fmmap.data); +#else + psstream=fopen(image.filename,"rb"); psimage=gdImageCreateFromJpeg(psstream); + fclose(psstream); +#endif + psimage=rescale(psimage,pngwidth,pngheight); #else DEBUG_PRINT(DEBUG_DVI,(" (NO JPEG DECODER)")); #endif break; default: /* Default, PostScript magic: "%!PS-Adobe" */ - if (flags & NO_GHOSTSCRIPT) { - Warning("GhostScript calls disallowed by --noghostscript", psfile ); - flags |= PAGE_GAVE_WARN; + if (option_flags & NO_GHOSTSCRIPT) { + Warning("GhostScript calls disallowed by --noghostscript" ); + page_flags |= PAGE_GAVE_WARN; } else { - gdImagePtr cacheimage=NULL; - if (flags & CACHE_IMAGES) - cacheimage=psimage=readcache(psname); /* Use alpha blending, and render transparent postscript images. The alpha blending works correctly only from libgd 2.0.12 upwards */ -#ifdef HAVE_GDIMAGECREATETRUECOLOR - if (!page_imagep->trueColor) - Warning("Palette output, opaque image inclusion"); #ifdef HAVE_GDIMAGEPNGEX - else if (psimage==NULL) { + if (page_imagep->trueColor) { + int tllx=llx,tlly=lly,turx=urx,tury=ury; + DEBUG_PRINT((DEBUG_DVI | DEBUG_GS), - ("\n GS RENDER \t%s -> pngalpha ",psfile)); - if (clip) { - DEBUG_PRINT((DEBUG_DVI | DEBUG_GS),(", CLIPPED TO BBOX")); - psimage = ps2png(psstream, "-sDEVICE=pngalpha", - hresolution, vresolution, - llx, lly, urx, ury, - 255,255,255); - } else { + ("\n GS RENDER \t%s -> pngalpha ",image.filename)); + if (!clip) { /* Render across the whole image */ + tllx=llx-(hh+1)*72/hresolution; + tlly=lly-(gdImageSY(page_imagep)-vv-1)*72/vresolution; + turx=llx+(gdImageSX(page_imagep)-hh)*72/hresolution; + tury=lly+(vv+1)*72/vresolution; DEBUG_PRINT((DEBUG_DVI | DEBUG_GS), ("\n EXPAND BBOX \t%d %d %d %d -> %d %d %d %d", - llx,lly,urx,ury, - llx-(hh+1)*72/hresolution, - lly-(gdImageSY(page_imagep)-vv-1)*72/vresolution, - llx+(gdImageSX(page_imagep)-hh)*72/hresolution, - lly+(vv+1)*72/vresolution)); - psimage = ps2png(psstream, "-sDEVICE=pngalpha", - hresolution, vresolution, - llx-(hh+1)*72/hresolution, - lly-(gdImageSY(page_imagep)-vv-1)*72/vresolution, - llx+(gdImageSX(page_imagep)-hh)*72/hresolution, - lly+(vv+1)*72/vresolution, - 255,255,255); - if (psimage!=NULL) { - hh=0; - vv=gdImageSY(page_imagep)-1; - pngwidth=gdImageSX(psimage); - pngheight=gdImageSY(psimage); - } + llx,lly,urx,ury,tllx,tlly,turx,tury)); +#ifdef DEBUG + } else { + DEBUG_PRINT((DEBUG_DVI | DEBUG_GS),(", CLIPPED TO BBOX")); +#endif } + psimage = ps2png(&image, "-sDEVICE=pngalpha", + hresolution, vresolution, + tllx, tlly, turx, tury, + 255,255,255); if (psimage==NULL) Warning("No GhostScript pngalpha output, opaque image inclusion"); - } -#endif + } else + Warning("Palette output, opaque image inclusion"); #endif if (psimage==NULL) { /* png256 gives inferior result */ DEBUG_PRINT((DEBUG_DVI | DEBUG_GS), - ("\n GS RENDER \t%s -> png16m", psfile)); - psimage = ps2png(psstream, "-sDEVICE=png16m", + ("\n GS RENDER \t%s -> png16m", image.filename)); + psimage = ps2png(&image, "-sDEVICE=png16m", hresolution, vresolution, llx, lly, urx, ury, cstack[0].red,cstack[0].green,cstack[0].blue); - flags |= PAGE_GAVE_WARN; + clip=true; + page_flags |= PAGE_GAVE_WARN; + } + if (!clip) { + /* Rendering across the whole image */ + hh=0; + vv=gdImageSY(psimage)-1; } - if (flags & CACHE_IMAGES && cacheimage==NULL) - storecache(psname,psimage); } } - fclose(psstream); + UnMmapFile(&(image.fmmap)); if (psimage!=NULL) { - /* Rescale, but ignore (one-pixel) rounding errors */ - if (gdImageSX(psimage)!=pngwidth - && gdImageSX(psimage)!=pngwidth+1 - && gdImageSY(psimage)!=pngheight - && gdImageSY(psimage)!=pngheight+1) { - gdImagePtr scaledimage; - - DEBUG_PRINT(DEBUG_DVI, - ("\n RESCALE INCLUDED BITMAP \t%s (%d,%d) -> (%d,%d)", - psfile, - gdImageSX(psimage),gdImageSY(psimage), - pngwidth,pngheight)); -#ifdef HAVE_GDIMAGECREATETRUECOLOR - scaledimage=gdImageCreateTrueColor(pngwidth,pngheight); - gdImageCopyResampled(scaledimage,psimage,0,0,0,0, - pngwidth,pngheight, - gdImageSX(psimage),gdImageSY(psimage)); -#else - scaledimage=gdImageCreate(pngwidth,pngheight); - gdImageCopyResized(scaledimage,psimage,0,0,0,0, - pngwidth,pngheight, - gdImageSX(psimage),gdImageSY(psimage)); -#endif - gdImageDestroy(psimage); - psimage=scaledimage; - } DEBUG_PRINT(DEBUG_DVI, ("\n GRAPHIC(X|S) INCLUDE \t%s (%d,%d) res %dx%d at (%d,%d)", psname,gdImageSX(psimage),gdImageSY(psimage), @@ -475,7 +550,7 @@ void SetSpecial(char * special, int32_t length, int32_t hh, int32_t vv) gdImageAlphaBlending(page_imagep,1); #else Warning("Using libgd < 2.0.12, opaque image inclusion"); - flags |= PAGE_GAVE_WARN; + page_flags |= PAGE_GAVE_WARN; #endif gdImageCopy(page_imagep, psimage, hh, vv-gdImageSY(psimage)+1, @@ -486,12 +561,12 @@ void SetSpecial(char * special, int32_t length, int32_t hh, int32_t vv) #endif gdImageDestroy(psimage); } else { - Warning("Unable to load %s, image will be left blank",psfile ); - flags |= PAGE_GAVE_WARN; + Warning("Unable to load %s, image will be left blank",image.filename); + page_flags |= PAGE_GAVE_WARN; } Message(BE_NONQUIET,">"); } else { /* Don't draw */ - flags |= PAGE_TRUECOLOR; + page_flags |= PAGE_TRUECOLOR; DEBUG_PRINT(DEBUG_DVI, ("\n GRAPHIC(X|S) INCLUDE \t%s (%d,%d) res %dx%d at (%d,%d)", psname,pngheight,pngwidth, @@ -504,53 +579,58 @@ void SetSpecial(char * special, int32_t length, int32_t hh, int32_t vv) return; } - if (strncmp(buffer,"!/preview@version(",18)==0) { - buffer+=18; - length-=18; - while (length>0 && buffer[length]!=')') - length--; + /******************* Raw PostScript ********************/ + + if (strncmp(special,"!/preview@version(",18)==0) { + int length=0; + special+=18; + while (special[length]!='\0' && special[length]!=')') + length++; if (page_imagep==NULL) - Message(BE_NONQUIET," (preview-latex version %.*s)",length,buffer); + Message(BE_NONQUIET," (preview-latex version %.*s)",length,special); return; } /* preview-latex' tightpage option */ - if (strncmp(buffer,"!/preview@tightpage",19)==0) { - buffer+=19; - SKIPSPACES(buffer); - if (strncmp(buffer,"true",4)==0) { + if (strncmp(special,"!/preview@tightpage",19)==0) { + special+=19; + SKIPSPACES(special); + if (strncmp(special,"true",4)==0) { if (page_imagep==NULL) Message(BE_NONQUIET," (preview-latex tightpage option detected, will use its bounding box)"); - flags |= PREVIEW_LATEX_TIGHTPAGE; - return; + dvi->flags |= DVI_PREVIEW_LATEX_TIGHTPAGE; } + return; } - if (strncmp(buffer,"!userdict",9)==0 - && strstr(buffer+10,"7{currentfile token not{stop}if 65781.76 div")!=NULL) { - if (page_imagep==NULL && ~flags & PREVIEW_LATEX_TIGHTPAGE) + if (strncmp(special,"!userdict",9)==0 + && strstr(special+10,"7{currentfile token not{stop}if 65781.76 div")!=NULL) { + if (page_imagep==NULL && ~dvi->flags & DVI_PREVIEW_LATEX_TIGHTPAGE) Message(BE_NONQUIET," (preview-latex <= 0.9.1 tightpage option detected, will use its bounding box)"); - flags |= PREVIEW_LATEX_TIGHTPAGE; + dvi->flags |= DVI_PREVIEW_LATEX_TIGHTPAGE; return; } /* preview-latex' dvips bop-hook redefinition */ - if (strncmp(buffer,"!userdict",9)==0 - && strstr(buffer+10,"preview-bop-")!=NULL) { + if (strncmp(special,"!userdict",9)==0 + && strstr(special+10,"preview-bop-")!=NULL) { + dvi->flags |= DVI_PREVIEW_BOP_HOOK; if (page_imagep==NULL) Message(BE_VERBOSE," (preview-latex beginning-of-page-hook detected)"); return; } - if (strncmp(buffer,"ps::",4)==0) { + if (dvi->flags & DVI_PREVIEW_BOP_HOOK && ~page_flags & PAGE_PREVIEW_BOP + && strncmp(special,"ps::",4)==0) { + page_flags |= PAGE_PREVIEW_BOP; /* Hokay, decode bounding box */ dviunits adj_llx,adj_lly,adj_urx,adj_ury,ht,dp,wd; - adj_llx = strtol(buffer+4,&buffer,10); - adj_lly = strtol(buffer,&buffer,10); - adj_urx = strtol(buffer,&buffer,10); - adj_ury = strtol(buffer,&buffer,10); - ht = strtol(buffer,&buffer,10); - dp = strtol(buffer,&buffer,10); - wd = strtol(buffer,&buffer,10); + adj_llx = strtol(special+4,&special,10); + adj_lly = strtol(special,&special,10); + adj_urx = strtol(special,&special,10); + adj_ury = strtol(special,&special,10); + ht = strtol(special,&special,10); + dp = strtol(special,&special,10); + wd = strtol(special,&special,10); if (wd>0) { x_offset_tightpage = (-adj_llx+dvi->conv*shrinkfactor-1)/dvi->conv/shrinkfactor; @@ -570,24 +650,125 @@ void SetSpecial(char * special, int32_t length, int32_t hh, int32_t vv) return; } - if (strncmp(buffer,"papersize=",10)==0) { /* papersize spec, ignored */ + if (special[0]=='"' || strncmp(special,"ps:",3)==0) { /* Literal PostScript */ + if (page_imagep != NULL) { /* Draw into image */ + static struct pscode *pscodep=NULL; + static bool psenvironment=false; + bool nextisps; + struct pscode *tmp; + gdImagePtr psimage=NULL; + char *txt; + + /* Some packages split their literal PostScript code into + several specials. Check for those, and concatenate them so + that they're given to one and the same invocation of gs */ + if (pscodep==NULL) { + Message(BE_NONQUIET," <literal PS"); + if ((tmp=pscodep=malloc(sizeof(struct pscode)))==NULL) + Fatal("cannot allocate space for raw PostScript struct"); + } else { + tmp=pscodep; + while(tmp->next != NULL) + tmp=tmp->next; + if ((tmp->next=malloc(sizeof(struct pscode)))==NULL) + Fatal("cannot allocate space for raw PostScript struct"); + tmp=tmp->next; + } + if (strncmp(special,"ps::[begin]",11)==0) + psenvironment=true; + else if (strncmp(special,"ps::[end]",9)==0) + psenvironment=false; + else if (strcmp(special,"ps:: pgfo")==0) + /* PostScript code to start page for pgf PostScript + specials. The first numbers are generally valid for the bop + instruction, and the latter code is to move the origin to + the right place. */ + special="ps:: 39139632 55387786 1000 600 600 (tikzdefault.dvi) @start 1 0 bop pgfo 0 0 matrix defaultmatrix transform itransform translate"; + else if (strcmp(special,"ps:: pgfc")==0) + special="ps:: pgfc eop end"; + nextisps=DVIIsNextPSSpecial(dvi); + if (psenvironment || nextisps) { + if (!nextisps) { + Warning("PostScript environment contains DVI commands"); + page_flags |= PAGE_GAVE_WARN; + } + /* Don't use alloca, we do not want to run out of stack space */ + DEBUG_PRINT(DEBUG_GS,("\n PS SPECIAL ")); + txt=malloc(strlen(special)+1); + strcpy(txt,special); + PSCodeInit(tmp,txt); + return; + } + DEBUG_PRINT(DEBUG_DVI,("\n LAST PS SPECIAL ")); + PSCodeInit(tmp,special); + /* Now, render image */ + if (option_flags & NO_GHOSTSCRIPT) + Warning("GhostScript calls disallowed by --noghostscript" ); + else { + /* Use alpha blending, and render transparent postscript + images. The alpha blending works correctly only from + libgd 2.0.12 upwards */ +#ifdef HAVE_GDIMAGEPNGEX + if (page_imagep->trueColor) { + /* Render across the whole image */ + psimage = ps2png(pscodep, "-sDEVICE=pngalpha", + dpi,dpi, + -(hh+1)*72/dpi, + -(gdImageSY(page_imagep)-vv-1)*72/dpi, + (gdImageSX(page_imagep)-hh)*72/dpi, + (vv+1)*72/dpi, + 255,255,255); + if (psimage!=NULL) { + gdImageAlphaBlending(page_imagep,1); + gdImageCopy(page_imagep, psimage, + 0,0,0,0, + gdImageSX(psimage),gdImageSY(psimage)); + gdImageAlphaBlending(page_imagep,0); + gdImageDestroy(psimage); + } else + Warning("No GhostScript pngalpha output, cannot render raw PostScript"); + } else + Warning("Palette output, cannot include raw PostScript"); +#else + Warning("Using libgd < 2.0.12, unable to include raw PostScript"); +#endif + } + while(pscodep->next != NULL) { + tmp=pscodep->next; + free(pscodep->special); + free(pscodep); + pscodep=tmp; + } + free(pscodep); + pscodep=NULL; + if (psimage==NULL) + page_flags |= PAGE_GAVE_WARN; + Message(BE_NONQUIET,">"); + } else { /* Don't draw */ + page_flags |= PAGE_TRUECOLOR; + } return; } - if (strncmp(buffer,"header=",7)==0 || buffer[0]=='!') { /* header, ignored */ - if ( page_imagep != NULL ) - Warning("at (%ld,%ld) ignored header \\special{%.*s}", - hh, vv, length,special); + + if (strncmp(special,"papersize=",10)==0) { /* papersize spec, ignored */ + return; + } + + if (special[0]=='!' || strncmp(special,"header=",7)==0) { /* PS header */ + newpsheader(special); return; } - if (strncmp(buffer,"src:",4)==0) { /* source special */ + + if (strncmp(special,"src:",4)==0) { /* source special */ if ( page_imagep != NULL ) - Message(BE_NONQUIET," at (%ld,%ld) source \\special{%.*s}", - hh, vv, length,special); + Message(BE_NONQUIET," at (%ld,%ld) source \\special{%s}", + hh, vv, special); return; } if ( page_imagep != NULL ) { - Warning("at (%ld,%ld) unimplemented \\special{%.*s}", - hh, vv, length,special); - flags |= PAGE_GAVE_WARN; + Warning("at (%ld,%ld) unimplemented \\special{%s}", + hh, vv, special); + page_flags |= PAGE_GAVE_WARN; } } + |