[GRASS-SVN] r63595 - in grass/branches/releasebranch_7_0: . lib/cairodriver

svn_grass at osgeo.org svn_grass at osgeo.org
Thu Dec 18 09:04:06 PST 2014


Author: martinl
Date: 2014-12-18 09:04:05 -0800 (Thu, 18 Dec 2014)
New Revision: 63595

Modified:
   grass/branches/releasebranch_7_0/
   grass/branches/releasebranch_7_0/lib/cairodriver/raster.c
Log:
glynn: Make cairo driver rescale rasters rather than having cairo do it (ticket #2403)
     (merge r63582 from trunk)



Property changes on: grass/branches/releasebranch_7_0
___________________________________________________________________
Modified: svn:mergeinfo
   - /grass/trunk:60817,61096,61141,61994,62105,62179-62180,62182,62403,62422,62424,62437,62466,62469,62487,62491,62494,62501,62506,62508-62509,62515,62518-62519,62521,62526,62533,62539,62541,62555,62562,62566,62570,62573,62575,62585,62588,62597,62603,62606,62608-62609,62614,62618,62628,62632,62638,62642,62648-62649,62652,62654-62657,62666,62691,62705,62709,62723,62730,62739,62741,62743,62746,62750,62752,62757,62762,62785,62798,62800-62801,62803,62805,62812,62822,62824,62831,62838,62847,62850,62856,62879,62881,62886,62904,62907-62908,62910,62912,62914,62916,62918,62920,62925,62932-62933,62935,62940,62942,62944-62946,62949,62955-62956,62958,62960,62962,62964,62966-62968,62970,62973,62975,62977,62981,62983,62985,62987,62989,62991,62993,62995,62997,62999-63000,63003,63005,63007,63009,63011,63013,63015,63017,63020,63022,63024,63026,63028-63031,63033,63035,63037,63040,63043-63044,63047,63049,63051,63053,63055,63057,63060,63062-63064,63066,63068,63070-63071,63074,63076,63079,63081,
 63083,63085,63087,63089,63091,63093,63095,63098,63100,63102,63105,63107,63109,63111,63113-63114,63116,63119,63121,63123,63125,63130,63132-63133,63135,63137,63140,63143,63145,63147,63149,63151,63153-63154,63157,63160,63165,63170,63173,63175,63187,63192-63193,63196,63199-63200,63202,63209,63216,63220-63221,63224,63227,63240,63246,63250,63255,63259,63261,63276,63279,63281,63283,63287,63290,63292,63302,63307,63315,63319,63330,63332,63339,63342,63345,63362,63367,63391,63393,63408-63409,63416-63417,63425,63427,63429,63431,63433,63451,63453,63457,63459,63464-63470,63473,63482,63497,63505,63508,63510,63515,63521-63524,63526,63536-63537,63551-63552,63554,63556,63558-63559,63562,63570,63576,63593
   + /grass/trunk:60817,61096,61141,61994,62105,62179-62180,62182,62403,62422,62424,62437,62466,62469,62487,62491,62494,62501,62506,62508-62509,62515,62518-62519,62521,62526,62533,62539,62541,62555,62562,62566,62570,62573,62575,62585,62588,62597,62603,62606,62608-62609,62614,62618,62628,62632,62638,62642,62648-62649,62652,62654-62657,62666,62691,62705,62709,62723,62730,62739,62741,62743,62746,62750,62752,62757,62762,62785,62798,62800-62801,62803,62805,62812,62822,62824,62831,62838,62847,62850,62856,62879,62881,62886,62904,62907-62908,62910,62912,62914,62916,62918,62920,62925,62932-62933,62935,62940,62942,62944-62946,62949,62955-62956,62958,62960,62962,62964,62966-62968,62970,62973,62975,62977,62981,62983,62985,62987,62989,62991,62993,62995,62997,62999-63000,63003,63005,63007,63009,63011,63013,63015,63017,63020,63022,63024,63026,63028-63031,63033,63035,63037,63040,63043-63044,63047,63049,63051,63053,63055,63057,63060,63062-63064,63066,63068,63070-63071,63074,63076,63079,63081,
 63083,63085,63087,63089,63091,63093,63095,63098,63100,63102,63105,63107,63109,63111,63113-63114,63116,63119,63121,63123,63125,63130,63132-63133,63135,63137,63140,63143,63145,63147,63149,63151,63153-63154,63157,63160,63165,63170,63173,63175,63187,63192-63193,63196,63199-63200,63202,63209,63216,63220-63221,63224,63227,63240,63246,63250,63255,63259,63261,63276,63279,63281,63283,63287,63290,63292,63302,63307,63315,63319,63330,63332,63339,63342,63345,63362,63367,63391,63393,63408-63409,63416-63417,63425,63427,63429,63431,63433,63448,63451,63453,63457,63459,63464-63470,63473,63482,63497,63505,63508,63510,63515,63521-63524,63526,63536-63537,63551-63552,63554,63556,63558-63559,63562,63570,63576,63582,63593

Modified: grass/branches/releasebranch_7_0/lib/cairodriver/raster.c
===================================================================
--- grass/branches/releasebranch_7_0/lib/cairodriver/raster.c	2014-12-18 16:29:30 UTC (rev 63594)
+++ grass/branches/releasebranch_7_0/lib/cairodriver/raster.c	2014-12-18 17:04:05 UTC (rev 63595)
@@ -3,7 +3,7 @@
 
   \brief GRASS cairo display driver - draw raster
 
-  (C) 2007-2008 by Lars Ahlzen and the GRASS Development Team
+  (C) 2007-2014 by Lars Ahlzen and the GRASS Development Team
   
   This program is free software under the GNU General Public License
   (>=v2). Read the file COPYING that comes with GRASS for details.
@@ -12,39 +12,74 @@
   \author Glynn Clements  
 */
 
+#include <math.h>
 
 #include "cairodriver.h"
 #include <grass/glocale.h>
 
+#define MAX_IMAGE_SIZE 32767
+#ifndef MIN
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#endif
+#ifndef MAX
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#endif
+
 static int src_t, src_b, src_l, src_r, src_w, src_h;
-static double dst_t, dst_b, dst_l, dst_r, dst_w, dst_h;
+static int dst_t, dst_b, dst_l, dst_r, dst_w, dst_h;
 
+static int *trans;
+
 static cairo_surface_t *src_surf;
 static unsigned char *src_data;
-static int src_stride;
+static int src_stride, ca_row;
 
 static int masked;
 
+static double scale(double k, int src_0, int src_1, int dst_0, int dst_1)
+{
+    return dst_0 + (double) (k - src_0) * (dst_1 - dst_0) / (src_1 - src_0);
+}
+
+static int scale_fwd_y(int sy)
+{
+    return (int)floor(scale(sy, src_t, src_b, dst_t, dst_b) + 0.5);
+}
+
+static int scale_rev_x(int dx)
+{
+    return (int)floor(scale(dx + 0.5, dst_l, dst_r, src_l, src_r));
+}
+
+static int next_row(int sy, int dy)
+{
+    sy++;
+
+    for (;;) {
+	int y = scale_fwd_y(sy);
+
+	if (y > dy)
+	    return sy - 1;
+	sy++;
+    }
+}
+
 /*!
   \brief Start drawing raster
 
-  \param mask
-  \param s
-  \param d
+  \todo are top and left swapped?
+
+  \param mask non-zero int for mask
+  \param s source (map) extent (left, right, top, bottom)
+  \param d destination (image) extent (left, right, top, bottom)
 */
 void Cairo_begin_raster(int mask, int s[2][2], double d[2][2])
 {
+    int i;
     cairo_status_t status;
     
-    G_debug(1, "Cairo_begin_raster: %d, %d %d %d %d, %f %f %f %f",
-	    mask,
-	    s[0][0], s[0][1], s[1][0], s[1][1],
-	    d[0][0], d[0][1], d[1][0], d[1][1]);
-
     masked = mask;
 
-    /* TODO: are top and left swapped? */
-
     src_l = s[0][0];
     src_r = s[0][1];
     src_t = s[1][0];
@@ -53,39 +88,43 @@
     src_w = src_r - src_l;
     src_h = src_b - src_t;
 
-    dst_l = d[0][0];
-    dst_r = d[0][1];
-    dst_t = d[1][0];
-    dst_b = d[1][1];
+    dst_l = (int) floor(d[0][0] + 0.5);
+    dst_r = (int) floor(d[0][1] + 0.5);
+    dst_t = (int) floor(d[1][0] + 0.5);
+    dst_b = (int) floor(d[1][1] + 0.5);
 
     dst_w = dst_r - dst_l;
     dst_h = dst_b - dst_t;
 
-    G_debug(1, " src (TBLR): %d %d %d %d, dst (TBLR) %f %f %f %f",
-	    src_t, src_b, src_l, src_r, dst_t, dst_b, dst_l, dst_r);
+    G_debug(1, "Cairo_begin_raster(): masked=%d, src_lrtb=%d %d %d %d -> w/h=%d/%d, "
+            "dst_lrtb=%d %d %d %d -> w/h=%d %d",
+            masked, src_l, src_r, src_t, src_b, src_w, src_h,
+            dst_l, dst_r, dst_t, dst_b, dst_w, dst_h);
 
     /* create source surface */
-    src_surf = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, src_w, src_h);
+    src_surf = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, ca.width, ca.height);
     status = cairo_surface_status(src_surf);
     if (status != CAIRO_STATUS_SUCCESS)
-#ifdef HAVE_LONG_LONG_INT
-        G_fatal_error("Cairo_begin_raster(): %s - %s. Using rows: %d, cols: %d, cells: %lld.",
-                      _("Failed to create surface"),
-                      cairo_status_to_string (status), src_b, src_r, (long long) src_b * src_r);
-#else
-        G_fatal_error("Cairo_begin_raster(): %s - %s. Using rows: %d, cols: %d, cells: %ld.",
-                      _("Failed to create surface"),
-                      cairo_status_to_string (status), src_b, src_r, (long) src_b * src_r);
-#endif
+        G_fatal_error("%s - %s - size: %dx%d (cairo limit: %dx%d)",
+                      _("Failed to create cairo surface"),
+                      cairo_status_to_string (status), ca.width, ca.height,
+                      MAX_IMAGE_SIZE, MAX_IMAGE_SIZE);
+
     src_data = cairo_image_surface_get_data(src_surf);
     src_stride = cairo_image_surface_get_stride(src_surf);
+    ca_row = 0;
+
+    /* allocate buffer for down-sampling data */
+    trans = G_malloc(dst_w * sizeof(int));
+    for (i = 0; i < dst_w; i++)
+        trans[i] = scale_rev_x(dst_l + i);
 }
 
 /*!
   \brief Draw raster row
 
-  \param n number of cell
-  \param row raster row
+  \param n number of cells
+  \param row raster row (starting at 0)
   \param red,grn,blu,nul red,green,blue and null value
 
   \return next row
@@ -94,26 +133,45 @@
 		 const unsigned char *red, const unsigned char *grn,
 		 const unsigned char *blu, const unsigned char *nul)
 {
-    unsigned int *dst =
-	(unsigned int *)(src_data + (row - src_t) * src_stride);
-    int i;
+    int d_y0 = scale_fwd_y(row + 0);
+    int d_y1 = scale_fwd_y(row + 1);
+    int d_rows = d_y1 - d_y0;
+    int x0 = MAX(0        - dst_l, 0);
+    int x1 = MIN(ca.width - dst_l, dst_w);
+    int y0 = MAX(0         - d_y0, 0);
+    int y1 = MIN(ca.height - d_y0, d_rows);
+    int x, y;
 
-    G_debug(3, "Cairo_raster: %d %d", n, row);
+    if (y1 <= y0)
+        return next_row(row, d_y1);
 
-    for (i = 0; i < n; i++) {
-	if (masked && nul && nul[i])
-	    *dst++ = 0;
+    G_debug(3, "Cairo_raster(): row=%d", row);
+
+    for (x = x0; x < x1; x++) {
+	int xx = dst_l + x;
+        int j = trans[x];
+	unsigned int c;
+
+	if (masked && nul && nul[j])
+	    c = 0;
 	else {
-	    unsigned int r = red[i];
-	    unsigned int g = grn[i];
-	    unsigned int b = blu[i];
+	    unsigned int r = red[j];
+	    unsigned int g = grn[j];
+	    unsigned int b = blu[j];
 	    unsigned int a = 0xFF;
+	    c = (a << 24) + (r << 16) + (g << 8) + (b << 0);
+	}
 
-	    *dst++ = (a << 24) + (r << 16) + (g << 8) + (b << 0);
-	}
+	for (y = y0; y < y1; y++) {
+	    int yy = d_y0 + y;
+	    *(unsigned int *)(src_data + yy * src_stride + xx * 4) = c;
+        }
     }
 
-    return row + 1;
+    ca.modified = 1;
+    ca_row++;
+
+    return next_row(row, d_y1);
 }
 
 /*!
@@ -121,12 +179,12 @@
 */
 void Cairo_end_raster(void)
 {
-    G_debug(1, "Cairo_end_raster");
+    G_debug(1, "Cairo_end_raster()");
 
-    /* paint source surface onto dstination (scaled) */
+    /* paint source surface onto destination (scaled) */
     cairo_save(cairo);
-    cairo_translate(cairo, dst_l, dst_t);
-    cairo_scale(cairo, dst_w / src_w, dst_h / src_h);
+    /* cairo_translate(cairo, dst_l, dst_t); */
+    /* cairo_scale(cairo, dst_w / src_w, dst_h / src_h); */
     cairo_surface_mark_dirty(src_surf);
     cairo_set_source_surface(cairo, src_surf, 0, 0);
     cairo_pattern_set_filter(cairo_get_source(cairo), CAIRO_FILTER_NEAREST);
@@ -134,6 +192,7 @@
     cairo_restore(cairo);
 
     /* cleanup */
+    G_free(trans);
     cairo_surface_destroy(src_surf);
     ca.modified = 1;
 }



More information about the grass-commit mailing list