ignore overlarge bitmaps
[swftools.git] / lib / pdf / BitmapOutputDev.cc
index 9e8123b..d54c8ea 100644 (file)
@@ -29,6 +29,7 @@
 #include "../log.h"
 #include "../png.h"
 #include "../devices/record.h"
+#include "../gfxtools.h"
 #include "../types.h"
 #include "bbox.h"
 
@@ -80,6 +81,7 @@ BitmapOutputDev::BitmapOutputDev(InfoOutputDev*info, PDFDoc*doc)
     this->gfxdev->setDevice(this->gfxoutput);
     
     this->config_extrafontdata = 0;
+    this->config_optimizeplaincolorfills = 0;
     this->bboxpath = 0;
     //this->clipdev = 0;
     //this->clipstates = 0;
@@ -311,7 +313,16 @@ void BitmapOutputDev::flushBitmap()
 void BitmapOutputDev::flushText()
 {
     msg("<verbose> Flushing text");
-    gfxdevice_record_flush(this->gfxoutput, this->dev);
+
+    static gfxfontlist_t*output_font_list = 0;
+    static gfxdevice_t*last = 0;
+    if(last != this->dev) {
+       if(output_font_list)
+           gfxfontlist_free(output_font_list, 0);
+       output_font_list = gfxfontlist_create();
+    }
+    gfxdevice_record_flush(this->gfxoutput, this->dev, &output_font_list);
+    last = this->dev;
     
     this->emptypage = 0;
 }
@@ -903,13 +914,7 @@ void BitmapOutputDev::finishPage()
     msg("<verbose> finishPage (BitmapOutputDev)");
     gfxdev->endPage();
    
-    if(layerstate == STATE_BITMAP_IS_ABOVE) {
-       this->flushText();
-       this->flushBitmap();
-    } else {
-       this->flushBitmap();
-       this->flushText();
-    }
+    flushEverything();
 
     /* splash will now destroy alpha, and paint the 
        background color into the "holes" in the bitmap */
@@ -1335,11 +1340,47 @@ void BitmapOutputDev::stroke(GfxState *state)
     rgbdev->stroke(state);
     dbg_newdata("stroke");
 }
+
+extern gfxcolor_t getFillColor(GfxState * state);
+
+char area_is_plain_colored(GfxState*state, SplashBitmap*boolpoly, SplashBitmap*rgbbitmap, int x1, int y1, int x2, int y2)
+{
+    int width = boolpoly->getWidth();
+    int height = boolpoly->getHeight();
+    if(!fixBBox(&x1, &y1, &x2, &y2, width, height)) {
+       return 0;
+    }
+    gfxcolor_t color = getFillColor(state);
+    SplashColorPtr rgb = rgbbitmap->getDataPtr() 
+                      + (y1*width+x1)*sizeof(SplashColor);
+    int width8 = (width+7)/8;
+    unsigned char*bits = (unsigned char*)boolpoly->getDataPtr() 
+                        + (y1*width8+x1);
+    int x,y;
+    int w = x2-x1;
+    int h = y2-y1;
+    for(y=0;y<h;y++) {
+       for(x=0;x<w;x++) {
+           if(rgb[x*3+0] != color.r ||
+              rgb[x*3+1] != color.g ||
+              rgb[x*3+2] != color.b)
+               return 0;
+       }
+       rgb += width*sizeof(SplashColor);
+    }
+    return 1;
+}
+
 void BitmapOutputDev::fill(GfxState *state)
 {
     msg("<debug> fill");
     boolpolydev->fill(state);
     gfxbbox_t bbox = getBBox(state);
+    if(config_optimizeplaincolorfills) {
+       if(area_is_plain_colored(state, boolpolybitmap, rgbbitmap, bbox.xmin, bbox.ymin, bbox.xmax, bbox.ymax)) {
+           return;
+       }
+    }
     checkNewBitmap(bbox.xmin, bbox.ymin, ceil(bbox.xmax), ceil(bbox.ymax));
     rgbdev->fill(state);
     dbg_newdata("fill");
@@ -1658,11 +1699,20 @@ gfxbbox_t BitmapOutputDev::getImageBBox(GfxState*state)
     bbox.ymax=max(bbox.ymax,y);
     return bbox;
 }
+
+GBool invalid_size(int width, int height)
+{
+    if((U64)width*(U64)height > 0x7fffffffll)
+       return 1;
+    return 0;
+}
+
 void BitmapOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
                           int width, int height, GBool invert,
                           GBool inlineImg)
 {
     msg("<debug> drawImageMask streamkind=%d", str->getKind());
+    if(invalid_size(width,height)) return;
 
     CopyStream*cpystr = new CopyStream(str, height * ((width + 7) / 8));
     str = cpystr->getStream();
@@ -1679,6 +1729,7 @@ void BitmapOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
                       int *maskColors, GBool inlineImg)
 {
     msg("<debug> drawImage streamkind=%d", str->getKind());
+    if(invalid_size(width,height)) return;
        
     CopyStream*cpystr = new CopyStream(str, height * ((width * colorMap->getNumPixelComps() * colorMap->getBits() + 7) / 8));
     str = cpystr->getStream();
@@ -1697,6 +1748,7 @@ void BitmapOutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str,
                             GBool maskInvert)
 {
     msg("<debug> drawMaskedImage streamkind=%d", str->getKind());
+    if(invalid_size(width,height)) return;
     
     CopyStream*cpystr = new CopyStream(str, height * ((width * colorMap->getNumPixelComps() * colorMap->getBits() + 7) / 8));
     str = cpystr->getStream();
@@ -1716,6 +1768,7 @@ void BitmapOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *
                                 GfxImageColorMap *maskColorMap)
 {
     msg("<debug> drawSoftMaskedImage %dx%d (%dx%d) streamkind=%d", width, height, maskWidth, maskHeight, str->getKind());
+    if(invalid_size(width,height)) return;
 
     CopyStream*cpystr = new CopyStream(str, height * ((width * colorMap->getNumPixelComps() * colorMap->getBits() + 7) / 8));
     str = cpystr->getStream();
@@ -1738,8 +1791,19 @@ void BitmapOutputDev::drawForm(Ref id)
 void BitmapOutputDev::processLink(Link *link, Catalog *catalog)
 {
     msg("<debug> processLink");
+    flushEverything();
     gfxdev->processLink(link, catalog);
 }
+void BitmapOutputDev::flushEverything()
+{
+    if(layerstate == STATE_BITMAP_IS_ABOVE) {
+       this->flushText();
+       this->flushBitmap();
+    } else {
+       this->flushBitmap();
+       this->flushText();
+    }
+}
 
 void BitmapOutputDev::beginTransparencyGroup(GfxState *state, double *bbox,
                                    GfxColorSpace *blendingColorSpace,