summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvipng/special.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/dvipng/special.c')
-rw-r--r--Build/source/texk/dvipng/special.c695
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;
}
}
+