32
pixel_surround_init (PixelSurround *ps,
36
guchar bg[MAX_CHANNELS])
40
for (i = 0; i < MAX_CHANNELS; ++i)
47
ps->bpp = tile_manager_bpp (tm);
50
/* make sure buffer is big enough */
51
ps->buff_size = w * h * ps->bpp;
52
ps->buff = g_new (guchar, ps->buff_size);
57
pixel_surround_lock (PixelSurround *ps,
65
ps->tile = tile_manager_get_tile (ps->mgr, x, y, TRUE, FALSE);
70
/* do we have the whole region? */
72
(i < (tile_ewidth(ps->tile) - ps->w)) &&
73
(j < (tile_eheight(ps->tile) - ps->h)))
75
ps->row_stride = tile_ewidth (ps->tile) * ps->bpp;
76
/* is this really the correct way? */
77
return tile_data_pointer (ps->tile, i, j);
80
/* nope, do this the hard way (for now) */
83
tile_release (ps->tile, FALSE);
87
/* copy pixels, one by one */
88
/* no, this is not the best way, but it's much better than before */
90
for (j = y; j < y+ps->h; ++j)
92
for (i = x; i < x+ps->w; ++i)
94
Tile *tile = tile_manager_get_tile (ps->mgr, i, j, TRUE, FALSE);
98
guchar *buff = tile_data_pointer (tile,
102
for (k = buff; k < buff+ps->bpp; ++k, ++ptr)
106
tile_release (tile, FALSE);
110
for (k = ps->bg; k < ps->bg+ps->bpp; ++k, ++ptr)
117
ps->row_stride = ps->w * ps->bpp;
123
pixel_surround_rowstride (PixelSurround *ps)
125
return ps->row_stride;
129
pixel_surround_release (PixelSurround *ps)
131
/* always get new tile (for now), so release the old one */
134
tile_release (ps->tile, FALSE);
140
pixel_surround_clear (PixelSurround *ps)
35
TileManager *mgr; /* tile manager to access tiles from */
36
gint bpp; /* bytes per pixel in tile manager */
37
gint w; /* width of pixel surround area */
38
gint h; /* height of pixel surround area */
39
Tile *tile; /* locked tile (may be NULL) */
40
gint tile_x; /* origin of locked tile */
41
gint tile_y; /* origin of locked tile */
42
gint tile_w; /* width of locked tile */
43
gint tile_h; /* height of locked tile */
44
gint rowstride; /* rowstride of buffers */
45
guchar *bg; /* buffer filled with background color */
46
guchar *buf; /* buffer used for combining tile data */
50
/* inlining this function gives a few percent speedup */
51
static inline const guchar *
52
pixel_surround_get_data (PixelSurround *surround,
59
/* do we still have a tile lock that we can use? */
62
if (x < surround->tile_x || x >= surround->tile_x + surround->tile_w ||
63
y < surround->tile_y || y >= surround->tile_y + surround->tile_h)
65
tile_release (surround->tile, FALSE);
66
surround->tile = NULL;
70
/* if not, try to get one for the target pixel */
73
surround->tile = tile_manager_get_tile (surround->mgr, x, y, TRUE, FALSE);
77
/* store offset and size of the locked tile */
78
surround->tile_x = x & ~(TILE_WIDTH - 1);
79
surround->tile_y = y & ~(TILE_HEIGHT - 1);
80
surround->tile_w = tile_ewidth (surround->tile);
81
surround->tile_h = tile_eheight (surround->tile);
87
*w = surround->tile_x + surround->tile_w - x;
88
*h = surround->tile_y + surround->tile_h - y;
90
*rowstride = surround->tile_w * surround->bpp;
92
return tile_data_pointer (surround->tile,
93
x % TILE_WIDTH, y % TILE_HEIGHT);
97
/* return a pointer to a virtual background tile */
99
*w = MIN (- x, surround->w);
104
*h = MIN (- y, surround->h);
108
*rowstride = surround->rowstride;
115
* pixel_surround_new:
116
* @tiles: tile manager
117
* @width: width of surround region
118
* @height: height of surround region
119
* @bg: color to use for pixels that are not covered by the tile manager
121
* Return value: a new #PixelSurround.
124
pixel_surround_new (TileManager *tiles,
127
const guchar bg[MAX_CHANNELS])
129
PixelSurround *surround;
133
g_return_val_if_fail (tiles != NULL, NULL);
135
surround = g_new0 (PixelSurround, 1);
137
surround->mgr = tiles;
138
surround->bpp = tile_manager_bpp (tiles);
140
surround->h = height;
141
surround->rowstride = width * surround->bpp;
142
surround->bg = g_new (guchar, surround->rowstride * height);
143
surround->buf = g_new (guchar, surround->rowstride * height);
146
pixels = width * height;
152
for (i = 0; i < surround->bpp; i++)
160
* pixel_surround_lock:
161
* @surround: a #PixelSurround
162
* @x: X coordinate of upper left corner
163
* @y: Y coordinate of upper left corner
164
* @rowstride: return location for rowstride
166
* Gives access to a region of pixels. The upper left corner is
167
* specified by the @x and @y parameters. The size of the region
168
* is determined by the dimensions given when creating the @surround.
170
* When you don't need to read from the pixels any longer, you should
171
* unlock the @surround using pixel_surround_unlock(). If you need a
172
* different region, just call pixel_surround_lock() again.
174
* Return value: pointer to pixel data (read-only)
177
pixel_surround_lock (PixelSurround *surround,
185
src = pixel_surround_get_data (surround, x, y, &w, &h, rowstride);
187
if (w >= surround->w && h >= surround->h)
189
/* return a pointer to the data if it covers the whole region */
194
/* otherwise, copy region to our internal buffer */
195
guchar *dest = surround->buf;
196
gint inc = surround->w;
200
/* These loops are somewhat twisted. The idea is to make as few
201
* calls to pixel_surround_get_data() as possible. Thus whenever we
202
* have source data, we copy all of it to the destination buffer.
203
* The inner loops that copy data are nested into outer loops that
204
* make sure that the destination area is completley filled.
207
/* jump right into the loops since we already have source data */
210
while (i < surround->w)
212
dest = surround->buf + i * surround->bpp;
214
for (j = 0; j < surround->h;)
218
src = pixel_surround_get_data (surround,
219
x + i, y + j, &w, &h, rowstride);
223
w = MIN (w, surround->w - i);
224
h = MIN (h, surround->h - j);
230
memcpy (dest, src, w * surround->bpp);
233
dest += surround->rowstride;
244
*rowstride = surround->rowstride;
246
return surround->buf;
250
* pixel_surround_release:
251
* @surround: #PixelSurround
253
* Unlocks pixels locked by @surround. See pixel_surround_lock().
256
pixel_surround_release (PixelSurround *surround)
260
tile_release (surround->tile, FALSE);
261
surround->tile = NULL;
266
* pixel_surround_destroy:
267
* @surround: #PixelSurround
269
* Unlocks pixels and frees any resources allocated for @surround. You
270
* must not use @surround any longer after calling this function.
273
pixel_surround_destroy (PixelSurround *surround)
275
g_return_if_fail (surround != NULL);
277
pixel_surround_release (surround);
279
g_free (surround->buf);
280
g_free (surround->bg);