swf_output_startframe() and swf_output_endframe() now replace swf_output_pagefeed()
[swftools.git] / pdf2swf / SWFOutputDev.cc
index e246867..4ee30d7 100644 (file)
@@ -144,7 +144,6 @@ typedef struct _fontlist
 } fontlist_t;
 
 class SWFOutputDev:  public OutputDev {
-  int outputstarted;
 public:
   gfxdevice_t* output;
 
@@ -158,7 +157,13 @@ public:
   void setClip(int x1,int y1,int x2,int y2);
   
   int save(char*filename);
-  void  pagefeed();
+    
+  // Start a page.
+  void startFrame(int width, int height);
+
+  virtual void startPage(int pageNum, GfxState *state, double x1, double y1, double x2, double y2) ;
+
+  void endframe();
   void* getSWF();
 
   void getDimensions(int*x1,int*y1,int*x2,int*y2);
@@ -181,9 +186,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) ;
 
@@ -253,7 +255,9 @@ public:
 
   void finish();
 
-  SWF*swf; //filled upon completion
+  gfxresult_t*result; //filled when complete
+
+  char outer_clip_box; //whether the page clip box is still on
 
   SWFOutputState states[64];
   int statepos;
@@ -365,7 +369,6 @@ SWFOutputDev::SWFOutputDev()
     pbminfo = 0;
     type3active = 0;
     statepos = 0;
-    outputstarted = 0;
     xref = 0;
     substitutepos = 0;
     type3Warning = 0;
@@ -378,9 +381,16 @@ SWFOutputDev::SWFOutputDev()
     current_text_stroke = 0;
     current_text_clip = 0;
     fontlist = 0;
-    swf = 0;
+    result = 0;
+    outer_clip_box = 0;
     output = (gfxdevice_t*)malloc(sizeof(gfxdevice_t));
-    memset(output, 0, sizeof(output));
+    gfxdevice_swf_init(output);
+    /* 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)
@@ -399,9 +409,17 @@ void SWFOutputDev::setClip(int x1,int y1,int x2,int y2)
     this->user_clipx2 = x2;
     this->user_clipy2 = y2;
 }
+
 void SWFOutputDev::getDimensions(int*x1,int*y1,int*x2,int*y2)
 {
-    return gfxdevice_swf_getdimensions(output, x1,y1,x2,y2);
+    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");
+    } else {
+       *x1 = *y1 = *x2 = *y2 = 0;
+    }
 }
 
 static char*getFontID(GfxFont*font)
@@ -648,7 +666,7 @@ void dump_outline(gfxline_t*line)
     }
 }
 
-gfxline_t* gfxPath_to_gfxline(GfxState*state, GfxPath*path, int closed)
+gfxline_t* gfxPath_to_gfxline(GfxState*state, GfxPath*path, int closed, int user_movex, int user_movey)
 {
     int num = path->getNumSubpaths();
     int s,t;
@@ -669,7 +687,11 @@ gfxline_t* gfxPath_to_gfxline(GfxState*state, GfxPath*path, int closed)
 
        for(s=0;s<subnum;s++) {
           double x,y;
+          
           state->transform(subpath->getX(s),subpath->getY(s),&x,&y);
+          x += user_movex;
+          y += user_movey;
+
           if(s==0) {
                if(closed && needsfix && (fabs(posx-lastx)+fabs(posy-lasty))>0.001) {
                    draw.lineTo(&draw, lastx, lasty);
@@ -715,7 +737,7 @@ gfxline_t* gfxPath_to_gfxline(GfxState*state, GfxPath*path, int closed)
 void SWFOutputDev::stroke(GfxState *state) 
 {
     GfxPath * path = state->getPath();
-    gfxline_t*line= gfxPath_to_gfxline(state, path, 0);
+    gfxline_t*line= gfxPath_to_gfxline(state, path, 0, user_movex, user_movey);
     strokeGfxline(state, line);
     gfxline_free(line);
 }
@@ -774,6 +796,7 @@ void SWFOutputDev::strokeGfxline(GfxState *state, gfxline_t*line)
 
        line2 = gfxtool_dash_line(line, dash, dashphase);
        line = line2;
+       free(dash);
        msg("<trace> After dashing:");
     }
     
@@ -824,7 +847,7 @@ void SWFOutputDev::fillGfxLine(GfxState *state, gfxline_t*line)
 void SWFOutputDev::fill(GfxState *state) 
 {
     GfxPath * path = state->getPath();
-    gfxline_t*line= gfxPath_to_gfxline(state, path, 1);
+    gfxline_t*line= gfxPath_to_gfxline(state, path, 1, user_movex, user_movey);
     fillGfxLine(state, line);
     gfxline_free(line);
 }
@@ -833,7 +856,7 @@ void SWFOutputDev::eoFill(GfxState *state)
     GfxPath * path = state->getPath();
     gfxcolor_t col = getFillColor(state);
 
-    gfxline_t*line= gfxPath_to_gfxline(state, path, 1);
+    gfxline_t*line= gfxPath_to_gfxline(state, path, 1, user_movex, user_movey);
 
     if(getLogLevel() >= LOGLEVEL_TRACE)  {
         msg("<trace> eofill\n");
@@ -847,7 +870,7 @@ void SWFOutputDev::eoFill(GfxState *state)
 void SWFOutputDev::clip(GfxState *state) 
 {
     GfxPath * path = state->getPath();
-    gfxline_t*line = gfxPath_to_gfxline(state, path, 1);
+    gfxline_t*line = gfxPath_to_gfxline(state, path, 1, user_movex, user_movey);
     clipToGfxLine(state, line);
     gfxline_free(line);
 }
@@ -865,7 +888,7 @@ void SWFOutputDev::clipToGfxLine(GfxState *state, gfxline_t*line)
 void SWFOutputDev::eoClip(GfxState *state) 
 {
     GfxPath * path = state->getPath();
-    gfxline_t*line = gfxPath_to_gfxline(state, path, 1);
+    gfxline_t*line = gfxPath_to_gfxline(state, path, 1, user_movex, user_movey);
 
     if(getLogLevel() >= LOGLEVEL_TRACE)  {
         msg("<trace> eoclip\n");
@@ -877,37 +900,48 @@ void SWFOutputDev::eoClip(GfxState *state)
     gfxline_free(line);
 }
 
-/* pass through functions for swf_output */
-int SWFOutputDev::save(char*filename)
-{
-    return gfxdevice_swf_save(output, filename);
-}
-void SWFOutputDev::pagefeed()
+void SWFOutputDev::endframe()
 {
-    swfoutput_pagefeed(output);
-}
-void* SWFOutputDev::getSWF()
-{
-    return (void*)gfxdevice_swf_get(output);
+    if(outer_clip_box) {
+       output->endclip(output);
+       outer_clip_box = 0;
+    }
+
+    output->endpage(output);
 }
 
 void SWFOutputDev::finish()
 {
+    if(outer_clip_box) {
+       if(output) {
+           output->endclip(output);
+       }
+       outer_clip_box = 0;
+    }
     if(output) {
-       this->swf = (SWF*)output->finish(output);
+       this->result = output->finish(output);
        free(output);output=0;
     }
 }
 
+int SWFOutputDev::save(char*filename)
+{
+    finish();
+    return result->save(result, filename);
+}
+void* SWFOutputDev::getSWF()
+{
+    finish();
+    return result->get(result, "swf");
+}
+
 SWFOutputDev::~SWFOutputDev() 
 {
     finish();
-    outputstarted = 0;
 
-    if(this->swf) {
-       swf_FreeTags(this->swf);
-       free(this->swf);
-       this->swf = 0;
+    if(this->result) {
+       this->result->destroy(this->result);
+       this->result = 0;
     }
 
     fontlist_t*l = this->fontlist;
@@ -920,10 +954,10 @@ SWFOutputDev::~SWFOutputDev()
        free(l);
        l = next;
     }
+    this->fontlist = 0;
 };
 GBool SWFOutputDev::upsideDown() 
 {
-    msg("<debug> upsidedown? yes");
     return gTrue;
 };
 GBool SWFOutputDev::useDrawChar() 
@@ -1110,6 +1144,8 @@ void SWFOutputDev::drawChar(GfxState *state, double x, double y,
 
     gfxmatrix_t m = this->current_font_matrix;
     state->transform(x, y, &m.tx, &m.ty);
+    m.tx += user_movex;
+    m.ty += user_movey;
 
     if(render == RENDER_FILL) {
        output->drawchar(output, current_font_id, charid, &col, &m);
@@ -1206,15 +1242,21 @@ void SWFOutputDev::endType3Char(GfxState *state)
     msg("<debug> 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;
     double x1,y1,x2,y2;
     int rot = doc->getPageRotate(1);
+    gfxcolor_t white;
     laststate = state;
-    msg("<verbose> startPage %d (%f,%f,%f,%f)\n", pageNum, crop_x1, crop_y1, crop_x2, crop_y2);
-    if(rot!=0)
-        msg("<verbose> page is rotated %d degrees\n", rot);
+    gfxline_t clippath[5];
+
+    white.r = white.g = white.b = white.a = 255;
 
     /* state->transform(state->getX1(),state->getY1(),&x1,&y1);
     state->transform(state->getX2(),state->getY2(),&x2,&y2);
@@ -1225,12 +1267,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) {double x3=x1;x1=x2;x2=x3;}
     if(y2<y1) {double y3=y1;y1=y2;y2=y3;}
 
+
     /* apply user clip box */
     if(user_clipx1|user_clipy1|user_clipx2|user_clipy2) {
         /*if(user_clipx1 > x1)*/ x1 = user_clipx1;
@@ -1239,22 +1282,24 @@ void SWFOutputDev::startPage(int pageNum, GfxState *state, double crop_x1, doubl
         /*if(user_clipy2 < y2)*/ y2 = user_clipy2;
     }
 
-    if(!outputstarted) {
-        msg("<verbose> 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("<verbose> 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;
     }
-      
-    swfoutput_newpage(output, pageNum, user_movex, user_movey, (int)x1, (int)y1, (int)x2, (int)y2);
+
+    msg("<notice> 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("<verbose> 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];
+    clippath[2].type = gfx_lineTo;clippath[2].x = x2; clippath[2].y = y2; clippath[2].next = &clippath[3];
+    clippath[3].type = gfx_lineTo;clippath[3].x = x1; clippath[3].y = y2; clippath[3].next = &clippath[4];
+    clippath[4].type = gfx_lineTo;clippath[4].x = x1; clippath[4].y = y1; clippath[4].next = 0;
+    output->startclip(output, clippath); outer_clip_box = 1;
+    output->fill(output, clippath, &white);
 }
 
 void SWFOutputDev::drawLink(Link *link, Catalog *catalog) 
@@ -1275,28 +1320,28 @@ void SWFOutputDev::drawLink(Link *link, Catalog *catalog)
     rgb.b = 1;
     cvtUserToDev(x1, y1, &x, &y);
     points[0].type = gfx_moveTo;
-    points[0].x = points[4].x = (int)x;
-    points[0].y = points[4].y = (int)y;
+    points[0].x = points[4].x = x + user_movex;
+    points[0].y = points[4].y = y + user_movey;
     points[0].next = &points[1];
     cvtUserToDev(x2, y1, &x, &y);
     points[1].type = gfx_lineTo;
-    points[1].x = (int)x;
-    points[1].y = (int)y;
+    points[1].x = x + user_movex;
+    points[1].y = y + user_movey;
     points[1].next = &points[2];
     cvtUserToDev(x2, y2, &x, &y);
     points[2].type = gfx_lineTo;
-    points[2].x = (int)x;
-    points[2].y = (int)y;
+    points[2].x = x + user_movex;
+    points[2].y = y + user_movey;
     points[2].next = &points[3];
     cvtUserToDev(x1, y2, &x, &y);
     points[3].type = gfx_lineTo;
-    points[3].x = (int)x;
-    points[3].y = (int)y;
+    points[3].x = x + user_movex;
+    points[3].y = y + user_movey;
     points[3].next = &points[4];
     cvtUserToDev(x1, y1, &x, &y);
     points[4].type = gfx_lineTo;
-    points[4].x = (int)x;
-    points[4].y = (int)y;
+    points[4].x = x + user_movex;
+    points[4].y = y + user_movey;
     points[4].next = 0;
 
     LinkAction*action=link->getAction();
@@ -1903,6 +1948,7 @@ void SWFOutputDev::updateFont(GfxState *state)
       char * fontname = getFontName(gfxFont);
       fileName = searchFont(fontname);
       if(!fileName) showFontError(gfxFont,0);
+      free(fontname);
     }
     if(!fileName) {
        char * fontname = getFontName(gfxFont);
@@ -2086,10 +2132,10 @@ void SWFOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str,
       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);
+  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) {
@@ -2544,7 +2590,7 @@ pdf_doc_t* pdf_init(char*filename, char*userPassword)
     return pdf_doc;
 }
 
-void pdfswf_preparepage(int page)
+static void pdfswf_preparepage(int page)
 {
     /*FIXME*/
     if(!pages) {
@@ -2574,7 +2620,6 @@ void pdf_destroy(pdf_doc_t*pdf_doc)
 {
     pdf_doc_internal_t*i= (pdf_doc_internal_t*)pdf_doc->internal;
 
-    msg("<debug> pdfswf.cc: pdfswf_close()");
     delete i->doc; i->doc=0;
     
     free(pages); pages = 0; //FIXME
@@ -2619,16 +2664,22 @@ swf_output_t* swf_output_init()
     return swf_output;
 }
 
-void swf_output_setparameter(swf_output_t*swf_output, char*name, char*value)
+void swf_output_setparameter(swf_output_t*swf, char*name, char*value)
 {
-    /* FIXME */
     pdfswf_setparameter(name, value);
 }
 
-void swf_output_pagefeed(swf_output_t*swf)
+void swf_output_startframe(swf_output_t*swf, int width, int height)
+{
+    swf_output_internal_t*i= (swf_output_internal_t*)swf->internal;
+    i->outputDev->startFrame(width, height);
+    i->outputDev->getDimensions(&swf->x1, &swf->y1, &swf->x2, &swf->y2);
+}
+
+void swf_output_endframe(swf_output_t*swf)
 {
     swf_output_internal_t*i= (swf_output_internal_t*)swf->internal;
-    i->outputDev->pagefeed();
+    i->outputDev->endframe();
     i->outputDev->getDimensions(&swf->x1, &swf->y1, &swf->x2, &swf->y2);
 }