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