GRASS GIS 8 Programmer's Manual  8.4.0dev(2024)-6c790bf5c0
cairodriver/raster.c
Go to the documentation of this file.
1 /*!
2  \file lib/cairodriver/raster.c
3 
4  \brief GRASS cairo display driver - draw raster
5 
6  (C) 2007-2014 by Lars Ahlzen and the GRASS Development Team
7 
8  This program is free software under the GNU General Public License
9  (>=v2). Read the file COPYING that comes with GRASS for details.
10 
11  \author Lars Ahlzen <lars ahlzen.com> (original contributor)
12  \author Glynn Clements
13  */
14 
15 #include <math.h>
16 
17 #include "cairodriver.h"
18 #include <grass/gis.h>
19 #include <grass/glocale.h>
20 
21 #define MAX_IMAGE_SIZE 32767
22 
23 static int src_t, src_b, src_l, src_r, src_w, src_h;
24 static int dst_t, dst_b, dst_l, dst_r, dst_w, dst_h;
25 
26 static int *trans;
27 
28 static cairo_surface_t *src_surf;
29 static unsigned char *src_data;
30 static int src_stride, ca_row;
31 
32 static int masked;
33 
34 static double scale(double k, int src_0, int src_1, int dst_0, int dst_1)
35 {
36  return dst_0 + (double)(k - src_0) * (dst_1 - dst_0) / (src_1 - src_0);
37 }
38 
39 static int scale_fwd_y(int sy)
40 {
41  return (int)floor(scale(sy, src_t, src_b, dst_t, dst_b) + 0.5);
42 }
43 
44 static int scale_rev_x(int dx)
45 {
46  return (int)floor(scale(dx + 0.5, dst_l, dst_r, src_l, src_r));
47 }
48 
49 static int next_row(int sy, int dy)
50 {
51  sy++;
52 
53  for (;;) {
54  int y = scale_fwd_y(sy);
55 
56  if (y > dy)
57  return sy - 1;
58  sy++;
59  }
60 }
61 
62 /*!
63  \brief Start drawing raster
64 
65  \todo are top and left swapped?
66 
67  \param mask non-zero int for mask
68  \param s source (map) extent (left, right, top, bottom)
69  \param d destination (image) extent (left, right, top, bottom)
70  */
71 void Cairo_begin_raster(int mask, int s[2][2], double d[2][2])
72 {
73  int i;
74  cairo_status_t status;
75 
76  masked = mask;
77 
78  src_l = s[0][0];
79  src_r = s[0][1];
80  src_t = s[1][0];
81  src_b = s[1][1];
82 
83  src_w = src_r - src_l;
84  src_h = src_b - src_t;
85 
86  dst_l = (int)floor(d[0][0] + 0.5);
87  dst_r = (int)floor(d[0][1] + 0.5);
88  dst_t = (int)floor(d[1][0] + 0.5);
89  dst_b = (int)floor(d[1][1] + 0.5);
90 
91  dst_w = dst_r - dst_l;
92  dst_h = dst_b - dst_t;
93 
94  G_debug(
95  1,
96  "Cairo_begin_raster(): masked=%d, src_lrtb=%d %d %d %d -> w/h=%d %d, "
97  "dst_lrtb=%d %d %d %d -> w/h=%d %d",
98  masked, src_l, src_r, src_t, src_b, src_w, src_h, dst_l, dst_r, dst_t,
99  dst_b, dst_w, dst_h);
100 
101  /* create source surface */
102  src_surf =
103  cairo_image_surface_create(CAIRO_FORMAT_ARGB32, ca.width, ca.height);
104  status = cairo_surface_status(src_surf);
105  if (status != CAIRO_STATUS_SUCCESS)
106  G_fatal_error("%s - %s - size: %dx%d (cairo limit: %dx%d)",
107  _("Failed to create cairo surface"),
108  cairo_status_to_string(status), ca.width, ca.height,
110 
111  src_data = cairo_image_surface_get_data(src_surf);
112  src_stride = cairo_image_surface_get_stride(src_surf);
113  ca_row = 0;
114 
115  /* allocate buffer for down-sampling data */
116  trans = G_malloc(dst_w * sizeof(int));
117  for (i = 0; i < dst_w; i++)
118  trans[i] = scale_rev_x(dst_l + i);
119 }
120 
121 /*!
122  \brief Draw raster row
123 
124  \param n number of cells
125  \param row raster row (starting at 0)
126  \param red,grn,blu,nul red,green,blue and null value
127 
128  \return next row
129  */
130 int Cairo_raster(int n, int row, const unsigned char *red,
131  const unsigned char *grn, const unsigned char *blu,
132  const unsigned char *nul)
133 {
134  int d_y0 = scale_fwd_y(row + 0);
135  int d_y1 = scale_fwd_y(row + 1);
136  int d_rows = d_y1 - d_y0;
137  int x0 = MAX(0 - dst_l, 0);
138  int x1 = MIN(ca.width - dst_l, dst_w);
139  int y0 = MAX(0 - d_y0, 0);
140  int y1 = MIN(ca.height - d_y0, d_rows);
141  int x, y;
142 
143  if (y1 <= y0)
144  return next_row(row, d_y1);
145 
146  G_debug(3, "Cairo_raster(): n=%d row=%d", n, row);
147 
148  for (x = x0; x < x1; x++) {
149  int xx = dst_l + x;
150  int j = trans[x];
151  unsigned int c;
152 
153  if (masked && nul && nul[j])
154  c = 0;
155  else {
156  unsigned int r = red[j];
157  unsigned int g = grn[j];
158  unsigned int b = blu[j];
159  unsigned int a = 0xFF;
160 
161  c = (a << 24) + (r << 16) + (g << 8) + (b << 0);
162  }
163 
164  for (y = y0; y < y1; y++) {
165  int yy = d_y0 + y;
166 
167  *(unsigned int *)(src_data + yy * src_stride + xx * 4) = c;
168  }
169  }
170 
171  ca.modified = 1;
172  ca_row++;
173 
174  return next_row(row, d_y1);
175 }
176 
177 /*!
178  \brief Finish drawing raster
179  */
181 {
182  G_debug(1, "Cairo_end_raster()");
183 
184  /* paint source surface onto destination (scaled) */
185  cairo_save(cairo);
186  /* cairo_translate(cairo, dst_l, dst_t); */
187  /* cairo_scale(cairo, dst_w / src_w, dst_h / src_h); */
188  cairo_surface_mark_dirty(src_surf);
189  cairo_set_source_surface(cairo, src_surf, 0, 0);
190  cairo_pattern_set_filter(cairo_get_source(cairo), CAIRO_FILTER_NEAREST);
191  cairo_paint(cairo);
192  cairo_restore(cairo);
193 
194  /* cleanup */
195  G_free(trans);
196  cairo_surface_destroy(src_surf);
197  ca.modified = 1;
198 }
void Cairo_begin_raster(int mask, int s[2][2], double d[2][2])
Start drawing raster.
void Cairo_end_raster(void)
Finish drawing raster.
#define MAX_IMAGE_SIZE
int Cairo_raster(int n, int row, const unsigned char *red, const unsigned char *grn, const unsigned char *blu, const unsigned char *nul)
Draw raster row.
GRASS cairo display driver - header file.
struct cairo_state ca
cairo_t * cairo
void G_free(void *)
Free allocated memory.
Definition: gis/alloc.c:150
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
#define G_malloc(n)
Definition: defs/gis.h:94
int G_debug(int, const char *,...) __attribute__((format(printf
#define MIN(a, b)
Definition: gis.h:154
#define MAX(a, b)
Definition: gis.h:149
#define _(str)
Definition: glocale.h:10
float g
Definition: named_colr.c:7
double b
Definition: r_raster.c:39
double r
Definition: r_raster.c:39
#define x