+
+ this->emptypage = 0;
+}
+
+void BitmapOutputDev::flushText()
+{
+ msg("<verbose> Flushing text/polygons");
+ gfxdevice_record_flush(this->gfxoutput, this->dev);
+
+ this->emptypage = 0;
+}
+
+void writeAlpha(SplashBitmap*bitmap, char*filename)
+{
+ int y,x;
+
+ int width = bitmap->getWidth();
+ int height = bitmap->getHeight();
+
+ gfxcolor_t*data = (gfxcolor_t*)malloc(sizeof(gfxcolor_t)*width*height);
+
+ for(y=0;y<height;y++) {
+ gfxcolor_t*line = &data[y*width];
+ for(x=0;x<width;x++) {
+ int a = bitmap->getAlpha(x,y);
+ line[x].r = a;
+ line[x].g = a;
+ line[x].b = a;
+ line[x].a = 255;
+ }
+ }
+ writePNG(filename, (unsigned char*)data, width, height);
+ free(data);
+}
+static int dbg_btm_counter=1;
+
+static const char*STATE_NAME[] = {"parallel", "textabovebitmap", "bitmapabovetext"};
+
+void BitmapOutputDev::checkNewText()
+{
+ /* called once some new text was drawn on booltextdev, and
+ before the same thing is drawn on gfxdev */
+
+ msg("<trace> Testing new text data against current bitmap data, state=%s, counter=%d\n", STATE_NAME[layerstate], dbg_btm_counter);
+
+ char filename1[80];
+ char filename2[80];
+ sprintf(filename1, "state%dbitmap_afternewtext.png", dbg_btm_counter);
+ sprintf(filename2, "state%dtext_afternewtext.png", dbg_btm_counter);
+ if(0) {
+ writeAlpha(boolpolybitmap, filename1);
+ writeAlpha(booltextbitmap, filename2);
+ }
+ dbg_btm_counter++;
+
+ if(intersection()) {
+ if(layerstate==STATE_PARALLEL) {
+ /* the new text is above the bitmap. So record that fact,
+ and also clear the bitmap buffer, so we can check for
+ new intersections */
+ msg("<verbose> Text is above current bitmap/polygon data");
+ layerstate=STATE_TEXT_IS_ABOVE;
+ clearBoolPolyDev();
+ } else if(layerstate==STATE_BITMAP_IS_ABOVE) {
+ /* there's a bitmap above the (old) text. So we need
+ to flush out that text, and record that the *new*
+ text is now *above* the bitmap
+ */
+ msg("<verbose> Text is above current bitmap/polygon data (which is above some other text)");
+ flushText();
+ layerstate=STATE_TEXT_IS_ABOVE;
+ /* clear both bool devices- the text device because
+ we just dumped out all the (old) text, and the
+ poly dev so we can check for new intersections */
+ clearBoolPolyDev();
+ clearBoolTextDev();
+ } else {
+ /* we already know that the current text section is
+ above the current bitmap section- now just new
+ bitmap data *and* new text data was drawn, and
+ *again* it's above the current bitmap- so clear
+ the polygon bitmap again, so we can check for
+ new intersections */
+ msg("<verbose> Text is still above current bitmap/polygon data");
+ clearBoolPolyDev();
+ }
+ }
+}
+
+void BitmapOutputDev::checkNewBitmap()
+{
+ /* similar to checkNewText() above, only in reverse */
+ msg("<trace> Testing new graphics data against current text data, state=%s, counter=%d\n", STATE_NAME[layerstate], dbg_btm_counter);
+
+ char filename1[80];
+ char filename2[80];
+ sprintf(filename1, "state%dbitmap_afternewgfx.png", dbg_btm_counter);
+ sprintf(filename2, "state%dtext_afternewgfx.png", dbg_btm_counter);
+ if(0) {
+ writeAlpha(boolpolybitmap, filename1);
+ writeAlpha(booltextbitmap, filename2);
+ }
+ dbg_btm_counter++;
+
+ if(intersection()) {
+ if(layerstate==STATE_PARALLEL) {
+ msg("<verbose> Bitmap is above current text data");
+ layerstate=STATE_BITMAP_IS_ABOVE;
+ clearBoolTextDev();
+ } else if(layerstate==STATE_TEXT_IS_ABOVE) {
+ msg("<verbose> Bitmap is above current text data (which is above some bitmap)");
+ flushBitmap();
+ layerstate=STATE_BITMAP_IS_ABOVE;
+ clearBoolTextDev();
+ clearBoolPolyDev();
+ } else {
+ msg("<verbose> Bitmap is still above current text data");
+ clearBoolTextDev();
+ }
+ }
+}
+
+//void checkNewText() {
+// Guchar*alpha = rgbbitmap->getAlphaPtr();
+// Guchar*charpixels = clip1bitmap->getDataPtr();
+// int xx,yy;
+// for(yy=0;yy<height;yy++) {
+// Guchar*aline = &alpha[yy*width];
+// Guchar*cline = &charpixels[yy*width8];
+// for(xx=0;xx<width;xx++) {
+// int bit = xx&7;
+// int bytepos = xx>>3;
+// /* TODO: is the bit order correct? */
+// if(aline[xx] && (cline[bytepos]&(1<<bit)))
+// break;
+// }
+// if(xx!=width)
+// break;
+//}
+
+GBool BitmapOutputDev::clip0and1differ()
+{
+ if(clip0bitmap->getMode()==splashModeMono1) {
+ SplashBitmap*clip0 = clip0bitmap;
+ SplashBitmap*clip1 = clip1bitmap;
+ int width8 = (clip0->getWidth()+7)/8;
+ int height = clip0->getHeight();
+ return memcmp(clip0->getDataPtr(), clip1->getDataPtr(), width8*height);
+ } else {
+ SplashBitmap*clip0 = clip0bitmap;
+ SplashBitmap*clip1 = clip1bitmap;
+ int width = clip0->getAlphaRowSize();
+ int height = clip0->getHeight();
+ return memcmp(clip0->getAlphaPtr(), clip1->getAlphaPtr(), width*height);
+ }
+}
+
+static void clearBooleanBitmap(SplashBitmap*btm)
+{
+ if(btm->getMode()==splashModeMono1) {
+ int width8 = (btm->getWidth()+7)/8;
+ int width = btm->getWidth();
+ int height = btm->getHeight();
+ memset(btm->getDataPtr(), 0, width8*height);
+ } else {
+ int width = btm->getAlphaRowSize();
+ int height = btm->getHeight();
+ memset(btm->getAlphaPtr(), 0, width*height);
+ }
+}
+
+GBool BitmapOutputDev::intersection()
+{
+ SplashBitmap*boolpoly = boolpolybitmap;
+ SplashBitmap*booltext = booltextbitmap;
+
+ if(boolpoly->getMode()==splashModeMono1) {
+ /* alternative implementation, using one bit per pixel-
+ would work if xpdf wouldn't try to dither everything */
+
+ Guchar*polypixels = boolpoly->getDataPtr();
+ Guchar*textpixels = booltext->getDataPtr();
+
+ int width8 = (width+7)/8;
+ int height = boolpoly->getHeight();
+
+ int t;
+ int len = height*width8;
+ unsigned int c=0;
+ if(len & (sizeof(unsigned int)-1)) {
+ Guchar c2=0;
+ for(t=0;t<len;t++) {
+ c2 |= polypixels[t]&textpixels[t];
+ }
+ c = c2;
+ } else {
+ len /= sizeof(unsigned int);
+ for(t=0;t<len;t++) {
+ c |= (((unsigned int*)polypixels)[t]) & (((unsigned int*)textpixels)[t]);
+ }
+ }
+ if(c)
+ /* if graphic data and the characters overlap, they have common bits */
+ return gTrue;
+ else
+ return gFalse;
+ } else {
+ Guchar*polypixels = boolpoly->getAlphaPtr();
+ Guchar*textpixels = booltext->getAlphaPtr();
+
+ int width = boolpoly->getAlphaRowSize();
+ int height = boolpoly->getHeight();
+
+ int t;
+ int len = height*width;
+ unsigned int c=0;
+ if(len & (sizeof(unsigned int)-1)) {
+ Guchar c2=0;
+ for(t=0;t<len;t++) {
+ if(polypixels[t]&&textpixels[t])
+ return gTrue;
+ }
+ } else {
+ len /= sizeof(unsigned int);
+ for(t=0;t<len;t++) {
+ if((((unsigned int*)polypixels)[t]) & (((unsigned int*)textpixels)[t]))
+ return gTrue;
+ }
+ }
+ return gFalse;
+ }