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

« back to all changes in this revision

Viewing changes to app/display/gimpdisplayshell-render.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
24
24
#include <gtk/gtk.h>
25
25
 
26
26
#include "libgimpbase/gimpbase.h"
 
27
#include "libgimpmath/gimpmath.h"
27
28
#include "libgimpwidgets/gimpwidgets.h"
28
29
 
29
30
#include "display-types.h"
32
33
#include "base/tile.h"
33
34
 
34
35
#include "core/gimp.h"
 
36
#include "core/gimpdrawable.h"
35
37
#include "core/gimpimage.h"
36
38
#include "core/gimpimage-colormap.h"
37
39
#include "core/gimpprojection.h"
38
40
 
 
41
#include "widgets/gimprender.h"
 
42
 
39
43
#include "gimpcanvas.h"
40
44
#include "gimpdisplay.h"
41
45
#include "gimpdisplayshell.h"
51
55
{
52
56
  GimpDisplayShell *shell;
53
57
  TileManager      *src_tiles;
54
 
  guint            *alpha;
55
 
  guchar           *scale;
56
 
  guchar           *src;
 
58
  const guint      *alpha;
 
59
  const guchar     *scale;
 
60
  const guchar     *src;
57
61
  guchar           *dest;
58
62
  gint              x, y;
59
63
  gint              w, h;
60
64
  gdouble           scalex;
61
65
  gdouble           scaley;
62
 
  gint              src_x, src_y;
63
 
  gint              src_bpp;
 
66
  gint              src_x;
 
67
  gint              src_y;
64
68
  gint              dest_bpp;
65
69
  gint              dest_bpl;
66
70
  gint              dest_width;
67
 
  gint              byte_order;
68
71
};
69
72
 
70
73
 
73
76
                                   Gimp       *gimp);
74
77
 
75
78
 
76
 
/*  accelerate transparency of image scaling  */
77
 
guchar *render_check_buf         = NULL;
78
 
guchar *render_empty_buf         = NULL;
79
 
guchar *render_white_buf         = NULL;
80
 
guchar *render_temp_buf          = NULL;
81
 
 
82
 
guchar *render_blend_dark_check  = NULL;
83
 
guchar *render_blend_light_check = NULL;
84
 
guchar *render_blend_white       = NULL;
85
 
 
86
 
 
87
 
static guchar *tile_buf           = NULL;
88
 
static guint   tile_shift         = 0;
89
 
static guint   check_mod          = 0;
90
 
static guint   check_shift        = 0;
 
79
static guchar *tile_buf    = NULL;
 
80
 
 
81
static guint   check_mod   = 0;
 
82
static guint   check_shift = 0;
91
83
 
92
84
 
93
85
void
94
 
render_init (Gimp *gimp)
 
86
gimp_display_shell_render_init (Gimp *gimp)
95
87
{
96
88
  g_return_if_fail (GIMP_IS_GIMP (gimp));
 
89
  g_return_if_fail (tile_buf == NULL);
97
90
 
98
91
  g_signal_connect (gimp->config, "notify::transparency-size",
99
92
                    G_CALLBACK (render_setup_notify),
102
95
                    G_CALLBACK (render_setup_notify),
103
96
                    gimp);
104
97
 
 
98
  /*  allocate a buffer for arranging information from a row of tiles  */
 
99
  tile_buf = g_new (guchar, GIMP_RENDER_BUF_WIDTH * MAX_CHANNELS);
 
100
 
105
101
  render_setup_notify (gimp->config, NULL, gimp);
106
102
}
107
103
 
108
104
void
109
 
render_exit (Gimp *gimp)
 
105
gimp_display_shell_render_exit (Gimp *gimp)
110
106
{
111
107
  g_return_if_fail (GIMP_IS_GIMP (gimp));
112
108
 
119
115
      g_free (tile_buf);
120
116
      tile_buf = NULL;
121
117
    }
122
 
 
123
 
  if (render_blend_dark_check)
124
 
    {
125
 
      g_free (render_blend_dark_check);
126
 
      render_blend_dark_check = NULL;
127
 
    }
128
 
 
129
 
  if (render_blend_light_check)
130
 
    {
131
 
      g_free (render_blend_light_check);
132
 
      render_blend_light_check = NULL;
133
 
    }
134
 
 
135
 
  if (render_blend_white)
136
 
    {
137
 
      g_free (render_blend_white);
138
 
      render_blend_white = NULL;
139
 
    }
140
 
 
141
 
  if (render_check_buf)
142
 
    {
143
 
      g_free (render_check_buf);
144
 
      render_check_buf = NULL;
145
 
    }
146
 
 
147
 
  if (render_empty_buf)
148
 
    {
149
 
      g_free (render_empty_buf);
150
 
      render_empty_buf = NULL;
151
 
    }
152
 
 
153
 
  if (render_white_buf)
154
 
    {
155
 
      g_free (render_white_buf);
156
 
      render_white_buf = NULL;
157
 
    }
158
 
 
159
 
  if (render_temp_buf)
160
 
    {
161
 
      g_free (render_temp_buf);
162
 
      render_temp_buf = NULL;
163
 
    }
164
118
}
165
119
 
166
 
 
167
120
static void
168
121
render_setup_notify (gpointer    config,
169
122
                     GParamSpec *param_spec,
170
123
                     Gimp       *gimp)
171
124
{
172
 
  GimpCheckType check_type;
173
125
  GimpCheckSize check_size;
174
 
  guchar        light, dark;
175
 
  gint          i, j;
176
126
 
177
127
  g_object_get (config,
178
 
                "transparency-type", &check_type,
179
128
                "transparency-size", &check_size,
180
129
                NULL);
181
130
 
182
 
  /*  based on the tile size, determine the tile shift amount
183
 
   *  (assume here that tile_height and tile_width are equal)
184
 
   */
185
 
  tile_shift = 0;
186
 
  while ((1 << tile_shift) < TILE_WIDTH)
187
 
    tile_shift++;
188
 
 
189
 
  /*  allocate a buffer for arranging information from a row of tiles  */
190
 
  if (! tile_buf)
191
 
    tile_buf = g_new (guchar,
192
 
                      GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH * MAX_CHANNELS);
193
 
 
194
 
  if (! render_blend_dark_check)
195
 
    render_blend_dark_check = g_new (guchar, 65536);
196
 
  if (! render_blend_light_check)
197
 
    render_blend_light_check = g_new (guchar, 65536);
198
 
  if (! render_blend_white)
199
 
    render_blend_white = g_new (guchar, 65536);
200
 
 
201
 
  gimp_checks_get_shades (check_type, &light, &dark);
202
 
 
203
 
  for (i = 0; i < 256; i++)
204
 
    for (j = 0; j < 256; j++)
205
 
      {
206
 
        render_blend_dark_check [(i << 8) + j] =
207
 
          (guchar) ((j * i + dark * (255 - i)) / 255);
208
 
        render_blend_light_check [(i << 8) + j] =
209
 
          (guchar) ((j * i + light * (255 - i)) / 255);
210
 
        render_blend_white [(i << 8) + j] =
211
 
          (guchar) ((j * i + 255 * (255 - i)) / 255);
212
 
      }
213
 
 
214
131
  switch (check_size)
215
132
    {
216
133
    case GIMP_CHECK_SIZE_SMALL_CHECKS:
226
143
      check_shift = 4;
227
144
      break;
228
145
    }
229
 
 
230
 
  g_free (render_check_buf);
231
 
  g_free (render_empty_buf);
232
 
  g_free (render_white_buf);
233
 
  g_free (render_temp_buf);
234
 
 
235
 
#define BUF_SIZE (MAX (GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH, \
236
 
                       GIMP_VIEWABLE_MAX_PREVIEW_SIZE) + 4)
237
 
 
238
 
  render_check_buf = g_new  (guchar, BUF_SIZE * 3);
239
 
  render_empty_buf = g_new0 (guchar, BUF_SIZE * 3);
240
 
  render_white_buf = g_new  (guchar, BUF_SIZE * 3);
241
 
  render_temp_buf  = g_new  (guchar, BUF_SIZE * 3);
242
 
 
243
 
  /*  calculate check buffer for previews  */
244
 
 
245
 
  memset (render_white_buf, 255, BUF_SIZE * 3);
246
 
 
247
 
  for (i = 0; i < BUF_SIZE; i++)
248
 
    {
249
 
      if (i & 0x4)
250
 
        {
251
 
          render_check_buf[i * 3 + 0] = render_blend_dark_check[0];
252
 
          render_check_buf[i * 3 + 1] = render_blend_dark_check[0];
253
 
          render_check_buf[i * 3 + 2] = render_blend_dark_check[0];
254
 
        }
255
 
      else
256
 
        {
257
 
          render_check_buf[i * 3 + 0] = render_blend_light_check[0];
258
 
          render_check_buf[i * 3 + 1] = render_blend_light_check[0];
259
 
          render_check_buf[i * 3 + 2] = render_blend_light_check[0];
260
 
        }
261
 
    }
262
 
 
263
 
#undef BUF_SIZE
264
146
}
265
147
 
266
148
 
273
155
static void     render_image_indexed            (RenderInfo       *info);
274
156
static void     render_image_indexed_a          (RenderInfo       *info);
275
157
 
 
158
static void     render_image_init_info_full     (RenderInfo       *info,
 
159
                                                 GimpDisplayShell *shell,
 
160
                                                 gint              x,
 
161
                                                 gint              y,
 
162
                                                 gint              w,
 
163
                                                 gint              h,
 
164
                                                 GimpProjection   *projection);
276
165
static void     render_image_init_info          (RenderInfo       *info,
277
 
                                                 GimpDisplayShell *shell,
278
 
                                                 gint              x,
279
 
                                                 gint              y,
280
 
                                                 gint              w,
281
 
                                                 gint              h);
282
 
static guint  * render_image_init_alpha         (gint              mult);
283
 
static guchar * render_image_accelerate_scaling (gint              width,
284
 
                                                 gint              start,
285
 
                                                 gdouble           scalex);
286
 
static guchar * render_image_tile_fault         (RenderInfo       *info);
 
166
                                                 GimpDisplayShell *shell,
 
167
                                                 gint              x,
 
168
                                                 gint              y,
 
169
                                                 TileManager      *tiles);
 
170
static const guint  * render_image_init_alpha         (gint        mult);
 
171
 
 
172
static const guchar * render_image_accelerate_scaling (gint        width,
 
173
                                                       gint        start,
 
174
                                                       gdouble     scalex);
 
175
static const guchar * render_image_tile_fault         (RenderInfo *info);
287
176
 
288
177
 
289
178
static RenderFunc render_funcs[6] =
303
192
                                                  gint              w,
304
193
                                                  gint              h,
305
194
                                                  GdkRectangle     *highlight);
 
195
static void  gimp_display_shell_render_mask      (GimpDisplayShell *shell,
 
196
                                                  RenderInfo       *info);
306
197
 
307
198
 
308
199
/*****************************************************************/
309
200
/*  This function is the core of the display--it offsets and     */
310
201
/*  scales the image according to the current parameters in the  */
311
 
/*  gdisp object.  It handles color, grayscale, 8, 15, 16, 24,   */
 
202
/*  display object.  It handles color, grayscale, 8, 15, 16, 24  */
312
203
/*  & 32 bit output depths.                                      */
313
204
/*****************************************************************/
314
205
 
320
211
                           gint              h,
321
212
                           GdkRectangle     *highlight)
322
213
{
323
 
  RenderInfo     info;
324
 
  GimpImageType  image_type;
325
 
 
326
 
  render_image_init_info (&info, shell, x, y, w, h);
327
 
 
328
 
  image_type = gimp_projection_get_image_type (shell->gdisp->gimage->projection);
329
 
 
330
 
  if ((image_type < GIMP_RGB_IMAGE) || (image_type > GIMP_INDEXEDA_IMAGE))
331
 
    {
332
 
      g_message ("unknown gimage projection type: %d", image_type);
333
 
      return;
334
 
    }
335
 
 
336
 
  if ((info.dest_bpp < 1) || (info.dest_bpp > 4))
337
 
    {
338
 
      g_message ("unsupported destination bytes per pixel: %d", info.dest_bpp);
339
 
      return;
340
 
    }
 
214
  GimpProjection *projection;
 
215
  RenderInfo      info;
 
216
  GimpImageType   type;
 
217
 
 
218
  g_return_if_fail (w > 0 && h > 0);
 
219
 
 
220
  projection = shell->display->image->projection;
 
221
 
 
222
  render_image_init_info_full (&info, shell, x, y, w, h, projection);
 
223
 
 
224
  type = gimp_projection_get_image_type (projection);
341
225
 
342
226
  /* Currently, only RGBA and GRAYA projection types are used - the rest
343
227
   * are in case of future need.  -- austin, 28th Nov 1998.
344
228
   */
345
 
  if (image_type != GIMP_RGBA_IMAGE && image_type != GIMP_GRAYA_IMAGE)
346
 
    g_warning ("using untested projection type %d", image_type);
 
229
  if (G_UNLIKELY (type != GIMP_RGBA_IMAGE && type != GIMP_GRAYA_IMAGE))
 
230
    g_warning ("using untested projection type %d", type);
347
231
 
348
 
  (* render_funcs[image_type]) (&info);
 
232
  (* render_funcs[type]) (&info);
349
233
 
350
234
  /*  apply filters to the rendered projection  */
351
235
  if (shell->filter_stack)
353
237
                                      shell->render_buf,
354
238
                                      w, h,
355
239
                                      3,
356
 
                                      3 * GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH);
 
240
                                      3 * GIMP_RENDER_BUF_WIDTH);
357
241
 
358
242
  /*  dim pixels outside the highlighted rectangle  */
359
243
  if (highlight)
360
 
    gimp_display_shell_render_highlight (shell, x, y, w, h, highlight);
 
244
    {
 
245
      gimp_display_shell_render_highlight (shell, x, y, w, h, highlight);
 
246
    }
 
247
  else if (shell->mask)
 
248
    {
 
249
      render_image_init_info (&info, shell, x, y,
 
250
                              gimp_drawable_get_tiles (shell->mask));
 
251
 
 
252
      gimp_display_shell_render_mask (shell, &info);
 
253
    }
361
254
 
362
255
  /*  put it to the screen  */
363
256
  gimp_canvas_draw_rgb (GIMP_CANVAS (shell->canvas), GIMP_CANVAS_STYLE_RENDER,
364
257
                        x + shell->disp_xoffset, y + shell->disp_yoffset,
365
258
                        w, h,
366
259
                        shell->render_buf,
367
 
                        3 * GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH,
 
260
                        3 * GIMP_RENDER_BUF_WIDTH,
368
261
                        shell->offset_x, shell->offset_y);
369
262
}
370
263
 
404
297
          for (x = 0; x < w; x++)
405
298
            GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
406
299
 
407
 
          buf += 3 * GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH;
 
300
          buf += 3 * GIMP_RENDER_BUF_WIDTH;
408
301
        }
409
302
 
410
303
      for ( ; y < rect.y + rect.height; y++)
415
308
          for (x += rect.width; x < w; x++)
416
309
            GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
417
310
 
418
 
          buf += 3 * GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH;
 
311
          buf += 3 * GIMP_RENDER_BUF_WIDTH;
419
312
        }
420
313
 
421
314
      for ( ; y < h; y++)
423
316
          for (x = 0; x < w; x++)
424
317
            GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
425
318
 
426
 
          buf += 3 * GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH;
 
319
          buf += 3 * GIMP_RENDER_BUF_WIDTH;
427
320
        }
428
321
    }
429
322
  else
433
326
          for (x = 0; x < w; x++)
434
327
            GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
435
328
 
436
 
          buf += 3 * GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH;
 
329
          buf += 3 * GIMP_RENDER_BUF_WIDTH;
 
330
        }
 
331
    }
 
332
}
 
333
 
 
334
static void
 
335
gimp_display_shell_render_mask (GimpDisplayShell *shell,
 
336
                                RenderInfo       *info)
 
337
{
 
338
  gint      y, ye;
 
339
  gint      x, xe;
 
340
  gboolean  initial = TRUE;
 
341
 
 
342
  y  = info->y;
 
343
  ye = info->y + info->h;
 
344
  xe = info->x + info->w;
 
345
 
 
346
  info->src = render_image_tile_fault (info);
 
347
 
 
348
  while (TRUE)
 
349
    {
 
350
      gint error =
 
351
        RINT (floor ((y + 1) / info->scaley) - floor (y / info->scaley));
 
352
 
 
353
      if (!initial && (error == 0))
 
354
        {
 
355
          memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
 
356
        }
 
357
      else
 
358
        {
 
359
          const guchar *src  = info->src;
 
360
          guchar       *dest = info->dest;
 
361
 
 
362
          switch (shell->mask_color)
 
363
            {
 
364
            case GIMP_RED_CHANNEL:
 
365
              for (x = info->x; x < xe; x++, src++, dest += 3)
 
366
                {
 
367
                  if (*src & 0x80)
 
368
                    continue;
 
369
 
 
370
                  dest[1] = dest[1] >> 2;
 
371
                  dest[2] = dest[2] >> 2;
 
372
                }
 
373
              break;
 
374
 
 
375
            case GIMP_GREEN_CHANNEL:
 
376
              for (x = info->x; x < xe; x++, src++, dest += 3)
 
377
                {
 
378
                  if (*src & 0x80)
 
379
                    continue;
 
380
 
 
381
                  dest[0] = dest[0] >> 2;
 
382
                  dest[2] = dest[2] >> 2;
 
383
                }
 
384
              break;
 
385
 
 
386
            case GIMP_BLUE_CHANNEL:
 
387
              for (x = info->x; x < xe; x++, src++, dest += 3)
 
388
                {
 
389
                  if (*src & 0x80)
 
390
                    continue;
 
391
 
 
392
                  dest[0] = dest[0] >> 2;
 
393
                  dest[1] = dest[1] >> 2;
 
394
                }
 
395
              break;
 
396
 
 
397
            default:
 
398
              break;
 
399
            }
 
400
        }
 
401
 
 
402
      if (++y == ye)
 
403
        break;
 
404
 
 
405
      info->dest += info->dest_bpl;
 
406
 
 
407
      if (error)
 
408
        {
 
409
          info->src_y += error;
 
410
          info->src = render_image_tile_fault (info);
 
411
 
 
412
          initial = TRUE;
 
413
        }
 
414
      else
 
415
        {
 
416
          initial = FALSE;
437
417
        }
438
418
    }
439
419
}
446
426
static void
447
427
render_image_indexed (RenderInfo *info)
448
428
{
449
 
  guchar *src;
450
 
  guchar *dest;
451
 
  guchar *cmap;
452
 
  gulong  val;
453
 
  gint    byte_order;
454
 
  gint    y, ye;
455
 
  gint    x, xe;
456
 
  gint    initial;
 
429
  const guchar *cmap;
 
430
  gint          y, ye;
 
431
  gint          x, xe;
 
432
  gboolean      initial = TRUE;
457
433
 
458
 
  cmap = gimp_image_get_colormap (info->shell->gdisp->gimage);
 
434
  cmap = gimp_image_get_colormap (info->shell->display->image);
459
435
 
460
436
  y  = info->y;
461
437
  ye = info->y + info->h;
462
438
  xe = info->x + info->w;
463
439
 
464
 
  initial = TRUE;
465
 
  byte_order = info->byte_order;
466
440
  info->src = render_image_tile_fault (info);
467
441
 
468
 
  for (; y < ye; y++)
 
442
  while (TRUE)
469
443
    {
470
 
      gint error = RINT (floor ((y + 1) / info->scaley)
471
 
                         - floor (y / info->scaley));
 
444
      gint error =
 
445
        RINT (floor ((y + 1) / info->scaley) - floor (y / info->scaley));
472
446
 
473
447
      if (!initial && (error == 0))
474
 
        {
475
 
          memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
476
 
        }
 
448
        {
 
449
          memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
 
450
        }
477
451
      else
478
 
        {
479
 
          src = info->src;
480
 
          dest = info->dest;
481
 
 
482
 
          g_return_if_fail (src != NULL);
483
 
 
484
 
          for (x = info->x; x < xe; x++)
485
 
            {
486
 
              val = src[INDEXED_PIX] * 3;
487
 
              src += 1;
488
 
 
489
 
              dest[0] = cmap[val+0];
490
 
              dest[1] = cmap[val+1];
491
 
              dest[2] = cmap[val+2];
492
 
              dest += 3;
493
 
            }
494
 
        }
 
452
        {
 
453
          const guchar *src  = info->src;
 
454
          guchar       *dest = info->dest;
 
455
 
 
456
          for (x = info->x; x < xe; x++)
 
457
            {
 
458
              guint  val = src[INDEXED_PIX] * 3;
 
459
 
 
460
              src += 1;
 
461
 
 
462
              dest[0] = cmap[val + 0];
 
463
              dest[1] = cmap[val + 1];
 
464
              dest[2] = cmap[val + 2];
 
465
              dest += 3;
 
466
            }
 
467
        }
 
468
 
 
469
      if (++y == ye)
 
470
        break;
495
471
 
496
472
      info->dest += info->dest_bpl;
497
473
 
498
 
      initial = FALSE;
 
474
      if (error)
 
475
        {
 
476
          info->src_y += error;
 
477
          info->src = render_image_tile_fault (info);
499
478
 
500
 
      if (error >= 1)
501
 
        {
502
 
          info->src_y += error;
503
 
          info->src = render_image_tile_fault (info);
504
 
          initial = TRUE;
505
 
        }
 
479
          initial = TRUE;
 
480
        }
 
481
      else
 
482
        {
 
483
          initial = FALSE;
 
484
        }
506
485
    }
507
486
}
508
487
 
509
488
static void
510
489
render_image_indexed_a (RenderInfo *info)
511
490
{
512
 
  guchar *src;
513
 
  guchar *dest;
514
 
  guint  *alpha;
515
 
  guchar *cmap;
516
 
  gulong  r, g, b;
517
 
  gulong  val;
518
 
  guint   a;
519
 
  gint    dark_light;
520
 
  gint    byte_order;
521
 
  gint    y, ye;
522
 
  gint    x, xe;
523
 
  gint    initial;
524
 
 
525
 
  cmap = gimp_image_get_colormap (info->shell->gdisp->gimage);
526
 
  alpha = info->alpha;
 
491
  const guint  *alpha = info->alpha;
 
492
  const guchar *cmap  = gimp_image_get_colormap (info->shell->display->image);
 
493
  gint          y, ye;
 
494
  gint          x, xe;
 
495
  gboolean      initial = TRUE;
527
496
 
528
497
  y  = info->y;
529
498
  ye = info->y + info->h;
530
499
  xe = info->x + info->w;
531
500
 
532
 
  initial = TRUE;
533
 
  byte_order = info->byte_order;
534
501
  info->src = render_image_tile_fault (info);
535
502
 
536
 
  for (; y < ye; y++)
 
503
  while (TRUE)
537
504
    {
538
 
      gint error = RINT (floor ((y + 1) / info->scaley)
539
 
                         - floor (y / info->scaley));
 
505
      gint error =
 
506
        RINT (floor ((y + 1) / info->scaley) - floor (y / info->scaley));
540
507
 
541
508
      if (!initial && (error == 0) && (y & check_mod))
542
 
        {
543
 
          memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
544
 
        }
 
509
        {
 
510
          memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
 
511
        }
545
512
      else
546
 
        {
547
 
          src = info->src;
548
 
          dest = info->dest;
549
 
 
550
 
          dark_light = (y >> check_shift) + (info->x >> check_shift);
551
 
 
552
 
          g_return_if_fail (src != NULL);
553
 
 
554
 
          for (x = info->x; x < xe; x++)
555
 
            {
556
 
              a = alpha[src[ALPHA_I_PIX]];
557
 
              val = src[INDEXED_PIX] * 3;
558
 
              src += 2;
559
 
 
560
 
              if (dark_light & 0x1)
561
 
                {
562
 
                  r = render_blend_dark_check[(a | cmap[val + 0])];
563
 
                  g = render_blend_dark_check[(a | cmap[val + 1])];
564
 
                  b = render_blend_dark_check[(a | cmap[val + 2])];
565
 
                }
566
 
              else
567
 
                {
568
 
                  r = render_blend_light_check[(a | cmap[val + 0])];
569
 
                  g = render_blend_light_check[(a | cmap[val + 1])];
570
 
                  b = render_blend_light_check[(a | cmap[val + 2])];
571
 
                }
572
 
 
573
 
                dest[0] = r;
574
 
                dest[1] = g;
575
 
                dest[2] = b;
576
 
                dest += 3;
577
 
 
578
 
                if (((x + 1) & check_mod) == 0)
579
 
                  dark_light += 1;
580
 
              }
581
 
        }
 
513
        {
 
514
          const guchar *src  = info->src;
 
515
          guchar       *dest = info->dest;
 
516
          guint         dark_light;
 
517
 
 
518
          dark_light = (y >> check_shift) + (info->x >> check_shift);
 
519
 
 
520
          for (x = info->x; x < xe; x++)
 
521
            {
 
522
              guint r, g, b, a = alpha[src[ALPHA_I_PIX]];
 
523
              guint val        = src[INDEXED_PIX] * 3;
 
524
 
 
525
              src += 2;
 
526
 
 
527
              if (dark_light & 0x1)
 
528
                {
 
529
                  r = gimp_render_blend_dark_check[(a | cmap[val + 0])];
 
530
                  g = gimp_render_blend_dark_check[(a | cmap[val + 1])];
 
531
                  b = gimp_render_blend_dark_check[(a | cmap[val + 2])];
 
532
                }
 
533
              else
 
534
                {
 
535
                  r = gimp_render_blend_light_check[(a | cmap[val + 0])];
 
536
                  g = gimp_render_blend_light_check[(a | cmap[val + 1])];
 
537
                  b = gimp_render_blend_light_check[(a | cmap[val + 2])];
 
538
                }
 
539
 
 
540
                dest[0] = r;
 
541
                dest[1] = g;
 
542
                dest[2] = b;
 
543
                dest += 3;
 
544
 
 
545
                if (((x + 1) & check_mod) == 0)
 
546
                  dark_light += 1;
 
547
              }
 
548
        }
 
549
 
 
550
      if (++y == ye)
 
551
        break;
582
552
 
583
553
      info->dest += info->dest_bpl;
584
554
 
585
 
      initial = FALSE;
 
555
      if (error)
 
556
        {
 
557
          info->src_y += error;
 
558
          info->src = render_image_tile_fault (info);
586
559
 
587
 
      if (error >= 1)
588
 
        {
589
 
          info->src_y += error;
590
 
          info->src = render_image_tile_fault (info);
591
 
          initial = TRUE;
592
 
        }
 
560
          initial = TRUE;
 
561
        }
 
562
      else
 
563
        {
 
564
          initial = FALSE;
 
565
        }
593
566
    }
594
567
}
595
568
 
596
569
static void
597
570
render_image_gray (RenderInfo *info)
598
571
{
599
 
  guchar *src;
600
 
  guchar *dest;
601
 
  gulong  val;
602
 
  gint    byte_order;
603
 
  gint    y, ye;
604
 
  gint    x, xe;
605
 
  gint    initial;
 
572
  gint      y, ye;
 
573
  gint      x, xe;
 
574
  gboolean  initial = TRUE;
606
575
 
607
576
  y  = info->y;
608
577
  ye = info->y + info->h;
609
578
  xe = info->x + info->w;
610
579
 
611
 
  initial = TRUE;
612
 
  byte_order = info->byte_order;
613
580
  info->src = render_image_tile_fault (info);
614
581
 
615
 
  for (; y < ye; y++)
 
582
  while (TRUE)
616
583
    {
617
 
      gint error = RINT (floor ((y + 1) / info->scaley)
618
 
                         - floor (y / info->scaley));
 
584
      gint error =
 
585
        RINT (floor ((y + 1) / info->scaley) - floor (y / info->scaley));
619
586
 
620
587
      if (!initial && (error == 0))
621
 
        {
622
 
          memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
623
 
        }
 
588
        {
 
589
          memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
 
590
        }
624
591
      else
625
 
        {
626
 
          src = info->src;
627
 
          dest = info->dest;
628
 
 
629
 
          g_return_if_fail (src != NULL);
630
 
 
631
 
          for (x = info->x; x < xe; x++)
632
 
            {
633
 
              val = src[GRAY_PIX];
634
 
              src += 1;
635
 
 
636
 
              dest[0] = val;
637
 
              dest[1] = val;
638
 
              dest[2] = val;
639
 
              dest += 3;
640
 
            }
641
 
        }
 
592
        {
 
593
          const guchar *src  = info->src;
 
594
          guchar       *dest = info->dest;
 
595
 
 
596
          for (x = info->x; x < xe; x++)
 
597
            {
 
598
              guint val = src[GRAY_PIX];
 
599
 
 
600
              src += 1;
 
601
 
 
602
              dest[0] = val;
 
603
              dest[1] = val;
 
604
              dest[2] = val;
 
605
              dest += 3;
 
606
            }
 
607
        }
 
608
 
 
609
      if (++y == ye)
 
610
        break;
642
611
 
643
612
      info->dest += info->dest_bpl;
644
613
 
645
 
      initial = FALSE;
 
614
      if (error)
 
615
        {
 
616
          info->src_y += error;
 
617
          info->src = render_image_tile_fault (info);
646
618
 
647
 
      if (error >= 1)
648
 
        {
649
 
          info->src_y += error;
650
 
          info->src = render_image_tile_fault (info);
651
 
          initial = TRUE;
652
 
        }
 
619
          initial = TRUE;
 
620
        }
 
621
      else
 
622
        {
 
623
          initial = FALSE;
 
624
        }
653
625
    }
654
626
}
655
627
 
656
628
static void
657
629
render_image_gray_a (RenderInfo *info)
658
630
{
659
 
  guchar *src;
660
 
  guchar *dest;
661
 
  guint  *alpha;
662
 
  gulong  val;
663
 
  guint   a;
664
 
  gint    dark_light;
665
 
  gint    byte_order;
666
 
  gint    y, ye;
667
 
  gint    x, xe;
668
 
  gint    initial;
669
 
 
670
 
  alpha = info->alpha;
 
631
  const guint *alpha = info->alpha;
 
632
  gint         y, ye;
 
633
  gint         x, xe;
 
634
  gboolean     initial = TRUE;
671
635
 
672
636
  y  = info->y;
673
637
  ye = info->y + info->h;
674
638
  xe = info->x + info->w;
675
639
 
676
 
  initial = TRUE;
677
 
  byte_order = info->byte_order;
678
640
  info->src = render_image_tile_fault (info);
679
641
 
680
 
  for (; y < ye; y++)
 
642
  while (TRUE)
681
643
    {
682
 
      gint error = RINT (floor ((y + 1) / info->scaley)
683
 
                         - floor (y / info->scaley));
 
644
      gint error =
 
645
        RINT (floor ((y + 1) / info->scaley) - floor (y / info->scaley));
684
646
 
685
647
      if (!initial && (error == 0) && (y & check_mod))
686
 
        {
687
 
          memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
688
 
        }
 
648
        {
 
649
          memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
 
650
        }
689
651
      else
690
 
        {
691
 
          src = info->src;
692
 
          dest = info->dest;
693
 
 
694
 
          dark_light = (y >> check_shift) + (info->x >> check_shift);
695
 
 
696
 
          g_return_if_fail (src != NULL);
697
 
 
698
 
          for (x = info->x; x < xe; x++)
699
 
            {
700
 
              a = alpha[src[ALPHA_G_PIX]];
701
 
              if (dark_light & 0x1)
702
 
                val = render_blend_dark_check[(a | src[GRAY_PIX])];
703
 
              else
704
 
                val = render_blend_light_check[(a | src[GRAY_PIX])];
705
 
              src += 2;
706
 
 
707
 
              dest[0] = val;
708
 
              dest[1] = val;
709
 
              dest[2] = val;
710
 
              dest += 3;
711
 
 
712
 
              if (((x + 1) & check_mod) == 0)
713
 
                dark_light += 1;
714
 
            }
715
 
        }
 
652
        {
 
653
          const guchar *src  = info->src;
 
654
          guchar       *dest = info->dest;
 
655
          guint         dark_light;
 
656
 
 
657
          dark_light = (y >> check_shift) + (info->x >> check_shift);
 
658
 
 
659
          for (x = info->x; x < xe; x++)
 
660
            {
 
661
              guint a = alpha[src[ALPHA_G_PIX]];
 
662
              guint val;
 
663
 
 
664
              if (dark_light & 0x1)
 
665
                val = gimp_render_blend_dark_check[(a | src[GRAY_PIX])];
 
666
              else
 
667
                val = gimp_render_blend_light_check[(a | src[GRAY_PIX])];
 
668
 
 
669
              src += 2;
 
670
 
 
671
              dest[0] = val;
 
672
              dest[1] = val;
 
673
              dest[2] = val;
 
674
              dest += 3;
 
675
 
 
676
              if (((x + 1) & check_mod) == 0)
 
677
                dark_light += 1;
 
678
            }
 
679
        }
 
680
 
 
681
      if (++y == ye)
 
682
        break;
716
683
 
717
684
      info->dest += info->dest_bpl;
718
685
 
719
 
      initial = FALSE;
 
686
      if (error)
 
687
        {
 
688
          info->src_y += error;
 
689
          info->src = render_image_tile_fault (info);
720
690
 
721
 
      if (error >= 1)
722
 
        {
723
 
          info->src_y += error;
724
 
          info->src = render_image_tile_fault (info);
725
 
          initial = TRUE;
726
 
        }
 
691
          initial = TRUE;
 
692
        }
 
693
      else
 
694
        {
 
695
          initial = FALSE;
 
696
        }
727
697
    }
728
698
}
729
699
 
730
700
static void
731
701
render_image_rgb (RenderInfo *info)
732
702
{
733
 
  gint    byte_order;
734
 
  gint    y, ye;
735
 
  gint    xe;
736
 
  gint    initial;
 
703
  gint      y, ye;
 
704
  gint      xe;
 
705
  gboolean  initial = TRUE;
737
706
 
738
707
  y  = info->y;
739
708
  ye = info->y + info->h;
740
709
  xe = info->x + info->w;
741
710
 
742
 
  initial = TRUE;
743
 
  byte_order = info->byte_order;
744
711
  info->src = render_image_tile_fault (info);
745
712
 
746
 
  for (; y < ye; y++)
 
713
  while (TRUE)
747
714
    {
748
 
      gint error = RINT (floor ((y + 1) / info->scaley)
749
 
                         - floor (y / info->scaley));
 
715
      gint error =
 
716
        RINT (floor ((y + 1) / info->scaley) - floor (y / info->scaley));
750
717
 
751
718
      if (!initial && (error == 0))
752
 
        {
753
 
          memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
754
 
        }
 
719
        {
 
720
          memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
 
721
        }
755
722
      else
756
 
        {
757
 
          g_return_if_fail (info->src != NULL);
758
 
 
 
723
        {
759
724
          memcpy (info->dest, info->src, 3 * info->w);
760
 
        }
 
725
        }
 
726
 
 
727
      if (++y == ye)
 
728
        break;
761
729
 
762
730
      info->dest += info->dest_bpl;
763
731
 
764
 
      initial = FALSE;
 
732
      if (error)
 
733
        {
 
734
          info->src_y += error;
 
735
          info->src = render_image_tile_fault (info);
765
736
 
766
 
      if (error >= 1)
767
 
        {
768
 
          info->src_y += error;
769
 
          info->src = render_image_tile_fault (info);
770
 
          initial = TRUE;
771
 
        }
 
737
          initial = TRUE;
 
738
        }
 
739
      else
 
740
        {
 
741
          initial = FALSE;
 
742
        }
772
743
    }
773
744
}
774
745
 
775
746
static void
776
747
render_image_rgb_a (RenderInfo *info)
777
748
{
778
 
  guchar *src;
779
 
  guchar *dest;
780
 
  guint  *alpha;
781
 
  gulong  r, g, b;
782
 
  guint   a;
783
 
  gint    dark_light;
784
 
  gint    byte_order;
785
 
  gint    y, ye;
786
 
  gint    x, xe;
787
 
  gint    initial;
788
 
 
789
 
  alpha = info->alpha;
 
749
  const guint *alpha = info->alpha;
 
750
  gint         y, ye;
 
751
  gint         x, xe;
 
752
  gint         initial = TRUE;
790
753
 
791
754
  y  = info->y;
792
755
  ye = info->y + info->h;
793
756
  xe = info->x + info->w;
794
757
 
795
 
  initial = TRUE;
796
 
  byte_order = info->byte_order;
797
758
  info->src = render_image_tile_fault (info);
798
759
 
799
 
  for (; y < ye; y++)
 
760
  while (TRUE)
800
761
    {
801
 
      gint error = RINT (floor ((y + 1) / info->scaley)
802
 
                         - floor (y / info->scaley));
 
762
      gint error =
 
763
        RINT (floor ((y + 1) / info->scaley) - floor (y / info->scaley));
803
764
 
804
765
      if (!initial && (error == 0) && (y & check_mod))
805
 
        {
806
 
          memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
807
 
        }
 
766
        {
 
767
          memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
 
768
        }
808
769
      else
809
 
        {
810
 
          src = info->src;
811
 
          dest = info->dest;
812
 
 
813
 
          dark_light = (y >> check_shift) + (info->x >> check_shift);
814
 
 
815
 
          g_return_if_fail (src != NULL);
816
 
 
817
 
          for (x = info->x; x < xe; x++)
818
 
            {
819
 
              a = alpha[src[ALPHA_PIX]];
820
 
              if (dark_light & 0x1)
821
 
                {
822
 
                  r = render_blend_dark_check[(a | src[RED_PIX])];
823
 
                  g = render_blend_dark_check[(a | src[GREEN_PIX])];
824
 
                  b = render_blend_dark_check[(a | src[BLUE_PIX])];
825
 
                }
826
 
              else
827
 
                {
828
 
                  r = render_blend_light_check[(a | src[RED_PIX])];
829
 
                  g = render_blend_light_check[(a | src[GREEN_PIX])];
830
 
                  b = render_blend_light_check[(a | src[BLUE_PIX])];
831
 
                }
832
 
 
833
 
              src += 4;
834
 
 
835
 
              dest[0] = r;
836
 
              dest[1] = g;
837
 
              dest[2] = b;
838
 
              dest += 3;
839
 
 
840
 
              if (((x + 1) & check_mod) == 0)
841
 
                dark_light += 1;
842
 
            }
843
 
        }
 
770
        {
 
771
          const guchar *src  = info->src;
 
772
          guchar       *dest = info->dest;
 
773
          guint         dark_light;
 
774
 
 
775
          dark_light = (y >> check_shift) + (info->x >> check_shift);
 
776
 
 
777
          for (x = info->x; x < xe; x++)
 
778
            {
 
779
              guint r, g, b, a = alpha[src[ALPHA_PIX]];
 
780
 
 
781
              if (dark_light & 0x1)
 
782
                {
 
783
                  r = gimp_render_blend_dark_check[(a | src[RED_PIX])];
 
784
                  g = gimp_render_blend_dark_check[(a | src[GREEN_PIX])];
 
785
                  b = gimp_render_blend_dark_check[(a | src[BLUE_PIX])];
 
786
                }
 
787
              else
 
788
                {
 
789
                  r = gimp_render_blend_light_check[(a | src[RED_PIX])];
 
790
                  g = gimp_render_blend_light_check[(a | src[GREEN_PIX])];
 
791
                  b = gimp_render_blend_light_check[(a | src[BLUE_PIX])];
 
792
                }
 
793
 
 
794
              src += 4;
 
795
 
 
796
              dest[0] = r;
 
797
              dest[1] = g;
 
798
              dest[2] = b;
 
799
              dest += 3;
 
800
 
 
801
              if (((x + 1) & check_mod) == 0)
 
802
                dark_light += 1;
 
803
            }
 
804
        }
 
805
 
 
806
      if (++y == ye)
 
807
        break;
844
808
 
845
809
      info->dest += info->dest_bpl;
846
810
 
847
 
      initial = FALSE;
 
811
      if (error)
 
812
        {
 
813
          info->src_y += error;
 
814
          info->src = render_image_tile_fault (info);
848
815
 
849
 
      if (error >= 1)
850
 
        {
851
 
          info->src_y += error;
852
 
          info->src = render_image_tile_fault (info);
853
 
          initial = TRUE;
854
 
        }
 
816
          initial = TRUE;
 
817
        }
 
818
      else
 
819
        {
 
820
          initial = FALSE;
 
821
        }
855
822
    }
856
823
}
857
824
 
858
825
static void
859
 
render_image_init_info (RenderInfo       *info,
860
 
                        GimpDisplayShell *shell,
861
 
                        gint              x,
862
 
                        gint              y,
863
 
                        gint              w,
864
 
                        gint              h)
 
826
render_image_init_info_full (RenderInfo       *info,
 
827
                             GimpDisplayShell *shell,
 
828
                             gint              x,
 
829
                             gint              y,
 
830
                             gint              w,
 
831
                             gint              h,
 
832
                             GimpProjection   *projection)
865
833
{
866
 
  GimpImage *gimage = shell->gdisp->gimage;
867
 
 
868
834
  info->shell      = shell;
869
 
  info->src_tiles  = gimp_projection_get_tiles (gimage->projection);
870
 
  info->x          = x + shell->offset_x;
871
 
  info->y          = y + shell->offset_y;
872
835
  info->w          = w;
873
836
  info->h          = h;
874
 
  info->scalex     = SCALEFACTOR_X (shell);
875
 
  info->scaley     = SCALEFACTOR_Y (shell);
876
 
  info->src_x      = (gdouble) info->x / info->scalex;
877
 
  info->src_y      = (gdouble) info->y / info->scaley;
878
 
  info->src_bpp    = gimp_projection_get_bytes (gimage->projection);
879
 
  info->dest       = shell->render_buf;
 
837
  info->scalex     = shell->scale_x;
 
838
  info->scaley     = shell->scale_y;
880
839
  info->dest_bpp   = 3;
881
 
  info->dest_bpl   = info->dest_bpp * GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH;
882
 
  info->dest_width = info->w * info->dest_bpp;
883
 
  info->byte_order = GDK_MSB_FIRST;
884
 
  info->scale      = render_image_accelerate_scaling (w,
885
 
                                                      info->x, info->scalex);
886
 
  info->alpha      = NULL;
887
 
 
888
 
  if (GIMP_IMAGE_TYPE_HAS_ALPHA (gimp_projection_get_image_type (gimage->projection)))
 
840
  info->dest_bpl   = info->dest_bpp * GIMP_RENDER_BUF_WIDTH;
 
841
  info->dest_width = info->dest_bpp * info->w;
 
842
 
 
843
  render_image_init_info (info, shell, x, y,
 
844
                          gimp_projection_get_tiles (projection));
 
845
 
 
846
  info->scale      = render_image_accelerate_scaling (w, info->x, info->scalex);
 
847
 
 
848
  if (GIMP_IMAGE_TYPE_HAS_ALPHA (gimp_projection_get_image_type (projection)))
889
849
    {
890
 
      info->alpha =
891
 
        render_image_init_alpha (gimp_projection_get_opacity (gimage->projection) * 255.999);
 
850
      gdouble opacity = gimp_projection_get_opacity (projection);
 
851
 
 
852
      info->alpha = render_image_init_alpha (opacity * 255.999);
892
853
    }
893
854
}
894
855
 
895
 
static guint *
 
856
static void
 
857
render_image_init_info (RenderInfo       *info,
 
858
                        GimpDisplayShell *shell,
 
859
                        gint              x,
 
860
                        gint              y,
 
861
                        TileManager      *tiles)
 
862
{
 
863
  info->src_tiles = tiles;
 
864
  info->x         = x + shell->offset_x;
 
865
  info->y         = y + shell->offset_y;
 
866
  info->src_x     = (gdouble) info->x / info->scalex;
 
867
  info->src_y     = (gdouble) info->y / info->scaley;
 
868
  info->dest      = shell->render_buf;
 
869
}
 
870
 
 
871
static const guint *
896
872
render_image_init_alpha (gint mult)
897
873
{
898
874
  static guint *alpha_mult = NULL;
903
879
  if (alpha_val != mult)
904
880
    {
905
881
      if (!alpha_mult)
906
 
        alpha_mult = g_new (guint, 256);
 
882
        alpha_mult = g_new (guint, 256);
907
883
 
908
884
      alpha_val = mult;
909
885
      for (i = 0; i < 256; i++)
910
 
        alpha_mult[i] = ((mult * i) / 255) << 8;
 
886
        alpha_mult[i] = ((mult * i) / 255) << 8;
911
887
    }
912
888
 
913
889
  return alpha_mult;
914
890
}
915
891
 
916
 
static guchar *
 
892
static const guchar *
917
893
render_image_accelerate_scaling (gint    width,
918
 
                                 gint    start,
919
 
                                 gdouble scalex)
 
894
                                 gint    start,
 
895
                                 gdouble scalex)
920
896
{
921
897
  static guchar *scale = NULL;
922
898
 
923
899
  gint  i;
924
900
 
925
901
  if (! scale)
926
 
    scale = g_new (guchar, GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH + 1);
 
902
    scale = g_new (guchar, GIMP_RENDER_BUF_WIDTH + 1);
927
903
 
928
904
  for (i = 0; i <= width; i++)
929
905
    {
934
910
  return scale;
935
911
}
936
912
 
937
 
static guchar *
 
913
static const guchar *
938
914
render_image_tile_fault (RenderInfo *info)
939
915
{
940
 
  Tile   *tile;
941
 
  guchar *data;
942
 
  guchar *dest;
943
 
  guchar *scale;
944
 
  gint    width;
945
 
  gint    tilex;
946
 
  gint    step;
947
 
  gint    bpp = info->src_bpp;
948
 
  gint    x, b;
 
916
  Tile         *tile;
 
917
  const guchar *src;
 
918
  const guchar *scale;
 
919
  guchar       *dest;
 
920
  gint          width;
 
921
  gint          tilex;
 
922
  gint          step;
 
923
  gint          bpp;
 
924
  gint          x;
949
925
 
950
926
  tile = tile_manager_get_tile (info->src_tiles,
951
 
                                info->src_x, info->src_y,
952
 
                                TRUE, FALSE);
953
 
  if (!tile)
954
 
    return NULL;
955
 
 
956
 
  data = tile_data_pointer (tile,
957
 
                            info->src_x % TILE_WIDTH,
958
 
                            info->src_y % TILE_HEIGHT);
 
927
                                info->src_x, info->src_y, TRUE, FALSE);
 
928
 
 
929
  g_return_val_if_fail (tile != NULL, tile_buf);
 
930
 
 
931
  src = tile_data_pointer (tile,
 
932
                           info->src_x % TILE_WIDTH,
 
933
                           info->src_y % TILE_HEIGHT);
 
934
 
 
935
  bpp   = tile_manager_bpp (info->src_tiles);
959
936
  scale = info->scale;
960
937
  dest  = tile_buf;
961
938
 
964
941
 
965
942
  tilex = info->src_x / TILE_WIDTH;
966
943
 
967
 
  while (width--)
 
944
  do
968
945
    {
969
 
      for (b = 0; b < bpp; b++)
970
 
        *dest++ = data[b];
 
946
      const guchar *s = src;
 
947
 
 
948
      switch (bpp)
 
949
        {
 
950
        case 4:
 
951
          *dest++ = *s++;
 
952
        case 3:
 
953
          *dest++ = *s++;
 
954
        case 2:
 
955
          *dest++ = *s++;
 
956
        case 1:
 
957
          *dest++ = *s++;
 
958
        }
971
959
 
972
960
      step = *scale++;
973
 
      if (step != 0)
974
 
        {
975
 
          x += step;
976
 
          data += step * bpp;
977
 
 
978
 
          if ((x >> tile_shift) != tilex)
979
 
            {
980
 
              tile_release (tile, FALSE);
981
 
              tilex += 1;
982
 
 
983
 
              tile = tile_manager_get_tile (info->src_tiles,
984
 
                                            x, info->src_y,
985
 
                                            TRUE, FALSE);
986
 
 
987
 
              if (!tile)
988
 
                return tile_buf;
989
 
 
990
 
              data = tile_data_pointer (tile,
991
 
                                        x % TILE_WIDTH,
992
 
                                        info->src_y % TILE_HEIGHT);
993
 
            }
994
 
        }
 
961
 
 
962
      if (step)
 
963
        {
 
964
          x += step;
 
965
          src += step * bpp;
 
966
 
 
967
          if ((x / TILE_WIDTH) != tilex)
 
968
            {
 
969
              tile_release (tile, FALSE);
 
970
              tilex += 1;
 
971
 
 
972
              tile = tile_manager_get_tile (info->src_tiles,
 
973
                                            x, info->src_y, TRUE, FALSE);
 
974
              if (!tile)
 
975
                return tile_buf;
 
976
 
 
977
              src = tile_data_pointer (tile,
 
978
                                       x % TILE_WIDTH,
 
979
                                       info->src_y % TILE_HEIGHT);
 
980
            }
 
981
        }
995
982
    }
 
983
  while (--width);
996
984
 
997
985
  tile_release (tile, FALSE);
998
986