X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=pdf2swf%2FSWFOutputDev.cc;h=2728dcb24d87889f252dc3e0a713b89bdbfbef2e;hb=3223ebf85298888a0bda5a489e78584baafa151f;hp=0992ed96c39bc379e125e17ad0b07a2e87a978ff;hpb=5fa2ba8aaca9efa62430b2866ddee66705f3349d;p=swftools.git diff --git a/pdf2swf/SWFOutputDev.cc b/pdf2swf/SWFOutputDev.cc index 0992ed9..2728dcb 100644 --- a/pdf2swf/SWFOutputDev.cc +++ b/pdf2swf/SWFOutputDev.cc @@ -23,6 +23,12 @@ #include #include #include "../config.h" +#ifdef HAVE_DIRENT_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif #ifdef HAVE_FONTCONFIG_H #include #endif @@ -61,27 +67,28 @@ #include -static PDFDoc*doc = 0; -static char* swffilename = 0; -static int numpages; -static int currentpage; - typedef struct _fontfile { char*filename; int used; } fontfile_t; +// for pdfswf_addfont static fontfile_t fonts[2048]; static int fontnum = 0; +static int config_use_fontconfig = 1; + // swf <-> pdf pages +// TODO: move into pdf_doc_t static int*pages = 0; static int pagebuflen = 0; static int pagepos = 0; +/* config */ static double caplinewidth = 3.0; static int zoom = 72; /* xpdf: 86 */ +static int forceType0Fonts = 0; static void printInfoString(Dict *infoDict, char *key, char *fmt); static void printInfoDate(Dict *infoDict, char *key, char *fmt); @@ -106,8 +113,8 @@ struct mapping { {"ZapfDingbats", "d050000l"}}; class SWFOutputDev: public OutputDev { - struct swfoutput output; int outputstarted; + struct swfoutput output; public: // Constructor. @@ -116,6 +123,15 @@ public: // Destructor. virtual ~SWFOutputDev() ; + void setMove(int x,int y); + void setClip(int x1,int y1,int x2,int y2); + + int save(char*filename); + void pagefeed(); + void* getSWF(); + + void getDimensions(int*x1,int*y1,int*x2,int*y2); + //----- get info about output device // Does this device use upside-down coordinates? @@ -132,7 +148,7 @@ public: //----- initialization and control - void startDoc(XRef *xref); + void setXRef(PDFDoc*doc, XRef *xref); // Start a page. virtual void startPage(int pageNum, GfxState *state, double x1, double y1, double x2, double y2) ; @@ -199,6 +215,9 @@ public: int clipping[64]; int clippos; + int currentpage; + + PDFDoc*doc; XRef*xref; char* searchFont(char*name); @@ -227,6 +246,71 @@ public: char* substitutetarget[256]; char* substitutesource[256]; int substitutepos; + + int user_movex,user_movey; + int user_clipx1,user_clipx2,user_clipy1,user_clipy2; +}; + +static char*getFontID(GfxFont*font); + +class InfoOutputDev: public OutputDev +{ + public: + int x1,y1,x2,y2; + int num_links; + int num_images; + int num_fonts; + + InfoOutputDev() + { + num_links = 0; + num_images = 0; + num_fonts = 0; + } + virtual ~InfoOutputDev() + { + } + virtual GBool upsideDown() {return gTrue;} + virtual GBool useDrawChar() {return gTrue;} + virtual GBool useGradients() {return gTrue;} + virtual GBool interpretType3Chars() {return gTrue;} + virtual void startPage(int pageNum, GfxState *state, double crop_x1, double crop_y1, double crop_x2, double crop_y2) + { + double x1,y1,x2,y2; + state->transform(crop_x1,crop_y1,&x1,&y1); + state->transform(crop_x2,crop_y2,&x2,&y2); + if(x2x1 = (int)x1; + this->y1 = (int)y1; + this->x2 = (int)x2; + this->y2 = (int)y2; + } + virtual void drawLink(Link *link, Catalog *catalog) + { + num_links++; + } + virtual void updateFont(GfxState *state) + { + GfxFont*font = state->getFont(); + if(!font) + return; + char*id = getFontID(font); + /* FIXME*/ + num_fonts++; + } + virtual void drawImageMask(GfxState *state, Object *ref, Stream *str, + int width, int height, GBool invert, + GBool inlineImg) + { + num_images++; + } + virtual void drawImage(GfxState *state, Object *ref, Stream *str, + int width, int height, GfxImageColorMap *colorMap, + int *maskColors, GBool inlineImg) + { + num_images++; + } }; SWFOutputDev::SWFOutputDev() @@ -244,8 +328,36 @@ SWFOutputDev::SWFOutputDev() pic_id = 0; substitutepos = 0; type3Warning = 0; + user_movex = 0; + user_movey = 0; + user_clipx1 = 0; + user_clipy1 = 0; + user_clipx2 = 0; + user_clipy2 = 0; + memset(&output, 0, sizeof(output)); // printf("SWFOutputDev::SWFOutputDev() \n"); }; + +void SWFOutputDev::setMove(int x,int y) +{ + this->user_movex = x; + this->user_movey = y; +} + +void SWFOutputDev::setClip(int x1,int y1,int x2,int y2) +{ + if(x2user_clipx1 = x1; + this->user_clipy1 = y1; + this->user_clipx2 = x2; + this->user_clipy2 = y2; +} +void SWFOutputDev::getDimensions(int*x1,int*y1,int*x2,int*y2) +{ + return swfoutput_getdimensions(&output, x1,y1,x2,y2); +} static char*getFontID(GfxFont*font) { @@ -257,15 +369,20 @@ static char*getFontID(GfxFont*font) sprintf(buf, "UFONT%d", r->num); return strdup(buf); } - return fontname; + return strdup(fontname); } static char*getFontName(GfxFont*font) { - char*fontname = getFontID(font); - char* plus = strchr(fontname, '+'); - if(plus && plus < &fontname[strlen(fontname)-1]) - fontname = plus+1; + char*fontid = getFontID(font); + char*fontname= 0; + char* plus = strchr(fontid, '+'); + if(plus && plus < &fontid[strlen(fontid)-1]) { + fontname = strdup(plus+1); + } else { + fontname = strdup(fontid); + } + free(fontid); return fontname; } @@ -474,12 +591,35 @@ static void free_outline(SWF_OUTLINE*outline) } } +static void dump_outline(SWF_OUTLINE*outline) +{ + double x=0,y=0; + while(outline) { + double lastx=x,lasty=y; + x += (outline->dest.x/(float)0xffff); + y += (outline->dest.y/(float)0xffff); + if(outline->type == SWF_PATHTYPE_MOVE) { + msg(" | moveto %f,%f", x,y); + } else if(outline->type == SWF_PATHTYPE_LINE) { + msg(" | lineto: %f,%f\n",x,y); + } else if(outline->type == SWF_PATHTYPE_BEZIER) { + SWF_BEZIERSEGMENT*o2 = (SWF_BEZIERSEGMENT*)outline; + float x1 = o2->C.x/(float)0xffff+lastx; + float y1 = o2->C.y/(float)0xffff+lasty; + float x2 = o2->B.x/(float)0xffff+lastx; + float y2 = o2->B.y/(float)0xffff+lasty; + msg(" | spline: %f,%f -> %f,%f -> %f,%f\n",x1,y1,x2,y2,x,y); + } + outline = outline->link; + } +} + SWF_OUTLINE* gfxPath_to_SWF_OUTLINE(GfxState*state, GfxPath*path) { int num = path->getNumSubpaths(); int s,t; bezierpathsegment*start,*last=0; - bezierpathsegment*outline = start = new bezierpathsegment(); + bezierpathsegment*outline = start = (bezierpathsegment*)malloc(sizeof(bezierpathsegment)); int cpos = 0; double lastx=0,lasty=0; if(!num) { @@ -505,7 +645,7 @@ SWF_OUTLINE* gfxPath_to_SWF_OUTLINE(GfxState*state, GfxPath*path) outline->type = SWF_PATHTYPE_MOVE; outline->dest.x = x; outline->dest.y = y; - outline->link = (SWF_OUTLINE*)new bezierpathsegment(); + outline->link = (SWF_OUTLINE*)malloc(sizeof(bezierpathsegment)); outline = (bezierpathsegment*)outline->link; cpos = 0; lastx = nx; @@ -529,8 +669,7 @@ SWF_OUTLINE* gfxPath_to_SWF_OUTLINE(GfxState*state, GfxPath*path) outline->dest.x = x; outline->dest.y = y; outline->type = cpos?SWF_PATHTYPE_BEZIER:SWF_PATHTYPE_LINE; - outline->link = 0; - outline->link = (SWF_OUTLINE*)new bezierpathsegment(); + outline->link = (SWF_OUTLINE*)malloc(sizeof(bezierpathsegment)); outline = (bezierpathsegment*)outline->link; cpos = 0; lastx = nx; @@ -538,7 +677,9 @@ SWF_OUTLINE* gfxPath_to_SWF_OUTLINE(GfxState*state, GfxPath*path) } } } + if(last->link) {free(last->link);} last->link = 0; + return (SWF_OUTLINE*)start; } /*---------------------------------------------------------------------------- @@ -547,7 +688,6 @@ SWF_OUTLINE* gfxPath_to_SWF_OUTLINE(GfxState*state, GfxPath*path) void SWFOutputDev::stroke(GfxState *state) { - msg(" stroke\n"); GfxPath * path = state->getPath(); int lineCap = state->getLineCap(); // 0=butt, 1=round 2=square int lineJoin = state->getLineJoin(); // 0=miter, 1=round 2=bevel @@ -561,6 +701,11 @@ void SWFOutputDev::stroke(GfxState *state) m.m11 = 1; m.m21 = 0; m.m22 = 1; m.m12 = 0; m.m13 = 0; m.m23 = 0; SWF_OUTLINE*outline = gfxPath_to_SWF_OUTLINE(state, path); + + if(getLogLevel() >= LOGLEVEL_TRACE) { + msg(" stroke\n"); + dump_outline(outline); + } lineJoin = 1; // other line joins are not yet supported by the swf encoder // TODO: support bevel joints @@ -587,53 +732,90 @@ void SWFOutputDev::stroke(GfxState *state) } void SWFOutputDev::fill(GfxState *state) { - msg(" fill\n"); GfxPath * path = state->getPath(); struct swfmatrix m; m.m11 = 1; m.m21 = 0; m.m22 = 1; m.m12 = 0; m.m13 = 0; m.m23 = 0; SWF_OUTLINE*outline = gfxPath_to_SWF_OUTLINE(state, path); + + if(getLogLevel() >= LOGLEVEL_TRACE) { + msg(" fill\n"); + dump_outline(outline); + } + swfoutput_setdrawmode(&output, DRAWMODE_FILL); swfoutput_drawpath(&output, outline, &m); + free_outline(outline); } void SWFOutputDev::eoFill(GfxState *state) { - msg(" eofill\n"); GfxPath * path = state->getPath(); struct swfmatrix m; m.m11 = 1; m.m21 = 0; m.m22 = 1; m.m12 = 0; m.m13 = 0; m.m23 = 0; SWF_OUTLINE*outline = gfxPath_to_SWF_OUTLINE(state, path); + + if(getLogLevel() >= LOGLEVEL_TRACE) { + msg(" eofill\n"); + dump_outline(outline); + } + swfoutput_setdrawmode(&output, DRAWMODE_EOFILL); swfoutput_drawpath(&output, outline, &m); + free_outline(outline); } void SWFOutputDev::clip(GfxState *state) { - msg(" clip\n"); GfxPath * path = state->getPath(); struct swfmatrix m; m.m11 = 1; m.m22 = 1; m.m12 = 0; m.m21 = 0; m.m13 = 0; m.m23 = 0; SWF_OUTLINE*outline = gfxPath_to_SWF_OUTLINE(state, path); + + if(getLogLevel() >= LOGLEVEL_TRACE) { + msg(" clip\n"); + dump_outline(outline); + } + swfoutput_startclip(&output, outline, &m); clipping[clippos] ++; + free_outline(outline); } void SWFOutputDev::eoClip(GfxState *state) { - msg(" eoclip\n"); GfxPath * path = state->getPath(); struct swfmatrix m; m.m11 = 1; m.m21 = 0; m.m22 = 1; m.m12 = 0; m.m13 = 0; m.m23 = 0; SWF_OUTLINE*outline = gfxPath_to_SWF_OUTLINE(state, path); + + if(getLogLevel() >= LOGLEVEL_TRACE) { + msg(" eoclip\n"); + dump_outline(outline); + } + swfoutput_startclip(&output, outline, &m); clipping[clippos] ++; + free_outline(outline); +} + +/* pass through functions for swf_output */ +int SWFOutputDev::save(char*filename) +{ + return swfoutput_save(&output, filename); +} +void SWFOutputDev::pagefeed() +{ + swfoutput_pagefeed(&output); +} +void* SWFOutputDev::getSWF() +{ + return (void*)swfoutput_get(&output); } SWFOutputDev::~SWFOutputDev() { - swfoutput_save(&output, swffilename); swfoutput_destroy(&output); outputstarted = 0; }; @@ -674,7 +856,7 @@ void SWFOutputDev::drawChar(GfxState *state, double x, double y, // check for invisible text -- this is used by Acrobat Capture if ((state->getRender() & 3) == 3) return; - + Gushort *CIDToGIDMap = 0; GfxFont*font = state->getFont(); if(font->getType() == fontType3) { @@ -687,20 +869,29 @@ void SWFOutputDev::drawChar(GfxState *state, double x, double y, state->transform(x, y, &x1, &y1); Unicode u=0; - if(_u && uLen) + char*name=0; + + if(_u && uLen) { u = *_u; + if (u) { + int t; + /* find out char name from unicode index + TODO: should be precomputed + */ + for(t=0;tisCIDFont() && u) { + if(font->isCIDFont()) { GfxCIDFont*cfont = (GfxCIDFont*)font; - int t; - for(t=0;tgetType() == fontCIDType2) { + CIDToGIDMap = cfont->getCIDToGID(); } } else { Gfx8BitFont*font8; @@ -709,13 +900,14 @@ void SWFOutputDev::drawChar(GfxState *state, double x, double y, if(enc && enc[c]) name = enc[c]; } - - msg(" drawChar(%f,%f,c='%c' (%d),u=%d <%d>) CID=%d name=\"%s\"\n",x,y,(c&127)>=32?c:'?',c,u, uLen, font->isCIDFont(), FIXNULL(name)); - - /*x1 = (int)(x1+0.5); - y1 = (int)(y1+0.5);*/ - - int ret = swfoutput_drawchar(&output, x1, y1, name, c, u); + + if (CIDToGIDMap) { + msg(" drawChar(%f, %f, c='%c' (%d), GID=%d, u=%d <%d>) CID=%d name=\"%s\"\n", x, y, (c&127)>=32?c:'?', c, CIDToGIDMap[c], u, uLen, font->isCIDFont(), FIXNULL(name)); + swfoutput_drawchar(&output, x1, y1, name, CIDToGIDMap[c], u); + } else { + msg(" drawChar(%f,%f,c='%c' (%d), u=%d <%d>) CID=%d name=\"%s\"\n",x,y,(c&127)>=32?c:'?',c,u, uLen, font->isCIDFont(), FIXNULL(name)); + swfoutput_drawchar(&output, x1, y1, name, c, u); + } } void SWFOutputDev::endString(GfxState *state) { @@ -740,35 +932,44 @@ void SWFOutputDev::endType3Char(GfxState *state) void SWFOutputDev::startPage(int pageNum, GfxState *state, double crop_x1, double crop_y1, double crop_x2, double crop_y2) { - double x1,y1,x2,y2; - int rot = doc->getPageRotate(1); - laststate = state; - msg(" startPage %d (%f,%f,%f,%f)\n", pageNum, crop_x1, crop_y1, crop_x2, crop_y2); - if(rot!=0) - msg(" page is rotated %d degrees\n", rot); - - /* state->transform(state->getX1(),state->getY1(),&x1,&y1); - state->transform(state->getX2(),state->getY2(),&x2,&y2); - Use CropBox, not MediaBox, as page size - */ - - /*x1 = crop_x1; - y1 = crop_y1; - x2 = crop_x2; - y2 = crop_y2;*/ - state->transform(crop_x1,crop_y1,&x1,&y1); - state->transform(crop_x2,crop_y2,&x2,&y2); - - if(x2 Bounding box is (%f,%f)-(%f,%f)", x1,y1,x2,y2); - swfoutput_init(&output); - outputstarted = 1; - } + this->currentpage = pageNum; + double x1,y1,x2,y2; + int rot = doc->getPageRotate(1); + laststate = state; + msg(" startPage %d (%f,%f,%f,%f)\n", pageNum, crop_x1, crop_y1, crop_x2, crop_y2); + if(rot!=0) + msg(" page is rotated %d degrees\n", rot); + + /* state->transform(state->getX1(),state->getY1(),&x1,&y1); + state->transform(state->getX2(),state->getY2(),&x2,&y2); + Use CropBox, not MediaBox, as page size + */ - swfoutput_newpage(&output, pageNum, (int)x1, (int)y1, (int)x2, (int)y2); + /*x1 = crop_x1; + y1 = crop_y1; + x2 = crop_x2; + y2 = crop_y2;*/ + state->transform(crop_x1,crop_y1,&x1,&y1); + state->transform(crop_x2,crop_y2,&x2,&y2); + + if(x2 x1)*/ x1 = user_clipx1; + /*if(user_clipx2 < x2)*/ x2 = user_clipx2; + /*if(user_clipy1 > y1)*/ y1 = user_clipy1; + /*if(user_clipy2 < y2)*/ y2 = user_clipy2; + } + + if(!outputstarted) { + msg(" Bounding box is (%f,%f)-(%f,%f)", x1,y1,x2,y2); + swfoutput_init(&output); + outputstarted = 1; + } + + swfoutput_newpage(&output, pageNum, user_movex, user_movey, (int)x1, (int)y1, (int)x2, (int)y2); } void SWFOutputDev::drawLink(Link *link, Catalog *catalog) @@ -854,7 +1055,7 @@ void SWFOutputDev::drawLink(Link *link, Catalog *catalog) } else if(strstr(s, "last") || strstr(s, "end")) { - page = pages[pagepos-1]; //:) + page = pagepos>0?pages[pagepos-1]:0; } else if(strstr(s, "first") || strstr(s, "top")) { @@ -908,7 +1109,7 @@ void SWFOutputDev::drawLink(Link *link, Catalog *catalog) if(pages[t]==page) break; if(t!=pagepos) - swfoutput_linktopage(&output, t, points); + swfoutput_linktopage(&output, t, points); } else if(url) { @@ -971,7 +1172,7 @@ char* SWFOutputDev::searchFont(char*name) if(!is_standard_font) msg(" Using %s for %s", fonts[i].filename, name); } - return fonts[i].filename; + return strdup(fonts[i].filename); } } return 0; @@ -1060,9 +1261,11 @@ char*SWFOutputDev::writeEmbeddedFontToFile(XRef*ref, GfxFont*font) } #ifdef XPDF_101 Type1CFontFile *cvt = new Type1CFontFile(fontBuf, fontLen); + if(!cvt) return 0; cvt->convertToType1(f); #else FoFiType1C *cvt = FoFiType1C::make(fontBuf, fontLen); + if(!cvt) return 0; cvt->convertToType1(NULL, gTrue, FoFiWrite, f); #endif //cvt->convertToCIDType0("test", f); @@ -1123,37 +1326,54 @@ char*SWFOutputDev::writeEmbeddedFontToFile(XRef*ref, GfxFont*font) return strdup(tmpFileName); } - + char* searchForSuitableFont(GfxFont*gfxFont) { char*name = getFontName(gfxFont); char*fontname = 0; char*filename = 0; + + if(!config_use_fontconfig) + return 0; #ifdef HAVE_FONTCONFIG FcPattern *pattern, *match; FcResult result; FcChar8 *v; - // call init ony once static int fcinitcalled = false; + + msg(" searchForSuitableFont(%s)", name); + + // call init ony once if (!fcinitcalled) { + msg(" Initializing FontConfig..."); fcinitcalled = true; - FcInit(); + if(FcInit()) { + msg(" FontConfig Initialization failed. Disabling."); + config_use_fontconfig = 0; + return 0; + } + msg(" ...initialized FontConfig"); } + msg(" FontConfig: Create \"%s\" Family Pattern", name); pattern = FcPatternBuild(NULL, FC_FAMILY, FcTypeString, name, NULL); if (gfxFont->isItalic()) // check for italic + msg(" FontConfig: Adding Italic Slant"); FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); if (gfxFont->isBold()) // check for bold + msg(" FontConfig: Adding Bold Weight"); FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); + msg(" FontConfig: Try to match..."); // configure and match using the original font name FcConfigSubstitute(0, pattern, FcMatchPattern); FcDefaultSubstitute(pattern); match = FcFontMatch(0, pattern, &result); if (FcPatternGetString(match, "family", 0, &v) == FcResultMatch) { + msg(" FontConfig: family=%s", (char*)v); // if we get an exact match if (strcmp((char *)v, name) == 0) { if (FcPatternGetString(match, "file", 0, &v) == FcResultMatch) { @@ -1162,6 +1382,7 @@ char* searchForSuitableFont(GfxFont*gfxFont) if(nfn) fontname = strdup(nfn+1); else fontname = filename; } + msg(" FontConfig: Returning \"%s\"", fontname); } else { // initialize patterns FcPatternDestroy(pattern); @@ -1169,22 +1390,28 @@ char* searchForSuitableFont(GfxFont*gfxFont) // now match against serif etc. if (gfxFont->isSerif()) { + msg(" FontConfig: Create Serif Family Pattern"); pattern = FcPatternBuild (NULL, FC_FAMILY, FcTypeString, "serif", NULL); } else if (gfxFont->isFixedWidth()) { + msg(" FontConfig: Create Monospace Family Pattern"); pattern = FcPatternBuild (NULL, FC_FAMILY, FcTypeString, "monospace", NULL); } else { + msg(" FontConfig: Create Sans Family Pattern"); pattern = FcPatternBuild (NULL, FC_FAMILY, FcTypeString, "sans", NULL); } // check for italic if (gfxFont->isItalic()) { + msg(" FontConfig: Adding Italic Slant"); int bb = FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); } // check for bold if (gfxFont->isBold()) { + msg(" FontConfig: Adding Bold Weight"); int bb = FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); } + msg(" FontConfig: Try to match... (2)"); // configure and match using serif etc FcConfigSubstitute (0, pattern, FcMatchPattern); FcDefaultSubstitute (pattern); @@ -1196,6 +1423,7 @@ char* searchForSuitableFont(GfxFont*gfxFont) if(nfn) fontname = strdup(nfn+1); else fontname = filename; } + msg(" FontConfig: Returning \"%s\"", fontname); } } @@ -1223,6 +1451,10 @@ char* SWFOutputDev::substituteFont(GfxFont*gfxFont, char* oldname) fontname = "Times-Roman"; } filename = searchFont(fontname); + if(!filename) { + msg(" Couldn't find font %s- did you install the default fonts?"); + return 0; + } if(substitutepos>=sizeof(substitutesource)/sizeof(char*)) { msg(" Too many fonts in file."); @@ -1234,7 +1466,7 @@ char* SWFOutputDev::substituteFont(GfxFont*gfxFont, char* oldname) msg(" substituting %s -> %s", FIXNULL(oldname), FIXNULL(fontname)); substitutepos ++; } - return filename; + return strdup(filename); } void unlinkfont(char* filename) @@ -1266,8 +1498,9 @@ void unlinkfont(char* filename) } } -void SWFOutputDev::startDoc(XRef *xref) +void SWFOutputDev::setXRef(PDFDoc*doc, XRef *xref) { + this->doc = doc; this->xref = xref; } @@ -1321,7 +1554,7 @@ void SWFOutputDev::updateFont(GfxState *state) if(embedded && (gfxFont->getType() == fontType1 || gfxFont->getType() == fontType1C || - //gfxFont->getType() == fontCIDType0C || + (gfxFont->getType() == fontCIDType0C && forceType0Fonts) || gfxFont->getType() == fontTrueType || gfxFont->getType() == fontCIDType2 )) @@ -1355,6 +1588,8 @@ void SWFOutputDev::updateFont(GfxState *state) if(fileName && del) unlinkfont(fileName); + if(fileName) + free(fileName); } #define SQR(x) ((x)*(x)) @@ -1724,14 +1959,141 @@ static void printInfoDate(Dict *infoDict, char *key, char *fmt) { obj.free(); } -void pdfswf_init(char*filename, char*userPassword) +void pdfswf_setparameter(char*name, char*value) +{ + msg(" setting parameter %s to \"%s\"", name, value); + if(!strcmp(name, "caplinewidth")) { + caplinewidth = atof(value); + } else if(!strcmp(name, "zoom")) { + zoom = atoi(value); + } else if(!strcmp(name, "forceType0Fonts")) { + forceType0Fonts = atoi(value); + } else if(!strcmp(name, "fontdir")) { + pdfswf_addfontdir(value); + } else if(!strcmp(name, "languagedir")) { + pdfswf_addlanguagedir(value); + } else if(!strcmp(name, "fontconfig")) { + config_use_fontconfig = atoi(value); + } else { + swfoutput_setparameter(name, value); + } +} +void pdfswf_addfont(char*filename) { + fontfile_t f; + memset(&f, 0, sizeof(fontfile_t)); + f.filename = filename; + if(fontnum < sizeof(fonts)/sizeof(fonts[0])) { + fonts[fontnum++] = f; + } else { + msg(" Too many external fonts. Not adding font file \"%s\".", filename); + } +} + +static char* dirseparator() +{ +#ifdef WIN32 + return "\\"; +#else + return "/"; +#endif +} + +void pdfswf_addlanguagedir(char*dir) +{ + if(!globalParams) + globalParams = new GlobalParams(""); + + msg(" Adding %s to language pack directories", dir); + + int l; + FILE*fi = 0; + char* config_file = (char*)malloc(strlen(dir) + 1 + sizeof("add-to-xpdfrc")); + strcpy(config_file, dir); + strcat(config_file, dirseparator()); + strcat(config_file, "add-to-xpdfrc"); + + fi = fopen(config_file, "rb"); + if(!fi) { + msg(" Could not open %s", config_file); + return; + } + globalParams->parseFile(new GString(config_file), fi); + fclose(fi); +} + +void pdfswf_addfontdir(char*dirname) +{ +#ifdef HAVE_DIRENT_H + msg(" Adding %s to font directories", dirname); + DIR*dir = opendir(dirname); + if(!dir) { + msg(" Couldn't open directory %s\n", dirname); + return; + } + struct dirent*ent; + while(1) { + ent = readdir (dir); + if (!ent) + break; + int l; + char*name = ent->d_name; + char type = 0; + if(!name) continue; + l=strlen(name); + if(l<4) + continue; + if(!strncasecmp(&name[l-4], ".pfa", 4)) + type=1; + if(!strncasecmp(&name[l-4], ".pfb", 4)) + type=3; + if(!strncasecmp(&name[l-4], ".ttf", 4)) + type=2; + if(type) + { + char*fontname = (char*)malloc(strlen(dirname)+strlen(name)+2); + strcpy(fontname, dirname); + strcat(fontname, dirseparator()); + strcat(fontname, name); + msg(" Adding %s to fonts", fontname); + pdfswf_addfont(fontname); + } + } + closedir(dir); +#else + msg(" No dirent.h- unable to add font dir %s", dir); +#endif +} + + +typedef struct _pdf_doc_internal +{ + int protect; + PDFDoc*doc; +} pdf_doc_internal_t; +typedef struct _pdf_page_internal +{ +} pdf_page_internal_t; +typedef struct _swf_output_internal +{ + SWFOutputDev*outputDev; +} swf_output_internal_t; + +pdf_doc_t* pdf_init(char*filename, char*userPassword) +{ + pdf_doc_t*pdf_doc = (pdf_doc_t*)malloc(sizeof(pdf_doc_t)); + memset(pdf_doc, 0, sizeof(pdf_doc_t)); + pdf_doc_internal_t*i= (pdf_doc_internal_t*)malloc(sizeof(pdf_doc_internal_t)); + memset(i, 0, sizeof(pdf_doc_internal_t)); + pdf_doc->internal = i; + GString *fileName = new GString(filename); GString *userPW; Object info; // read config file - globalParams = new GlobalParams(""); + if(!globalParams) + globalParams = new GlobalParams(""); // open PDF file if (userPassword && userPassword[0]) { @@ -1739,18 +2101,18 @@ void pdfswf_init(char*filename, char*userPassword) } else { userPW = NULL; } - doc = new PDFDoc(fileName, userPW); + i->doc = new PDFDoc(fileName, userPW); if (userPW) { delete userPW; } - if (!doc->isOk()) { - exit(1); + if (!i->doc->isOk()) { + return 0; } // print doc info - doc->getDocInfo(&info); + i->doc->getDocInfo(&info); if (info.isDict() && - (screenloglevel>=LOGLEVEL_NOTICE)) { + (getScreenLogLevel()>=LOGLEVEL_NOTICE)) { printInfoString(info.getDict(), "Title", "Title: %s\n"); printInfoString(info.getDict(), "Subject", "Subject: %s\n"); printInfoString(info.getDict(), "Keywords", "Keywords: %s\n"); @@ -1759,66 +2121,39 @@ 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("Pages: %d\n", i->doc->getNumPages()); + printf("Linearized: %s\n", i->doc->isLinearized() ? "yes" : "no"); printf("Encrypted: "); - if (doc->isEncrypted()) { + if (i->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"); + i->doc->okToPrint() ? "yes" : "no", + i->doc->okToCopy() ? "yes" : "no", + i->doc->okToChange() ? "yes" : "no", + i->doc->okToAddNotes() ? "yes" : "no"); } else { printf("no\n"); } } info.free(); - numpages = doc->getNumPages(); - int protect = 0; - if (doc->isEncrypted()) { - if(!doc->okToCopy()) { - printf("PDF disallows copying. Terminating.\n"); - exit(1); //bail out + pdf_doc->num_pages = i->doc->getNumPages(); + i->protect = 0; + if (i->doc->isEncrypted()) { + if(!i->doc->okToCopy()) { + printf("PDF disallows copying.\n"); + return 0; } - if(!doc->okToChange() || !doc->okToAddNotes()) - protect = 1; + if(!i->doc->okToChange() || !i->doc->okToAddNotes()) + i->protect = 1; } - if(protect) - swfoutput_setparameter("protect", "1"); - - output = new SWFOutputDev(); - output->startDoc(doc->getXRef()); + return pdf_doc; } -void pdfswf_setparameter(char*name, char*value) +void pdfswf_preparepage(int page) { - if(!strcmp(name, "outputfilename")) { - swffilename = value; - } else if(!strcmp(name, "caplinewidth")) { - caplinewidth = atof(value); - } else if(!strcmp(name, "zoom")) { - zoom = atoi(value); - } else { - swfoutput_setparameter(name, value); - } -} - -void pdfswf_addfont(char*filename) -{ - fontfile_t f; - memset(&f, 0, sizeof(fontfile_t)); - f.filename = filename; - fonts[fontnum++] = f; -} - -void pdfswf_setoutputfilename(char*_filename) { swffilename = _filename; } - -void pdfswf_convertpage(int page) -{ - if(!pages) - { + /*FIXME*/ + if(!pages) { pages = (int*)malloc(1024*sizeof(int)); pagebuflen = 1024; } else { @@ -1831,33 +2166,171 @@ void pdfswf_convertpage(int page) pages[pagepos++] = page; } -void pdfswf_performconversion() +class MemCheck { - int t; - for(t=0;tinternal; + + msg(" pdfswf.cc: pdfswf_close()"); + delete i->doc; i->doc=0; + + free(pages); pages = 0; //FIXME + + free(pdf_doc->internal);pdf_doc->internal=0; + free(pdf_doc);pdf_doc=0; +} + +pdf_page_t* pdf_getpage(pdf_doc_t*pdf_doc, int page) +{ + pdf_doc_internal_t*di= (pdf_doc_internal_t*)pdf_doc->internal; + + if(page < 1 || page > pdf_doc->num_pages) + return 0; + + pdf_page_t* pdf_page = (pdf_page_t*)malloc(sizeof(pdf_page_t)); + pdf_page_internal_t*pi= (pdf_page_internal_t*)malloc(sizeof(pdf_page_internal_t)); + memset(pi, 0, sizeof(pdf_page_internal_t)); + pdf_page->internal = pi; + + pdf_page->parent = pdf_doc; + pdf_page->nr = page; + return pdf_page; +} + +void pdf_page_destroy(pdf_page_t*pdf_page) +{ + pdf_page_internal_t*i= (pdf_page_internal_t*)pdf_page->internal; + free(pdf_page->internal);pdf_page->internal = 0; + free(pdf_page);pdf_page=0; +} + +swf_output_t* swf_output_init() +{ + swf_output_t*swf_output = (swf_output_t*)malloc(sizeof(swf_output_t)); + memset(swf_output, 0, sizeof(swf_output_t)); + swf_output_internal_t*i= (swf_output_internal_t*)malloc(sizeof(swf_output_internal_t)); + memset(i, 0, sizeof(swf_output_internal_t)); + swf_output->internal = i; + + i->outputDev = new SWFOutputDev(); + return swf_output; +} + +void swf_output_setparameter(swf_output_t*swf_output, char*name, char*value) +{ + /* FIXME */ + pdfswf_setparameter(name, value); +} + +void swf_output_pagefeed(swf_output_t*swf) +{ + swf_output_internal_t*i= (swf_output_internal_t*)swf->internal; + i->outputDev->pagefeed(); + i->outputDev->getDimensions(&swf->x1, &swf->y1, &swf->x2, &swf->y2); +} + +int swf_output_save(swf_output_t*swf, char*filename) +{ + swf_output_internal_t*i= (swf_output_internal_t*)swf->internal; + int ret = i->outputDev->save(filename); + i->outputDev->getDimensions(&swf->x1, &swf->y1, &swf->x2, &swf->y2); + return ret; +} + +void* swf_output_get(swf_output_t*swf) +{ + swf_output_internal_t*i= (swf_output_internal_t*)swf->internal; + void* ret = i->outputDev->getSWF(); + i->outputDev->getDimensions(&swf->x1, &swf->y1, &swf->x2, &swf->y2); + return ret; +} + +void swf_output_destroy(swf_output_t*output) +{ + swf_output_internal_t*i = (swf_output_internal_t*)output->internal; + delete i->outputDev; i->outputDev=0; + free(output->internal);output->internal=0; + free(output); +} + +void pdf_page_render2(pdf_page_t*page, swf_output_t*swf) +{ + pdf_doc_internal_t*pi = (pdf_doc_internal_t*)page->parent->internal; + swf_output_internal_t*si = (swf_output_internal_t*)swf->internal; + + if(pi->protect) { + swfoutput_setparameter("protect", "1"); + } + si->outputDev->setXRef(pi->doc, pi->doc->getXRef()); #ifdef XPDF_101 - doc->displayPage((OutputDev*)output, currentpage, /*zoom*/zoom, /*rotate*/0, /*doLinks*/(int)1); + pi->doc->displayPage((OutputDev*)si->outputDev, page->nr, /*zoom*/zoom, /*rotate*/0, /*doLinks*/(int)1); #else - doc->displayPage((OutputDev*)output, currentpage, zoom, zoom, /*rotate*/0, true, /*doLinks*/(int)1); + pi->doc->displayPage((OutputDev*)si->outputDev, page->nr, zoom, zoom, /*rotate*/0, true, /*doLinks*/(int)1); #endif - } + si->outputDev->getDimensions(&swf->x1, &swf->y1, &swf->x2, &swf->y2); } -int pdfswf_numpages() + +void pdf_page_rendersection(pdf_page_t*page, swf_output_t*output, int x, int y, int x1, int y1, int x2, int y2) { - return doc->getNumPages(); + pdf_doc_internal_t*pi = (pdf_doc_internal_t*)page->parent->internal; + swf_output_internal_t*si = (swf_output_internal_t*)output->internal; + + si->outputDev->setMove(x,y); + if((x1|y1|x2|y2)==0) x2++; + si->outputDev->setClip(x1,y1,x2,y2); + + pdf_page_render2(page, output); } -void pdfswf_close() +void pdf_page_render(pdf_page_t*page, swf_output_t*output) { - msg(" pdfswf.cc: pdfswf_close()"); - delete output; output=0; - delete doc; doc=0; - free(pages); pages = 0; - //freeParams(); - // check for memory leaks - Object::memCheck(stderr); - gMemReport(stderr); + pdf_doc_internal_t*pi = (pdf_doc_internal_t*)page->parent->internal; + swf_output_internal_t*si = (swf_output_internal_t*)output->internal; + + si->outputDev->setMove(0,0); + si->outputDev->setClip(0,0,0,0); + + pdf_page_render2(page, output); } +pdf_page_info_t* pdf_page_getinfo(pdf_page_t*page) +{ + pdf_doc_internal_t*pi = (pdf_doc_internal_t*)page->parent->internal; + pdf_page_internal_t*i= (pdf_page_internal_t*)page->internal; + pdf_page_info_t*info = (pdf_page_info_t*)malloc(sizeof(pdf_page_info_t)); + memset(info, 0, sizeof(pdf_page_info_t)); + + InfoOutputDev*output = new InfoOutputDev; + +#ifdef XPDF_101 + pi->doc->displayPage((OutputDev*)output, page->nr, /*zoom*/zoom, /*rotate*/0, /*doLinks*/(int)1); +#else + pi->doc->displayPage((OutputDev*)output, page->nr, zoom, zoom, /*rotate*/0, true, /*doLinks*/(int)1); +#endif + + info->xMin = output->x1; + info->yMin = output->y1; + info->xMax = output->x2; + info->yMax = output->y2; + info->number_of_images = output->num_images; + info->number_of_links = output->num_links; + info->number_of_fonts = output->num_fonts; + + delete output; + + return info; +} + +void pdf_page_info_destroy(pdf_page_info_t*info) +{ + free(info); +}