fixed a soft mask bug
[swftools.git] / lib / pdf / GFXOutputDev.cc
index 4a1c310..1e5036a 100644 (file)
@@ -106,7 +106,7 @@ struct mapping {
 {"Symbol",                "s050000l"},
 {"ZapfDingbats",          "d050000l"}};
 
-static int verbose = 0;
+static int verbose = 1;
 static int dbgindent = 0;
 static void dbg(char*format, ...)
 {
@@ -141,7 +141,7 @@ typedef struct _feature
 } feature_t;
 feature_t*featurewarnings = 0;
 
-static void showfeature(char*feature,char fully, char warn)
+void GFXOutputDev::showfeature(char*feature,char fully, char warn)
 {
     feature_t*f = featurewarnings;
     while(f) {
@@ -155,15 +155,19 @@ static void showfeature(char*feature,char fully, char warn)
     featurewarnings = f;
     if(warn) {
        msg("<warning> %s not yet %ssupported!",feature,fully?"fully ":"");
+       if(this->config_break_on_warning) {
+           msg("<fatal> Aborting conversion due to unsupported feature");
+           exit(1);
+       }
     } else {
-       msg("<info> File contains %s",feature);
+       msg("<notice> File contains %s",feature);
     }
 }
-static void warnfeature(char*feature,char fully)
+void GFXOutputDev::warnfeature(char*feature,char fully)
 {
     showfeature(feature,fully,1);
 }
-static void infofeature(char*feature)
+void GFXOutputDev::infofeature(char*feature)
 {
     showfeature(feature,0,0);
 }
@@ -175,6 +179,7 @@ GFXOutputState::GFXOutputState() {
     this->transparencygroup = 0;
     this->softmask = 0;
     this->grouprecording = 0;
+    this->isolated = 0;
 }
 
 GBool GFXOutputDev::interpretType3Chars() 
@@ -255,18 +260,19 @@ GFXOutputDev::GFXOutputDev(parameter_t*p)
     this->pages = 0;
     this->pagebuflen = 0;
     this->pagepos = 0;
-  
-    this->forceType0Fonts=1;
     this->config_use_fontconfig=1;
+    this->config_break_on_warning=0;
 
     this->parameters = p;
+  
+    memset(states, 0, sizeof(states));
 
     /* configure device */
     while(p) {
-       if(!strcmp(p->name,"forceType0Fonts")) {
-           this->forceType0Fonts = atoi(p->value);
-       } else if(!strcmp(p->name,"fontconfig")) {
+       if(!strcmp(p->name,"fontconfig")) {
            this->config_use_fontconfig = atoi(p->value);
+       } else if(!strcmp(p->name,"breakonwarning")) {
+           this->config_break_on_warning = atoi(p->value);
        }
        p = p->next;
     }
@@ -276,7 +282,7 @@ void GFXOutputDev::setDevice(gfxdevice_t*dev)
 {
     parameter_t*p = this->parameters;
 
-    /* TODO: get rid of this */
+    /* pass parameters to output device */
     this->device = dev;
     if(this->device) {
        while(p) {
@@ -628,13 +634,13 @@ gfxline_t* gfxPath_to_gfxline(GfxState*state, GfxPath*path, int closed, int user
 
 GBool GFXOutputDev::useTilingPatternFill()
 {
-    warnfeature("tiled patterns", 1);
+    infofeature("tiled patterns");
     return gFalse;
 }
 
 GBool GFXOutputDev::useShadedFills()
 {
-    warnfeature("shaded fills", 1);
+    infofeature("shaded fills");
     return gFalse;
 }
 
@@ -1197,7 +1203,8 @@ void GFXOutputDev::startPage(int pageNum, GfxState *state, double crop_x1, doubl
     device->fill(device, clippath, &white);
 }
 
-void GFXOutputDev::processLink(Link *link, Catalog *catalog) 
+
+void GFXOutputDev::processLink(Link *link, Catalog *catalog)
 {
     double x1, y1, x2, y2, w;
     gfxline_t points[5];
@@ -1555,7 +1562,7 @@ char*GFXOutputDev::writeEmbeddedFontToFile(XRef*ref, GfxFont*font)
       }
       FoFiType1C *cvt = FoFiType1C::make(fontBuf, fontLen);
       if(!cvt) return 0;
-      cvt->convertToType1(NULL, gTrue, FoFiWrite, f);
+      cvt->convertToType1(0, NULL, gTrue, FoFiWrite, f);
       //cvt->convertToCIDType0("test", f);
       //cvt->convertToType0("test", f);
       delete cvt;
@@ -1900,7 +1907,7 @@ void GFXOutputDev::updateFont(GfxState *state)
     if(embedded &&
        (gfxFont->getType() == fontType1 ||
        gfxFont->getType() == fontType1C ||
-       (gfxFont->getType() == fontCIDType0C && forceType0Fonts) ||
+        gfxFont->getType() == fontCIDType0C ||
        gfxFont->getType() == fontTrueType ||
        gfxFont->getType() == fontCIDType2
        ))
@@ -2393,7 +2400,8 @@ void GFXOutputDev::stroke(GfxState *state)
 
 void GFXOutputDev::fill(GfxState *state) 
 {
-    dbg("fill");
+    gfxcolor_t col = getFillColor(state);
+    dbg("fill %02x%02x%02x%02x",col.r,col.g,col.b,col.a);
 
     GfxPath * path = state->getPath();
     gfxline_t*line= gfxPath_to_gfxline(state, path, 1, user_movex + clipmovex, user_movey + clipmovey);
@@ -2403,19 +2411,12 @@ void GFXOutputDev::fill(GfxState *state)
 
 void GFXOutputDev::eoFill(GfxState *state) 
 {
-    dbg("eofill");
-
-    GfxPath * path = state->getPath();
     gfxcolor_t col = getFillColor(state);
+    dbg("eofill %02x%02x%02x%02x",col.r,col.g,col.b,col.a);
 
+    GfxPath * path = state->getPath();
     gfxline_t*line= gfxPath_to_gfxline(state, path, 1, user_movex + clipmovex, user_movey + clipmovey);
-
-    if(getLogLevel() >= LOGLEVEL_TRACE)  {
-        msg("<trace> eofill\n");
-        dump_outline(line);
-    }
-
-    device->fill(device, line, &col);
+    fillGfxLine(state, line);
     gfxline_free(line);
 }
 
@@ -2612,7 +2613,6 @@ BBox mkBBox(GfxState*state, double*bbox, double width, double height)
     return nbbox;
 }
 
-#if xpdfUpdateVersion >= 16
 void GFXOutputDev::beginTransparencyGroup(GfxState *state, double *bbox,
                                      GfxColorSpace *blendingColorSpace,
                                      GBool isolated, GBool knockout,
@@ -2627,10 +2627,12 @@ void GFXOutputDev::beginTransparencyGroup(GfxState *state, double *bbox,
     dbg("beginTransparencyGroup %.1f/%.1f/%.1f/%.1f %s isolated=%d knockout=%d forsoftmask=%d", bbox[0],bbox[1],bbox[2],bbox[3], colormodename, isolated, knockout, forSoftMask);
     dbg("using clipping rect %f/%f/%f/%f\n", rect.posx,rect.posy,rect.width,rect.height);
     msg("<verbose> beginTransparencyGroup %.1f/%.1f/%.1f/%.1f %s isolated=%d knockout=%d forsoftmask=%d", bbox[0],bbox[1],bbox[2],bbox[3], colormodename, isolated, knockout, forSoftMask);
+    
     states[statepos].createsoftmask |= forSoftMask;
     states[statepos].transparencygroup = !forSoftMask;
-    states[statepos].olddevice = this->device;
+    states[statepos].isolated = isolated;
 
+    states[statepos].olddevice = this->device;
     this->device = (gfxdevice_t*)rfx_calloc(sizeof(gfxdevice_t));
 
     gfxdevice_record_init(this->device);
@@ -2676,7 +2678,7 @@ void GFXOutputDev::paintTransparencyGroup(GfxState *state, double *bbox)
     else {
        char buffer[80];
        sprintf(buffer, "%s blended transparency groups", blendmodes[state->getBlendMode()]);
-       warnfeature("transparency groups", 0);
+       warnfeature(buffer, 0);
     }
 
     gfxresult_t*grouprecording = states[statepos].grouprecording;
@@ -2712,6 +2714,11 @@ void GFXOutputDev::setSoftMask(GfxState *state, double *bbox, GBool alpha, Funct
     dbg("softmaskrecording is %08x at statepos %d\n", states[statepos].softmaskrecording, statepos);
     
     states[statepos].softmask = 1;
+    states[statepos].softmask_alpha = alpha;
+}
+
+static inline Guchar div255(int x) {
+  return (Guchar)((x + (x >> 8) + 0x80) >> 8);
 }
 
 void GFXOutputDev::clearSoftMask(GfxState *state)
@@ -2751,12 +2758,16 @@ void GFXOutputDev::clearSoftMask(GfxState *state)
 
     gfxdevice_t belowrender;
     gfxdevice_render_init(&belowrender);
+    if(states[statepos+1].isolated) {
+       belowrender.setparameter(&belowrender, "fillwhite", "1");
+    }
     belowrender.setparameter(&belowrender, "antialize", "2");
     belowrender.startpage(&belowrender, width, height);
     gfxresult_record_replay(below, &belowrender);
     belowrender.endpage(&belowrender);
     gfxresult_t* belowresult = belowrender.finish(&belowrender);
     gfximage_t* belowimg = (gfximage_t*)belowresult->get(belowresult,"page0");
+    writePNG("below.png", (unsigned char*)belowimg->data, belowimg->width, belowimg->height);
 
     gfxdevice_t maskrender;
     gfxdevice_render_init(&maskrender);
@@ -2776,14 +2787,18 @@ void GFXOutputDev::clearSoftMask(GfxState *state)
        gfxcolor_t* l1 = &maskimg->data[maskimg->width*y];
        gfxcolor_t* l2 = &belowimg->data[belowimg->width*y];
        for(x=0;x<width;x++) {
-           l1->a = 255;
-           l2->a = (77*l1->r + 151*l1->g + 28*l1->b) >> 8;
+           int alpha;
+           if(states[statepos].softmask_alpha) {
+               alpha = l1->a;
+           } else {
+               alpha = (77*l1->r + 151*l1->g + 28*l1->b) >> 8;
+           }
 
-           /* premultiply alpha... do we need this? (depends on output device)
-           l2->r = (l2->a*l2->r) >> 8;
-           l2->g = (l2->a*l2->g) >> 8;
-           l2->b = (l2->a*l2->b) >> 8;
-           */
+           /* premultiply alpha */
+           l2->a = div255(alpha*l2->a);
+           l2->r = div255(alpha*l2->r);
+           l2->g = div255(alpha*l2->g);
+           l2->b = div255(alpha*l2->b);
 
            l1++;
            l2++;
@@ -2804,8 +2819,6 @@ void GFXOutputDev::clearSoftMask(GfxState *state)
     states[statepos].softmaskrecording = 0;
 }
   
-#endif
-
 /*class MemCheck
 {
     public: ~MemCheck()