added two pass support and device filters to gfx library
[swftools.git] / lib / pdf / BitmapOutputDev.cc
index 2889e5e..1a735e3 100644 (file)
@@ -30,6 +30,7 @@
 #include "../png.h"
 #include "../devices/record.h"
 #include "../types.h"
+#include "bbox.h"
 
 #define UNKNOWN_BOUNDING_BOX 0,0,0,0
 
@@ -74,7 +75,7 @@ BitmapOutputDev::BitmapOutputDev(InfoOutputDev*info, PDFDoc*doc)
     this->clip1dev->startDoc(this->xref);
 
     this->gfxoutput = (gfxdevice_t*)malloc(sizeof(gfxdevice_t));
-    gfxdevice_record_init(this->gfxoutput);
+    gfxdevice_record_init(this->gfxoutput, 0);
 
     this->gfxdev->setDevice(this->gfxoutput);
     
@@ -158,63 +159,7 @@ void BitmapOutputDev::setPageMap(int*page2page, int num_pages)
     this->gfxdev->setPageMap(page2page, num_pages);
 }
 
-typedef struct _ibbox {
-    int xmin,ymin,xmax,ymax;
-    struct _ibbox*next;
-} ibbox_t;
-
-static ibbox_t* ibbox_new(int x1, int y1, int x2, int y2)
-{
-    ibbox_t*b = (ibbox_t*)rfx_calloc(sizeof(ibbox_t)); 
-    b->xmin = x1;
-    b->ymin = y1;
-    b->xmax = x2;
-    b->ymax = y2;
-    return b;
-}
-
-static void ibbox_destroy(ibbox_t*b)
-{
-    while(b) {
-       ibbox_t*next = b->next;
-       free(b);
-       b = next;
-    }
-}
-
-static ibbox_t*getBitmapBBoxes(Guchar*alpha, int width, int height)
-{
-    int ymin = -1;
-    int ymax = -1;
-    int xmin = width;
-    int xmax = 0;
-
-    int x,y;
-    for(y=0;y<height;y++) {
-       Guchar*a = &alpha[y*width];
-       for(x=0;x<width;x++) {
-           if(a[x]) break;
-       }
-       int left = x; //first occupied pixel from left
-       int right = x+1; //last non-occupied pixel from right
-       for(;x<width;x++) {
-           if(a[x]) right=x+1;
-       }
-
-       if(left!=width) {
-           if(ymin<0) 
-               ymin=y;
-           ymax=y+1;
-           if(left<xmin) xmin = left;
-           if(right>xmax) xmax = right;
-       }
-    }
-    ibbox_t* bbox = 0;
-    if(xmin<xmax || ymin<ymax) {
-       bbox = ibbox_new(xmin, ymin, xmax, ymax);
-    }
-    return bbox;
-}
+void writeBitmap(SplashBitmap*bitmap, char*filename);
 
 void BitmapOutputDev::flushBitmap()
 {
@@ -225,15 +170,23 @@ void BitmapOutputDev::flushBitmap()
        msg("<error> sizeof(SplashColor)!=3");
        return;
     }
+
+    /*static int counter=0;
+    if(!counter) {
+       writeBitmap(rgbdev->getBitmap(), "test.png");
+    } counter++;*/
     
     SplashColorPtr rgb = rgbbitmap->getDataPtr();
     Guchar*alpha = rgbbitmap->getAlphaPtr();
-    Guchar*alpha2 = boolpolybitmap->getAlphaPtr();
+    
+    Guchar*alpha2 = boolpolybitmap->getDataPtr();
+    int width8 = (boolpolybitmap->getWidth()+7)/8;
 
-    ibbox_t* boxes = getBitmapBBoxes(alpha, width, height);
+    ibbox_t* boxes = get_bitmap_bboxes((unsigned char*)alpha, width, height);
     ibbox_t*b;
 
-    for(b=boxes;boxes;boxes=boxes->next) {
+
+    for(b=boxes;b;b=b->next) {
        int xmin = b->xmin;
        int ymin = b->ymin;
        int xmax = b->xmax;
@@ -261,7 +214,7 @@ void BitmapOutputDev::flushBitmap()
            SplashColorPtr in=&rgb[((y+ymin)*width+xmin)*sizeof(SplashColor)];
            gfxcolor_t*out = &img->data[y*rangex];
            Guchar*ain = &alpha[(y+ymin)*width+xmin];
-           Guchar*ain2 = &alpha2[(y+ymin)*width+xmin];
+           Guchar*ain2 = &alpha2[(y+ymin)*width8];
            if(this->emptypage) {
                for(x=0;x<rangex;x++) {
                    /* the first bitmap on the page doesn't need to have an alpha channel-
@@ -273,18 +226,20 @@ void BitmapOutputDev::flushBitmap()
                }
            } else {
                for(x=0;x<rangex;x++) {
-                   /*
-                   if(!ain2[x]) {
+                   if(!(ain2[(x+xmin)/8]&(0x80>>((x+xmin)&7)))) {
+                       /* cut away pixels that we don't remember drawing (i.e., that are
+                          not in the monochrome bitmap). Prevents some "hairlines" showing
+                          up to the left and right of bitmaps. */
                        out[x].r = 0;out[x].g = 0;out[x].b = 0;out[x].a = 0;
-                   } else */
-
-                   /* according to endPage()/compositeBackground() in xpdf/SplashOutputDev.cc, we
-                      have to premultiply alpha (mix background and pixel according to the alpha channel).
-                   */
-                   out[x].r = (in[x*3+0]*ain[x])/255;
-                   out[x].g = (in[x*3+1]*ain[x])/255;
-                   out[x].b = (in[x*3+2]*ain[x])/255;
-                   out[x].a = ain[x];
+                   } else {
+                       /* according to endPage()/compositeBackground() in xpdf/SplashOutputDev.cc, we
+                          have to premultiply alpha (mix background and pixel according to the alpha channel).
+                       */
+                       out[x].r = (in[x*3+0]*ain[x])/255;
+                       out[x].g = (in[x*3+1]*ain[x])/255;
+                       out[x].b = (in[x*3+2]*ain[x])/255;
+                       out[x].a = ain[x];
+                   }
                }
            }
        }