+ for(y=0;y<height;y++) {
+ for(x=0;x<width;x++) {
+ int a1 = alphabtm->getAlpha(x,y);
+ int a2 = boolbtm->getAlpha(x,y);
+ if(a1!=a2) {
+ bad++;
+ }
+ }
+ }
+ double badness = bad/(double)(width*height);
+ if(badness>0.2) {
+ msg("<error> Bitmaps don't correspond: %d out of %d pixels wrong (%.2f%%)", bad, width*height,
+ badness*100.0);
+ return 0;
+ }
+ msg("<notice> %f", badness);
+ return 1;
+}
+
+GBool BitmapOutputDev::checkNewText(int x1, int y1, int x2, int y2)
+{
+ /* 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);
+
+ if(0) {
+ char filename1[80];
+ char filename2[80];
+ char filename3[80];
+ sprintf(filename1, "state%dboolbitmap_afternewtext.png", dbg_btm_counter);
+ sprintf(filename2, "state%dbooltext_afternewtext.png", dbg_btm_counter);
+ sprintf(filename3, "state%dbitmap_afternewtext.png", dbg_btm_counter);
+ msg("<verbose> %s %s %s", filename1, filename2, filename3);
+ writeAlpha(boolpolybitmap, filename1);
+ writeAlpha(booltextbitmap, filename2);
+ writeBitmap(rgbdev->getBitmap(), filename3);
+ }
+ dbg_btm_counter++;
+
+ GBool ret = false;
+ if(intersection(x1,y1,x2,y2)) {
+ 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(x1,y1,x2,y2);
+ } 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(x1,y1,x2,y2);
+ /* FIXME this destroys the text pixels we just
+ drew to test for the intersection- however we need
+ those to check for the *new* intersections */
+ clearBoolTextDev(x1,y1,x2,y2);
+ ret = true;
+ } 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(x1,y1,x2,y2);
+ }
+ }
+ return ret;
+}
+
+GBool BitmapOutputDev::checkNewBitmap(int x1, int y1, int x2, int y2)
+{
+ /* 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);
+
+ if(0) {
+ char filename1[80];
+ char filename2[80];
+ char filename3[80];
+ sprintf(filename1, "state%dboolbitmap_afternewgfx.png", dbg_btm_counter);
+ sprintf(filename2, "state%dbooltext_afternewgfx.png", dbg_btm_counter);
+ sprintf(filename3, "state%dbitmap_afternewgfx.png", dbg_btm_counter);
+ msg("<verbose> %s %s %s", filename1, filename2, filename3);
+ writeAlpha(boolpolybitmap, filename1);
+ writeAlpha(booltextbitmap, filename2);
+ writeBitmap(rgbdev->getBitmap(), filename3);
+ }
+ dbg_btm_counter++;
+
+ GBool ret = false;
+ if(intersection(x1,y1,x2,y2)) {
+ if(layerstate==STATE_PARALLEL) {
+ msg("<verbose> Bitmap is above current text data");
+ layerstate=STATE_BITMAP_IS_ABOVE;
+ clearBoolTextDev(x1,y1,x2,y2);
+ } 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(x1,y1,x2,y2);
+ /* FIXME this destroys the polygon pixels we just
+ drew to test for the intersection- however we need
+ those to check for the *new* intersections */
+ clearBoolPolyDev(x1,y1,x2,y2);
+ ret = true;
+ } else {
+ msg("<verbose> Bitmap is still above current text data");
+ clearBoolTextDev(x1,y1,x2,y2);
+ }
+ }
+ return ret;
+}
+
+//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;
+//}
+
+static inline GBool fixBBox(int*x1, int*y1, int*x2, int*y2, int width, int height)
+{
+ if(!(*x1|*y1|*x2|*y2)) {
+ // undefined bbox
+ *x1 = *y1 = 0;
+ *x2 = width;
+ *y2 = height;
+ return gTrue;
+ }
+ if(*x2<=*x1) return gFalse;
+ if(*x2<0) return gFalse;
+ if(*x1<0) *x1 = 0;
+ if(*x1>=width) return gFalse;
+ if(*x2>width) *x2=width;
+
+ if(*y2<=*y1) return gFalse;
+ if(*y2<0) return gFalse;
+ if(*y1<0) *y1 = 0;
+ if(*y1>=height) return gFalse;
+ if(*y2>height) *y2=height;
+ return gTrue;
+}
+
+GBool BitmapOutputDev::clip0and1differ(int x1,int y1,int x2,int y2)
+{
+ if(clip0bitmap->getMode()==splashModeMono1) {
+ int width = clip0bitmap->getWidth();
+ int width8 = (width+7)/8;
+ int height = clip0bitmap->getHeight();
+
+ if(!fixBBox(&x1,&y1,&x2,&y2,width,height)) {
+ /* area is outside or null */
+ return gFalse;
+ }
+
+ SplashBitmap*clip0 = clip0bitmap;
+ SplashBitmap*clip1 = clip1bitmap;
+ int x18 = x1/8;
+ int x28 = (x2+7)/8;
+ int y;
+
+ for(y=y1;y<y2;y++) {
+ unsigned char*row1 = &clip0bitmap->getDataPtr()[width8*y+x18];
+ unsigned char*row2 = &clip1bitmap->getDataPtr()[width8*y+x18];
+ if(memcmp(row1, row2, x28-x18)) {
+ return gTrue;
+ }