X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=pdf2swf%2FSWFOutputDev.cc;h=c6ad24ea344a4a60794929fb55dabbbeb7a2d4e5;hb=a05bfe04e9f497f3f7257e6e560ceb63a6910c55;hp=262550c538cf69b7ceef6a843e45fa9c6ad8068d;hpb=38bde89116e018468a3979c37664c13c2ccc81b0;p=swftools.git diff --git a/pdf2swf/SWFOutputDev.cc b/pdf2swf/SWFOutputDev.cc index 262550c..c6ad24e 100644 --- a/pdf2swf/SWFOutputDev.cc +++ b/pdf2swf/SWFOutputDev.cc @@ -46,15 +46,19 @@ extern "C" { #include "../lib/log.h" } +static PDFDoc*doc = 0; static char* swffilename = 0; +int numpages; +int currentpage; + +// swf <-> pdf pages +int*pages = 0; +int pagebuflen = 0; +int pagepos = 0; static void printInfoString(Dict *infoDict, char *key, char *fmt); static void printInfoDate(Dict *infoDict, char *key, char *fmt); -static char userPassword[33] = ""; -static GBool printVersion = gFalse; -static GBool printHelp = gFalse; - double fontsizes[] = { 0.833,0.833,0.889,0.889,0.788,0.722,0.833,0.778,0.600,0.600,0.600,0.600,0.576,0.576,0.576,0.576 @@ -217,11 +221,18 @@ public: 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 t1id; + int jpeginfo; // did we write "Page contains jpegs" yet? + int pbminfo; // did we write "Page contains jpegs" yet? + + GfxState *laststate; }; char mybuf[1024]; @@ -350,13 +361,13 @@ void showFontError(GfxFont*font, int nr) if(lastdumppos The following font caused problems:"); + logf(" The following font caused problems:"); else if(nr == 1) - logf(" The following font caused problems (substituting):"); + 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(" This document contains Type 3 Fonts: (some text may be incorrectly displayed)"); - dumpFontInfo("", font); + dumpFontInfo("", font); } void dumpFontInfo(char*loglevel, GfxFont*font) @@ -417,6 +428,8 @@ void dumpFontInfo(char*loglevel, GfxFont*font) SWFOutputDev::SWFOutputDev() { + jpeginfo = 0; + pbminfo = 0; clippos = 0; clipping[clippos] = 0; outputstarted = 0; @@ -488,55 +501,56 @@ T1_OUTLINE* gfxPath_to_T1_OUTLINE(GfxState*state, GfxPath*path) void SWFOutputDev::stroke(GfxState *state) { - logf(" %s stroke\n",gfxstate2str(state)); + logf(" 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(" %s fill\n",gfxstate2str(state)); + logf(" 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(" %s eofill\n",gfxstate2str(state)); + logf(" 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(" %s clip\n",gfxstate2str(state)); + logf(" 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(" %s eoclip\n",gfxstate2str(state)); + logf(" 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; @@ -561,7 +575,7 @@ GBool SWFOutputDev::useDrawChar() void SWFOutputDev::beginString(GfxState *state, GString *s) { double m11,m21,m12,m22; - logf(" %s beginstring \"%s\"\n", gfxstate2str(state), s->getCString()); + logf(" beginstring \"%s\"\n", s->getCString()); state->getFontTransMat(&m11, &m12, &m21, &m22); m11 *= state->getHorizScaling(); m21 *= state->getHorizScaling(); @@ -571,7 +585,7 @@ 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) { - logf(" %s drawChar(%f,%f,%f,%f,'%c')\n",gfxstate2str(state), x,y,dx,dy,c); + 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) { @@ -582,25 +596,29 @@ void SWFOutputDev::drawChar(GfxState *state, double x, double y, double dx, doub y1 = y; state->transform(x, y, &x1, &y1); - swfoutput_drawchar(&output, x1, y1, enc->getCharName(c)); + if(enc->getCharName(c)) + swfoutput_drawchar(&output, x1, y1, enc->getCharName(c)); + else + logf(" 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(" %s drawChar16(%f,%f,%f,%f,%08x)\n",gfxstate2str(state), x,y,dx,dy,c); + printf(" drawChar16(%f,%f,%f,%f,%08x)\n",x,y,dx,dy,c); exit(1); } void SWFOutputDev::endString(GfxState *state) { - logf(" %s endstring\n", gfxstate2str(state)); + logf(" endstring\n"); } void SWFOutputDev::startPage(int pageNum, GfxState *state) { double x1,y1,x2,y2; - logf(" %s, startPage %d\n", gfxstate2str(state), pageNum); + laststate = state; + logf(" startPage %d\n", pageNum); logf(" processing page %d", pageNum); state->transform(state->getX1(),state->getY1(),&x1,&y1); @@ -615,45 +633,91 @@ void SWFOutputDev::startPage(int pageNum, GfxState *state) void SWFOutputDev::drawLink(Link *link, Catalog *catalog) { - logf(" drawlink\n"); double x1, y1, x2, y2, w; GfxRGB rgb; swfcoord points[5]; int x, y; link->getBorder(&x1, &y1, &x2, &y2, &w); - if (w > 0) { +// if (w > 0) + { rgb.r = 0; rgb.g = 0; rgb.b = 1; cvtUserToDev(x1, y1, &x, &y); - points[0].x = points[4].x = x; - points[0].y = points[4].y = y; + points[0].x = points[4].x = (int)x; + points[0].y = points[4].y = (int)y; cvtUserToDev(x2, y1, &x, &y); - points[1].x = x; - points[1].y = y; + points[1].x = (int)x; + points[1].y = (int)y; cvtUserToDev(x2, y2, &x, &y); - points[2].x = x; - points[2].y = y; + points[2].x = (int)x; + points[2].y = (int)y; cvtUserToDev(x1, y2, &x, &y); - points[3].x = x; - points[3].y = y; - //PDF: draw rect + points[3].x = (int)x; + points[3].y = (int)y; + LinkAction*action=link->getAction(); - char*s; + char buf[128]; + char*s = "-?-"; + char*type = "-?-"; + char*url = 0; + int page = -1; switch(action->getKind()) { case actionGoTo: { - LinkGoTo*l = (LinkGoTo*)action; - s = l->getNamedDest()->getCString(); + type = "GoTo"; + LinkGoTo *ha=(LinkGoTo *)link->getAction(); + LinkDest *dest=NULL; + if (ha->getDest()==NULL) + dest=catalog->findDest(ha->getNamedDest()); + else dest=ha->getDest(); + if (dest){ + if (dest->isPageRef()){ + Ref pageref=dest->getPageRef(); + page=catalog->findPage(pageref.num,pageref.gen); + } + else page=dest->getPageNum(); + sprintf(buf, "%d", page); + s = buf; + } } break; case actionGoToR: { + type = "GoToR"; LinkGoToR*l = (LinkGoToR*)action; - s = l->getNamedDest()->getCString(); + GString*g = l->getNamedDest(); + if(g) + s = g->getCString(); + } + break; + case actionNamed: { + type = "Named"; + LinkNamed*l = (LinkNamed*)action; + GString*name = l->getName(); + if(name) { + s = name->lowerCase()->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; + } + } } break; case actionLaunch: { + type = "Launch"; LinkLaunch*l = (LinkLaunch*)action; GString * str = new GString(l->getFileName()); str->append(l->getParams()); @@ -661,34 +725,52 @@ void SWFOutputDev::drawLink(Link *link, Catalog *catalog) } break; case actionURI: { + type = "URI"; LinkURI*l = (LinkURI*)action; - s = l->getURI()->getCString(); - } - break; - case actionNamed: { - LinkNamed*l = (LinkNamed*)action; - s = l->getName()->getCString(); + GString*g = l->getURI(); + if(g) { + url = g->getCString(); + s = url; + } } break; case actionUnknown: { + type = "Unknown"; LinkUnknown*l = (LinkUnknown*)action; s = ""; } break; + default: { + logf(" Unknown link type!\n"); + break; + } + } + if(page>0) + { + int t; + for(t=0;t link to \"%s\"\n", s); + logf(" \"%s\" link to \"%s\" (%d)\n", type, s, page); } } void SWFOutputDev::saveState(GfxState *state) { - logf(" %s saveState\n", gfxstate2str(state)); + logf(" saveState\n"); updateAll(state); clippos ++; clipping[clippos] = 0; }; void SWFOutputDev::restoreState(GfxState *state) { - logf(" %s restoreState\n", gfxstate2str(state)); + logf(" restoreState\n"); updateAll(state); if(clipping[clippos]) swfoutput_endclip(&output); @@ -726,11 +808,12 @@ int SWFOutputDev::setT1Font(char*name, FontEncoding*encoding) return 0; this->t1id = id; + return 1; } void SWFOutputDev::updateLineWidth(GfxState *state) { - double width = state->getLineWidth(); + double width = state->getTransformedLineWidth(); swfoutput_setlinewidth(&output, width); } @@ -936,70 +1019,211 @@ void SWFOutputDev::updateFont(GfxState *state) 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(" Found picture. Temporary storage is %s", fileName); + logf(" Found jpeg. Temporary storage is %s", fileName); + if(!jpeginfo) + { + logf(" file contains jpeg pictures"); + jpeginfo = 1; + } if (!(fi = fopen(fileName, "wb"))) { logf(" 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 File contains pbm pictures."); + + if(!pbminfo) { + logf(" file contains pbm pictures %s",mask?"(masked)":""); + if(mask) + logf(" 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;tgetRGB(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;ttransform(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(" 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); - unlink(fileName); - } else { - logf(" File contains pbm pictures."); - } + GfxImageColorMap *colorMap, GBool inlineImg) +{ + drawGeneralImage(state,ref,str,width,height,colorMap,0,inlineImg,0); } -PDFDoc*doc = 0; SWFOutputDev*output = 0; void pdfswf_init(char*filename, char*userPassword) @@ -1044,6 +1268,7 @@ void pdfswf_init(char*filename, char*userPassword) // print page count printf("Pages: %d\n", doc->getNumPages()); + numpages = doc->getNumPages(); // print linearization info printf("Linearized: %s\n", doc->isLinearized() ? "yes" : "no"); @@ -1077,14 +1302,63 @@ void pdfswf_init(char*filename, char*userPassword) output = new SWFOutputDev(); } +void pdfswf_drawonlyshapes() +{ + drawonlyshapes = 1; +} + +void pdfswf_ignoredraworder() +{ + ignoredraworder = 1; +} + +void pdfswf_linksopennewwindow() +{ + opennewwindow = 1; +} + +void pdfswf_storeallcharacters() +{ + storeallcharacters = 1; +} + +void pdfswf_jpegquality(int val) +{ + if(val<0) val=0; + if(val>100) val=100; + jpegquality = val; +} + void pdfswf_setoutputfilename(char*_filename) { swffilename = _filename; } + void pdfswf_convertpage(int page) { - doc->displayPage((OutputDev*)output, page, /*zoom*/100, /*rotate*/0, /*doLinks*/(int)1); + if(!pages) + { + pages = (int*)malloc(1024*sizeof(int)); + pagebuflen = 1024; + } else { + if(pagepos == pagebuflen) + { + pagebuflen+=1024; + pages = (int*)realloc(pages, pagebuflen); + } + } + pages[pagepos++] = page; +} + +void pdfswf_performconversion() +{ + int t; + for(t=0;tdisplayPage((OutputDev*)output, currentpage, /*zoom*/100, /*rotate*/0, /*doLinks*/(int)1); + } } int pdfswf_numpages() @@ -1092,11 +1366,12 @@ int pdfswf_numpages() return doc->getNumPages(); } +int closed=0; void pdfswf_close() { - delete doc; + logf(" pdfswf.cc: pdfswf_close()"); delete output; - + delete doc; freeParams(); // check for memory leaks Object::memCheck(stderr);