+ /* 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;
+ }
+}
+
+
+void BitmapOutputDev::startPage(int pageNum, GfxState *state, double crop_x1, double crop_y1, double crop_x2, double crop_y2)
+{
+ double x1,y1,x2,y2;
+ state->transform(crop_x1,crop_y1,&x1,&y1);
+ state->transform(crop_x2,crop_y2,&x2,&y2);
+ if(x2<x1) {double x3=x1;x1=x2;x2=x3;}
+ if(y2<y1) {double y3=y1;y1=y2;y2=y3;}
+
+ this->movex = -(int)x1 - user_movex;
+ this->movey = -(int)y1 - user_movey;
+
+ if(user_clipx1|user_clipy1|user_clipx2|user_clipy2) {
+ x1 = user_clipx1;
+ x2 = user_clipx2;
+ y1 = user_clipy1;
+ y2 = user_clipy2;
+ }
+ this->width = (int)(x2-x1);
+ this->height = (int)(y2-y1);
+
+ msg("<debug> startPage");
+ rgbdev->startPage(pageNum, state, crop_x1, crop_y1, crop_x2, crop_y2);
+ boolpolydev->startPage(pageNum, state, crop_x1, crop_y1, crop_x2, crop_y2);
+ booltextdev->startPage(pageNum, state, crop_x1, crop_y1, crop_x2, crop_y2);
+ clip0dev->startPage(pageNum, state, crop_x1, crop_y1, crop_x2, crop_y2);
+ clip1dev->startPage(pageNum, state, crop_x1, crop_y1, crop_x2, crop_y2);
+ gfxdev->startPage(pageNum, state, crop_x1, crop_y1, crop_x2, crop_y2);
+
+ boolpolybitmap = boolpolydev->getBitmap();
+ booltextbitmap = booltextdev->getBitmap();
+ clip0bitmap = clip0dev->getBitmap();
+ clip1bitmap = clip1dev->getBitmap();
+ rgbbitmap = rgbdev->getBitmap();
+
+ flushText(); // write out the initial clipping rectangle
+
+ /* just in case any device did draw a white background rectangle
+ into the device */
+ clearBoolTextDev();
+ clearBoolPolyDev();
+
+ this->layerstate = STATE_PARALLEL;
+ this->emptypage = 1;
+ msg("<debug> startPage done");