From 79b2c201a0d36651e97140ddff215a3b1bbde93e Mon Sep 17 00:00:00 2001
From: Manolo Gouy <Manolo>
Date: Wed, 14 Apr 2010 20:12:06 +0000
Subject: [PATCH] Fl_Pixmap: improved algorithm for WIN32 printing

git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@7503 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
---
 src/Fl_Pixmap.cxx      | 27 ++++--------------
 src/fl_draw_pixmap.cxx | 62 ++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 65 insertions(+), 24 deletions(-)

diff --git a/src/Fl_Pixmap.cxx b/src/Fl_Pixmap.cxx
index 0bb602e8e..d20132a35 100644
--- a/src/Fl_Pixmap.cxx
+++ b/src/Fl_Pixmap.cxx
@@ -152,37 +152,20 @@ void Fl_Pixmap::generic_device_draw(int XP, int YP, int WP, int HP, int cx, int
       if(hMod) fl_TransparentBlt = (fl_transp_func)GetProcAddress(hMod, "TransparentBlt");
       }
     if (hMod) {
-#     define UNLIKELY_RGB_COLOR 2,3,4 // a nearly black color unlikely to occur in pixmaps
-#     define WIN_COLOR RGB(2,3,4)
       Fl_Offscreen tmp_id = fl_create_offscreen(w(), h());
       fl_begin_offscreen(tmp_id);
       uchar *bitmap = 0;
       fl_mask_bitmap = &bitmap;
-      // draw pixmap to offscreen using the unlikely color for background
-      fl_draw_pixmap(data(), 0, 0, fl_rgb_color(UNLIKELY_RGB_COLOR) ); 
+      // draw pixmap to offscreen
+      fl_draw_pixmap(data(), 0, 0); 
       fl_end_offscreen();
       HDC new_gc = CreateCompatibleDC(fl_gc);
       int save = SaveDC(new_gc);
       SelectObject(new_gc, (void*)tmp_id);
-      // print all of offscreen but its parts using unlikely color
-      fl_TransparentBlt(fl_gc, X, Y, W, H, new_gc, cx, cy, w(), h(), WIN_COLOR );
+      // print all of offscreen but its parts in background color
+      extern UINT win_pixmap_bg_color; // computed by fl_draw_pixmap()
+      fl_TransparentBlt(fl_gc, X, Y, W, H, new_gc, cx, cy, w(), h(), win_pixmap_bg_color );
       RestoreDC(new_gc,save);
-      // This is an approximate algorithm that fails to print pixmap pixels that would use the unlikely color.
-      // It can be transformed into an exact algorithm by adding the following commented out statements
-      // that print pixmap one more time hiding another color (any color would fit)
-      /*
-#     define UNLIKELY_RGB_COLOR2 4,3,2
-#     define WIN_COLOR2 RGB(4,3,2)
-      {
-	fl_begin_offscreen(tmp_id);
-	fl_draw_pixmap(data(), 0, 0, fl_rgb_color(UNLIKELY_RGB_COLOR2) );
-	fl_end_offscreen();
-      }
-      save = SaveDC(new_gc);
-      SelectObject(new_gc, (void*)tmp_id);
-      fl_TransparentBlt(fl_gc, X, Y, W, H, new_gc, cx, cy, w(), h(), WIN_COLOR2 );
-      RestoreDC(new_gc,save);
-      */
       DeleteDC(new_gc);
       fl_delete_offscreen(tmp_id);
     }
diff --git a/src/fl_draw_pixmap.cxx b/src/fl_draw_pixmap.cxx
index 64bfd0589..f6dd07b3c 100644
--- a/src/fl_draw_pixmap.cxx
+++ b/src/fl_draw_pixmap.cxx
@@ -179,6 +179,40 @@ int fl_draw_pixmap(/*const*/ char* const* data, int x,int y,Fl_Color bg) {
   return fl_draw_pixmap((const char*const*)data,x,y,bg);
 }
 
+#ifdef WIN32
+// to compute an unused color to be used for the pixmap background
+FL_EXPORT UINT win_pixmap_bg_color; // the RGB() of the pixmap background color
+static int color_count; // # of non-transparent colors used in pixmap
+static uchar *used_colors; // used_colors[3*i+j] j=0,1,2 are the RGB values of the ith used color
+
+static void make_unused_color(uchar &r, uchar &g, uchar &b)
+// makes an RGB triplet different from all the colors used in the pixmap
+// and compute win_pixmap_bg_color from this triplet
+{
+  int i;
+  r = 2; g = 3; b = 4;
+  while (1) {
+    for ( i = 0; i < color_count; i++) {
+      if(used_colors[3*i] == r && used_colors[3*i+1] == g && used_colors[3*i+2] == b) break;
+      }
+    if (i >= color_count) {
+      free(used_colors);
+      win_pixmap_bg_color = RGB(r, g, b);
+      return;
+      }
+    if (r < 255) r++;
+    else {
+      r = 0;
+      if (g < 255) g++;
+      else {
+	g = 0;
+	b++;
+	}
+      }
+    }
+}
+#endif
+
 /**
   Draw XPM image data, with the top-left corner at the given position.
   \see fl_draw_pixmap(char* const* data, int x, int y, Fl_Color bg)
@@ -188,6 +222,11 @@ int fl_draw_pixmap(const char*const* cdata, int x, int y, Fl_Color bg) {
   if (!fl_measure_pixmap(cdata, d.w, d.h)) return 0;
   const uchar*const* data = (const uchar*const*)(cdata+1);
   int transparent_index = -1;
+  uchar *transparent_c; // such that transparent_c[0,1,2] are the RGB of the transparent color
+#ifdef WIN32
+  color_count = 0;
+  used_colors = (uchar *)malloc(abs(ncolors)*3*sizeof(uchar));
+#endif
 
   if (ncolors < 0) {	// FLTK (non standard) compressed colormap
     ncolors = -ncolors;
@@ -204,6 +243,7 @@ int fl_draw_pixmap(const char*const* cdata, int x, int y, Fl_Color bg) {
 #endif
       transparent_index = ' ';
       Fl::get_color(bg, c[0], c[1], c[2]); c[3] = 0;
+      transparent_c = c;
       p += 4;
       ncolors--;
     }
@@ -215,6 +255,12 @@ int fl_draw_pixmap(const char*const* cdata, int x, int y, Fl_Color bg) {
 #  if WORDS_BIGENDIAN
       c += 4;
 #  endif
+#endif
+#ifdef WIN32
+      used_colors[3*color_count] = *p;
+      used_colors[3*color_count+1] = *(p+1);
+      used_colors[3*color_count+2] = *(p+2);
+      color_count++;
 #endif
       *c++ = *p++;
       *c++ = *p++;
@@ -266,7 +312,16 @@ int fl_draw_pixmap(const char*const* cdata, int x, int y, Fl_Color bg) {
 #ifdef __APPLE_QUARTZ__
       c[3] = 255;
 #endif
-      if (!fl_parse_color((const char*)p, c[0], c[1], c[2])) {
+      int parse = fl_parse_color((const char*)p, c[0], c[1], c[2]);
+      if (parse) {
+#ifdef WIN32
+	used_colors[3*color_count] = c[0];
+	used_colors[3*color_count+1] = c[1];
+	used_colors[3*color_count+2] = c[2];
+	color_count++;
+#endif
+	}
+      else {
         // assume "None" or "#transparent" for any errors
 	// "bg" should be transparent...
 	Fl::get_color(bg, c[0], c[1], c[2]);
@@ -274,11 +329,14 @@ int fl_draw_pixmap(const char*const* cdata, int x, int y, Fl_Color bg) {
         c[3] = 0;
 #endif
 	transparent_index = ind;
+	transparent_c = c;
       }
     }
   }
   d.data = data;
-
+#ifdef WIN32
+    make_unused_color(transparent_c[0], transparent_c[1], transparent_c[2]);
+#endif
 #ifndef __APPLE_QUARTZ__
 
   // build the mask bitmap used by Fl_Pixmap:
-- 
GitLab