+ if(!(x1|y1|x2|y2)) {
+ x1 = y1 = 0;
+ x2 = btm->getWidth();
+ y2 = btm->getHeight();
+ }
+ 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 compare8(unsigned char*data1, unsigned char*data2, int len)
+{
+ if(!len)
+ return 0;
+ if(((ptroff_t)data1&7)==((ptroff_t)data2&7)) {
+ // oh good, we can do aligning
+ while((ptroff_t)data1&7) {
+ if(*data1&*data2)
+ return 1;
+ data1++;
+ data2++;
+ if(!--len)
+ return 0;
+ }
+ }
+ /* use 64 bit for the (hopefully aligned) middle section */
+ int l8 = len/8;
+ long long unsigned int*d1 = (long long unsigned int*)data1;
+ long long unsigned int*d2 = (long long unsigned int*)data2;
+ long long unsigned int x = 0;
+ int t;
+ for(t=0;t<l8;t++) {
+ x |= d1[t]&d2[t];
+ }
+ if(x)
+ return 1;
+
+ data1+=l8*8;
+ data2+=l8*8;
+ len -= l8*8;
+ for(t=0;t<len;t++) {
+ if(data1[t]&data2[t]) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+GBool BitmapOutputDev::intersection(int x1, int y1, int x2, int y2)
+{
+ SplashBitmap*boolpoly = boolpolybitmap;
+ SplashBitmap*booltext = booltextbitmap;
+
+ if(boolpoly->getMode()==splashModeMono1) {
+ /* alternative implementation, using one bit per pixel-
+ needs the no-dither patch in xpdf */
+
+ int width = boolpoly->getWidth();
+ int height = boolpoly->getHeight();
+
+ if(!fixBBox(&x1,&y1,&x2,&y2, width, height)) {
+ return gFalse;
+ }
+
+ Guchar*polypixels = boolpoly->getDataPtr();
+ Guchar*textpixels = booltext->getDataPtr();
+
+ int width8 = (width+7)/8;
+ int runx = width8;
+ int runy = height;
+
+ if(x1|y1|x2|y2) {
+ polypixels+=y1*width8+x1/8;
+ textpixels+=y1*width8+x1/8;
+ runx=(x2+7)/8 - x1/8;
+ runy=y2-y1;
+ }
+
+ int t;
+ unsigned char c=0;
+
+ /*assert(sizeof(unsigned long long int)==8);
+ if(((ptroff_t)polypixels&7) || ((ptroff_t)textpixels&7)) {
+ //msg("<warning> Non-optimal alignment");
+ }*/
+
+ int x,y;
+ unsigned char*data1 = (unsigned char*)polypixels;
+ unsigned char*data2 = (unsigned char*)textpixels;
+ msg("<verbose> Testing area (%d,%d,%d,%d), runx=%d,runy=%d", x1,y1,x2,y2, runx, runy);
+ for(y=0;y<runy;y++) {
+ if(compare8(data1,data2,runx))
+ return gTrue;
+ data1+=width8;
+ data2+=width8;
+ }
+ return gFalse;
+ } else {
+ int width = boolpoly->getAlphaRowSize();
+ int height = boolpoly->getHeight();
+
+ if(!fixBBox(&x1, &y1, &x2, &y2, width, height)) {
+ x1=y1=0;x2=y2=1;
+ }
+ Guchar*polypixels = boolpoly->getAlphaPtr();
+ Guchar*textpixels = booltext->getAlphaPtr();
+
+ int x,y;
+ char overlap1 = 0;
+ char overlap2 = 0;
+ for(x=x1;x<x2;x++) {
+ for(y=y1;y<y2;y++) {
+ if(polypixels[width*y+x]&&textpixels[width*y+x])
+ overlap1 = 1;
+ }
+ }
+ int ax1=0,ay1=0,ax2=0,ay2=0;
+ for(y=0;y<height;y++) {
+ for(x=0;x<width;x++) {
+ if(polypixels[width*y+x]&&textpixels[width*y+x]) {
+ overlap2 = 1;
+ if(!(ax1|ay1|ax2|ay2)) {
+ ax1 = ax2 = x;
+ ay1 = ay2 = y;
+ } else {
+ ax1 = ax1<x?ax1:x;
+ ay1 = ay1<y?ay1:y;
+ ax2 = ax2>x?ax2:x;
+ ay2 = ay2>y?ay2:y;
+ }
+ }
+ }
+ }
+ if(overlap1 && !overlap2)
+ msg("<warning> strange internal error");
+ if(!overlap1 && overlap2) {
+ msg("<warning> Bad bounding box: intersection outside bbox");
+ msg("<warning> given bbox: %d %d %d %d", x1, y1, x2, y2);
+ msg("<warning> changed area: %d %d %d %d", ax1, ay1, ax2, ay2);
+ //writeAlpha(booltextbitmap, "alpha.png");
+ }
+ return overlap2;
+ }
+}
+
+
+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(UNKNOWN_BOUNDING_BOX);
+ clearBoolPolyDev(UNKNOWN_BOUNDING_BOX);
+
+ this->layerstate = STATE_PARALLEL;
+ this->emptypage = 1;
+ msg("<debug> startPage done");