#include <stdlib.h>
#include <stddef.h>
#include <string.h>
+#include <unistd.h>
//xpdf header files
#include "GString.h"
#include "gmem.h"
#include "../lib/log.h"
}
-static char* filename = 0;
+static char* swffilename = 0;
static void printInfoString(Dict *infoDict, char *key, char *fmt);
static void printInfoDate(Dict *infoDict, char *key, char *fmt);
GBool inlineImg);
private:
+ void drawGeneralImage(GfxState *state, Object *ref, Stream *str,
+ int width, int height, GfxImageColorMap*colorMap, GBool invert,
+ GBool inlineImg, int mask);
int clipping[32];
int clippos;
int setT1Font(char*name,FontEncoding*enc);
- int initT1Font(int id, FontEncoding*encoding);
int t1id;
+ int jpeginfo; // did we write "Page contains jpegs" yet?
+ int pbminfo; // did we write "Page contains jpegs" yet?
};
char mybuf[1024];
if(lastdumppos<sizeof(lastdumps)/sizeof(int))
lastdumps[lastdumppos++] = r.num;
if(nr == 0)
- logf("<error> The following font caused problems:");
+ logf("<warning> The following font caused problems:");
else if(nr == 1)
- logf("<error> The following font caused problems (substituting):");
+ logf("<warning> The following font caused problems (substituting):");
else if(nr == 2)
- logf("<error> This document contains Type 3 Fonts: (some text may be incorrectly displayed)");
+ logf("<warning> This document contains Type 3 Fonts: (some text may be incorrectly displayed)");
- dumpFontInfo("<error>", font);
+ dumpFontInfo("<warning>", font);
}
void dumpFontInfo(char*loglevel, GfxFont*font)
char*name;
gstr = font->getName();
Ref r=font->getID();
- logf("%s=========== %s (ID:%d) ==========\n", loglevel, gstr?gstr->getCString():"(unknown font)", r.num);
+ logf("%s=========== %s (ID:%d,%d) ==========\n", loglevel, gstr?gstr->getCString():"(unknown font)", r.num,r.gen);
gstr = font->getTag();
if(gstr)
logf("%sType: TrueType\n",loglevel);
break;
}
+
+ Ref embRef;
+ GBool embedded = font->getEmbeddedFontID(&embRef);
name = font->getEmbeddedFontName();
- if(name)
- logf("%sEmbedded name: %s\n",loglevel, name);
+ if(embedded)
+ logf("%sEmbedded name: %s id: %d\n",loglevel, name, embRef.num);
gstr = font->getExtFontFile();
if(gstr)
SWFOutputDev::SWFOutputDev()
{
+ jpeginfo = 0;
+ pbminfo = 0;
clippos = 0;
clipping[clippos] = 0;
outputstarted = 0;
void SWFOutputDev::stroke(GfxState *state)
{
- logf("<debug> %s stroke\n",gfxstate2str(state));
+ logf("<debug> stroke\n");
GfxPath * path = state->getPath();
struct swfmatrix m;
m.m11 = 1; m.m21 = 0; m.m22 = 1;
- m.m21 = 0; m.m13 = 0; m.m23 = 0;
+ m.m12 = 0; m.m13 = 0; m.m23 = 0;
T1_OUTLINE*outline = gfxPath_to_T1_OUTLINE(state, path);
swfoutput_setdrawmode(&output, DRAWMODE_STROKE);
swfoutput_drawpath(&output, outline, &m);
}
void SWFOutputDev::fill(GfxState *state)
{
- logf("<debug> %s fill\n",gfxstate2str(state));
+ logf("<debug> fill\n");
GfxPath * path = state->getPath();
struct swfmatrix m;
m.m11 = 1; m.m21 = 0; m.m22 = 1;
- m.m21 = 0; m.m13 = 0; m.m23 = 0;
+ m.m12 = 0; m.m13 = 0; m.m23 = 0;
T1_OUTLINE*outline = gfxPath_to_T1_OUTLINE(state, path);
swfoutput_setdrawmode(&output, DRAWMODE_FILL);
swfoutput_drawpath(&output, outline, &m);
}
void SWFOutputDev::eoFill(GfxState *state)
{
- logf("<debug> %s eofill\n",gfxstate2str(state));
+ logf("<debug> eofill\n");
GfxPath * path = state->getPath();
struct swfmatrix m;
m.m11 = 1; m.m21 = 0; m.m22 = 1;
- m.m21 = 0; m.m13 = 0; m.m23 = 0;
+ m.m12 = 0; m.m13 = 0; m.m23 = 0;
T1_OUTLINE*outline = gfxPath_to_T1_OUTLINE(state, path);
swfoutput_setdrawmode(&output, DRAWMODE_EOFILL);
swfoutput_drawpath(&output, outline, &m);
}
void SWFOutputDev::clip(GfxState *state)
{
- logf("<debug> %s clip\n",gfxstate2str(state));
+ logf("<debug> clip\n");
GfxPath * path = state->getPath();
struct swfmatrix m;
- m.m11 = 1; m.m21 = 0; m.m22 = 1;
- m.m21 = 0; m.m13 = 0; m.m23 = 0;
+ m.m11 = 1; m.m22 = 1;
+ m.m12 = 0; m.m21 = 0;
+ m.m13 = 0; m.m23 = 0;
T1_OUTLINE*outline = gfxPath_to_T1_OUTLINE(state, path);
swfoutput_startclip(&output, outline, &m);
clipping[clippos] = 1;
}
void SWFOutputDev::eoClip(GfxState *state)
{
- logf("<debug> %s eoclip\n",gfxstate2str(state));
+ logf("<debug> eoclip\n");
GfxPath * path = state->getPath();
struct swfmatrix m;
m.m11 = 1; m.m21 = 0; m.m22 = 1;
- m.m21 = 0; m.m13 = 0; m.m23 = 0;
+ m.m12 = 0; m.m13 = 0; m.m23 = 0;
T1_OUTLINE*outline = gfxPath_to_T1_OUTLINE(state, path);
swfoutput_startclip(&output, outline, &m);
clipping[clippos] = 1;
void SWFOutputDev::beginString(GfxState *state, GString *s)
{
double m11,m21,m12,m22;
- logf("<debug> %s beginstring \"%s\"\n", gfxstate2str(state), s->getCString());
+ logf("<debug> beginstring \"%s\"\n", s->getCString());
state->getFontTransMat(&m11, &m12, &m21, &m22);
m11 *= state->getHorizScaling();
m21 *= state->getHorizScaling();
int charcounter = 0;
void SWFOutputDev::drawChar(GfxState *state, double x, double y, double dx, double dy, Guchar c)
{
- logf("<debug> %s drawChar(%f,%f,%f,%f,'%c')\n",gfxstate2str(state), x,y,dx,dy,c);
+ logf("<debug> drawChar(%f,%f,%f,%f,'%c')\n",x,y,dx,dy,c);
// check for invisible text -- this is used by Acrobat Capture
if ((state->getRender() & 3) != 3)
{
y1 = y;
state->transform(x, y, &x1, &y1);
- swfoutput_drawchar(&output, x1, y1, c);
+ if(enc->getCharName(c))
+ swfoutput_drawchar(&output, x1, y1, enc->getCharName(c));
+ else
+ logf("<warning> couldn't get name for character %02x from Encoding", c);
}
}
void SWFOutputDev::drawChar16(GfxState *state, double x, double y, double dx, double dy, int c)
{
- printf("<error> %s drawChar16(%f,%f,%f,%f,%08x)\n",gfxstate2str(state), x,y,dx,dy,c);
+ printf("<error> drawChar16(%f,%f,%f,%f,%08x)\n",x,y,dx,dy,c);
exit(1);
}
void SWFOutputDev::endString(GfxState *state)
{
- logf("<debug> %s endstring\n", gfxstate2str(state));
+ logf("<debug> endstring\n");
}
void SWFOutputDev::startPage(int pageNum, GfxState *state)
{
double x1,y1,x2,y2;
- logf("<debug> %s, startPage %d\n", gfxstate2str(state), pageNum);
+ logf("<debug> startPage %d\n", pageNum);
logf("<notice> processing page %d", pageNum);
state->transform(state->getX1(),state->getY1(),&x1,&y1);
state->transform(state->getX2(),state->getY2(),&x2,&y2);
if(!outputstarted) {
- swfoutput_init(&output, filename, abs((int)(x2-x1)),abs((int)(y2-y1)));
+ swfoutput_init(&output, swffilename, abs((int)(x2-x1)),abs((int)(y2-y1)));
outputstarted = 1;
}
else
}
void SWFOutputDev::saveState(GfxState *state) {
- logf("<debug> %s saveState\n", gfxstate2str(state));
+ logf("<debug> saveState\n");
updateAll(state);
clippos ++;
clipping[clippos] = 0;
};
void SWFOutputDev::restoreState(GfxState *state) {
- logf("<debug> %s restoreState\n", gfxstate2str(state));
+ logf("<debug> restoreState\n");
updateAll(state);
if(clipping[clippos])
swfoutput_endclip(&output);
if(id<0)
return 0;
- initT1Font(id, encoding);
-}
-
-int SWFOutputDev::initT1Font(int id, FontEncoding*encoding)
-{
- int encStrSize;
- char *encPtr;
- int i;
- T1_DeleteFont(id);
- T1_LoadFont(id);
- /* reencode the font:
- * This is the only way to get the unmapped characters
- * from t1lib
- */
- encStrSize = 0;
- for (i = 0; i < 256 && i < encoding->getSize(); ++i) {
- if (encoding->getCharName(i)) {
- encStrSize += strlen(encoding->getCharName(i)) + 1;
- }
- }
- char**enc = (char **)gmalloc(257 * sizeof(char *));
- char*encStr = (char *)gmalloc(encStrSize * sizeof(char));
- encPtr = encStr;
- for (i = 0; i < 256 && i < encoding->getSize(); ++i) {
- if (encoding->getCharName(i)) {
- strcpy(encPtr, encoding->getCharName(i));
- enc[i] = encPtr;
- encPtr += strlen(encPtr) + 1;
- } else {
- enc[i] = ".notdef";
- }
- }
- for (; i < 256; ++i) {
- enc[i] = ".notdef";
- }
- enc[256] = "custom";
- int ret=T1_ReencodeFont(id, enc);
- t1id = id;
- return 1;
+ this->t1id = id;
}
void SWFOutputDev::updateLineWidth(GfxState *state)
{
- double width = state->getLineWidth();
+ double width = state->getTransformedLineWidth();
swfoutput_setlinewidth(&output, width);
}
(char)(rgb.b*255), (char)(opaq*255));
}
-void SWFOutputDev::updateFont(GfxState *state)
+char*writeEmbeddedFontToFile(GfxFont*font)
{
- double m11, m12, m21, m22;
- char * fontname = 0;
- GfxFont*gfxFont = state->getFont();
- char * filename;
+ char*tmpFileName = NULL;
+ char*fileName = NULL;
+ FILE *f;
+ int c;
+ char *fontBuf;
+ int fontLen;
+ Type1CFontConverter *cvt;
+ Ref embRef;
+ Object refObj, strObj;
+ tmpFileName = "/tmp/tmpfont";
+ font->getEmbeddedFontID(&embRef);
- if (!gfxFont) {
- return;
- }
- // look for Type 3 font
- if (!type3Warning && gfxFont->getType() == fontType3) {
- type3Warning = gTrue;
- showFontError(gfxFont, 2);
- }
- //dumpFontInfo (gfxFont);
-
-
- Ref embRef;
- GBool embedded = gfxFont->getEmbeddedFontID(&embRef);
- if(embedded) {
- char*tmpFileName = NULL;
- char*fileName = NULL;
- FILE *f;
- char *fontBuf;
- int fontLen;
- Type1CFontConverter *cvt;
- Ref embRef;
- Object refObj, strObj;
- int c;
- if (!gfxFont->is16Bit() &&
- (gfxFont->getType() == fontType1 ||
- gfxFont->getType() == fontType1C) &&
- gfxFont->getEmbeddedFontID(&embRef)) {
- tmpFileName = "tmpfont";
f = fopen(tmpFileName, "wb");
if (!f) {
logf("<error> Couldn't create temporary Type 1 font file");
- return;
+ return 0;
}
- if (gfxFont->getType() == fontType1C) {
- if (!(fontBuf = gfxFont->readEmbFontFile(&fontLen))) {
+ if (font->getType() == fontType1C) {
+ if (!(fontBuf = font->readEmbFontFile(&fontLen))) {
fclose(f);
logf("<error> Couldn't read embedded font file");
- return ;
+ return 0;
}
cvt = new Type1CFontConverter(fontBuf, fontLen, f);
cvt->convert();
delete cvt;
gfree(fontBuf);
} else {
- gfxFont->getEmbeddedFontID(&embRef);
+ font->getEmbeddedFontID(&embRef);
refObj.initRef(embRef.num, embRef.gen);
refObj.fetch(&strObj);
refObj.free();
fileName = tmpFileName;
if(!fileName) {
logf("<error> Embedded font writer didn't create a file");
- return ;
+ return 0;
+ }
+ return fileName;
+}
+
+char* gfxFontName(GfxFont* gfxFont)
+{
+ GString *gstr;
+ gstr = gfxFont->getName();
+ if(gstr) {
+ return gstr->getCString();
+ }
+ else {
+ char buf[32];
+ Ref r=gfxFont->getID();
+ sprintf(buf, "UFONT%d", r.num);
+ return strdup(buf);
}
+}
+
+void SWFOutputDev::updateFont(GfxState *state)
+{
+ double m11, m12, m21, m22;
+ char * fontname = 0;
+ GfxFont*gfxFont = state->getFont();
+ char * fileName = 0;
+
+ if (!gfxFont) {
+ return;
+ }
+
+ if(swfoutput_queryfont(&output, gfxFontName(gfxFont)))
+ {
+ swfoutput_setfont(&output, gfxFontName(gfxFont), -1, 0);
+ return;
+ }
+
+ // look for Type 3 font
+ if (!type3Warning && gfxFont->getType() == fontType3) {
+ type3Warning = gTrue;
+ showFontError(gfxFont, 2);
+ }
+ //dumpFontInfo ("<notice>", gfxFont);
+
+ Ref embRef;
+ GBool embedded = gfxFont->getEmbeddedFontID(&embRef);
+ if(embedded) {
+ if (!gfxFont->is16Bit() &&
+ (gfxFont->getType() == fontType1 ||
+ gfxFont->getType() == fontType1C)) {
+
+ fileName = writeEmbeddedFontToFile(gfxFont);
+ if(!fileName)
+ return ;
}
else {
showFontError(gfxFont,0);
return ;
}
+
t1id = T1_AddFont(fileName);
- initT1Font(t1id, gfxFont->getEncoding());
} else {
fontname = NULL;
if(gfxFont->getName()) {
}
}
- swfoutput_setfont(&output,gfxFont->getID().num,t1id);
+ swfoutput_setfont(&output,gfxFontName(gfxFont),t1id, fileName);
+ if(fileName)
+ unlink(fileName);
}
-void SWFOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
- int width, int height, GBool invert,
- GBool inlineImg) {
+int pic_xids[1024];
+int pic_yids[1024];
+int pic_ids[1024];
+int picpos = 0;
+int pic_id = 0;
+
+void SWFOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str,
+ int width, int height, GfxImageColorMap*colorMap, GBool invert,
+ GBool inlineImg, int mask)
+{
FILE *fi;
int c;
char fileName[128];
double x1,y1,x2,y2,x3,y3,x4,y4;
+ ImageStream *imgStr;
+ Guchar pixBuf[4];
+ GfxRGB rgb;
+ if(!width || !height)
+ return;
+
state->transform(0, 1, &x1, &y1);
state->transform(0, 0, &x2, &y2);
state->transform(1, 0, &x3, &y3);
state->transform(1, 1, &x4, &y4);
- if (str->getKind() == strDCT) {
+ if (str->getKind() == strDCT &&
+ (colorMap->getNumPixelComps() == 3 || !mask) )
+ {
sprintf(fileName, "/tmp/tmp%08x.jpg",lrand48());
- logf("<notice> Found picture. Temporary storage is %s", fileName);
+ logf("<verbose> Found jpeg. Temporary storage is %s", fileName);
+ if(!jpeginfo)
+ {
+ logf("<notice> file contains jpeg pictures");
+ jpeginfo = 1;
+ }
if (!(fi = fopen(fileName, "wb"))) {
logf("<error> Couldn't open temporary image file '%s'", fileName);
return;
}
str = ((DCTStream *)str)->getRawStream();
str->reset();
+ int xid = 0;
+ int yid = 0;
+ int count = 0;
while ((c = str->getChar()) != EOF)
+ {
fputc(c, fi);
+ xid += count*c;
+ yid += (~count)*c;
+ count++;
+ }
fclose(fi);
- swfoutput_drawimagefile(&output, fileName, width, height, x1,y1,x2,y2,x3,y3,x4,y4);
+
+ int t,found = -1;
+ for(t=0;t<picpos;t++)
+ {
+ if(pic_xids[t] == xid &&
+ pic_yids[t] == yid) {
+ found = t;break;
+ }
+ }
+ if(found<0) {
+ pic_ids[picpos] = swfoutput_drawimagejpeg(&output, fileName, width, height,
+ x1,y1,x2,y2,x3,y3,x4,y4);
+ pic_xids[picpos] = xid;
+ pic_yids[picpos] = yid;
+ if(picpos<1024)
+ picpos++;
+ } else {
+ swfoutput_drawimageagain(&output, pic_ids[found], width, height,
+ x1,y1,x2,y2,x3,y3,x4,y4);
+ }
+ unlink(fileName);
} else {
- logf("<notice> File contains pbm pictures.");
+
+ if(!pbminfo) {
+ logf("<notice> file contains pbm pictures %s",mask?"(masked)":"");
+ if(mask)
+ logf("<verbose> ignoring %d by %d masked picture\n", width, height);
+ pbminfo = 1;
+ }
+
+ if(mask) {
+ str->reset();
+ int yes=0;
+ while ((c = str->getChar()) != EOF)
+ {
+ if((c<32 || c>'z') && yes && (c!=13) && (c!=10)) {
+ printf("no ascii: %02x\n", c);
+ yes = 1;
+ }
+ }
+ } else {
+ int x,y;
+ int width2 = (width+3)&(~3);
+ imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(),
+ colorMap->getBits());
+ imgStr->reset();
+
+ if(colorMap->getNumPixelComps()!=1)
+ {
+ RGBA*pic=new RGBA[width*height];
+ int xid = 0;
+ int yid = 0;
+ for (y = 0; y < height; ++y) {
+ for (x = 0; x < width; ++x) {
+ int r,g,b,a;
+ imgStr->getPixel(pixBuf);
+ colorMap->getRGB(pixBuf, &rgb);
+ pic[width*y+x].r = r = (U8)(rgb.r * 255 + 0.5);
+ pic[width*y+x].g = g = (U8)(rgb.g * 255 + 0.5);
+ pic[width*y+x].b = b = (U8)(rgb.b * 255 + 0.5);
+ pic[width*y+x].a = a = 255;//(U8)(rgb.a * 255 + 0.5);
+ xid += x*r+x*b*3+x*g*7+x*a*11;
+ yid += y*r*3+y*b*17+y*g*19+y*a*11;
+ }
+ }
+ int t,found = -1;
+ for(t=0;t<picpos;t++)
+ {
+ if(pic_xids[t] == xid &&
+ pic_yids[t] == yid) {
+ found = t;break;
+ }
+ }
+ if(found<0) {
+ pic_ids[picpos] = swfoutput_drawimagelossless(&output, pic, width, height,
+ x1,y1,x2,y2,x3,y3,x4,y4);
+ pic_xids[picpos] = xid;
+ pic_yids[picpos] = yid;
+ if(picpos<1024)
+ picpos++;
+ } else {
+ swfoutput_drawimageagain(&output, pic_ids[found], width, height,
+ x1,y1,x2,y2,x3,y3,x4,y4);
+ }
+ delete pic;
+ }
+ else
+ {
+ U8*pic = new U8[width2*height];
+ RGBA pal[256];
+ int t;
+ int xid=0,yid=0;
+ for(t=0;t<256;t++)
+ {
+ int r,g,b,a;
+ pixBuf[0] = t;
+ colorMap->getRGB(pixBuf, &rgb);
+ pal[t].r = r = (U8)(rgb.r * 255 + 0.5);
+ pal[t].g = g = (U8)(rgb.g * 255 + 0.5);
+ pal[t].b = b = (U8)(rgb.b * 255 + 0.5);
+ pal[t].a = a = 255;//(U8)(rgb.b * 255 + 0.5);
+ xid += t*r+t*b*3+t*g*7+t*a*11;
+ xid += (~t)*r+t*b*3+t*g*7+t*a*11;
+ }
+ for (y = 0; y < height; ++y) {
+ for (x = 0; x < width; ++x) {
+ imgStr->getPixel(pixBuf);
+ pic[width2*y+x] = pixBuf[0];
+ xid += x*pixBuf[0]*7;
+ yid += y*pixBuf[0]*3;
+ }
+ }
+ int found = -1;
+ for(t=0;t<picpos;t++)
+ {
+ if(pic_xids[t] == xid &&
+ pic_yids[t] == yid) {
+ found = t;break;
+ }
+ }
+ if(found<0) {
+ pic_ids[picpos] = swfoutput_drawimagelossless256(&output, pic, pal, width, height,
+ x1,y1,x2,y2,x3,y3,x4,y4);
+ pic_xids[picpos] = xid;
+ pic_yids[picpos] = yid;
+ if(picpos<1024)
+ picpos++;
+ } else {
+ swfoutput_drawimageagain(&output, pic_ids[found], width, height,
+ x1,y1,x2,y2,x3,y3,x4,y4);
+ }
+ delete pic;
+ }
+ delete imgStr;
+ }
+
}
}
+void SWFOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
+ int width, int height, GBool invert,
+ GBool inlineImg)
+{
+ drawGeneralImage(state,ref,str,width,height,0,invert,inlineImg,1);
+}
+
void SWFOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
int width, int height,
- GfxImageColorMap *colorMap, GBool inlineImg) {
- FILE *fi;
- int c;
- char fileName[128];
- double x1,y1,x2,y2,x3,y3,x4,y4;
- state->transform(0, 1, &x1, &y1);
- state->transform(0, 0, &x2, &y2);
- state->transform(1, 0, &x3, &y3);
- state->transform(1, 1, &x4, &y4);
-
- if (str->getKind() == strDCT &&
- colorMap->getNumPixelComps() == 3) {
- sprintf(fileName, "/tmp/tmp%08x.jpg", lrand48());
- logf("<notice> Found picture. Temporary storage is %s", fileName);
- if (!(fi = fopen(fileName, "wb"))) {
- error(-1, "Couldn't open temporary image file '%s'", fileName);
- return;
- }
- str = ((DCTStream *)str)->getRawStream();
- str->reset();
- while ((c = str->getChar()) != EOF)
- fputc(c, fi);
- fclose(fi);
- swfoutput_drawimagefile(&output, fileName, width, height, x1,y1,x2,y2,x3,y3,x4,y4);
- } else {
- logf("<notice> File contains pbm pictures.");
- }
+ GfxImageColorMap *colorMap, GBool inlineImg)
+{
+ drawGeneralImage(state,ref,str,width,height,colorMap,0,inlineImg,0);
}
PDFDoc*doc = 0;
output = new SWFOutputDev();
}
+void pdfswf_drawonlyshapes()
+{
+ drawonlyshapes = 1;
+}
+
+void pdfswf_ignoredraworder()
+{
+ ignoredraworder = 1;
+}
+
+void pdfswf_jpegquality(int val)
+{
+ if(val<0) val=0;
+ if(val>100) val=100;
+ jpegquality = val;
+}
+
void pdfswf_setoutputfilename(char*_filename)
{
- filename = _filename;
+ swffilename = _filename;
}
void pdfswf_convertpage(int page)
return doc->getNumPages();
}
+int closed=0;
void pdfswf_close()
{
- delete doc;
+ logf("<debug> pdfswf.cc: pdfswf_close()");
delete output;
-
+ delete doc;
freeParams();
// check for memory leaks
Object::memCheck(stderr);