X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fpdf%2FGFXOutputDev.cc;h=b8cc3f4af30902583ec1b51613227ef82a5a569b;hb=36bc7214626310b6ab79d9246cdec806c2da55ca;hp=cd0c87a3ea56fa1840438ffc3ef4d3fc118ebc6b;hpb=5e85f2318e021b29590ae201311350842122d1e8;p=swftools.git diff --git a/lib/pdf/GFXOutputDev.cc b/lib/pdf/GFXOutputDev.cc index cd0c87a..b8cc3f4 100644 --- a/lib/pdf/GFXOutputDev.cc +++ b/lib/pdf/GFXOutputDev.cc @@ -125,7 +125,7 @@ struct fontentry { static int verbose = 0; -static int dbgindent = 0; +static int dbgindent = 1; static void dbg(const char*format, ...) { char buf[1024]; @@ -151,19 +151,52 @@ static void dbg(const char*format, ...) fflush(stdout); } +GFXOutputGlobals*gfxglobals=0; -void GFXOutputDev::showfeature(const char*feature, char fully, char warn) +GFXOutputGlobals::GFXOutputGlobals() { + this->pages = 0; + this->pagebuflen = 0; + this->pagepos = 0; + this->featurewarnings = 0; + this->jpeginfo = 0; + this->textmodeinfo = 0; + this->linkinfo = 0; + this->pbminfo = 0; + this->gfxfontlist = gfxfontlist_create(); +} +GFXOutputGlobals::~GFXOutputGlobals() +{ + if(this->pages) { + free(this->pages); this->pages = 0; + } feature_t*f = this->featurewarnings; while(f) { + feature_t*next = f->next; + if(f->string) { + free(f->string);f->string =0; + } + f->next = 0; + free(f); + f = next; + } + this->featurewarnings = 0; + + gfxfontlist_free(this->gfxfontlist, 1);this->gfxfontlist = 0; +} + +void GFXOutputDev::showfeature(const char*feature, char fully, char warn) +{ + feature_t*f = gfxglobals->featurewarnings; + while(f) { if(!strcmp(feature, f->string)) return; f = f->next; } f = (feature_t*)malloc(sizeof(feature_t)); f->string = strdup(feature); - f->next = this->featurewarnings; - this->featurewarnings = f; + f->next = gfxglobals->featurewarnings; + gfxglobals->featurewarnings = f; if(warn) { msg(" %s not yet %ssupported!",feature,fully?"fully ":""); if(this->config_break_on_warning) { @@ -294,7 +327,7 @@ static int config_use_fontconfig = 1; static int fcinitcalled = 0; GFXGlobalParams::GFXGlobalParams() -: GlobalParams("") +: GlobalParams((char*)"") { //setupBaseFonts(char *dir); //not tested yet } @@ -537,19 +570,16 @@ DisplayFontParam *GFXGlobalParams::getDisplayFont(GString *fontName) GFXOutputDev::GFXOutputDev(InfoOutputDev*info, PDFDoc*doc) { + if(!gfxglobals) + gfxglobals = new GFXOutputGlobals(); + this->info = info; this->doc = doc; this->xref = doc->getXRef(); - - this->jpeginfo = 0; - this->textmodeinfo = 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->clipmovex = 0; @@ -561,9 +591,7 @@ GFXOutputDev::GFXOutputDev(InfoOutputDev*info, PDFDoc*doc) this->current_text_stroke = 0; this->current_text_clip = 0; this->outer_clip_box = 0; - this->pages = 0; - this->pagebuflen = 0; - this->pagepos = 0; + this->config_bigchar=0; this->config_convertgradients=1; this->config_break_on_warning=0; this->config_remapunicode=0; @@ -571,11 +599,10 @@ GFXOutputDev::GFXOutputDev(InfoOutputDev*info, PDFDoc*doc) this->config_extrafontdata = 0; this->config_fontquality = 10; this->config_optimize_polygons = 0; - - this->gfxfontlist = gfxfontlist_create(); + this->config_multiply = 1; + this->dashPattern = 0; memset(states, 0, sizeof(states)); - this->featurewarnings = 0; }; void GFXOutputDev::setParameter(const char*key, const char*value) @@ -590,8 +617,14 @@ void GFXOutputDev::setParameter(const char*key, const char*value) this->config_extrafontdata = atoi(value); } else if(!strcmp(key,"convertgradients")) { this->config_convertgradients = atoi(value); + } else if(!strcmp(key,"multiply")) { + this->config_multiply = atoi(value); + if(this->config_multiply<1) + this->config_multiply=1; } else if(!strcmp(key,"optimize_polygons")) { this->config_optimize_polygons = atoi(value); + } else if(!strcmp(key,"bigchar")) { + this->config_bigchar = atoi(value); } else if(!strcmp(key,"fontquality")) { this->config_fontquality = atof(value); if(this->config_fontquality<=1) @@ -996,6 +1029,8 @@ GBool GFXOutputDev::axialShadedFill(GfxState *state, GfxAxialShading *shading) m.ty = (y0 + y1)/2 - 0.5; device->fillgradient(device, &p1, g, gfxgradient_linear, &m); + + free(g); return gTrue; } @@ -1080,6 +1115,8 @@ void GFXOutputDev::strokeGfxline(GfxState *state, gfxline_t*line, int flags) msg(" | phase: %f", this->dashStart); for(t=0;tdashLength;t++) { dash[t] = (float)this->dashPattern[t] * f; + if(!dash[t]) + dash[t] = 1e-37; msg(" | d%-3d: %f", t, this->dashPattern[t]); } dash[this->dashLength] = -1; @@ -1216,24 +1253,9 @@ void GFXOutputDev::finish() GFXOutputDev::~GFXOutputDev() { finish(); - - if(this->pages) { - free(this->pages); this->pages = 0; + if(this->dashPattern) { + free(this->dashPattern);this->dashPattern = 0; } - - feature_t*f = this->featurewarnings; - while(f) { - feature_t*next = f->next; - if(f->string) { - free(f->string);f->string =0; - } - f->next = 0; - free(f); - f = next; - } - this->featurewarnings = 0; - - gfxfontlist_free(this->gfxfontlist, 1);this->gfxfontlist = 0; }; GBool GFXOutputDev::upsideDown() { @@ -1356,15 +1378,16 @@ void GFXOutputDev::drawChar(GfxState *state, double x, double y, msg(" drawChar(%f,%f,c='%c' (%d), u=%d <%d>) CID=%d render=%d glyphid=%d font=%08x",x,y,(charid&127)>=32?charid:'?', charid, u, uLen, font->isCIDFont(), render, glyphid, current_gfxfont); gfxmatrix_t m = this->current_font_matrix; - this->transformXY(state, x, y, &m.tx, &m.ty); + this->transformXY(state, x-originX, y-originY, &m.tx, &m.ty); + //m.tx += originX; m.ty += originY; if(render == RENDER_FILL || render == RENDER_INVISIBLE) { device->drawchar(device, current_gfxfont, glyphid, &col, &m); } else { msg(" Drawing glyph %d as shape", charid); - if(!textmodeinfo) { + if(!gfxglobals->textmodeinfo) { msg(" Some texts will be rendered as shape"); - textmodeinfo = 1; + gfxglobals->textmodeinfo = 1; } gfxline_t*glyph = current_gfxfont->glyphs[glyphid].line; gfxline_t*tglyph = gfxline_clone(glyph); @@ -1649,8 +1672,8 @@ void GFXOutputDev::processLink(Link *link, Catalog *catalog) } else if(strstr(s, "last") || strstr(s, "end")) { - if(pages && pagepos>0) - page = pages[pagepos-1]; + if(gfxglobals->pages && gfxglobals->pagepos>0) + page = gfxglobals->pages[gfxglobals->pagepos-1]; } else if(strstr(s, "first") || strstr(s, "top")) { @@ -1698,18 +1721,18 @@ void GFXOutputDev::processLink(Link *link, Catalog *catalog) msg(" drawlink s=%s", s); - if(!linkinfo && (page || s)) + if(!gfxglobals->linkinfo && (page || s)) { msg(" File contains links"); - linkinfo = 1; + gfxglobals->linkinfo = 1; } if(page>0) { int t; int lpage = -1; - for(t=1;t<=pagepos;t++) { - if(pages[t]==page) { + for(t=1;t<=gfxglobals->pagepos;t++) { + if(gfxglobals->pages[t]==page) { lpage = t; break; } @@ -1731,47 +1754,64 @@ void GFXOutputDev::processLink(Link *link, Catalog *catalog) } void GFXOutputDev::saveState(GfxState *state) { - dbg("saveState"); dbgindent+=2; + dbg("saveState %08x", state); dbgindent+=2; - msg(" saveState"); + msg(" saveState %08x", state); updateAll(state); if(statepos>=64) { - msg(" Too many nested states in pdf."); - return; + msg(" Too many nested states in pdf."); + exit(1); } statepos ++; + states[statepos].state = state; states[statepos].createsoftmask = states[statepos-1].createsoftmask; states[statepos].transparencygroup = states[statepos-1].transparencygroup; states[statepos].clipping = 0; + states[statepos].olddevice = 0; states[statepos].clipbbox = states[statepos-1].clipbbox; }; void GFXOutputDev::restoreState(GfxState *state) { - dbgindent-=2; dbg("restoreState"); + dbgindent-=2; dbg("restoreState %08x", state); if(statepos==0) { - msg(" Invalid restoreState"); - return; + msg(" Invalid restoreState"); + exit(1); } - msg(" restoreState%s%s", states[statepos].softmask?" (end softmask)":"", + msg(" restoreState %08x%s%s", state, + states[statepos].softmask?" (end softmask)":"", states[statepos].clipping?" (end clipping)":""); if(states[statepos].softmask) { clearSoftMask(state); } updateAll(state); + while(states[statepos].clipping) { device->endclip(device); states[statepos].clipping--; } + if(states[statepos].state!=state) { + msg(" bad state nesting"); + exit(1); + } + states[statepos].state=0; statepos--; } void GFXOutputDev::updateLineDash(GfxState *state) { - state->getLineDash(&this->dashPattern, &this->dashLength, &this->dashStart); + if(this->dashPattern) { + free(this->dashPattern);this->dashPattern = 0; + } + double *pattern = 0; + state->getLineDash(&pattern, &this->dashLength, &this->dashStart); msg(" updateLineDash, %d dashes", this->dashLength); if(!this->dashLength) { this->dashPattern = 0; + } else { + double*p = (double*)malloc(this->dashLength*sizeof(this->dashPattern[0])); + memcpy(p, pattern, this->dashLength*sizeof(this->dashPattern[0])); + this->dashPattern = p; } } @@ -1832,7 +1872,7 @@ void GFXOutputDev::updateStrokeColor(GfxState *state) } -static gfxfont_t* createGfxFont(GfxFont*xpdffont, FontInfo*src, double config_fontquality) +gfxfont_t* GFXOutputDev::createGfxFont(GfxFont*xpdffont, FontInfo*src) { gfxfont_t*font = (gfxfont_t*)malloc(sizeof(gfxfont_t)); memset(font, 0, sizeof(gfxfont_t)); @@ -1841,11 +1881,14 @@ static gfxfont_t* createGfxFont(GfxFont*xpdffont, FontInfo*src, double config_fo memset(font->glyphs, 0, sizeof(gfxglyph_t)*src->num_glyphs); font->id = 0; int t; - + double quality = (INTERNAL_FONT_SIZE * 200 / config_fontquality) / src->max_size; double scale = 1; //printf("%d glyphs\n", font->num_glyphs); font->num_glyphs = 0; + font->ascent = fabs(src->descender); + font->descent = fabs(src->ascender); + for(t=0;tnum_glyphs;t++) { if(src->glyphs[t]) { SplashPath*path = src->glyphs[t]->path; @@ -1887,8 +1930,21 @@ static gfxfont_t* createGfxFont(GfxFont*xpdffont, FontInfo*src, double config_fo // (f&splashPathFirst)?"first":"", // (f&splashPathLast)?"last":""); } + glyph->line = (gfxline_t*)drawer.result(&drawer); - glyph->advance = xmax*scale; // we don't know the real advance value, so this'll have to do + if(src->glyphs[t]->advance>0) { + glyph->advance = src->glyphs[t]->advance; + } else { + msg(" Approximating advance value for glyph %d", t); + glyph->advance = xmax*scale; + } + if(this->config_bigchar) { + double max = src->glyphs[t]->advance_max; + if(max>0 && max > glyph->advance) { + glyph->advance = max; + } + } + font->num_glyphs++; } } @@ -1932,11 +1988,11 @@ void GFXOutputDev::updateFont(GfxState *state) dumpFontInfo("", gfxFont); } - gfxfont_t*font = gfxfontlist_findfont(this->gfxfontlist,id); + gfxfont_t*font = gfxfontlist_findfont(gfxglobals->gfxfontlist,id); if(!font) { - font = createGfxFont(gfxFont, current_fontinfo, this->config_fontquality); + font = this->createGfxFont(gfxFont, current_fontinfo); font->id = strdup(id); - this->gfxfontlist = gfxfontlist_addfont(this->gfxfontlist, font); + gfxglobals->gfxfontlist = gfxfontlist_addfont(gfxglobals->gfxfontlist, font); } device->addfont(device, font); @@ -1950,7 +2006,7 @@ void GFXOutputDev::updateFont(GfxState *state) unsigned char* antialize(unsigned char*data, int width, int height, int newwidth, int newheight, int palettesize) { - if((newwidth<2 || newheight<2) || + if((newwidth<1 || newheight<1) || (width<=newwidth || height<=newheight)) return 0; unsigned char*newdata; @@ -2006,7 +2062,7 @@ 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) + double x4,double y4, int type, int multiply) { gfxcolor_t*newpic=0; @@ -2031,12 +2087,13 @@ static void drawimage(gfxdevice_t*dev, gfxcolor_t* data, int sizex,int sizey, p5.x = (int)(p5.x*20)/20.0; p5.y = (int)(p5.y*20)/20.0; } - + gfxmatrix_t m; m.m00 = (p4.x-p1.x)/sizex; m.m10 = (p2.x-p1.x)/sizey; m.m01 = (p4.y-p1.y)/sizex; m.m11 = (p2.y-p1.y)/sizey; - m.tx = p1.x - 0.5; - m.ty = p1.y - 0.5; + + m.tx = p1.x - 0.5*multiply; + m.ty = p1.y - 0.5*multiply; gfximage_t img; img.data = (gfxcolor_t*)data; @@ -2052,15 +2109,15 @@ static void drawimage(gfxdevice_t*dev, gfxcolor_t* data, 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) + double x1,double y1, double x2,double y2, double x3,double y3, double x4,double y4, int multiply) { - drawimage(dev,mem,sizex,sizey,x1,y1,x2,y2,x3,y3,x4,y4, IMAGE_TYPE_JPEG); + drawimage(dev,mem,sizex,sizey,x1,y1,x2,y2,x3,y3,x4,y4, IMAGE_TYPE_JPEG, multiply); } 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) + double x1,double y1, double x2,double y2, double x3,double y3, double x4,double y4, int multiply) { - drawimage(dev,mem,sizex,sizey,x1,y1,x2,y2,x3,y3,x4,y4, IMAGE_TYPE_LOSSLESS); + drawimage(dev,mem,sizex,sizey,x1,y1,x2,y2,x3,y3,x4,y4, IMAGE_TYPE_LOSSLESS, multiply); } @@ -2069,6 +2126,8 @@ void GFXOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str, GBool inlineImg, int mask, int*maskColors, Stream *maskStr, int maskWidth, int maskHeight, GBool maskInvert, GfxImageColorMap*maskColorMap) { + /* the code in this function is *old*. It's not pretty, but it works. */ + double x1,y1,x2,y2,x3,y3,x4,y4; ImageStream *imgStr; Guchar pixBuf[4]; @@ -2123,7 +2182,7 @@ void GFXOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str, imgStr = new ImageStream(str, width, ncomps,bits); imgStr->reset(); - if(!width || !height || (height<=1 && width<=1 && maskWidth<=1 && maskHeight<=1)) + if(!width || !height || ((height+width)<=1 && (maskWidth+maskHeight)<=1)) { msg(" Ignoring %d by %d image", width, height); unsigned char buf[8]; @@ -2153,17 +2212,17 @@ void GFXOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str, x4 = (int)(x4);y4 = (int)(y4); } - if(!pbminfo && !(str->getKind()==strDCT)) { + if(!gfxglobals->pbminfo && !(str->getKind()==strDCT)) { if(!type3active) { msg(" File contains pbm pictures %s",mask?"(masked)":""); - pbminfo = 1; + gfxglobals->pbminfo = 1; } if(mask) msg(" drawing %d by %d masked picture", width, height); } - if(!jpeginfo && (str->getKind()==strDCT)) { + if(!gfxglobals->jpeginfo && (str->getKind()==strDCT)) { msg(" File contains jpeg pictures"); - jpeginfo = 1; + gfxglobals->jpeginfo = 1; } if(mask) { @@ -2191,11 +2250,7 @@ void GFXOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str, buf[0]=1-buf[0]; pic[width*y+x] = buf[0]; } - - /* the size of the drawn image is added to the identifier - as the same image may require different bitmaps if displayed - at different sizes (due to antialiasing): */ - int found = -1; + if(type3active) { unsigned char*pic2 = 0; numpalette = 16; @@ -2232,7 +2287,7 @@ void GFXOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str, pic2[width*y+x] = pal[pic[y*width+x]]; } } - drawimagelossless(device, pic2, width, height, x1,y1,x2,y2,x3,y3,x4,y4); + drawimagelossless(device, pic2, width, height, x1,y1,x2,y2,x3,y3,x4,y4, config_multiply); delete[] pic2; delete[] pic; delete imgStr; @@ -2253,14 +2308,30 @@ void GFXOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str, 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)]; + int x1 = x*maskWidth/width; + int y1 = y*maskHeight/height; + int x2 = (x+1)*maskWidth/width; + int y2 = (y+1)*maskHeight/height; + int xx,yy; + unsigned int alpha=0; + unsigned int count=0; + for(xx=x1;xxgetKind()==strDCT) - drawimagejpeg(device, pic, width, height, x1,y1,x2,y2,x3,y3,x4,y4); + drawimagejpeg(device, pic, width, height, x1,y1,x2,y2,x3,y3,x4,y4, config_multiply); else - drawimagelossless(device, pic, width, height, x1,y1,x2,y2,x3,y3,x4,y4); + drawimagelossless(device, pic, width, height, x1,y1,x2,y2,x3,y3,x4,y4, config_multiply); delete[] pic; delete imgStr; if(maskbitmap) free(maskbitmap); @@ -2335,7 +2406,7 @@ void GFXOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str, height = maskHeight; } } - drawimagelossless(device, pic, width, height, x1,y1,x2,y2,x3,y3,x4,y4); + drawimagelossless(device, pic, width, height, x1,y1,x2,y2,x3,y3,x4,y4, config_multiply); delete[] pic; delete imgStr; @@ -2545,22 +2616,25 @@ void GFXOutputDev::preparePage(int pdfpage, int outputpage) if(pdfpage < 0) return; - if(!this->pages) { - this->pagebuflen = 1024; - this->pages = (int*)malloc(this->pagebuflen*sizeof(int)); - memset(this->pages, -1, this->pagebuflen*sizeof(int)); - } else { - while(pdfpage >= this->pagebuflen) - { - int oldlen = this->pagebuflen; - this->pagebuflen+=1024; - this->pages = (int*)realloc(this->pages, this->pagebuflen*sizeof(int)); - memset(&this->pages[oldlen], -1, (this->pagebuflen-oldlen)*sizeof(int)); - } + if(!gfxglobals->pages) { + gfxglobals->pagebuflen = 1024; + if(pdfpage > gfxglobals->pagebuflen) + gfxglobals->pagebuflen = pdfpage+1; + gfxglobals->pages = (int*)malloc(gfxglobals->pagebuflen*sizeof(int)); + memset(gfxglobals->pages, -1, gfxglobals->pagebuflen*sizeof(int)); + } + + while(pdfpage >= gfxglobals->pagebuflen) + { + int oldlen = gfxglobals->pagebuflen; + gfxglobals->pagebuflen+=1024; + gfxglobals->pages = (int*)realloc(gfxglobals->pages, gfxglobals->pagebuflen*sizeof(int)); + memset(&gfxglobals->pages[oldlen], -1, (gfxglobals->pagebuflen-oldlen)*sizeof(int)); } - this->pages[pdfpage] = outputpage; - if(pdfpage>this->pagepos) - this->pagepos = pdfpage; + + gfxglobals->pages[pdfpage] = outputpage; + if(pdfpage > gfxglobals->pagepos) + gfxglobals->pagepos = pdfpage; } void GFXOutputDev::beginTransparencyGroup(GfxState *state, double *bbox, @@ -2583,6 +2657,7 @@ void GFXOutputDev::beginTransparencyGroup(GfxState *state, double *bbox, states[statepos].olddevice = this->device; this->device = (gfxdevice_t*)rfx_calloc(sizeof(gfxdevice_t)); + dbg("this->device now %08x (old: %08x)", this->device, states[statepos].olddevice); gfxdevice_record_init(this->device); @@ -2597,11 +2672,21 @@ void GFXOutputDev::endTransparencyGroup(GfxState *state) dbgindent-=2; gfxdevice_t*r = this->device; + dbg("endTransparencyGroup this->device now back to %08x (destroying %08x)", states[statepos].olddevice, this->device); + this->device = states[statepos].olddevice; + if(!this->device) { + msg(" bad state nesting in transparency group- PDF file broken?"); + /* if these errors occur more often, we should build a seperate + transparency group stack, like xpdf/SplashOutputDev.cc does */ + restoreState(state); + this->device = states[statepos].olddevice; + } + states[statepos].olddevice = 0; gfxresult_t*recording = r->finish(r); - dbg("endTransparencyGroup forsoftmask=%d recording=%08x/%08x", states[statepos].createsoftmask, r, recording); + dbg(" forsoftmask=%d recording=%08x/%08x", states[statepos].createsoftmask, r, recording); msg(" endTransparencyGroup forsoftmask=%d recording=%08x/%08x", states[statepos].createsoftmask, r, recording); if(states[statepos].createsoftmask) { @@ -2621,9 +2706,9 @@ void GFXOutputDev::paintTransparencyGroup(GfxState *state, double *bbox) "colordodge","colorburn","hardlight","softlight","difference", "exclusion","hue","saturation","color","luminosity"}; - dbg("paintTransparencyGroup blend=%s softmaskon=%d", blendmodes[state->getBlendMode()], states[statepos].softmask); + dbg("paintTransparencyGroup blend=%s softmaskon=%d recording=%08x", blendmodes[state->getBlendMode()], states[statepos].softmask, states[statepos].grouprecording); msg(" paintTransparencyGroup blend=%s softmaskon=%d", blendmodes[state->getBlendMode()], states[statepos].softmask); - + if(state->getBlendMode() == gfxBlendNormal) infofeature("transparency groups"); else { @@ -2640,6 +2725,7 @@ void GFXOutputDev::paintTransparencyGroup(GfxState *state, double *bbox) if(blendmode == gfxBlendMultiply && alpha>200) alpha = 128; gfxdevice_t ops; + dbg("this->device=%08x, this->device->name=%s\n", this->device, this->device->name); gfxdevice_ops_init(&ops, this->device, alpha); gfxresult_record_replay(grouprecording, &ops); ops.finish(&ops); @@ -2667,7 +2753,11 @@ void GFXOutputDev::setSoftMask(GfxState *state, double *bbox, GBool alpha, Funct infofeature("soft masks"); else warnfeature("soft masks from alpha channel",0); - + + if(states[statepos].olddevice) { + msg(" Internal error: badly balanced softmasks/transparency groups"); + exit(1); + } states[statepos].olddevice = this->device; this->device = (gfxdevice_t*)rfx_calloc(sizeof(gfxdevice_t)); gfxdevice_record_init(this->device);