X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=pdf2swf%2FSWFOutputDev.cc;h=b447a7e58113ec37de611449dedb5bdfd8da5ba1;hb=3c35bf20441ec1fec554a085e1b29a1dadf8b46d;hp=b0fd6cb39341f2c686130a966c9daee195f96a72;hpb=242870f51bcada26c934f5229f1d7aac9117eee5;p=swftools.git diff --git a/pdf2swf/SWFOutputDev.cc b/pdf2swf/SWFOutputDev.cc index b0fd6cb..b447a7e 100644 --- a/pdf2swf/SWFOutputDev.cc +++ b/pdf2swf/SWFOutputDev.cc @@ -46,23 +46,20 @@ #include "Page.h" #include "PDFDoc.h" #include "Error.h" +#include "Link.h" #include "OutputDev.h" #include "GfxState.h" #include "GfxFont.h" #include "CharCodeToUnicode.h" #include "NameToUnicodeTable.h" #include "GlobalParams.h" -//#define XPDF_101 -#ifdef XPDF_101 -#include "FontFile.h" -#else #include "FoFiType1C.h" #include "FoFiTrueType.h" -#endif +#include "GHash.h" #include "SWFOutputDev.h" //swftools header files -#include "swfoutput.h" +#include "../lib/devices/swf.h" #include "../lib/log.h" #include "../lib/gfxdevice.h" #include "../lib/gfxtools.h" @@ -92,12 +89,6 @@ 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 double zoom = 72; /* xpdf: 86 */ @@ -106,6 +97,8 @@ static int forceType0Fonts = 1; static void printInfoString(Dict *infoDict, char *key, char *fmt); static void printInfoDate(Dict *infoDict, char *key, char *fmt); +static char* lastfontdir = 0; + struct mapping { char*pdffont; char*filename; @@ -143,25 +136,29 @@ typedef struct _fontlist _fontlist*next; } fontlist_t; +class InfoOutputDev; + class SWFOutputDev: public OutputDev { - int outputstarted; public: gfxdevice_t* output; // Constructor. - SWFOutputDev(); + SWFOutputDev(gfxdevice_t*output); // Destructor. virtual ~SWFOutputDev() ; void setMove(int x,int y); void setClip(int x1,int y1,int x2,int y2); + + void setInfo(InfoOutputDev*info) {this->info = info;} - int save(char*filename); - void pagefeed(); - void* getSWF(); + // Start a page. + void startFrame(int width, int height); - void getDimensions(int*x1,int*y1,int*x2,int*y2); + virtual void startPage(int pageNum, GfxState *state, double x1, double y1, double x2, double y2) ; + + void endframe(); //----- get info about output device @@ -181,9 +178,6 @@ public: void setXRef(PDFDoc*doc, XRef *xref); - // Start a page. - virtual void startPage(int pageNum, GfxState *state, double x1, double y1, double x2, double y2) ; - //----- link borders virtual void drawLink(Link *link, Catalog *catalog) ; @@ -226,7 +220,7 @@ public: virtual void drawChar(GfxState *state, double x, double y, double dx, double dy, double originX, double originY, - CharCode code, Unicode *u, int uLen); + CharCode code, int nBytes, Unicode *u, int uLen); //----- image drawing virtual void drawImageMask(GfxState *state, Object *ref, Stream *str, @@ -235,6 +229,17 @@ public: virtual void drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, int *maskColors, GBool inlineImg); + virtual void drawMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Stream *maskStr, int maskWidth, int maskHeight, + GBool maskInvert); + virtual void drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Stream *maskStr, + int maskWidth, int maskHeight, + GfxImageColorMap *maskColorMap); virtual GBool beginType3Char(GfxState *state, double x, double y, double dx, double dy, CharCode code, Unicode *u, int uLen); virtual void endType3Char(GfxState *state); @@ -242,21 +247,21 @@ public: virtual void type3D0(GfxState *state, double wx, double wy); virtual void type3D1(GfxState *state, double wx, double wy, double llx, double lly, double urx, double ury); + void finish(); + private: void drawGeneralImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap*colorMap, GBool invert, - GBool inlineImg, int mask, int *maskColors); - int SWFOutputDev::setGfxFont(char*id, char*filename); + GBool inlineImg, int mask, int *maskColors, + Stream *maskStr, int maskWidth, int maskHeight, GBool maskInvert, GfxImageColorMap*maskColorMap); + int SWFOutputDev::setGfxFont(char*id, char*name, char*filename, double quality); void strokeGfxline(GfxState *state, gfxline_t*line); void clipToGfxLine(GfxState *state, gfxline_t*line); void fillGfxLine(GfxState *state, gfxline_t*line); - void finish(); - - gfxresult_t*result; //filled when complete - char outer_clip_box; //whether the page clip box is still on + InfoOutputDev*info; SWFOutputState states[64]; int statepos; @@ -269,6 +274,7 @@ public: char* substituteFont(GfxFont*gfxFont, char*oldname); char* writeEmbeddedFontToFile(XRef*ref, GfxFont*font); int t1id; + int textmodeinfo; // did we write "Text will be rendered as polygon" yet? 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? @@ -295,12 +301,71 @@ public: gfxmatrix_t current_font_matrix; fontlist_t* fontlist; + + int*pages; + int pagebuflen; + int pagepos; + + friend void dev_output_preparepage(dev_output_t*swf, int pdfpage, int outputpage); +}; + +typedef struct _drawnchar +{ + gfxcoord_t x,y; + int charid; + gfxcolor_t color; +} drawnchar_t; + +class CharBuffer +{ + drawnchar_t * chars; + int buf_size; + int num_chars; + +public: + + CharBuffer() + { + buf_size = 32; + chars = (drawnchar_t*)malloc(sizeof(drawnchar_t)*buf_size); + memset(chars, 0, sizeof(drawnchar_t)*buf_size); + num_chars = 0; + } + ~CharBuffer() + { + free(chars);chars = 0; + } + + void grow(int size) + { + if(size>=buf_size) { + buf_size += 32; + chars = (drawnchar_t*)realloc(chars, sizeof(drawnchar_t)*buf_size); + } + } + + void addChar(int charid, gfxcoord_t x, gfxcoord_t y, gfxcolor_t color) + { + grow(num_chars); + chars[num_chars].x = x; + chars[num_chars].y = y; + chars[num_chars].color = color; + chars[num_chars].charid = charid; + } }; static char*getFontID(GfxFont*font); +struct FontInfo +{ + GfxFont*font; + double max_size; +}; + class InfoOutputDev: public OutputDev { + GHash* id2font; + FontInfo* currentfont; public: int x1,y1,x2,y2; int num_links; @@ -312,9 +377,11 @@ class InfoOutputDev: public OutputDev num_links = 0; num_images = 0; num_fonts = 0; + id2font = new GHash(); } virtual ~InfoOutputDev() { + delete id2font; } virtual GBool upsideDown() {return gTrue;} virtual GBool useDrawChar() {return gTrue;} @@ -336,14 +403,54 @@ class InfoOutputDev: public OutputDev { num_links++; } + virtual double getMaximumFontSize(char*id) + { + FontInfo*info = (FontInfo*)id2font->lookup(id); + if(!info) { + msg(" Unknown font id: %s", id); + return 0.0; + } + return info->max_size; + } + virtual void updateFont(GfxState *state) { GfxFont*font = state->getFont(); if(!font) return; - /*char*id = getFontID(font);*/ - /* FIXME*/ - num_fonts++; + char*id = getFontID(font); + + FontInfo*info = (FontInfo*)id2font->lookup(id); + if(!info) { + GString* idStr = new GString(id); + info = new FontInfo; + info->font = font; + info->max_size = 0; + id2font->add(idStr, (void*)info); + free(id); + num_fonts++; + } + currentfont = info; + } + + virtual void drawChar(GfxState *state, double x, double y, + double dx, double dy, + double originX, double originY, + CharCode code, int nBytes, Unicode *u, int uLen) + { + int render = state->getRender(); + if (render == 3) + return; + double m11,m21,m12,m22; + state->getFontTransMat(&m11, &m12, &m21, &m22); + m11 *= state->getHorizScaling(); + m21 *= state->getHorizScaling(); + double lenx = sqrt(m11*m11 + m12*m12); + double leny = sqrt(m21*m21 + m22*m22); + double len = lenx>leny?lenx:leny; + if(currentfont && currentfont->max_size < len) { + currentfont->max_size = len; + } } virtual void drawImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, @@ -359,31 +466,39 @@ class InfoOutputDev: public OutputDev } }; -SWFOutputDev::SWFOutputDev() -{ - jpeginfo = 0; - ttfinfo = 0; - linkinfo = 0; - pbminfo = 0; - type3active = 0; - statepos = 0; - outputstarted = 0; - xref = 0; - substitutepos = 0; - type3Warning = 0; - user_movex = 0; - user_movey = 0; - user_clipx1 = 0; - user_clipy1 = 0; - user_clipx2 = 0; - user_clipy2 = 0; - current_text_stroke = 0; - current_text_clip = 0; - fontlist = 0; - result = 0; - outer_clip_box = 0; - output = (gfxdevice_t*)malloc(sizeof(gfxdevice_t)); - memset(output, 0, sizeof(output)); +SWFOutputDev::SWFOutputDev(gfxdevice_t*output) +{ + this->output = output; + this->jpeginfo = 0; + this->textmodeinfo = 0; + this->ttfinfo = 0; + this->linkinfo = 0; + this->pbminfo = 0; + this->type3active = 0; + this->statepos = 0; + this->xref = 0; + this->substitutepos = 0; + this->type3Warning = 0; + this->user_movex = 0; + this->user_movey = 0; + this->user_clipx1 = 0; + this->user_clipy1 = 0; + this->user_clipx2 = 0; + this->user_clipy2 = 0; + this->current_text_stroke = 0; + this->current_text_clip = 0; + this->fontlist = 0; + this->outer_clip_box = 0; + this->pages = 0; + this->pagebuflen = 0; + this->pagepos = 0; + + /* configure device */ + parameter_t*p = device_config; + while(p) { + output->setparameter(output, p->name, p->value); + p = p->next; + } }; void SWFOutputDev::setMove(int x,int y) @@ -403,34 +518,33 @@ void SWFOutputDev::setClip(int x1,int y1,int x2,int y2) this->user_clipy2 = y2; } -void SWFOutputDev::getDimensions(int*x1,int*y1,int*x2,int*y2) +static char*getFontID(GfxFont*font) { - if(result) { - *x1 = (int)result->get(result, "xmin"); - *y1 = (int)result->get(result, "ymin"); - *x2 = (int)result->get(result, "xmax"); - *y2 = (int)result->get(result, "ymax"); + Ref*ref = font->getID(); + GString*gstr = font->getName(); + char* fname = gstr==0?0:gstr->getCString(); + char buf[128]; + if(fname==0) { + sprintf(buf, "font-%d-%d", ref->num, ref->gen); } else { - *x1 = *y1 = *x2 = *y2 = 0; + sprintf(buf, "%s-%d-%d", fname, ref->num, ref->gen); } + return strdup(buf); } -static char*getFontID(GfxFont*font) +static char*getFontName(GfxFont*font) { + char*fontid; GString*gstr = font->getName(); - char* fontname = gstr==0?0:gstr->getCString(); - if(fontname==0) { + char* fname = gstr==0?0:gstr->getCString(); + if(fname==0) { char buf[32]; Ref*r=font->getID(); sprintf(buf, "UFONT%d", r->num); - return strdup(buf); + fontid = strdup(buf); } - return strdup(fontname); -} + fontid = strdup(fname); -static char*getFontName(GfxFont*font) -{ - char*fontid = getFontID(font); char*fontname= 0; char* plus = strchr(fontid, '+'); if(plus && plus < &fontid[strlen(fontid)-1]) { @@ -708,7 +822,7 @@ gfxline_t* gfxPath_to_gfxline(GfxState*state, GfxPath*path, int closed, int user if(cpos==0) { draw.lineTo(&draw, x,y); } else { - gfxdraw_cubicTo(&draw, bx,by, cx,cy, x,y); + gfxdraw_cubicTo(&draw, bx,by, cx,cy, x,y, 0.05); } needsfix = 1; cpos = 0; @@ -749,9 +863,9 @@ void SWFOutputDev::strokeGfxline(GfxState *state, gfxline_t*line) else state->getStrokeRGB(&rgb); gfxcolor_t col; - col.r = (unsigned char)(rgb.r*255); - col.g = (unsigned char)(rgb.g*255); - col.b = (unsigned char)(rgb.b*255); + col.r = colToByte(rgb.r); + col.g = colToByte(rgb.g); + col.b = colToByte(rgb.b); col.a = (unsigned char)(opaq*255); gfx_capType capType = gfx_capRound; @@ -789,19 +903,17 @@ void SWFOutputDev::strokeGfxline(GfxState *state, gfxline_t*line) line2 = gfxtool_dash_line(line, dash, dashphase); line = line2; + free(dash); msg(" After dashing:"); } if(getLogLevel() >= LOGLEVEL_TRACE) { - double gray; - state->getStrokeGray(&gray); - msg(" stroke width=%f join=%s cap=%s dashes=%d color=%02x%02x%02x%02x gray=%f\n", + msg(" stroke width=%f join=%s cap=%s dashes=%d color=%02x%02x%02x%02x\n", width, lineJoin==0?"miter": (lineJoin==1?"round":"bevel"), lineCap==0?"butt": (lineJoin==1?"round":"square"), dashnum, - col.r,col.g,col.b,col.a, - gray + col.r,col.g,col.b,col.a ); dump_outline(line); } @@ -813,15 +925,19 @@ void SWFOutputDev::strokeGfxline(GfxState *state, gfxline_t*line) gfxline_free(line2); } +void convertRGB() +{ +} + gfxcolor_t getFillColor(GfxState * state) { GfxRGB rgb; double opaq = state->getFillOpacity(); state->getFillRGB(&rgb); gfxcolor_t col; - col.r = (unsigned char)(rgb.r*255); - col.g = (unsigned char)(rgb.g*255); - col.b = (unsigned char)(rgb.b*255); + col.r = colToByte(rgb.r); + col.g = colToByte(rgb.g); + col.b = colToByte(rgb.b); col.a = (unsigned char)(opaq*255); return col; } @@ -892,47 +1008,32 @@ void SWFOutputDev::eoClip(GfxState *state) gfxline_free(line); } -/* pass through functions for swf_output */ -int SWFOutputDev::save(char*filename) -{ - finish(); - return result->save(result, filename); -} -void SWFOutputDev::pagefeed() +void SWFOutputDev::endframe() { if(outer_clip_box) { output->endclip(output); outer_clip_box = 0; } - swfoutput_pagefeed(output); -} -void* SWFOutputDev::getSWF() -{ - finish(); - return result->get(result, "swf"); + output->endpage(output); } void SWFOutputDev::finish() { if(outer_clip_box) { - output->endclip(output); + if(output) { + output->endclip(output); + } outer_clip_box = 0; } - if(output) { - this->result = output->finish(output); - free(output);output=0; - } } SWFOutputDev::~SWFOutputDev() { finish(); - outputstarted = 0; - if(this->result) { - this->result->destroy(this->result); - this->result = 0; + if(this->pages) { + free(this->pages); this->pages = 0; } fontlist_t*l = this->fontlist; @@ -940,15 +1041,15 @@ SWFOutputDev::~SWFOutputDev() fontlist_t*next = l->next; l->next = 0; gfxfont_free(l->font); - free(l->id); - free(l->filename); + free(l->id);l->id=0; + free(l->filename);l->filename=0; free(l); l = next; } + this->fontlist = 0; }; GBool SWFOutputDev::upsideDown() { - msg(" upsidedown? yes"); return gTrue; }; GBool SWFOutputDev::useDrawChar() @@ -1003,8 +1104,22 @@ char* makeStringPrintable(char*str) int getGfxCharID(gfxfont_t*font, int charnr, char *charname, int u) { - int t; + char*uniname = 0; + if(u>0) { + int t; + /* find out char name from unicode index + TODO: should be precomputed + */ + for(t=0;tnum_glyphs;t++) { if(font->glyphs[t].name && !strcmp(font->glyphs[t].name,charname)) { msg(" Char [%d,>%s<,%d] maps to %d\n", charnr, charname, u, t); @@ -1021,6 +1136,24 @@ int getGfxCharID(gfxfont_t*font, int charnr, char *charname, int u) } } + if(uniname) { + int t; + for(t=0;tnum_glyphs;t++) { + if(font->glyphs[t].name && !strcmp(font->glyphs[t].name,uniname)) { + msg(" Char [%d,%s,>%d(%s)<] maps to %d\n", charnr, charname, u, uniname, t); + return t; + } + } + /* if we didn't find the character, maybe + we can find the capitalized version */ + for(t=0;tnum_glyphs;t++) { + if(font->glyphs[t].name && !strcasecmp(font->glyphs[t].name,uniname)) { + msg(" Char [%d,%s,>>%d(%s)<<] maps to %d\n", charnr, charname, u, uniname, t); + return t; + } + } + } + /* try to use the unicode id */ if(u>=0 && umax_unicode && font->unicode2glyph[u]>=0) { msg(" Char [%d,%s,>%d<] maps to %d\n", charnr, charname, u, font->unicode2glyph[u]); @@ -1067,12 +1200,14 @@ void SWFOutputDev::beginString(GfxState *state, GString *s) void SWFOutputDev::drawChar(GfxState *state, double x, double y, double dx, double dy, double originX, double originY, - CharCode c, Unicode *_u, int uLen) + CharCode c, int nBytes, Unicode *_u, int uLen) { int render = state->getRender(); // check for invisible text -- this is used by Acrobat Capture - if (render == 3) + if (render == 3) { + msg(" Ignoring invisible text: char %d at %f,%f", c, x, y); return; + } if(states[statepos].textRender != render) msg(" Internal error: drawChar.render!=beginString.render"); @@ -1091,22 +1226,6 @@ void SWFOutputDev::drawChar(GfxState *state, double x, double y, Unicode u=0; 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()) { GfxCIDFont*cfont = (GfxCIDFont*)font; @@ -1116,8 +1235,7 @@ void SWFOutputDev::drawChar(GfxState *state, double x, double y, Gfx8BitFont*font8; font8 = (Gfx8BitFont*)font; char**enc=font8->getEncoding(); - if(enc && enc[c]) - name = enc[c]; + name = enc[c]; } if (CIDToGIDMap) { msg(" drawChar(%f, %f, c='%c' (%d), GID=%d, u=%d <%d>) CID=%d name=\"%s\" render=%d\n", x, y, (c&127)>=32?c:'?', c, CIDToGIDMap[c], u, uLen, font->isCIDFont(), FIXNULL(name), render); @@ -1126,7 +1244,25 @@ void SWFOutputDev::drawChar(GfxState *state, double x, double y, msg(" drawChar(%f,%f,c='%c' (%d), u=%d <%d>) CID=%d name=\"%s\" render=%d\n",x,y,(c&127)>=32?c:'?',c,u, uLen, font->isCIDFont(), FIXNULL(name), render); } - int charid = getGfxCharID(current_gfxfont, c, name, u); + int charid = -1; + + if(uLen<=1) { + charid = getGfxCharID(current_gfxfont, c, name, u); + } else { + charid = getGfxCharID(current_gfxfont, c, name, -1); + + if(charid < 0) { + /* multiple unicodes- should usually map to a ligature. + if the ligature doesn't exist, we need to draw + the characters one-by-one. */ + int t; + msg(" ligature %d missing in font %s\n", c, current_font_id); + for(t=0;t Didn't find character '%s' (c=%d,u=%d) in current charset (%s, %d characters)", FIXNULL(name),c, u, FIXNULL((char*)current_font_id), current_gfxfont->num_glyphs); @@ -1142,6 +1278,10 @@ void SWFOutputDev::drawChar(GfxState *state, double x, double y, output->drawchar(output, current_font_id, charid, &col, &m); } else { msg(" Drawing glyph %d as shape", charid); + if(!textmodeinfo) { + msg(" Some texts will be rendered as shape"); + textmodeinfo = 1; + } gfxline_t*glyph = current_gfxfont->glyphs[charid].line; gfxline_t*tglyph = gfxline_clone(glyph); gfxline_transform(tglyph, &m); @@ -1169,6 +1309,7 @@ void SWFOutputDev::endString(GfxState *state) now (as there may be texts of other rendering modes in this text object)- clipping objects have to wait until endTextObject, however */ + output->setparameter(output, "mark","TXT"); if((render&3) == RENDER_FILL) { fillGfxLine(state, current_text_stroke); gfxline_free(current_text_stroke); @@ -1183,6 +1324,7 @@ void SWFOutputDev::endString(GfxState *state) gfxline_free(current_text_stroke); current_text_stroke = 0; } + output->setparameter(output, "mark",""); } } @@ -1194,7 +1336,9 @@ void SWFOutputDev::endTextObject(GfxState *state) msg(" Internal error: drawChar.render!=beginString.render"); if(current_text_clip) { + output->setparameter(output, "mark","TXT"); clipToGfxLine(state, current_text_clip); + output->setparameter(output, "mark",""); gfxline_free(current_text_clip); current_text_clip = 0; } @@ -1233,6 +1377,11 @@ void SWFOutputDev::endType3Char(GfxState *state) msg(" endType3Char"); } +void SWFOutputDev::startFrame(int width, int height) +{ + output->startpage(output, width, height); +} + void SWFOutputDev::startPage(int pageNum, GfxState *state, double crop_x1, double crop_y1, double crop_x2, double crop_y2) { this->currentpage = pageNum; @@ -1244,10 +1393,6 @@ void SWFOutputDev::startPage(int pageNum, GfxState *state, double crop_x1, doubl white.r = white.g = white.b = white.a = 255; - 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 @@ -1257,12 +1402,13 @@ void SWFOutputDev::startPage(int pageNum, GfxState *state, double crop_x1, doubl 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); + state->transform(crop_x1,crop_y1,&x1,&y1); //x1 += user_movex; y1 += user_movey; + state->transform(crop_x2,crop_y2,&x2,&y2); //x2 += user_movex; y2 += user_movey; if(x2 x1)*/ x1 = user_clipx1; @@ -1271,29 +1417,16 @@ void SWFOutputDev::startPage(int pageNum, GfxState *state, double crop_x1, doubl /*if(user_clipy2 < y2)*/ y2 = user_clipy2; } - if(!outputstarted) { - msg(" Bounding box is (%f,%f)-(%f,%f)", x1,y1,x2,y2); - - gfxdevice_swf_init(output); - - /* configure device */ - parameter_t*p = device_config; - while(p) { - output->setparameter(output, p->name, p->value); - p = p->next; - } - - outputstarted = 1; - } - + //msg(" Bounding box is (%f,%f)-(%f,%f) [shifted by %d/%d]", x1,y1,x2,y2, user_movex, user_movey); + if(outer_clip_box) { output->endclip(output); outer_clip_box = 0; } - msg(" processing page %d (%dx%d:%d:%d)", pageNum, (int)x2-(int)x1,(int)y2-(int)y1, (int)x1, (int)y1); - - swfoutput_newpage(output, (int)x1, (int)y1, (int)x2, (int)y2); + msg(" processing PDF page %d (%dx%d:%d:%d) (move:%d:%d)", pageNum, (int)x2-(int)x1,(int)y2-(int)y1, (int)x1, (int)y1, user_movex, user_movey); + if(rot!=0) + msg(" page is rotated %d degrees\n", rot); clippath[0].type = gfx_moveTo;clippath[0].x = x1; clippath[0].y = y1; clippath[0].next = &clippath[1]; clippath[1].type = gfx_lineTo;clippath[1].x = x2; clippath[1].y = y1; clippath[1].next = &clippath[2]; @@ -1306,20 +1439,13 @@ void SWFOutputDev::startPage(int pageNum, GfxState *state, double crop_x1, doubl void SWFOutputDev::drawLink(Link *link, Catalog *catalog) { - msg(" drawlink\n"); double x1, y1, x2, y2, w; - GfxRGB rgb; gfxline_t points[5]; int x, y; + + msg(" drawlink\n"); -#ifdef XPDF_101 - link->getBorder(&x1, &y1, &x2, &y2, &w); -#else link->getRect(&x1, &y1, &x2, &y2); -#endif - rgb.r = 0; - rgb.g = 0; - rgb.b = 1; cvtUserToDev(x1, y1, &x, &y); points[0].type = gfx_moveTo; points[0].x = points[4].x = x + user_movex; @@ -1400,7 +1526,8 @@ void SWFOutputDev::drawLink(Link *link, Catalog *catalog) } else if(strstr(s, "last") || strstr(s, "end")) { - page = pagepos>0?pages[pagepos-1]:0; + if(pages && pagepos>0) + page = pages[pagepos-1]; } else if(strstr(s, "first") || strstr(s, "top")) { @@ -1414,7 +1541,9 @@ void SWFOutputDev::drawLink(Link *link, Catalog *catalog) type = "Launch"; LinkLaunch*l = (LinkLaunch*)action; GString * str = new GString(l->getFileName()); - str->append(l->getParams()); + GString * params = l->getParams(); + if(params) + str->append(params); s = strdup(str->getCString()); delete str; } @@ -1440,6 +1569,7 @@ void SWFOutputDev::drawLink(Link *link, Catalog *catalog) break; } } + if(!s) s = strdup("-?-"); if(!linkinfo && (page || url)) @@ -1451,14 +1581,19 @@ void SWFOutputDev::drawLink(Link *link, Catalog *catalog) if(page>0) { int t; - for(t=0;tdrawlink(output, points, buf); + } + } + if(lpage<0) { + lpage = page; } + char buf[80]; + sprintf(buf, "page%d", lpage); + output->drawlink(output, points, buf); } else if(url) { @@ -1604,15 +1739,9 @@ char*SWFOutputDev::writeEmbeddedFontToFile(XRef*ref, GfxFont*font) msg(" Couldn't read embedded font file"); return 0; } -#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); //cvt->convertToType0("test", f); delete cvt; @@ -1624,13 +1753,8 @@ char*SWFOutputDev::writeEmbeddedFontToFile(XRef*ref, GfxFont*font) msg(" Couldn't read embedded font file"); return 0; } -#ifdef XPDF_101 - TrueTypeFontFile *cvt = new TrueTypeFontFile(fontBuf, fontLen); - cvt->writeTTF(f); -#else FoFiTrueType *cvt = FoFiTrueType::make(fontBuf, fontLen); cvt->writeTTF(FoFiWrite, f); -#endif delete cvt; gfree(fontBuf); } else { @@ -1790,7 +1914,7 @@ char* searchForSuitableFont(GfxFont*gfxFont) char* SWFOutputDev::substituteFont(GfxFont*gfxFont, char* oldname) { char*fontname = 0, *filename = 0; - msg(" subsituteFont(%s)", oldname); + msg(" substituteFont(%s)", oldname); if(!(fontname = searchForSuitableFont(gfxFont))) { fontname = "Times-Roman"; @@ -1849,7 +1973,7 @@ void SWFOutputDev::setXRef(PDFDoc*doc, XRef *xref) this->xref = xref; } -int SWFOutputDev::setGfxFont(char*id, char*filename) +int SWFOutputDev::setGfxFont(char*id, char*name, char*filename, double maxSize) { gfxfont_t*font = 0; fontlist_t*last=0,*l = this->fontlist; @@ -1867,7 +1991,17 @@ int SWFOutputDev::setGfxFont(char*id, char*filename) l = l->next; } if(!filename) return 0; - font = gfxfont_load(filename); + + /* A font size of e.g. 9 means the font will be scaled down by + 1024 and scaled up by 9. So to have a maximum error of 1/20px, + we have to divide 0.05 by (fontsize/1024) + */ + double quality = (1024 * 0.05) / maxSize; + + msg(" Loading %s...", filename); + font = gfxfont_load(filename, quality); + msg(" Font %s loaded successfully", filename); + l = new fontlist_t; l->font = font; l->filename = strdup(filename); @@ -1891,7 +2025,15 @@ void SWFOutputDev::updateFont(GfxState *state) if (!gfxFont) { return; } + char * fontid = getFontID(gfxFont); + char * fontname = getFontName(gfxFont); + + double maxSize = 1.0; + + if(this->info) { + maxSize = this->info->getMaximumFontSize(fontid); + } int t; /* first, look if we substituted this font before- @@ -1907,8 +2049,9 @@ void SWFOutputDev::updateFont(GfxState *state) /* second, see if this is a font which was used before- if so, we are done */ - if(setGfxFont(fontid, 0)) { + if(setGfxFont(fontid, fontname, 0, 0)) { free(fontid); + free(fontname); return; } /* if(swfoutput_queryfont(&output, fontid)) @@ -1925,6 +2068,7 @@ void SWFOutputDev::updateFont(GfxState *state) showFontError(gfxFont, 2); } free(fontid); + free(fontname); return; } @@ -1947,15 +2091,21 @@ void SWFOutputDev::updateFont(GfxState *state) if(!fileName) showFontError(gfxFont,0); else del = 1; } else { - char * fontname = getFontName(gfxFont); fileName = searchFont(fontname); if(!fileName) showFontError(gfxFont,0); } if(!fileName) { char * fontname = getFontName(gfxFont); msg(" Font %s %scould not be loaded.", fontname, embedded?"":"(not embedded) "); - msg(" Try putting a TTF version of that font (named \"%s.ttf\") into /swftools/fonts", fontname); + + if(lastfontdir) + msg(" Try putting a TTF version of that font (named \"%s.ttf\") into %s", fontname, lastfontdir); + else + msg(" Try specifying one or more font directories"); + fileName = substituteFont(gfxFont, fontid); + if(!fileName) + exit(1); if(fontid) { free(fontid);fontid = strdup(substitutetarget[substitutepos-1]); /*ugly hack*/}; msg(" Font is now %s (%s)", fontid, fileName); } @@ -1963,23 +2113,28 @@ void SWFOutputDev::updateFont(GfxState *state) if(!fileName) { msg(" Couldn't set font %s\n", fontid); free(fontid); + free(fontname); return; } - msg(" updateFont(%s) -> %s", fontid, fileName); + msg(" updateFont(%s) -> %s (max size: %f)", fontid, fileName, maxSize); dumpFontInfo("", gfxFont); //swfoutput_setfont(&output, fontid, fileName); - if(!setGfxFont(fontid, 0)) { - setGfxFont(fontid, fileName); + if(!setGfxFont(fontid, fontname, 0, 0)) { + setGfxFont(fontid, fontname, fileName, maxSize); } if(fileName && del) unlinkfont(fileName); + if(fileName) free(fileName); free(fontid); + free(fontname); + + msg(" |"); } #define SQR(x) ((x)*(x)) @@ -2035,13 +2190,13 @@ unsigned char* antialize(unsigned char*data, int width, int height, int newwidth #define IMAGE_TYPE_JPEG 0 #define IMAGE_TYPE_LOSSLESS 1 -static void drawimage(gfxdevice_t*dev, RGBA* data, int sizex,int sizey, +static void drawimage(gfxdevice_t*dev, gfxcolor_t* data, int sizex,int sizey, double x1,double y1, double x2,double y2, double x3,double y3, double x4,double y4, int type) { - RGBA*newpic=0; + gfxcolor_t*newpic=0; double l1 = sqrt((x4-x1)*(x4-x1) + (y4-y1)*(y4-y1)); double l2 = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1)); @@ -2086,13 +2241,13 @@ static void drawimage(gfxdevice_t*dev, RGBA* data, int sizex,int sizey, dev->fillbitmap(dev, &p1, &img, &m, 0); } -void drawimagejpeg(gfxdevice_t*dev, RGBA*mem, int sizex,int sizey, +void drawimagejpeg(gfxdevice_t*dev, gfxcolor_t*mem, int sizex,int sizey, double x1,double y1, double x2,double y2, double x3,double y3, double x4,double y4) { drawimage(dev,mem,sizex,sizey,x1,y1,x2,y2,x3,y3,x4,y4, IMAGE_TYPE_JPEG); } -void drawimagelossless(gfxdevice_t*dev, RGBA*mem, int sizex,int sizey, +void drawimagelossless(gfxdevice_t*dev, gfxcolor_t*mem, int sizex,int sizey, double x1,double y1, double x2,double y2, double x3,double y3, double x4,double y4) { drawimage(dev,mem,sizex,sizey,x1,y1,x2,y2,x3,y3,x4,y4, IMAGE_TYPE_LOSSLESS); @@ -2101,22 +2256,59 @@ void drawimagelossless(gfxdevice_t*dev, RGBA*mem, int sizex,int sizey, void SWFOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap*colorMap, GBool invert, - GBool inlineImg, int mask, int*maskColors) + GBool inlineImg, int mask, int*maskColors, + Stream *maskStr, int maskWidth, int maskHeight, GBool maskInvert, GfxImageColorMap*maskColorMap) { - FILE *fi; - int c; - char fileName[128]; double x1,y1,x2,y2,x3,y3,x4,y4; ImageStream *imgStr; Guchar pixBuf[4]; GfxRGB rgb; int ncomps = 1; int bits = 1; + unsigned char* maskbitmap = 0; if(colorMap) { ncomps = colorMap->getNumPixelComps(); bits = colorMap->getBits(); } + + if(maskStr) { + int x,y; + unsigned char buf[8]; + maskbitmap = (unsigned char*)malloc(maskHeight*maskWidth); + if(maskColorMap) { + ImageStream*imgMaskStr = new ImageStream(maskStr, maskWidth, maskColorMap->getNumPixelComps(), maskColorMap->getBits()); + imgMaskStr->reset(); + unsigned char pal[256]; + int n = 1 << colorMap->getBits(); + int t; + for(t=0;tgetGray(pixBuf, &gray); + pal[t] = colToByte(gray); + } + for (y = 0; y < maskHeight; y++) { + for (x = 0; x < maskWidth; x++) { + imgMaskStr->getPixel(buf); + maskbitmap[y*maskWidth+x] = pal[buf[0]]; + } + } + delete imgMaskStr; + } else { + ImageStream*imgMaskStr = new ImageStream(maskStr, maskWidth, 1, 1); + imgMaskStr->reset(); + for (y = 0; y < maskHeight; y++) { + for (x = 0; x < maskWidth; x++) { + imgMaskStr->getPixel(buf); + buf[0]^=maskInvert; + maskbitmap[y*maskWidth+x] = (buf[0]^1)*255; + } + } + delete imgMaskStr; + } + } + imgStr = new ImageStream(str, width, ncomps,bits); imgStr->reset(); @@ -2130,13 +2322,15 @@ void SWFOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str, imgStr->getPixel(buf); } delete imgStr; + if(maskbitmap) + free(maskbitmap); return; } - - state->transform(0, 1, &x1, &y1); x1 += user_movex; y1+= user_movey; - state->transform(0, 0, &x2, &y2); x2 += user_movex; y2+= user_movey; - state->transform(1, 0, &x3, &y3); x3 += user_movex; y3+= user_movey; - state->transform(1, 1, &x4, &y4); x4 += user_movex; y4+= user_movey; + + state->transform(0, 1, &x1, &y1); x1 += user_movex; y1 += user_movey; + state->transform(0, 0, &x2, &y2); x2 += user_movex; y2 += user_movey; + state->transform(1, 0, &x3, &y3); x3 += user_movex; y3 += user_movey; + state->transform(1, 1, &x4, &y4); x4 += user_movex; y4 += user_movey; if(!pbminfo && !(str->getKind()==strDCT)) { if(!type3active) { @@ -2156,16 +2350,16 @@ void SWFOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str, unsigned char buf[8]; int x,y; unsigned char*pic = new unsigned char[width*height]; - RGBA pal[256]; + gfxcolor_t pal[256]; GfxRGB rgb; state->getFillRGB(&rgb); memset(pal,255,sizeof(pal)); - pal[0].r = (int)(rgb.r*255); pal[1].r = 0; - pal[0].g = (int)(rgb.g*255); pal[1].g = 0; - pal[0].b = (int)(rgb.b*255); pal[1].b = 0; + pal[0].r = (int)(colToByte(rgb.r)); pal[1].r = 0; + pal[0].g = (int)(colToByte(rgb.g)); pal[1].g = 0; + pal[0].b = (int)(colToByte(rgb.b)); pal[1].b = 0; pal[0].a = 255; pal[1].a = 0; - + int numpalette = 2; int realwidth = (int)sqrt(SQR(x2-x3) + SQR(y2-y3)); int realheight = (int)sqrt(SQR(x1-x2) + SQR(y1-y2)); @@ -2200,21 +2394,18 @@ void SWFOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str, pic = pic2; /* make a black/white palette */ - GfxRGB rgb2; - rgb2.r = 1 - rgb.r; - rgb2.g = 1 - rgb.g; - rgb2.b = 1 - rgb.b; + float r = 255/(numpalette-1); int t; for(t=0;tgetNumPixelComps()!=1 || str->getKind()==strDCT) { - RGBA*pic=new RGBA[width*height]; + gfxcolor_t*pic=new gfxcolor_t[width*height]; for (y = 0; y < height; ++y) { for (x = 0; x < width; ++x) { imgStr->getPixel(pixBuf); colorMap->getRGB(pixBuf, &rgb); - pic[width*y+x].r = (U8)(rgb.r * 255 + 0.5); - pic[width*y+x].g = (U8)(rgb.g * 255 + 0.5); - pic[width*y+x].b = (U8)(rgb.b * 255 + 0.5); + pic[width*y+x].r = (unsigned char)(colToByte(rgb.r)); + pic[width*y+x].g = (unsigned char)(colToByte(rgb.g)); + pic[width*y+x].b = (unsigned char)(colToByte(rgb.b)); pic[width*y+x].a = 255;//(U8)(rgb.a * 255 + 0.5); + if(maskbitmap) { + pic[width*y+x].a = maskbitmap[(y*maskHeight/height)*maskWidth+(x*maskWidth/width)]; + } } } if(str->getKind()==strDCT) @@ -2247,15 +2442,18 @@ void SWFOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str, drawimagelossless(output, pic, width, height, x1,y1,x2,y2,x3,y3,x4,y4); delete pic; delete imgStr; + if(maskbitmap) free(maskbitmap); return; } else { - RGBA*pic=new RGBA[width*height]; - RGBA pal[256]; + gfxcolor_t*pic=new gfxcolor_t[width*height]; + gfxcolor_t pal[256]; + int n = 1 << colorMap->getBits(); int t; for(t=0;t<256;t++) { pixBuf[0] = t; colorMap->getRGB(pixBuf, &rgb); - /*if(maskColors && *maskColors==t) { + + {/*if(maskColors && *maskColors==t) { msg(" Color %d is transparent", t); if (imgData->maskColors) { *alpha = 0; @@ -2275,10 +2473,10 @@ void SWFOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str, pal[t].b = 0; pal[t].a = 0; } - } else*/ { - pal[t].r = (U8)(rgb.r * 255 + 0.5); - pal[t].g = (U8)(rgb.g * 255 + 0.5); - pal[t].b = (U8)(rgb.b * 255 + 0.5); + } else {*/ + pal[t].r = (unsigned char)(colToByte(rgb.r)); + pal[t].g = (unsigned char)(colToByte(rgb.g)); + pal[t].b = (unsigned char)(colToByte(rgb.b)); pal[t].a = 255;//(U8)(rgb.b * 255 + 0.5); } } @@ -2286,12 +2484,16 @@ void SWFOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str, for (x = 0; x < width; ++x) { imgStr->getPixel(pixBuf); pic[width*y+x] = pal[pixBuf[0]]; + if(maskbitmap) { + pic[width*y+x].a = maskbitmap[(y*maskHeight/height)*maskWidth+(x*maskWidth/width)]; + } } } drawimagelossless(output, pic, width, height, x1,y1,x2,y2,x3,y3,x4,y4); delete pic; delete imgStr; + if(maskbitmap) free(maskbitmap); return; } } @@ -2303,7 +2505,7 @@ void SWFOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, if(states[statepos].textRender & 4) //clipped return; msg(" drawImageMask %dx%d, invert=%d inline=%d", width, height, invert, inlineImg); - drawGeneralImage(state,ref,str,width,height,0,invert,inlineImg,1, 0); + drawGeneralImage(state,ref,str,width,height,0,invert,inlineImg,1, 0, 0,0,0,0, 0); } void SWFOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, @@ -2313,14 +2515,51 @@ void SWFOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, if(states[statepos].textRender & 4) //clipped return; - msg(" drawImage %dx%d, %s %s, inline=%d", width, height, + msg(" drawImage %dx%d, %s, %s, inline=%d", width, height, colorMap?"colorMap":"no colorMap", maskColors?"maskColors":"no maskColors", inlineImg); if(colorMap) msg(" colorMap pixcomps:%d bits:%d mode:%d\n", colorMap->getNumPixelComps(), colorMap->getBits(),colorMap->getColorSpace()->getMode()); - drawGeneralImage(state,ref,str,width,height,colorMap,0,inlineImg,0,maskColors); + drawGeneralImage(state,ref,str,width,height,colorMap,0,inlineImg,0,maskColors, 0,0,0,0, 0); +} + +void SWFOutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Stream *maskStr, int maskWidth, int maskHeight, + GBool maskInvert) +{ + if(states[statepos].textRender & 4) //clipped + return; + + msg(" drawMaskedImage %dx%d, %s, %dx%d mask", width, height, + colorMap?"colorMap":"no colorMap", + maskWidth, maskHeight); + if(colorMap) + msg(" colorMap pixcomps:%d bits:%d mode:%d\n", colorMap->getNumPixelComps(), + colorMap->getBits(),colorMap->getColorSpace()->getMode()); + drawGeneralImage(state,ref,str,width,height,colorMap,0,0,0,0, maskStr, maskWidth, maskHeight, maskInvert, 0); +} + +void SWFOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + Stream *maskStr, + int maskWidth, int maskHeight, + GfxImageColorMap *maskColorMap) +{ + if(states[statepos].textRender & 4) //clipped + return; + + msg(" drawSoftMaskedImage %dx%d, %s, %dx%d mask", width, height, + colorMap?"colorMap":"no colorMap", + maskWidth, maskHeight); + if(colorMap) + msg(" colorMap pixcomps:%d bits:%d mode:%d\n", colorMap->getNumPixelComps(), + colorMap->getBits(),colorMap->getColorSpace()->getMode()); + drawGeneralImage(state,ref,str,width,height,colorMap,0,0,0,0, maskStr, maskWidth, maskHeight, 0, maskColorMap); } //SWFOutputDev*output = 0; @@ -2409,9 +2648,9 @@ void pdfswf_setparameter(char*name, char*value) storeDeviceParameter("ppmsubpixels", buf); } else if(!strcmp(name, "forceType0Fonts")) { forceType0Fonts = atoi(value); - } else if(!strcmp(name, "fontdir")) { + } else if(!strncmp(name, "fontdir", strlen("fontdir"))) { pdfswf_addfontdir(value); - } else if(!strcmp(name, "languagedir")) { + } else if(!strncmp(name, "languagedir", strlen("languagedir"))) { pdfswf_addlanguagedir(value); } else if(!strcmp(name, "fontconfig")) { config_use_fontconfig = atoi(value); @@ -2449,7 +2688,7 @@ void pdfswf_addlanguagedir(char*dir) int l; FILE*fi = 0; - char* config_file = (char*)malloc(strlen(dir) + 1 + sizeof("add-to-xpdfrc")); + char* config_file = (char*)malloc(strlen(dir) + 1 + sizeof("add-to-xpdfrc") + 1); strcpy(config_file, dir); strcat(config_file, dirseparator()); strcat(config_file, "add-to-xpdfrc"); @@ -2467,6 +2706,7 @@ void pdfswf_addfontdir(char*dirname) { #ifdef HAVE_DIRENT_H msg(" Adding %s to font directories", dirname); + lastfontdir = strdup(dirname); DIR*dir = opendir(dirname); if(!dir) { msg(" Couldn't open directory %s\n", dirname); @@ -2511,14 +2751,15 @@ typedef struct _pdf_doc_internal { int protect; PDFDoc*doc; + InfoOutputDev*info; } pdf_doc_internal_t; typedef struct _pdf_page_internal { } pdf_page_internal_t; -typedef struct _swf_output_internal +typedef struct _dev_output_internal { SWFOutputDev*outputDev; -} swf_output_internal_t; +} dev_output_internal_t; pdf_doc_t* pdf_init(char*filename, char*userPassword) { @@ -2587,24 +2828,15 @@ pdf_doc_t* pdf_init(char*filename, char*userPassword) if(!i->doc->okToChange() || !i->doc->okToAddNotes()) i->protect = 1; } - - return pdf_doc; -} -void pdfswf_preparepage(int page) -{ - /*FIXME*/ - if(!pages) { - pages = (int*)malloc(1024*sizeof(int)); - pagebuflen = 1024; - } else { - if(pagepos == pagebuflen) - { - pagebuflen+=1024; - pages = (int*)realloc(pages, pagebuflen); - } + InfoOutputDev*io = new InfoOutputDev(); + int t; + for(t=1;t<=pdf_doc->num_pages;t++) { + i->doc->displayPage((OutputDev*)io, t, zoom, zoom, /*rotate*/0, /*usemediabox*/true, /*crop*/true, /*doLinks*/(int)1); } - pages[pagepos++] = page; + i->info = io; + + return pdf_doc; } class MemCheck @@ -2621,10 +2853,11 @@ void pdf_destroy(pdf_doc_t*pdf_doc) { pdf_doc_internal_t*i= (pdf_doc_internal_t*)pdf_doc->internal; - msg(" pdfswf.cc: pdfswf_close()"); delete i->doc; i->doc=0; - free(pages); pages = 0; //FIXME + if(i->info) { + delete i->info;i->info=0; + } free(pdf_doc->internal);pdf_doc->internal=0; free(pdf_doc);pdf_doc=0; @@ -2654,77 +2887,98 @@ void pdf_page_destroy(pdf_page_t*pdf_page) free(pdf_page);pdf_page=0; } -swf_output_t* swf_output_init() +dev_output_t* dev_output_init(gfxdevice_t*dev) { - 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; + dev_output_t*dev_output = (dev_output_t*)malloc(sizeof(dev_output_t)); + memset(dev_output, 0, sizeof(dev_output_t)); + dev_output_internal_t*i= (dev_output_internal_t*)malloc(sizeof(dev_output_internal_t)); + memset(i, 0, sizeof(dev_output_internal_t)); + dev_output->internal = i; - i->outputDev = new SWFOutputDev(); - return swf_output; + i->outputDev = new SWFOutputDev(dev); + return dev_output; } -void swf_output_setparameter(swf_output_t*swf_output, char*name, char*value) +void dev_output_setparameter(dev_output_t*swf, char*name, char*value) { - /* FIXME */ pdfswf_setparameter(name, value); } -void swf_output_pagefeed(swf_output_t*swf) +void dev_output_startframe(dev_output_t*swf, int width, int height) { - 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); + dev_output_internal_t*i= (dev_output_internal_t*)swf->internal; + i->outputDev->startFrame(width, height); } -int swf_output_save(swf_output_t*swf, char*filename) +void dev_output_endframe(dev_output_t*swf) { - 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; + dev_output_internal_t*i= (dev_output_internal_t*)swf->internal; + i->outputDev->endframe(); } -void* swf_output_get(swf_output_t*swf) +void dev_output_finish(dev_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; + dev_output_internal_t*i= (dev_output_internal_t*)swf->internal; + i->outputDev->finish(); +} + +void dev_output_preparepage(dev_output_t*swf, int pdfpage, int outputpage) +{ + dev_output_internal_t*i= (dev_output_internal_t*)swf->internal; + SWFOutputDev*o = i->outputDev; + + if(pdfpage < 0) + return; + + if(!o->pages) { + o->pagebuflen = 1024; + o->pages = (int*)malloc(o->pagebuflen*sizeof(int)); + memset(o->pages, -1, o->pagebuflen*sizeof(int)); + } else { + while(pdfpage >= o->pagebuflen) + { + int oldlen = o->pagebuflen; + o->pagebuflen+=1024; + o->pages = (int*)realloc(o->pages, o->pagebuflen*sizeof(int)); + memset(&o->pages[oldlen], -1, (o->pagebuflen-oldlen)*sizeof(int)); + } + } + o->pages[pdfpage] = outputpage; + if(pdfpage>o->pagepos) + o->pagepos = pdfpage; } -void swf_output_destroy(swf_output_t*output) +void dev_output_destroy(dev_output_t*output) { - swf_output_internal_t*i = (swf_output_internal_t*)output->internal; + dev_output_internal_t*i = (dev_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) +void pdf_page_render2(pdf_page_t*page, dev_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; + dev_output_internal_t*si = (dev_output_internal_t*)swf->internal; + + if(!pi) { + msg(" pdf_page_render: Parent PDF this page belongs to doesn't exist yet/anymore"); + return; + } if(pi->protect) { gfxdevice_t*dev = si->outputDev->output; dev->setparameter(dev, "protect", "1"); } + si->outputDev->setInfo(pi->info); si->outputDev->setXRef(pi->doc, pi->doc->getXRef()); -#ifdef XPDF_101 - pi->doc->displayPage((OutputDev*)si->outputDev, page->nr, /*zoom*/zoom, /*rotate*/0, /*doLinks*/(int)1); -#else - 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); + pi->doc->displayPage((OutputDev*)si->outputDev, page->nr, zoom, zoom, /*rotate*/0, true, true, /*doLinks*/(int)1); } -void pdf_page_rendersection(pdf_page_t*page, swf_output_t*output, int x, int y, int x1, int y1, int x2, int y2) +void pdf_page_rendersection(pdf_page_t*page, dev_output_t*output, int x, int y, int x1, int y1, int x2, int y2) { pdf_doc_internal_t*pi = (pdf_doc_internal_t*)page->parent->internal; - swf_output_internal_t*si = (swf_output_internal_t*)output->internal; + dev_output_internal_t*si = (dev_output_internal_t*)output->internal; si->outputDev->setMove(x,y); if((x1|y1|x2|y2)==0) x2++; @@ -2732,10 +2986,10 @@ void pdf_page_rendersection(pdf_page_t*page, swf_output_t*output, int x, int y, pdf_page_render2(page, output); } -void pdf_page_render(pdf_page_t*page, swf_output_t*output) +void pdf_page_render(pdf_page_t*page, dev_output_t*output) { pdf_doc_internal_t*pi = (pdf_doc_internal_t*)page->parent->internal; - swf_output_internal_t*si = (swf_output_internal_t*)output->internal; + dev_output_internal_t*si = (dev_output_internal_t*)output->internal; si->outputDev->setMove(0,0); si->outputDev->setClip(0,0,0,0); @@ -2753,11 +3007,7 @@ pdf_page_info_t* pdf_page_getinfo(pdf_page_t*page) 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 + pi->doc->displayPage((OutputDev*)output, page->nr, zoom, zoom, /*rotate*/0, true, true, /*doLinks*/(int)1); info->xMin = output->x1; info->yMin = output->y1; @@ -2775,4 +3025,5 @@ pdf_page_info_t* pdf_page_getinfo(pdf_page_t*page) void pdf_page_info_destroy(pdf_page_info_t*info) { free(info); + }