~ubuntu-branches/ubuntu/jaunty/gimp/jaunty-security

« back to all changes in this revision

Viewing changes to app/base/tile-manager.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2007-05-02 16:33:03 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20070502163303-bvzhjzbpw8qglc4y
Tags: 2.3.16-1ubuntu1
* Resynchronized with Debian, remaining Ubuntu changes:
  - debian/rules: i18n magic.
* debian/control.in:
  - Maintainer: Ubuntu Core Developers <ubuntu-devel@lists.ubuntu.com>
* debian/patches/02_help-message.patch,
  debian/patches/03_gimp.desktop.in.in.patch,
  debian/patches/10_dont_show_wizard.patch: updated.
* debian/patches/04_composite-signedness.patch,
  debian/patches/05_add-letter-spacing.patch: dropped, used upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* The GIMP -- an image manipulation program
 
1
/* GIMP - The GNU Image Manipulation Program
2
2
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3
3
 *
4
4
 * This program is free software; you can redistribute it and/or modify
32
32
#include "tile-swap.h"
33
33
 
34
34
 
35
 
static gint  tile_manager_get_tile_num (TileManager *tm,
36
 
                                        gint         xpixel,
37
 
                                        gint         ypixel);
 
35
static inline gint
 
36
tile_manager_get_tile_num (TileManager *tm,
 
37
                           gint         xpixel,
 
38
                           gint         ypixel)
 
39
{
 
40
  if ((xpixel < 0) || (xpixel >= tm->width) ||
 
41
      (ypixel < 0) || (ypixel >= tm->height))
 
42
    return -1;
 
43
 
 
44
  return (ypixel / TILE_HEIGHT) * tm->ntile_cols + (xpixel / TILE_WIDTH);
 
45
}
38
46
 
39
47
 
40
48
TileManager *
41
 
tile_manager_new (gint toplevel_width,
42
 
                  gint toplevel_height,
43
 
                  gint bpp)
 
49
tile_manager_new (gint width,
 
50
                  gint height,
 
51
                  gint bpp)
44
52
{
45
53
  TileManager *tm;
46
 
  gint         width;
47
 
  gint         height;
48
54
 
49
 
  g_return_val_if_fail (toplevel_width > 0, NULL);
50
 
  g_return_val_if_fail (toplevel_height > 0, NULL);
51
 
  g_return_val_if_fail (bpp  > 0, NULL);
 
55
  g_return_val_if_fail (width > 0 && height > 0, NULL);
 
56
  g_return_val_if_fail (bpp > 0 && bpp <= 4, NULL);
52
57
 
53
58
  tm = g_new0 (TileManager, 1);
54
59
 
55
 
  width  = toplevel_width;
56
 
  height = toplevel_height;
57
 
 
58
 
  tm->ref_count     = 1;
59
 
  tm->x             = 0;
60
 
  tm->y             = 0;
61
 
  tm->width         = width;
62
 
  tm->height        = height;
63
 
  tm->bpp           = bpp;
64
 
  tm->ntile_rows    = (height + TILE_HEIGHT - 1) / TILE_HEIGHT;
65
 
  tm->ntile_cols    = (width  + TILE_WIDTH  - 1) / TILE_WIDTH;
66
 
  tm->tiles         = NULL;
67
 
  tm->validate_proc = NULL;
68
 
 
69
 
  tm->cached_num    = -1;
70
 
  tm->cached_tile   = NULL;
71
 
 
72
 
  tm->user_data     = NULL;
 
60
  tm->ref_count  = 1;
 
61
  tm->width      = width;
 
62
  tm->height     = height;
 
63
  tm->bpp        = bpp;
 
64
  tm->ntile_rows = (height + TILE_HEIGHT - 1) / TILE_HEIGHT;
 
65
  tm->ntile_cols = (width  + TILE_WIDTH  - 1) / TILE_WIDTH;
 
66
  tm->cached_num = -1;
73
67
 
74
68
  return tm;
75
69
}
93
87
 
94
88
  if (tm->ref_count < 1)
95
89
    {
96
 
      gint ntiles;
97
 
      gint i;
98
 
 
99
90
      if (tm->cached_tile)
100
91
        tile_release (tm->cached_tile, FALSE);
101
92
 
102
93
      if (tm->tiles)
103
94
        {
104
 
          ntiles = tm->ntile_rows * tm->ntile_cols;
 
95
          gint ntiles = tm->ntile_rows * tm->ntile_cols;
 
96
          gint i;
105
97
 
106
98
          for (i = 0; i < ntiles; i++)
107
 
            {
108
 
              TILE_MUTEX_LOCK (tm->tiles[i]);
109
 
              tile_detach (tm->tiles[i], tm, i);
110
 
            }
 
99
            tile_detach (tm->tiles[i], tm, i);
111
100
 
112
101
          g_free (tm->tiles);
113
102
        }
116
105
    }
117
106
}
118
107
 
119
 
 
120
108
void
121
109
tile_manager_set_validate_proc (TileManager      *tm,
122
 
                                TileValidateProc  proc)
 
110
                                TileValidateProc  proc)
123
111
{
124
112
  g_return_if_fail (tm != NULL);
125
113
 
126
114
  tm->validate_proc = proc;
127
115
}
128
116
 
129
 
 
130
117
Tile *
131
118
tile_manager_get_tile (TileManager *tm,
132
 
                       gint         xpixel,
133
 
                       gint         ypixel,
134
 
                       gint         wantread,
135
 
                       gint         wantwrite)
 
119
                       gint         xpixel,
 
120
                       gint         ypixel,
 
121
                       gint         wantread,
 
122
                       gint         wantwrite)
136
123
{
137
 
  gint tile_num;
138
 
 
139
124
  g_return_val_if_fail (tm != NULL, NULL);
140
125
 
141
 
  tile_num = tile_manager_get_tile_num (tm, xpixel, ypixel);
142
 
  if (tile_num < 0)
143
 
    return NULL;
144
 
 
145
 
  return tile_manager_get (tm, tile_num, wantread, wantwrite);
 
126
  return tile_manager_get (tm,
 
127
                           tile_manager_get_tile_num (tm, xpixel, ypixel),
 
128
                           wantread, wantwrite);
146
129
}
147
130
 
148
131
Tile *
149
132
tile_manager_get (TileManager *tm,
150
 
                  gint         tile_num,
151
 
                  gint         wantread,
152
 
                  gint         wantwrite)
 
133
                  gint         tile_num,
 
134
                  gint         wantread,
 
135
                  gint         wantwrite)
153
136
{
154
137
  Tile **tiles;
155
138
  Tile **tile_ptr;
166
149
  if ((tile_num < 0) || (tile_num >= ntiles))
167
150
    return NULL;
168
151
 
169
 
  if (!tm->tiles)
 
152
  if (! tm->tiles)
170
153
    {
171
154
      tm->tiles = g_new (Tile *, ntiles);
172
155
      tiles = tm->tiles;
178
161
      bottom_tile = tm->height - ((nrows - 1) * TILE_HEIGHT);
179
162
 
180
163
      for (i = 0, k = 0; i < nrows; i++)
181
 
        {
182
 
          for (j = 0; j < ncols; j++, k++)
183
 
            {
184
 
              tiles[k] = g_new (Tile, 1);
185
 
              tile_init (tiles[k], tm->bpp);
186
 
              tile_attach (tiles[k], tm, k);
187
 
 
188
 
              if (j == (ncols - 1))
189
 
                tiles[k]->ewidth = right_tile;
190
 
 
191
 
              if (i == (nrows - 1))
192
 
                tiles[k]->eheight = bottom_tile;
193
 
            }
194
 
        }
 
164
        {
 
165
          for (j = 0; j < ncols; j++, k++)
 
166
            {
 
167
              Tile *new = g_new (Tile, 1);
 
168
 
 
169
              tile_init (new, tm->bpp);
 
170
              tile_attach (new, tm, k);
 
171
 
 
172
              if (j == (ncols - 1))
 
173
                new->ewidth = right_tile;
 
174
 
 
175
              if (i == (nrows - 1))
 
176
                new->eheight = bottom_tile;
 
177
 
 
178
              new->size = new->ewidth * new->eheight * new->bpp;
 
179
 
 
180
              tiles[k] = new;
 
181
            }
 
182
        }
195
183
    }
196
184
 
197
185
  tile_ptr = &tm->tiles[tile_num];
198
186
 
199
 
  if (wantwrite && !wantread)
200
 
    {
201
 
      g_warning ("WRITE-ONLY TILE... UNTESTED!");
202
 
    }
 
187
  if (G_UNLIKELY (wantwrite && !wantread))
 
188
    g_warning ("WRITE-ONLY TILE... UNTESTED!");
203
189
 
204
190
#ifdef DEBUG_TILE_MANAGER
205
 
  if ((*tile_ptr)->share_count && (*tile_ptr)->write_count)
 
191
  if (G_UNLIKELY ((*tile_ptr)->share_count && (*tile_ptr)->write_count))
206
192
    g_printerr (">> MEEPITY %d,%d <<\n",
207
193
                (*tile_ptr)->share_count, (*tile_ptr)->write_count);
208
194
#endif
209
195
 
210
196
  if (wantread)
211
197
    {
212
 
      TILE_MUTEX_LOCK (*tile_ptr);
213
198
      if (wantwrite)
214
 
        {
215
 
          if ((*tile_ptr)->share_count > 1)
216
 
            {
217
 
              /* Copy-on-write required */
218
 
              Tile *newtile = g_new (Tile, 1);
219
 
              gint  newsize;
220
 
 
221
 
              tile_init (newtile, (*tile_ptr)->bpp);
222
 
 
223
 
              newtile->ewidth  = (*tile_ptr)->ewidth;
224
 
              newtile->eheight = (*tile_ptr)->eheight;
225
 
              newtile->valid   = (*tile_ptr)->valid;
226
 
 
227
 
              newsize = tile_size_inline (newtile);
228
 
              newtile->data    = g_new (guchar, newsize);
229
 
 
230
 
              if (!newtile->valid)
231
 
                g_warning ("Oh boy, r/w tile is invalid... we suck. "
232
 
                           "Please report.");
 
199
        {
 
200
          if ((*tile_ptr)->share_count > 1)
 
201
            {
 
202
              /* Copy-on-write required */
 
203
              Tile *new = g_new (Tile, 1);
 
204
 
 
205
              tile_init (new, (*tile_ptr)->bpp);
 
206
 
 
207
              new->ewidth  = (*tile_ptr)->ewidth;
 
208
              new->eheight = (*tile_ptr)->eheight;
 
209
              new->valid   = (*tile_ptr)->valid;
 
210
 
 
211
              new->size    = new->ewidth * new->eheight * new->bpp;
 
212
              new->data    = g_new (guchar, new->size);
233
213
 
234
214
              if ((*tile_ptr)->rowhint)
235
 
                newtile->rowhint = g_memdup ((*tile_ptr)->rowhint,
236
 
                                             newtile->eheight *
 
215
                new->rowhint = g_memdup ((*tile_ptr)->rowhint,
 
216
                                             new->eheight *
237
217
                                             sizeof (TileRowHint));
238
218
 
239
 
              if ((*tile_ptr)->data)
240
 
                {
241
 
                  memcpy (newtile->data, (*tile_ptr)->data, newsize);
242
 
                }
243
 
              else
244
 
                {
245
 
                  tile_lock (*tile_ptr);
246
 
                  memcpy (newtile->data, (*tile_ptr)->data, newsize);
247
 
                  tile_release (*tile_ptr, FALSE);
248
 
                }
249
 
 
250
 
              tile_detach (*tile_ptr, tm, tile_num);
251
 
              TILE_MUTEX_LOCK (newtile);
252
 
              tile_attach (newtile, tm, tile_num);
253
 
              *tile_ptr = newtile;
254
 
            }
255
 
 
256
 
          (*tile_ptr)->write_count++;
257
 
          (*tile_ptr)->dirty = TRUE;
258
 
        }
 
219
              if ((*tile_ptr)->data)
 
220
                {
 
221
                  memcpy (new->data, (*tile_ptr)->data, new->size);
 
222
                }
 
223
              else
 
224
                {
 
225
                  tile_lock (*tile_ptr);
 
226
                  memcpy (new->data, (*tile_ptr)->data, new->size);
 
227
                  tile_release (*tile_ptr, FALSE);
 
228
                }
 
229
 
 
230
              tile_detach (*tile_ptr, tm, tile_num);
 
231
 
 
232
              tile_attach (new, tm, tile_num);
 
233
              *tile_ptr = new;
 
234
            }
 
235
 
 
236
          (*tile_ptr)->write_count++;
 
237
          (*tile_ptr)->dirty = TRUE;
 
238
        }
259
239
#ifdef DEBUG_TILE_MANAGER
260
240
      else
261
 
        {
262
 
          if ((*tile_ptr)->write_count)
263
 
            g_printerr ("STINK! r/o on r/w tile (%d)\n",
 
241
        {
 
242
          if (G_UNLIKELY ((*tile_ptr)->write_count))
 
243
            g_printerr ("STINK! r/o on r/w tile (%d)\n",
264
244
                        (*tile_ptr)->write_count);
265
 
        }
 
245
        }
266
246
#endif
267
247
 
268
 
      TILE_MUTEX_UNLOCK (*tile_ptr);
269
248
      tile_lock (*tile_ptr);
270
249
    }
271
250
 
273
252
}
274
253
 
275
254
void
276
 
tile_manager_get_async (TileManager *tm,
277
 
                        gint         xpixel,
278
 
                        gint         ypixel)
279
 
{
280
 
  Tile *tile_ptr;
281
 
  gint  tile_num;
282
 
 
283
 
  g_return_if_fail (tm != NULL);
284
 
 
285
 
  tile_num = tile_manager_get_tile_num (tm, xpixel, ypixel);
286
 
  if (tile_num < 0)
287
 
    return;
288
 
 
289
 
  tile_ptr = tm->tiles[tile_num];
290
 
 
291
 
  tile_swap_in_async (tile_ptr);
292
 
}
293
 
 
294
 
void
295
255
tile_manager_validate (TileManager *tm,
296
 
                       Tile        *tile)
 
256
                       Tile        *tile)
297
257
{
298
258
  g_return_if_fail (tm != NULL);
299
259
  g_return_if_fail (tile != NULL);
310
270
 
311
271
void
312
272
tile_manager_invalidate_tiles (TileManager *tm,
313
 
                               Tile        *toplevel_tile)
 
273
                               Tile        *toplevel_tile)
314
274
{
315
275
  gdouble x, y;
316
276
  gint    row, col;
317
 
  gint    num;
318
277
 
319
278
  g_return_if_fail (tm != NULL);
320
279
  g_return_if_fail (toplevel_tile != NULL);
322
281
  col = toplevel_tile->tlink->tile_num % tm->ntile_cols;
323
282
  row = toplevel_tile->tlink->tile_num / tm->ntile_cols;
324
283
 
325
 
  x = ((col * TILE_WIDTH  + toplevel_tile->ewidth  / 2.0) /
326
 
       (gdouble) tm->width);
327
 
  y = ((row * TILE_HEIGHT + toplevel_tile->eheight / 2.0) /
328
 
       (gdouble) tm->height);
 
284
  x = (col * TILE_WIDTH  + toplevel_tile->ewidth  / 2.0) / (gdouble) tm->width;
 
285
  y = (row * TILE_HEIGHT + toplevel_tile->eheight / 2.0) / (gdouble) tm->height;
329
286
 
330
287
  if (tm->tiles)
331
288
    {
 
289
      gint num;
 
290
 
332
291
      col = x * tm->width / TILE_WIDTH;
333
292
      row = y * tm->height / TILE_HEIGHT;
 
293
 
334
294
      num = row * tm->ntile_cols + col;
 
295
 
335
296
      tile_invalidate (&tm->tiles[num], tm, num);
336
297
    }
337
298
}
338
299
 
339
 
 
340
300
void
341
301
tile_invalidate_tile (Tile        **tile_ptr,
342
 
                      TileManager  *tm,
343
 
                      gint          xpixel,
344
 
                      gint          ypixel)
 
302
                      TileManager  *tm,
 
303
                      gint          xpixel,
 
304
                      gint          ypixel)
345
305
{
346
 
  gint tile_num;
 
306
  gint num;
347
307
 
348
308
  g_return_if_fail (tile_ptr != NULL);
349
309
  g_return_if_fail (tm != NULL);
350
310
 
351
 
  tile_num = tile_manager_get_tile_num (tm, xpixel, ypixel);
352
 
  if (tile_num < 0)
 
311
  num = tile_manager_get_tile_num (tm, xpixel, ypixel);
 
312
  if (num < 0)
353
313
    return;
354
314
 
355
 
  tile_invalidate (tile_ptr, tm, tile_num);
 
315
  tile_invalidate (tile_ptr, tm, num);
356
316
}
357
317
 
358
 
 
359
318
void
360
319
tile_invalidate (Tile        **tile_ptr,
361
 
                 TileManager  *tm,
362
 
                 gint          tile_num)
 
320
                 TileManager  *tm,
 
321
                 gint          tile_num)
363
322
{
364
323
  Tile *tile = *tile_ptr;
365
324
 
366
325
  g_return_if_fail (tile_ptr != NULL);
367
326
  g_return_if_fail (tm != NULL);
368
327
 
369
 
  TILE_MUTEX_LOCK (tile);
370
 
 
371
 
  if (!tile->valid)
372
 
    goto leave;
373
 
 
374
 
  if (tile->share_count > 1)
 
328
  if (! tile->valid)
 
329
    return;
 
330
 
 
331
  if (G_UNLIKELY (tile->share_count > 1))
375
332
    {
376
333
      /* This tile is shared.  Replace it with a new, invalid tile. */
377
 
      Tile *newtile = g_new (Tile, 1);
 
334
      Tile *new = g_new (Tile, 1);
378
335
 
379
336
      g_print ("invalidating shared tile (executing buggy code!!!)\n");
380
337
 
381
 
      tile_init (newtile, tile->bpp);
382
 
      newtile->ewidth  = tile->ewidth;
383
 
      newtile->eheight = tile->eheight;
 
338
      tile_init (new, tile->bpp);
 
339
 
 
340
      new->ewidth  = tile->ewidth;
 
341
      new->eheight = tile->eheight;
 
342
      new->size    = tile->size;
 
343
 
384
344
      tile_detach (tile, tm, tile_num);
385
 
      TILE_MUTEX_LOCK (newtile);
386
 
      tile_attach (newtile, tm, tile_num);
387
 
      tile = *tile_ptr = newtile;
 
345
 
 
346
      tile_attach (new, tm, tile_num);
 
347
      tile = *tile_ptr = new;
388
348
    }
389
349
 
390
350
  if (tile->listhead)
391
351
    tile_cache_flush (tile);
392
352
 
393
353
  tile->valid = FALSE;
 
354
 
394
355
  if (tile->data)
395
356
    {
396
357
      g_free (tile->data);
397
358
      tile->data = NULL;
398
359
    }
 
360
 
399
361
  if (tile->swap_offset != -1)
400
362
    {
401
363
      /* If the tile is on disk, then delete its
403
365
       */
404
366
      tile_swap_delete (tile);
405
367
    }
406
 
 
407
 
leave:
408
 
  TILE_MUTEX_UNLOCK (tile);
409
368
}
410
369
 
411
 
 
412
370
void
413
371
tile_manager_map_tile (TileManager *tm,
414
 
                       gint         xpixel,
415
 
                       gint         ypixel,
416
 
                       Tile        *srctile)
 
372
                       gint         xpixel,
 
373
                       gint         ypixel,
 
374
                       Tile        *srctile)
417
375
{
418
 
  gint tile_row;
419
 
  gint tile_col;
420
 
  gint tile_num;
 
376
  gint num;
421
377
 
422
378
  g_return_if_fail (tm != NULL);
423
379
  g_return_if_fail (srctile != NULL);
424
380
 
425
 
  if ((xpixel < 0) || (xpixel >= tm->width) ||
426
 
      (ypixel < 0) || (ypixel >= tm->height))
 
381
  num = tile_manager_get_tile_num (tm, xpixel, ypixel);
 
382
 
 
383
  if (G_UNLIKELY (num < 0))
427
384
    {
428
 
      g_warning ("tile_manager_map_tile: tile co-ord out of range.");
 
385
      g_warning ("%s: tile coordinates out of range.", G_GNUC_FUNCTION);
429
386
      return;
430
387
    }
431
388
 
432
 
  tile_row = ypixel / TILE_HEIGHT;
433
 
  tile_col = xpixel / TILE_WIDTH;
434
 
  tile_num = tile_row * tm->ntile_cols + tile_col;
435
 
 
436
 
  tile_manager_map (tm, tile_num, srctile);
 
389
  tile_manager_map (tm, num, srctile);
437
390
}
438
391
 
439
392
void
440
393
tile_manager_map (TileManager *tm,
441
 
                  gint         tile_num,
442
 
                  Tile        *srctile)
 
394
                  gint         tile_num,
 
395
                  Tile        *srctile)
443
396
{
444
397
  Tile **tiles;
445
398
  Tile **tile_ptr;
454
407
 
455
408
  ntiles = tm->ntile_rows * tm->ntile_cols;
456
409
 
457
 
  if ((tile_num < 0) || (tile_num >= ntiles))
 
410
  if (G_UNLIKELY ((tile_num < 0) || (tile_num >= ntiles)))
458
411
    {
459
 
      g_warning ("tile_manager_map: tile out of range.");
 
412
      g_warning ("%s: tile out of range", G_GNUC_FUNCTION);
460
413
      return;
461
414
    }
462
415
 
463
 
  if (!tm->tiles)
 
416
  if (G_UNLIKELY (! tm->tiles))
464
417
    {
465
 
      g_warning ("tile_manager_map: empty tile level - init'ing.");
 
418
      g_warning ("%s: empty tile level - initializing", G_GNUC_FUNCTION);
466
419
 
467
420
      tm->tiles = g_new (Tile *, ntiles);
468
421
      tiles = tm->tiles;
474
427
      bottom_tile = tm->height - ((nrows - 1) * TILE_HEIGHT);
475
428
 
476
429
      for (i = 0, k = 0; i < nrows; i++)
477
 
        {
478
 
          for (j = 0; j < ncols; j++, k++)
479
 
            {
 
430
        {
 
431
          for (j = 0; j < ncols; j++, k++)
 
432
            {
 
433
              Tile *new = g_new (Tile, 1);
 
434
 
480
435
#ifdef DEBUG_TILE_MANAGER
481
 
              g_printerr (",");
 
436
              g_printerr (",");
482
437
#endif
483
 
              tiles[k] = g_new (Tile, 1);
484
 
              tile_init (tiles[k], tm->bpp);
485
 
              tile_attach (tiles[k], tm, k);
486
 
 
487
 
              if (j == (ncols - 1))
488
 
                tiles[k]->ewidth = right_tile;
489
 
 
490
 
              if (i == (nrows - 1))
491
 
                tiles[k]->eheight = bottom_tile;
492
 
            }
493
 
        }
 
438
              tile_init (new, tm->bpp);
 
439
              tile_attach (new, tm, k);
 
440
 
 
441
              if (j == (ncols - 1))
 
442
                new->ewidth = right_tile;
 
443
 
 
444
              if (i == (nrows - 1))
 
445
                new->eheight = bottom_tile;
 
446
 
 
447
              new->size = new->ewidth * new->eheight * new->bpp;
 
448
 
 
449
              tiles[k] = new;
 
450
            }
 
451
        }
494
452
    }
495
453
 
496
454
  tile_ptr = &tm->tiles[tile_num];
499
457
  g_printerr (")");
500
458
#endif
501
459
 
502
 
  if (!srctile->valid)
503
 
    g_warning("tile_manager_map: srctile not validated yet!  please report.");
 
460
  if (G_UNLIKELY (! srctile->valid))
 
461
    g_warning("%s: srctile not validated yet!  please report", G_GNUC_FUNCTION);
504
462
 
505
 
  TILE_MUTEX_LOCK (*tile_ptr);
506
 
  if ((*tile_ptr)->ewidth  != srctile->ewidth ||
507
 
      (*tile_ptr)->eheight != srctile->eheight ||
508
 
      (*tile_ptr)->bpp     != srctile->bpp)
 
463
  if (G_UNLIKELY ((*tile_ptr)->ewidth  != srctile->ewidth  ||
 
464
                  (*tile_ptr)->eheight != srctile->eheight ||
 
465
                  (*tile_ptr)->bpp     != srctile->bpp))
509
466
    {
510
 
      g_warning ("tile_manager_map: nonconformant map (%p -> %p)",
511
 
                 srctile, *tile_ptr);
 
467
      g_warning ("%s: nonconformant map (%p -> %p)",
 
468
                 G_GNUC_FUNCTION, srctile, *tile_ptr);
512
469
    }
 
470
 
513
471
  tile_detach (*tile_ptr, tm, tile_num);
514
472
 
515
473
#ifdef DEBUG_TILE_MANAGER
516
474
  g_printerr (">");
517
475
#endif
518
476
 
519
 
  TILE_MUTEX_LOCK (srctile);
520
 
 
521
477
#ifdef DEBUG_TILE_MANAGER
522
478
  g_printerr (" [src:%p tm:%p tn:%d] ", srctile, tm, tile_num);
523
479
#endif
525
481
  tile_attach (srctile, tm, tile_num);
526
482
  *tile_ptr = srctile;
527
483
 
528
 
  TILE_MUTEX_UNLOCK (srctile);
529
 
 
530
484
#ifdef DEBUG_TILE_MANAGER
531
485
  g_printerr ("}\n");
532
486
#endif
533
487
}
534
488
 
535
 
static gint
536
 
tile_manager_get_tile_num (TileManager *tm,
537
 
                           gint         xpixel,
538
 
                           gint         ypixel)
539
 
{
540
 
  gint tile_row;
541
 
  gint tile_col;
542
 
  gint tile_num;
543
 
 
544
 
  g_return_val_if_fail (tm != NULL, -1);
545
 
 
546
 
  if ((xpixel < 0) || (xpixel >= tm->width) ||
547
 
      (ypixel < 0) || (ypixel >= tm->height))
548
 
    return -1;
549
 
 
550
 
  tile_row = ypixel / TILE_HEIGHT;
551
 
  tile_col = xpixel / TILE_WIDTH;
552
 
  tile_num = tile_row * tm->ntile_cols + tile_col;
553
 
 
554
 
  return tile_num;
555
 
}
556
 
 
557
489
void
558
490
tile_manager_set_user_data (TileManager *tm,
559
 
                            gpointer     user_data)
 
491
                            gpointer     user_data)
560
492
{
561
493
  g_return_if_fail (tm != NULL);
562
494
 
597
529
 
598
530
void
599
531
tile_manager_get_offsets (const TileManager *tm,
600
 
                          gint              *x,
601
 
                          gint              *y)
 
532
                          gint              *x,
 
533
                          gint              *y)
602
534
{
603
 
  g_return_if_fail (x!= NULL && y != NULL);
 
535
  g_return_if_fail (tm != NULL);
 
536
  g_return_if_fail (x != NULL && y != NULL);
604
537
 
605
538
  *x = tm->x;
606
539
  *y = tm->y;
608
541
 
609
542
void
610
543
tile_manager_set_offsets (TileManager *tm,
611
 
                          gint         x,
612
 
                          gint         y)
 
544
                          gint         x,
 
545
                          gint         y)
613
546
{
614
547
  g_return_if_fail (tm != NULL);
615
548
 
659
592
 
660
593
void
661
594
tile_manager_get_tile_coordinates (TileManager *tm,
662
 
                                   Tile        *tile,
663
 
                                   gint        *x,
664
 
                                   gint        *y)
 
595
                                   Tile        *tile,
 
596
                                   gint        *x,
 
597
                                   gint        *y)
665
598
{
666
599
  TileLink *tl;
667
600
 
670
603
 
671
604
  for (tl = tile->tlink; tl; tl = tl->next)
672
605
    {
673
 
      if (tl->tm == tm) break;
 
606
      if (tl->tm == tm)
 
607
        break;
674
608
    }
675
609
 
676
 
  if (tl == NULL)
 
610
  if (G_UNLIKELY (tl == NULL))
677
611
    {
678
 
      g_warning ("tile_manager_get_tile_coordinates: "
679
 
                 "tile not attached to manager");
 
612
      g_warning ("%s: tile not attached to manager", G_GNUC_FUNCTION);
680
613
      return;
681
614
    }
682
615
 
684
617
  *y = TILE_HEIGHT * (tl->tile_num / tm->ntile_cols);
685
618
}
686
619
 
687
 
 
688
620
void
689
621
tile_manager_map_over_tile (TileManager *tm,
690
 
                            Tile        *tile,
691
 
                            Tile        *srctile)
 
622
                            Tile        *tile,
 
623
                            Tile        *srctile)
692
624
{
693
625
  TileLink *tl;
694
626
 
698
630
 
699
631
  for (tl = tile->tlink; tl; tl = tl->next)
700
632
    {
701
 
      if (tl->tm == tm) break;
 
633
      if (tl->tm == tm)
 
634
        break;
702
635
    }
703
636
 
704
 
  if (tl == NULL)
 
637
  if (G_UNLIKELY (tl == NULL))
705
638
    {
706
 
      g_warning ("tile_manager_map_over_tile: tile not attached to manager");
 
639
      g_warning ("%s: tile not attached to manager", G_GNUC_FUNCTION);
707
640
      return;
708
641
    }
709
642
 
712
645
 
713
646
PixelDataHandle *
714
647
request_pixel_data (TileManager *tm,
715
 
                    gint         x1,
716
 
                    gint         y1,
717
 
                    gint         x2,
718
 
                    gint         y2,
719
 
                    gboolean     wantread,
720
 
                    gboolean     wantwrite)
 
648
                    gint         x1,
 
649
                    gint         y1,
 
650
                    gint         x2,
 
651
                    gint         y2,
 
652
                    gboolean     wantread,
 
653
                    gboolean     wantwrite)
721
654
{
722
655
  PixelDataHandlePrivate *pdh;
723
656
  guint tile_num_1, tile_num_2;
724
657
  guint w, h;
725
658
 
726
659
  pdh = g_new (PixelDataHandlePrivate, 1);
727
 
  pdh->tm = tm;
728
 
  pdh->readable  = wantread;
729
 
  pdh->writeable = wantwrite;
730
 
  pdh->x1 = x1;
731
 
  pdh->y1 = y1;
732
 
  pdh->x2 = x2;
733
 
  pdh->y2 = y2;
734
 
  pdh->public.width = w = (x2-x1)+1;
735
 
  pdh->public.height = h = (y2-y1)+1;
 
660
 
 
661
  pdh->tm            = tm;
 
662
  pdh->readable      = wantread;
 
663
  pdh->writeable     = wantwrite;
 
664
  pdh->x1            = x1;
 
665
  pdh->y1            = y1;
 
666
  pdh->x2            = x2;
 
667
  pdh->y2            = y2;
 
668
  pdh->public.width  = w = (x2 - x1) + 1;
 
669
  pdh->public.height = h = (y2 - y1) + 1;
736
670
 
737
671
  tile_num_1 = tile_manager_get_tile_num (tm, x1, y1);
738
672
  tile_num_2 = tile_manager_get_tile_num (tm, x2, y2);
754
688
      pdh->tile = NULL;
755
689
 
756
690
      if (wantread)
757
 
        read_pixel_data (tm, x1, y1, x2, y2,
758
 
                         pdh->public.data, pdh->public.stride);
 
691
        read_pixel_data (tm, x1, y1, x2, y2,
 
692
                         pdh->public.data, pdh->public.stride);
759
693
    }
760
694
  return (PixelDataHandle *) pdh;
761
695
}
763
697
void
764
698
release_pixel_data (PixelDataHandle *xpdh)
765
699
{
766
 
  PixelDataHandlePrivate *pdh = (PixelDataHandlePrivate *)(xpdh);
 
700
  PixelDataHandlePrivate *pdh = (PixelDataHandlePrivate *) xpdh;
767
701
 
768
702
  if (pdh->local_buffer)
769
703
    {
770
704
      if (pdh->writeable)
771
 
        write_pixel_data (pdh->tm, pdh->x1, pdh->y1, pdh->x2, pdh->y2,
772
 
                          pdh->public.data, pdh->public.stride);
 
705
        write_pixel_data (pdh->tm, pdh->x1, pdh->y1, pdh->x2, pdh->y2,
 
706
                          pdh->public.data, pdh->public.stride);
773
707
      g_free (pdh->public.data);
774
708
    }
775
709
  else
782
716
 
783
717
void
784
718
read_pixel_data (TileManager *tm,
785
 
                 gint         x1,
786
 
                 gint         y1,
787
 
                 gint         x2,
788
 
                 gint         y2,
789
 
                 guchar      *buffer,
790
 
                 guint        stride)
 
719
                 gint         x1,
 
720
                 gint         y1,
 
721
                 gint         x2,
 
722
                 gint         y2,
 
723
                 guchar      *buffer,
 
724
                 guint        stride)
791
725
{
792
726
  Tile   *t;
793
727
  guchar *s, *d;
798
732
  for (y = y1; y <= y2; y += TILE_HEIGHT - (y % TILE_HEIGHT))
799
733
    for (x = x1; x <= x2; x += TILE_WIDTH - (x % TILE_WIDTH))
800
734
      {
801
 
        t = tile_manager_get_tile (tm, x, y, TRUE, FALSE);
802
 
        s = tile_data_pointer (t, x % TILE_WIDTH, y % TILE_HEIGHT);
803
 
        d = buffer + stride * (y - y1) + tm->bpp * (x - x1);
804
 
        rows = tile_eheight (t) - y % TILE_HEIGHT;
805
 
        if (rows > (y2 - y + 1))
806
 
          rows = y2 - y + 1;
807
 
 
808
 
        cols = tile_ewidth (t) - x % TILE_WIDTH;
809
 
        if (cols > (x2 - x + 1))
810
 
          cols = x2 - x + 1;
811
 
 
812
 
        srcstride = tile_ewidth (t) * tile_bpp (t);
813
 
 
814
 
        while (rows --)
815
 
          {
816
 
            memcpy (d, s, cols * tm->bpp);
817
 
            s += srcstride;
818
 
            d += stride;
819
 
          }
820
 
 
821
 
        tile_release (t, FALSE);
 
735
        t = tile_manager_get_tile (tm, x, y, TRUE, FALSE);
 
736
        s = tile_data_pointer (t, x % TILE_WIDTH, y % TILE_HEIGHT);
 
737
        d = buffer + stride * (y - y1) + tm->bpp * (x - x1);
 
738
 
 
739
        rows = tile_eheight (t) - y % TILE_HEIGHT;
 
740
        if (rows > (y2 - y + 1))
 
741
          rows = y2 - y + 1;
 
742
 
 
743
        cols = tile_ewidth (t) - x % TILE_WIDTH;
 
744
        if (cols > (x2 - x + 1))
 
745
          cols = x2 - x + 1;
 
746
 
 
747
        srcstride = tile_ewidth (t) * tile_bpp (t);
 
748
 
 
749
        while (rows --)
 
750
          {
 
751
            memcpy (d, s, cols * tm->bpp);
 
752
            s += srcstride;
 
753
            d += stride;
 
754
          }
 
755
 
 
756
        tile_release (t, FALSE);
822
757
      }
823
758
}
824
759
 
825
760
void
826
 
write_pixel_data (TileManager *tm,
827
 
                  gint         x1,
828
 
                  gint         y1,
829
 
                  gint         x2,
830
 
                  gint         y2,
831
 
                  guchar      *buffer,
832
 
                  guint        stride)
 
761
write_pixel_data (TileManager  *tm,
 
762
                  gint          x1,
 
763
                  gint          y1,
 
764
                  gint          x2,
 
765
                  gint          y2,
 
766
                  const guchar *buffer,
 
767
                  guint         stride)
833
768
{
834
 
  Tile   *t;
835
 
  guchar *s, *d;
836
 
  guint   x, y;
837
 
  guint   rows, cols;
838
 
  guint   dststride;
 
769
  Tile         *t;
 
770
  const guchar *s;
 
771
  guchar       *d;
 
772
  guint         x, y;
 
773
  guint         rows, cols;
 
774
  guint         dststride;
839
775
 
840
776
  for (y = y1; y <= y2; y += TILE_HEIGHT - (y % TILE_HEIGHT))
841
777
    for (x = x1; x <= x2; x += TILE_WIDTH - (x % TILE_WIDTH))
842
778
      {
843
 
        t = tile_manager_get_tile (tm, x, y, TRUE, TRUE);
844
 
        s = buffer + stride * (y - y1) + tm->bpp * (x - x1);
845
 
        d = tile_data_pointer (t, x % TILE_WIDTH, y % TILE_HEIGHT);
846
 
        rows = tile_eheight (t) - y % TILE_HEIGHT;
847
 
        if (rows > (y2 - y + 1))
848
 
          rows = y2 - y + 1;
849
 
 
850
 
        cols = tile_ewidth (t) - x % TILE_WIDTH;
851
 
        if (cols > (x2 - x + 1))
852
 
          cols = x2 - x + 1;
853
 
 
854
 
        dststride = tile_ewidth (t) * tile_bpp (t);
855
 
 
856
 
        while (rows --)
857
 
          {
858
 
            memcpy (d, s, cols * tm->bpp);
859
 
            s += stride;
860
 
            d += dststride;
861
 
          }
862
 
 
863
 
        tile_release (t, TRUE);
 
779
        t = tile_manager_get_tile (tm, x, y, TRUE, TRUE);
 
780
        s = buffer + stride * (y - y1) + tm->bpp * (x - x1);
 
781
        d = tile_data_pointer (t, x % TILE_WIDTH, y % TILE_HEIGHT);
 
782
        rows = tile_eheight (t) - y % TILE_HEIGHT;
 
783
        if (rows > (y2 - y + 1))
 
784
          rows = y2 - y + 1;
 
785
 
 
786
        cols = tile_ewidth (t) - x % TILE_WIDTH;
 
787
        if (cols > (x2 - x + 1))
 
788
          cols = x2 - x + 1;
 
789
 
 
790
        dststride = tile_ewidth (t) * tile_bpp (t);
 
791
 
 
792
        while (rows --)
 
793
          {
 
794
            memcpy (d, s, cols * tm->bpp);
 
795
            s += stride;
 
796
            d += dststride;
 
797
          }
 
798
 
 
799
        tile_release (t, TRUE);
864
800
      }
865
801
}
866
802
 
867
803
void
868
804
read_pixel_data_1 (TileManager *tm,
869
 
                   gint          x,
870
 
                   gint          y,
871
 
                   guchar       *buffer)
 
805
                   gint         x,
 
806
                   gint         y,
 
807
                   guchar      *buffer)
872
808
{
873
809
  if (x >= 0 && y >= 0 && x < tm->width && y < tm->height)
874
810
    {
885
821
 
886
822
      if (tm->cached_tile)
887
823
        {
888
 
           guchar *data = tile_data_pointer (tm->cached_tile,
889
 
                                             x % TILE_WIDTH, y % TILE_HEIGHT);
 
824
          const guchar *src = tile_data_pointer (tm->cached_tile,
 
825
                                                 x % TILE_WIDTH,
 
826
                                                 y % TILE_HEIGHT);
 
827
 
890
828
           switch (tm->bpp)
891
829
             {
892
830
             case 4:
893
 
               *(guint32*)buffer = *(guint32*)data;
894
 
               break;
895
 
             default:
896
 
               {
897
 
                 gint i;
898
 
                 for (i = 0; i < tm->bpp; i++)
899
 
                   buffer[i] = data[i];
900
 
               }
901
 
               break;
 
831
               *buffer++ = *src++;
 
832
             case 3:
 
833
               *buffer++ = *src++;
 
834
             case 2:
 
835
               *buffer++ = *src++;
 
836
             case 1:
 
837
               *buffer++ = *src++;
902
838
             }
903
839
        }
904
840
    }
905
841
}
906
842
 
907
843
void
908
 
write_pixel_data_1 (TileManager *tm,
909
 
                    gint          x,
910
 
                    gint          y,
911
 
                    guchar       *buffer)
 
844
write_pixel_data_1 (TileManager  *tm,
 
845
                    gint          x,
 
846
                    gint          y,
 
847
                    const guchar *buffer)
912
848
{
913
 
  Tile   *t;
914
 
  guchar *d;
915
 
 
916
 
  t = tile_manager_get_tile (tm, x, y, TRUE, TRUE);
917
 
  d = tile_data_pointer (t, x % TILE_WIDTH, y % TILE_HEIGHT);
918
 
  memcpy (d, buffer, tm->bpp);
919
 
  tile_release (t, TRUE);
 
849
  Tile   *tile = tile_manager_get_tile (tm, x, y, TRUE, TRUE);
 
850
  guchar *dest = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT);
 
851
 
 
852
  switch (tm->bpp)
 
853
    {
 
854
    case 4:
 
855
      *dest++ = *buffer++;
 
856
    case 3:
 
857
      *dest++ = *buffer++;
 
858
    case 2:
 
859
      *dest++ = *buffer++;
 
860
    case 1:
 
861
      *dest++ = *buffer++;
 
862
    }
 
863
 
 
864
  tile_release (tile, TRUE);
920
865
}