From 3bf6a6c26f5dda79b6de3b236c9867fcf6a3f17b Mon Sep 17 00:00:00 2001
From: Matthias Kramm <kramm@quiss.org>
Date: Tue, 8 Jun 2010 13:01:12 -0700
Subject: [PATCH] reduced memory requirements for Illustrator files

---
 lib/pdf/BitmapOutputDev.cc |   27 +++++++++++++++------------
 lib/pdf/bbox.c             |   33 ++++++++++++++++++++++++++-------
 lib/pdf/bbox.h             |    6 ++++--
 3 files changed, 45 insertions(+), 21 deletions(-)

diff --git a/lib/pdf/BitmapOutputDev.cc b/lib/pdf/BitmapOutputDev.cc
index d54c8ea..a858765 100644
--- a/lib/pdf/BitmapOutputDev.cc
+++ b/lib/pdf/BitmapOutputDev.cc
@@ -174,8 +174,8 @@ static int dbg_btm_counter=1;
 
 void BitmapOutputDev::flushBitmap()
 {
-    int width = rgbdev->getBitmapWidth();
-    int height = rgbdev->getBitmapHeight();
+    int bitmap_width = rgbdev->getBitmapWidth();
+    int bitmap_height = rgbdev->getBitmapHeight();
 
     if(sizeof(SplashColor)!=3) {
 	msg("<error> sizeof(SplashColor)!=3");
@@ -196,7 +196,7 @@ void BitmapOutputDev::flushBitmap()
     Guchar*alpha = rgbbitmap->getAlphaPtr();
     
     Guchar*alpha2 = stalepolybitmap->getDataPtr();
-    int width8 = (stalepolybitmap->getWidth()+7)/8;
+    int bitmap_width8 = (stalepolybitmap->getWidth()+7)/8;
 
     /*char filename[80];
     sprintf(filename, "flush%d_mask.png", dbg_btm_counter);
@@ -206,14 +206,17 @@ void BitmapOutputDev::flushBitmap()
     sprintf(filename, "flush%d_bitmap.png", dbg_btm_counter);
     writeBitmap(rgbbitmap, filename);*/
 
-    ibbox_t* boxes = get_bitmap_bboxes((unsigned char*)alpha, width, height);
-    ibbox_t*b;
+    ibbox_t pagebox = {-movex, -movey, -movex + this->width, -movey + this->height, 0};
+    ibbox_t bitmapbox = {0, 0, bitmap_width, bitmap_height, 0};
+    ibbox_t c = ibbox_clip(&bitmapbox, &pagebox);
+    ibbox_t* boxes = get_bitmap_bboxes((unsigned char*)(alpha+c.ymin*bitmap_width+c.xmin), c.xmax - c.xmin, c.ymax - c.ymin, bitmap_width);
 
+    ibbox_t*b;
     for(b=boxes;b;b=b->next) {
-	int xmin = b->xmin;
-	int ymin = b->ymin;
-	int xmax = b->xmax;
-	int ymax = b->ymax;
+	int xmin = b->xmin - this->movex;
+	int ymin = b->ymin - this->movey;
+	int xmax = b->xmax - this->movex;
+	int ymax = b->ymax - this->movey;
 
 	/* clip against (-movex, -movey, -movex+width, -movey+height) */
 
@@ -248,10 +251,10 @@ void BitmapOutputDev::flushBitmap()
 	img->height = rangey;
 	int x,y;
 	for(y=0;y<rangey;y++) {
-	    SplashColorPtr in=&rgb[((y+ymin)*width+xmin)*sizeof(SplashColor)];
+	    SplashColorPtr in=&rgb[((y+ymin)*bitmap_width+xmin)*sizeof(SplashColor)];
 	    gfxcolor_t*out = &img->data[y*rangex];
-	    Guchar*ain = &alpha[(y+ymin)*width+xmin];
-	    Guchar*ain2 = &alpha2[(y+ymin)*width8];
+	    Guchar*ain = &alpha[(y+ymin)*bitmap_width+xmin];
+	    Guchar*ain2 = &alpha2[(y+ymin)*bitmap_width8];
 	    if(this->emptypage) {
 		for(x=0;x<rangex;x++) {
 		    /* the first bitmap on the page doesn't need to have an alpha channel-
diff --git a/lib/pdf/bbox.c b/lib/pdf/bbox.c
index 1f24567..ac7285c 100644
--- a/lib/pdf/bbox.c
+++ b/lib/pdf/bbox.c
@@ -30,7 +30,7 @@ void ibbox_destroy(ibbox_t*b)
     }
 }
 
-ibbox_t*get_bitmap_bboxes_simple(unsigned char*alpha, int width, int height)
+ibbox_t*get_bitmap_bboxes_simple(unsigned char*alpha, int width, int height, int rowsize)
 {
     int ymin = -1;
     int ymax = -1;
@@ -39,7 +39,7 @@ ibbox_t*get_bitmap_bboxes_simple(unsigned char*alpha, int width, int height)
 
     int x,y;
     for(y=0;y<height;y++) {
-	unsigned char*a = &alpha[y*width];
+	unsigned char*a = &alpha[y*rowsize];
 	for(x=0;x<width;x++) {
 	    if(a[x]) break;
 	}
@@ -79,6 +79,7 @@ typedef struct _head {
 typedef struct _context {
     void**group;
     unsigned char*alpha;
+    int rowsize;
     int width;
     int height;
     head_t*heads;
@@ -193,6 +194,21 @@ static inline void merge(context_t*context, int set1, int set2)
     }
 }
 
+ibbox_t ibbox_clip(ibbox_t* outer, ibbox_t* inner)
+{
+    ibbox_t i = {inner->xmin, inner->ymin, inner->xmax, inner->ymax, 0};
+    if(i.xmax > outer->xmax) i.xmax = outer->xmax;
+    if(i.ymax > outer->ymax) i.ymax = outer->ymax;
+    if(i.xmax < outer->xmin) i.xmax = outer->xmin;
+    if(i.ymax < outer->ymin) i.ymax = outer->ymin;
+    
+    if(i.xmin > outer->xmax) i.xmin = outer->xmax;
+    if(i.ymin > outer->ymax) i.ymin = outer->ymax;
+    if(i.xmin < outer->xmin) i.xmin = outer->xmin;
+    if(i.ymin < outer->ymin) i.ymin = outer->ymin;
+    return i;
+}
+
 static void** annotate(context_t*context)
 {
     unsigned char*alpha = context->alpha;
@@ -211,9 +227,11 @@ static void** annotate(context_t*context)
 	}
     }
     int pos = 0;
+    int apos = 0;
     for(y=1;y<height;y++) {
 	pos += width;
-	if(alpha[pos]) {
+	apos += context->rowsize;
+	if(alpha[apos]) {
 	    if(group[pos-width])
 		link_to(context,pos,pos-width);
 	    else
@@ -223,7 +241,7 @@ static void** annotate(context_t*context)
 	    /* once this code is stable we should copy&paste it
 	       out of the loop, change the loop end to width-1 and
 	       add the pos-width+1 case */
-	    if(alpha[pos+x]) {
+	    if(alpha[apos+x]) {
 		if(group[pos+x-width]) {
 		    link_to(context,pos+x,pos+x-width);
 		    if(group[pos+x-1])
@@ -403,14 +421,15 @@ static void display(context_t*context)
     }
 }
 
-ibbox_t*get_bitmap_bboxes(unsigned char*alpha, int width, int height)
+ibbox_t*get_bitmap_bboxes(unsigned char*alpha, int width, int height, int rowsize)
 {
     int size = width*height;
     if(width<=1 || height<=1)
-	return get_bitmap_bboxes_simple(alpha, width, height);
+	return get_bitmap_bboxes_simple(alpha, width, height, rowsize);
     
     context_t context;
     context.alpha = alpha;
+    context.rowsize = rowsize;
     context.width = width;
     context.height = height;
     context.heads = 0;
@@ -457,6 +476,6 @@ int main(int argn, char*argv[])
 	"\1\0\0\0\0\0\1\0"
 	"\1\1\1\0\0\0\0\0";
 
-    get_bitmap_bboxes(alpha, 8,8);
+    get_bitmap_bboxes(alpha, 8,8, 8);
 }
 #endif
diff --git a/lib/pdf/bbox.h b/lib/pdf/bbox.h
index 25675c8..8ee9487 100644
--- a/lib/pdf/bbox.h
+++ b/lib/pdf/bbox.h
@@ -10,9 +10,11 @@ typedef struct _ibbox {
     struct _ibbox*next;
 } ibbox_t;
 
-ibbox_t* ibbox_new(int x1, int y1, int x2, int y2);
+ibbox_t ibbox_clip(ibbox_t* outer, ibbox_t* inner);
+
+ibbox_t* ibbox_new(int x1, int y1, int x2, int y2, int rowsize);
 void ibbox_destroy(ibbox_t*b);
-ibbox_t*get_bitmap_bboxes(unsigned char*alpha, int width, int height);
+ibbox_t*get_bitmap_bboxes(unsigned char*alpha, int width, int height, int rowsize);
 
 #ifdef __cplusplus
 }
-- 
1.7.10.4