X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=pdf2swf%2FSWFOutputDev.cc;h=070e34aa9debef17a95bd2a4b5a48c25c4c3703f;hb=98224e6d436b226dc8445db494efa7e8c3635c34;hp=d5a9c99e09fe7cf32079492fc9dc6235df716ab1;hpb=866c8bb6feb71040e36a89c177cb1c024f3d9ba4;p=swftools.git diff --git a/pdf2swf/SWFOutputDev.cc b/pdf2swf/SWFOutputDev.cc index d5a9c99..070e34a 100644 --- a/pdf2swf/SWFOutputDev.cc +++ b/pdf2swf/SWFOutputDev.cc @@ -39,7 +39,10 @@ #include "OutputDev.h" #include "GfxState.h" #include "GfxFont.h" +#include "CharCodeToUnicode.h" +#include "NameToUnicodeTable.h" #include "FontFile.h" +#include "GlobalParams.h" //swftools header files #include "swfoutput.h" extern "C" { @@ -47,6 +50,10 @@ extern "C" { #include "ttf2pt1.h" } +#define logf logarithmf // logf is also used by ../lib/log.h +#include +#undef logf + static PDFDoc*doc = 0; static char* swffilename = 0; int numpages; @@ -131,10 +138,12 @@ public: // Does this device use drawChar() or drawString()? virtual GBool useDrawChar(); - virtual GBool interpretType3Chars() {return false;} + virtual GBool interpretType3Chars() {return gTrue;} //----- initialization and control + void startDoc(XRef *xref); + // Start a page. virtual void startPage(int pageNum, GfxState *state) ; @@ -173,9 +182,9 @@ public: virtual void beginString(GfxState *state, GString *s) ; virtual void endString(GfxState *state) ; virtual void drawChar(GfxState *state, double x, double y, - double dx, double dy, Guchar c) ; - virtual void drawChar16(GfxState *state, double x, double y, - double dx, double dy, int c) ; + double dx, double dy, + double originX, double originY, + CharCode code, Unicode *u, int uLen); //----- image drawing virtual void drawImageMask(GfxState *state, Object *ref, Stream *str, @@ -183,7 +192,11 @@ public: GBool inlineImg); virtual void drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, - GBool inlineImg); + int *maskColors, GBool inlineImg); + + virtual GBool beginType3Char(GfxState *state, + CharCode code, Unicode *u, int uLen); + virtual void endType3Char(GfxState *state); private: void drawGeneralImage(GfxState *state, Object *ref, Stream *str, @@ -192,15 +205,19 @@ public: int clipping[64]; int clippos; + XRef*xref; + int searchT1Font(char*name); char* substituteFont(GfxFont*gfxFont, char*oldname); - char* writeEmbeddedFontToFile(GfxFont*font); + char* writeEmbeddedFontToFile(XRef*ref, GfxFont*font); int t1id; int jpeginfo; // did we write "File contains jpegs" yet? int pbminfo; // did we write "File contains jpegs" yet? int linkinfo; // did we write "File contains links" yet? int ttfinfo; // did we write "File contains TrueType Fonts" yet? + int type3active; // are we between beginType3()/endType3()? + GfxState *laststate; }; @@ -334,7 +351,7 @@ void showFontError(GfxFont*font, int nr) else if(nr == 1) logf(" The following font caused problems (substituting):"); else if(nr == 2) - logf(" This document contains Type 3 Fonts: (some text may be incorrectly displayed)"); + logf(" The following Type 3 Font will be rendered as bitmap:"); dumpFontInfo("", font); } @@ -350,7 +367,7 @@ void dumpFontInfo(char*loglevel, GfxFont*font) if(gstr) logf("%sTag: %s\n", loglevel, FIXNULL(gstr->getCString())); - //if(font->is16Bit()) logf("%sis 16 bit\n", loglevel); //FIXME: not existing in xpdf 1.01 + if(font->isCIDFont()) logf("%sis CID font\n", loglevel); GfxFontType type=font->getType(); switch(type) { @@ -408,9 +425,11 @@ SWFOutputDev::SWFOutputDev() ttfinfo = 0; linkinfo = 0; pbminfo = 0; + type3active = 0; clippos = 0; clipping[clippos] = 0; outputstarted = 0; + xref = 0; // printf("SWFOutputDev::SWFOutputDev() \n"); }; @@ -561,38 +580,61 @@ void SWFOutputDev::beginString(GfxState *state, GString *s) } int charcounter = 0; -void SWFOutputDev::drawChar(GfxState *state, double x, double y, double dx, double dy, Guchar c) +void SWFOutputDev::drawChar(GfxState *state, double x, double y, + double dx, double dy, + double originX, double originY, + CharCode c, Unicode *_u, int uLen) { logf(" 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) - { - GfxFont*font = state->getFont(); - Gfx8BitFont*font8; - if(font->isCIDFont()) { - logf(" CID Font\n"); - return; - } - font8 = (Gfx8BitFont*)font; - - char**enc=font8->getEncoding(); - - double x1,y1; - x1 = x; - y1 = y; - state->transform(x, y, &x1, &y1); - - if(enc[c]) - swfoutput_drawchar(&output, x1, y1, enc[c], c); - else - logf(" couldn't get name for character %02x from Encoding", c); + if ((state->getRender() & 3) == 3) + return; + + GfxFont*font = state->getFont(); + + if(font->getType() == fontType3) { + /* type 3 chars are passed primarily as graphics */ + return; } -} + double x1,y1; + x1 = x; + y1 = y; + state->transform(x, y, &x1, &y1); + + if(font->isCIDFont()) { + GfxCIDFont*cfont = (GfxCIDFont*)font; + Unicode u=0; + char*name=0; + if(_u) + u = *_u; + if(u) { + int t; + for(t=0;tgetName()->getCString(), + cfont->getType());*/ -void SWFOutputDev::drawChar16(GfxState *state, double x, double y, double dx, double dy, int c) -{ - printf(" drawChar16(%f,%f,%f,%f,%08x)\n",x,y,dx,dy,c); - exit(1); + if(name) + swfoutput_drawchar(&output, x1, y1, name, c); + else + logf(" couldn't get name for CID character %02x from Encoding", c); + } else { + Gfx8BitFont*font8; + font8 = (Gfx8BitFont*)font; + char**enc=font8->getEncoding(); + + if(enc && enc[c]) + swfoutput_drawchar(&output, x1, y1, enc[c], c); + else { + logf(" couldn't get name for character %02x from Encoding", c); + } + } } void SWFOutputDev::endString(GfxState *state) @@ -600,6 +642,23 @@ void SWFOutputDev::endString(GfxState *state) logf(" endstring\n"); } + +GBool SWFOutputDev::beginType3Char(GfxState *state, + CharCode code, Unicode *u, int uLen) +{ + logf(" beginType3Char %d, %08x, %d", code, *u, uLen); + type3active = 1; + /* the character itself is going to be passed using + drawImageMask() */ + return gFalse; /* gTrue= is_in_cache? */ +} + +void SWFOutputDev::endType3Char(GfxState *state) +{ + type3active = 0; + logf(" endType3Char"); +} + void SWFOutputDev::startPage(int pageNum, GfxState *state) { double x1,y1,x2,y2; @@ -684,24 +743,27 @@ void SWFOutputDev::drawLink(Link *link, Catalog *catalog) LinkNamed*l = (LinkNamed*)action; GString*name = l->getName(); if(name) { - s = name->lowerCase()->getCString(); - named = name->getCString(); - if(strstr(s, "next") || strstr(s, "forward")) - { - page = currentpage + 1; - } - else if(strstr(s, "prev") || strstr(s, "back")) - { - page = currentpage - 1; - } - else if(strstr(s, "last") || strstr(s, "end")) - { - page = pages[pagepos-1]; //:) - } - else if(strstr(s, "first") || strstr(s, "top")) - { - page = 1; - } + s = name->lowerCase()->getCString(); + named = name->getCString(); + if(!strchr(s,':')) + { + if(strstr(s, "next") || strstr(s, "forward")) + { + page = currentpage + 1; + } + else if(strstr(s, "prev") || strstr(s, "back")) + { + page = currentpage - 1; + } + else if(strstr(s, "last") || strstr(s, "end")) + { + page = pages[pagepos-1]; //:) + } + else if(strstr(s, "first") || strstr(s, "top")) + { + page = 1; + } + } } } break; @@ -787,6 +849,7 @@ int SWFOutputDev::searchT1Font(char*name) int i; int mapid=-1; char*filename=0; + for(i=0;i Loading extra font %s from %s\n", FIXNULL(fontname), FIXNULL(T1_GetFontFileName(i))); } + if(fontname && !strcmp(name, fontname)) { logf(" Extra font %s is being used.\n", fontname); return i; @@ -858,38 +922,46 @@ void SWFOutputDev::updateStrokeColor(GfxState *state) (char)(rgb.b*255), (char)(opaq*255)); } -char*SWFOutputDev::writeEmbeddedFontToFile(GfxFont*font) +char*SWFOutputDev::writeEmbeddedFontToFile(XRef*ref, GfxFont*font) { -/* char*tmpFileName = NULL; + char*tmpFileName = NULL; FILE *f; int c; char *fontBuf; int fontLen; -// Type1CFontConverter *cvt; + Type1CFontFile *cvt; Ref embRef; Object refObj, strObj; tmpFileName = "/tmp/tmpfont"; - font->getEmbeddedFontID(&embRef); + int ret; + + ret = font->getEmbeddedFontID(&embRef); + if(!ret) { + logf(" Didn't get embedded font id"); + /* not embedded- the caller should now search the font + directories for this font */ + return 0; + } f = fopen(tmpFileName, "wb"); if (!f) { logf(" Couldn't create temporary Type 1 font file"); - return 0; + return 0; } if (font->getType() == fontType1C) { - if (!(fontBuf = font->readEmbFontFile(&fontLen))) { + if (!(fontBuf = font->readEmbFontFile(xref, &fontLen))) { fclose(f); logf(" Couldn't read embedded font file"); return 0; } - cvt = new Type1CFontConverter(fontBuf, fontLen, f); - cvt->convert(); + cvt = new Type1CFontFile(fontBuf, fontLen); + cvt->convertToType1(f); delete cvt; gfree(fontBuf); } else { font->getEmbeddedFontID(&embRef); refObj.initRef(embRef.num, embRef.gen); - refObj.fetch(&strObj); + refObj.fetch(ref, &strObj); refObj.free(); strObj.streamReset(); while ((c = strObj.streamGetChar()) != EOF) { @@ -900,7 +972,8 @@ char*SWFOutputDev::writeEmbeddedFontToFile(GfxFont*font) } fclose(f); - if(font->getType() == fontTrueType) + if(font->getType() == fontTrueType || + font->getType() == fontCIDType2) { if(!ttfinfo) { logf(" File contains TrueType fonts"); @@ -918,9 +991,7 @@ char*SWFOutputDev::writeEmbeddedFontToFile(GfxFont*font) tmpFileName = strdup(name2); } - return tmpFileName;*/ - - return 0; + return tmpFileName; } char* gfxFontName(GfxFont* gfxFont) @@ -944,7 +1015,24 @@ int substitutepos = 0; char* SWFOutputDev::substituteFont(GfxFont*gfxFont, char* oldname) { - return "Times-Roman"; +/* ------------------------------ V1 */ + + char*fontname = "Times-Roman"; + this->t1id = searchT1Font(fontname); + if(substitutepos>=sizeof(substitutesource)/sizeof(char*)) { + logf(" Too many fonts in file."); + exit(1); + } + if(oldname) { + substitutesource[substitutepos] = oldname; + substitutetarget[substitutepos] = fontname; + logf(" substituting %s -> %s", FIXNULL(oldname), FIXNULL(fontname)); + substitutepos ++; + } + return fontname; + +/* ------------------------------ V2 */ + /* //substitute font char* fontname = 0; double m11, m12, m21, m22; @@ -959,7 +1047,7 @@ char* SWFOutputDev::substituteFont(GfxFont*gfxFont, char* oldname) // printf("%d %s\n", t, gfxFont->getCharName(t)); showFontError(gfxFont, 1); - if(1) { //if (!gfxFont->is16Bit()) { FIXME: xpdf 1.01 does not have is16Bit() + if(1) { //if (!gfxFont->isCIDFont()) { FIXME: xpdf 1.01 does not have is16Bit() if(gfxFont->isSymbolic()) { if(fontname && (strstr(fontname,"ing"))) //Dingbats, Wingdings etc. index = 16; @@ -1061,6 +1149,12 @@ void unlinkfont(char* filename) } } +void SWFOutputDev::startDoc(XRef *xref) +{ + this->xref = xref; +} + + void SWFOutputDev::updateFont(GfxState *state) { GfxFont*gfxFont = state->getFont(); @@ -1072,6 +1166,9 @@ void SWFOutputDev::updateFont(GfxState *state) char * fontname = gfxFontName(gfxFont); int t; + /* first, look if we substituted this font before- + this way, we don't initialize the T1 Fonts + too often */ for(t=0;t", gfxFont); + + /* now either load the font, or find a substitution */ Ref embRef; GBool embedded = gfxFont->getEmbeddedFontID(&embRef); if(embedded) { - if (//!gfxFont->is16Bit() && FIXME: not in xpdf 1.01 - (gfxFont->getType() == fontType1 || - gfxFont->getType() == fontType1C || - gfxFont->getType() == fontTrueType)) { - - fileName = writeEmbeddedFontToFile(gfxFont); + if (gfxFont->getType() == fontType1 || + gfxFont->getType() == fontType1C || + gfxFont->getType() == fontTrueType || + gfxFont->getType() == fontCIDType2) + { + fileName = writeEmbeddedFontToFile(xref, gfxFont); if(!fileName) { logf(" Couldn't write font to file"); showFontError(gfxFont,0); @@ -1115,8 +1216,15 @@ void SWFOutputDev::updateFont(GfxState *state) } } else { - showFontError(gfxFont,0); - fontname = substituteFont(gfxFont, fontname); + /* in case the font is embedded, but has an + unsupported format, we just look through the + font directories */ + int newt1id = searchT1Font(fontname); + if(newt1id<0) { + showFontError(gfxFont,0); + fontname = substituteFont(gfxFont, fontname); + } else + this->t1id = newt1id; } } else { if(fontname) { @@ -1152,9 +1260,61 @@ void SWFOutputDev::updateFont(GfxState *state) int pic_xids[1024]; int pic_yids[1024]; int pic_ids[1024]; +int pic_width[1024]; +int pic_height[1024]; int picpos = 0; int pic_id = 0; +#define SQR(x) ((x)*(x)) + +unsigned char* antialize(unsigned char*data, int width, int height, int newwidth, int newheight, int palettesize) +{ + if((newwidth<2 || newheight<2) || + (width<=newwidth || height<=newheight)) + return 0; + unsigned char*newdata; + int x,y; + newdata= (unsigned char*)malloc(newwidth*newheight); + int t; + double fx = (double)(width)/newwidth; + double fy = (double)(height)/newheight; + double px = 0; + int blocksize = (int)(8192/(fx*fy)); + int r = 8192*256/palettesize; + for(x=0;xtransform(1, 1, &x4, &y4); if(!pbminfo && !(str->getKind()==strDCT)) { - logf(" file contains pbm pictures %s",mask?"(masked)":""); + if(!type3active) { + logf(" file contains pbm pictures %s",mask?"(masked)":""); + pbminfo = 1; + } if(mask) logf(" drawing %d by %d masked picture\n", width, height); - pbminfo = 1; } if(!jpeginfo && (str->getKind()==strDCT)) { logf(" file contains jpeg pictures"); @@ -1211,38 +1373,86 @@ void SWFOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str, int xid = 0; int yid = 0; int x,y; - int width2 = (width+3)&(~3); - unsigned char*pic = new unsigned char[width2*height]; + unsigned char*pic = new unsigned char[width*height]; RGBA pal[256]; GfxRGB rgb; state->getFillRGB(&rgb); + memset(pal,255,sizeof(pal)); pal[0].r = (int)(rgb.r*255); pal[0].g = (int)(rgb.g*255); pal[0].b = (int)(rgb.b*255); pal[0].a = 255; pal[1].r = 0; pal[1].g = 0; pal[1].b = 0; pal[1].a = 0; + int numpalette = 2; xid += pal[1].r*3 + pal[1].g*11 + pal[1].b*17; yid += pal[1].r*7 + pal[1].g*5 + pal[1].b*23; + int realwidth = (int)sqrt(SQR(x2-x3) + SQR(y2-y3)); + int realheight = (int)sqrt(SQR(x1-x2) + SQR(y1-y2)); for (y = 0; y < height; ++y) for (x = 0; x < width; ++x) { imgStr->getPixel(buf); - // if(invert) buf[0]=255-buf[0]? + if(invert) + buf[0]=1-buf[0]; pic[width*y+x] = buf[0]; xid+=x*buf[0]+1; - yid+=y*buf[0]+1; + yid+=y*buf[0]*3+1; + } + + /* the size of the drawn image is added to the identifier + as the same image may require different bitmaps if displayed + at different sizes (due to antialiasing): */ + if(type3active) { + xid += realwidth; + yid += realheight; } int t,found = -1; for(t=0;t drawImage %dx%d, %s, inline=%d", width, height, - colorMap?"colorMap":"no colorMap", inlineImg); + logf(" drawImage %dx%d, %s %s, inline=%d", width, height, + colorMap?"colorMap":"no colorMap", + maskColors?"maskColors":"no maskColors", + inlineImg); if(colorMap) logf(" colorMap pixcomps:%d bits:%d mode:%d\n", colorMap->getNumPixelComps(), colorMap->getBits(),colorMap->getColorSpace()->getMode()); @@ -1421,11 +1637,9 @@ void pdfswf_init(char*filename, char*userPassword) GString *fileName = new GString(filename); GString *userPW; Object info; - // init error file - //errorInit(); FIXME xpdf 1.01 // read config file - //initParams(xpdfConfigFile); FIXME xpdf 1.01 + globalParams = new GlobalParams(""); // open PDF file if (userPassword && userPassword[0]) { @@ -1443,7 +1657,8 @@ void pdfswf_init(char*filename, char*userPassword) // print doc info doc->getDocInfo(&info); - if (info.isDict()) { + if (info.isDict() && + (screenloglevel>=LOGLEVEL_NOTICE)) { printInfoString(info.getDict(), "Title", "Title: %s\n"); printInfoString(info.getDict(), "Subject", "Subject: %s\n"); printInfoString(info.getDict(), "Keywords", "Keywords: %s\n"); @@ -1452,24 +1667,23 @@ void pdfswf_init(char*filename, char*userPassword) printInfoString(info.getDict(), "Producer", "Producer: %s\n"); printInfoDate(info.getDict(), "CreationDate", "CreationDate: %s\n"); printInfoDate(info.getDict(), "ModDate", "ModDate: %s\n"); + printf("Pages: %d\n", doc->getNumPages()); + printf("Linearized: %s\n", doc->isLinearized() ? "yes" : "no"); + printf("Encrypted: "); + if (doc->isEncrypted()) { + printf("yes (print:%s copy:%s change:%s addNotes:%s)\n", + doc->okToPrint() ? "yes" : "no", + doc->okToCopy() ? "yes" : "no", + doc->okToChange() ? "yes" : "no", + doc->okToAddNotes() ? "yes" : "no"); + } else { + printf("no\n"); + } } info.free(); - // print page count - printf("Pages: %d\n", doc->getNumPages()); numpages = doc->getNumPages(); - - // print linearization info - printf("Linearized: %s\n", doc->isLinearized() ? "yes" : "no"); - - // print encryption info - printf("Encrypted: "); if (doc->isEncrypted()) { - printf("yes (print:%s copy:%s change:%s addNotes:%s)\n", - doc->okToPrint() ? "yes" : "no", - doc->okToCopy() ? "yes" : "no", - doc->okToChange() ? "yes" : "no", - doc->okToAddNotes() ? "yes" : "no"); /*ERROR: This pdf is encrypted, and disallows copying. Due to the DMCA, paragraph 1201, (2) A-C, circumventing a technological measure that efficively controls access to @@ -1482,13 +1696,10 @@ void pdfswf_init(char*filename, char*userPassword) } if(!doc->okToChange() || !doc->okToAddNotes()) swfoutput_setprotected(); - } - else { - printf("no\n"); } - output = new SWFOutputDev(); + output->startDoc(doc->getXRef()); } void pdfswf_drawonlyshapes() @@ -1560,6 +1771,16 @@ int pdfswf_numpages() return doc->getNumPages(); } +void pdfswf_insertstop() +{ + insertstoptag = 1; +} + +void pdfswf_setversion(int n) +{ + flashversion = n; +} + int closed=0; void pdfswf_close() { @@ -1572,3 +1793,4 @@ void pdfswf_close() gMemReport(stderr); } +