~ubuntu-branches/ubuntu/maverick/gimp/maverick-updates

« back to all changes in this revision

Viewing changes to app/display/gimpdisplayshell-render.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2005-12-09 19:44:52 UTC
  • Revision ID: james.westby@ubuntu.com-20051209194452-yggpemjlofpjqyf4
Tags: upstream-2.2.9
ImportĀ upstreamĀ versionĀ 2.2.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* The GIMP -- an image manipulation program
 
2
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License as published by
 
6
 * the Free Software Foundation; either version 2 of the License, or
 
7
 * (at your option) any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software
 
16
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
17
 */
 
18
 
 
19
#include "config.h"
 
20
 
 
21
#include <stdlib.h>
 
22
#include <string.h>
 
23
 
 
24
#include <gtk/gtk.h>
 
25
 
 
26
#include "libgimpbase/gimpbase.h"
 
27
#include "libgimpwidgets/gimpwidgets.h"
 
28
 
 
29
#include "display-types.h"
 
30
 
 
31
#include "base/tile-manager.h"
 
32
#include "base/tile.h"
 
33
 
 
34
#include "core/gimp.h"
 
35
#include "core/gimpimage.h"
 
36
#include "core/gimpimage-colormap.h"
 
37
#include "core/gimpprojection.h"
 
38
 
 
39
#include "gimpcanvas.h"
 
40
#include "gimpdisplay.h"
 
41
#include "gimpdisplayshell.h"
 
42
#include "gimpdisplayshell-filter.h"
 
43
#include "gimpdisplayshell-render.h"
 
44
 
 
45
 
 
46
typedef struct _RenderInfo  RenderInfo;
 
47
 
 
48
typedef void (* RenderFunc) (RenderInfo *info);
 
49
 
 
50
struct _RenderInfo
 
51
{
 
52
  GimpDisplayShell *shell;
 
53
  TileManager      *src_tiles;
 
54
  guint            *alpha;
 
55
  guchar           *scale;
 
56
  guchar           *src;
 
57
  guchar           *dest;
 
58
  gint              x, y;
 
59
  gint              w, h;
 
60
  gdouble           scalex;
 
61
  gdouble           scaley;
 
62
  gint              src_x, src_y;
 
63
  gint              src_bpp;
 
64
  gint              dest_bpp;
 
65
  gint              dest_bpl;
 
66
  gint              dest_width;
 
67
  gint              byte_order;
 
68
};
 
69
 
 
70
 
 
71
static void   render_setup_notify (gpointer    config,
 
72
                                   GParamSpec *param_spec,
 
73
                                   Gimp       *gimp);
 
74
 
 
75
 
 
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;
 
91
 
 
92
 
 
93
void
 
94
render_init (Gimp *gimp)
 
95
{
 
96
  g_return_if_fail (GIMP_IS_GIMP (gimp));
 
97
 
 
98
  g_signal_connect (gimp->config, "notify::transparency-size",
 
99
                    G_CALLBACK (render_setup_notify),
 
100
                    gimp);
 
101
  g_signal_connect (gimp->config, "notify::transparency-type",
 
102
                    G_CALLBACK (render_setup_notify),
 
103
                    gimp);
 
104
 
 
105
  render_setup_notify (gimp->config, NULL, gimp);
 
106
}
 
107
 
 
108
void
 
109
render_exit (Gimp *gimp)
 
110
{
 
111
  g_return_if_fail (GIMP_IS_GIMP (gimp));
 
112
 
 
113
  g_signal_handlers_disconnect_by_func (gimp->config,
 
114
                                        render_setup_notify,
 
115
                                        gimp);
 
116
 
 
117
  if (tile_buf)
 
118
    {
 
119
      g_free (tile_buf);
 
120
      tile_buf = NULL;
 
121
    }
 
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
}
 
165
 
 
166
 
 
167
static void
 
168
render_setup_notify (gpointer    config,
 
169
                     GParamSpec *param_spec,
 
170
                     Gimp       *gimp)
 
171
{
 
172
  GimpCheckType check_type;
 
173
  GimpCheckSize check_size;
 
174
  guchar        light, dark;
 
175
  gint          i, j;
 
176
 
 
177
  g_object_get (config,
 
178
                "transparency-type", &check_type,
 
179
                "transparency-size", &check_size,
 
180
                NULL);
 
181
 
 
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
  switch (check_size)
 
215
    {
 
216
    case GIMP_CHECK_SIZE_SMALL_CHECKS:
 
217
      check_mod   = 0x3;
 
218
      check_shift = 2;
 
219
      break;
 
220
    case GIMP_CHECK_SIZE_MEDIUM_CHECKS:
 
221
      check_mod   = 0x7;
 
222
      check_shift = 3;
 
223
      break;
 
224
    case GIMP_CHECK_SIZE_LARGE_CHECKS:
 
225
      check_mod   = 0xf;
 
226
      check_shift = 4;
 
227
      break;
 
228
    }
 
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
}
 
265
 
 
266
 
 
267
/*  Render Image functions  */
 
268
 
 
269
static void     render_image_rgb                (RenderInfo       *info);
 
270
static void     render_image_rgb_a              (RenderInfo       *info);
 
271
static void     render_image_gray               (RenderInfo       *info);
 
272
static void     render_image_gray_a             (RenderInfo       *info);
 
273
static void     render_image_indexed            (RenderInfo       *info);
 
274
static void     render_image_indexed_a          (RenderInfo       *info);
 
275
 
 
276
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);
 
287
 
 
288
 
 
289
static RenderFunc render_funcs[6] =
 
290
{
 
291
  render_image_rgb,
 
292
  render_image_rgb_a,
 
293
  render_image_gray,
 
294
  render_image_gray_a,
 
295
  render_image_indexed,
 
296
  render_image_indexed_a,
 
297
};
 
298
 
 
299
 
 
300
static void  gimp_display_shell_render_highlight (GimpDisplayShell *shell,
 
301
                                                  gint              x,
 
302
                                                  gint              y,
 
303
                                                  gint              w,
 
304
                                                  gint              h,
 
305
                                                  GdkRectangle     *highlight);
 
306
 
 
307
 
 
308
/*****************************************************************/
 
309
/*  This function is the core of the display--it offsets and     */
 
310
/*  scales the image according to the current parameters in the  */
 
311
/*  gdisp object.  It handles color, grayscale, 8, 15, 16, 24,   */
 
312
/*  & 32 bit output depths.                                      */
 
313
/*****************************************************************/
 
314
 
 
315
void
 
316
gimp_display_shell_render (GimpDisplayShell *shell,
 
317
                           gint              x,
 
318
                           gint              y,
 
319
                           gint              w,
 
320
                           gint              h,
 
321
                           GdkRectangle     *highlight)
 
322
{
 
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
    }
 
341
 
 
342
  /* Currently, only RGBA and GRAYA projection types are used - the rest
 
343
   * are in case of future need.  -- austin, 28th Nov 1998.
 
344
   */
 
345
  if (image_type != GIMP_RGBA_IMAGE && image_type != GIMP_GRAYA_IMAGE)
 
346
    g_warning ("using untested projection type %d", image_type);
 
347
 
 
348
  (* render_funcs[image_type]) (&info);
 
349
 
 
350
  /*  apply filters to the rendered projection  */
 
351
  if (shell->filter_stack)
 
352
    gimp_color_display_stack_convert (shell->filter_stack,
 
353
                                      shell->render_buf,
 
354
                                      w, h,
 
355
                                      3,
 
356
                                      3 * GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH);
 
357
 
 
358
  /*  dim pixels outside the highlighted rectangle  */
 
359
  if (highlight)
 
360
    gimp_display_shell_render_highlight (shell, x, y, w, h, highlight);
 
361
 
 
362
  /*  put it to the screen  */
 
363
  gimp_canvas_draw_rgb (GIMP_CANVAS (shell->canvas), GIMP_CANVAS_STYLE_RENDER,
 
364
                        x + shell->disp_xoffset, y + shell->disp_yoffset,
 
365
                        w, h,
 
366
                        shell->render_buf,
 
367
                        3 * GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH,
 
368
                        shell->offset_x, shell->offset_y);
 
369
}
 
370
 
 
371
 
 
372
#define GIMP_DISPLAY_SHELL_DIM_PIXEL(buf,x) \
 
373
{ \
 
374
  buf[3 * (x) + 0] >>= 1; \
 
375
  buf[3 * (x) + 1] >>= 1; \
 
376
  buf[3 * (x) + 2] >>= 1; \
 
377
}
 
378
 
 
379
/*  This function highlights the given area by dimming all pixels outside. */
 
380
 
 
381
static void
 
382
gimp_display_shell_render_highlight (GimpDisplayShell *shell,
 
383
                                     gint              x,
 
384
                                     gint              y,
 
385
                                     gint              w,
 
386
                                     gint              h,
 
387
                                     GdkRectangle     *highlight)
 
388
{
 
389
  guchar       *buf  = shell->render_buf;
 
390
  GdkRectangle  rect;
 
391
 
 
392
  rect.x      = shell->offset_x + x;
 
393
  rect.y      = shell->offset_y + y;
 
394
  rect.width  = w;
 
395
  rect.height = h;
 
396
 
 
397
  if (gdk_rectangle_intersect (highlight, &rect, &rect))
 
398
    {
 
399
      rect.x -= shell->offset_x + x;
 
400
      rect.y -= shell->offset_y + y;
 
401
 
 
402
      for (y = 0; y < rect.y; y++)
 
403
        {
 
404
          for (x = 0; x < w; x++)
 
405
            GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
 
406
 
 
407
          buf += 3 * GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH;
 
408
        }
 
409
 
 
410
      for ( ; y < rect.y + rect.height; y++)
 
411
        {
 
412
          for (x = 0; x < rect.x; x++)
 
413
            GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
 
414
 
 
415
          for (x += rect.width; x < w; x++)
 
416
            GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
 
417
 
 
418
          buf += 3 * GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH;
 
419
        }
 
420
 
 
421
      for ( ; y < h; y++)
 
422
        {
 
423
          for (x = 0; x < w; x++)
 
424
            GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
 
425
 
 
426
          buf += 3 * GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH;
 
427
        }
 
428
    }
 
429
  else
 
430
    {
 
431
      for (y = 0; y < h; y++)
 
432
        {
 
433
          for (x = 0; x < w; x++)
 
434
            GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
 
435
 
 
436
          buf += 3 * GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH;
 
437
        }
 
438
    }
 
439
}
 
440
 
 
441
 
 
442
/*************************/
 
443
/*  8 Bit functions      */
 
444
/*************************/
 
445
 
 
446
static void
 
447
render_image_indexed (RenderInfo *info)
 
448
{
 
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;
 
457
 
 
458
  cmap = gimp_image_get_colormap (info->shell->gdisp->gimage);
 
459
 
 
460
  y  = info->y;
 
461
  ye = info->y + info->h;
 
462
  xe = info->x + info->w;
 
463
 
 
464
  initial = TRUE;
 
465
  byte_order = info->byte_order;
 
466
  info->src = render_image_tile_fault (info);
 
467
 
 
468
  for (; y < ye; y++)
 
469
    {
 
470
      gint error = RINT (floor ((y + 1) / info->scaley)
 
471
                         - floor (y / info->scaley));
 
472
 
 
473
      if (!initial && (error == 0))
 
474
        {
 
475
          memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
 
476
        }
 
477
      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
        }
 
495
 
 
496
      info->dest += info->dest_bpl;
 
497
 
 
498
      initial = FALSE;
 
499
 
 
500
      if (error >= 1)
 
501
        {
 
502
          info->src_y += error;
 
503
          info->src = render_image_tile_fault (info);
 
504
          initial = TRUE;
 
505
        }
 
506
    }
 
507
}
 
508
 
 
509
static void
 
510
render_image_indexed_a (RenderInfo *info)
 
511
{
 
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;
 
527
 
 
528
  y  = info->y;
 
529
  ye = info->y + info->h;
 
530
  xe = info->x + info->w;
 
531
 
 
532
  initial = TRUE;
 
533
  byte_order = info->byte_order;
 
534
  info->src = render_image_tile_fault (info);
 
535
 
 
536
  for (; y < ye; y++)
 
537
    {
 
538
      gint error = RINT (floor ((y + 1) / info->scaley)
 
539
                         - floor (y / info->scaley));
 
540
 
 
541
      if (!initial && (error == 0) && (y & check_mod))
 
542
        {
 
543
          memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
 
544
        }
 
545
      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
        }
 
582
 
 
583
      info->dest += info->dest_bpl;
 
584
 
 
585
      initial = FALSE;
 
586
 
 
587
      if (error >= 1)
 
588
        {
 
589
          info->src_y += error;
 
590
          info->src = render_image_tile_fault (info);
 
591
          initial = TRUE;
 
592
        }
 
593
    }
 
594
}
 
595
 
 
596
static void
 
597
render_image_gray (RenderInfo *info)
 
598
{
 
599
  guchar *src;
 
600
  guchar *dest;
 
601
  gulong  val;
 
602
  gint    byte_order;
 
603
  gint    y, ye;
 
604
  gint    x, xe;
 
605
  gint    initial;
 
606
 
 
607
  y  = info->y;
 
608
  ye = info->y + info->h;
 
609
  xe = info->x + info->w;
 
610
 
 
611
  initial = TRUE;
 
612
  byte_order = info->byte_order;
 
613
  info->src = render_image_tile_fault (info);
 
614
 
 
615
  for (; y < ye; y++)
 
616
    {
 
617
      gint error = RINT (floor ((y + 1) / info->scaley)
 
618
                         - floor (y / info->scaley));
 
619
 
 
620
      if (!initial && (error == 0))
 
621
        {
 
622
          memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
 
623
        }
 
624
      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
        }
 
642
 
 
643
      info->dest += info->dest_bpl;
 
644
 
 
645
      initial = FALSE;
 
646
 
 
647
      if (error >= 1)
 
648
        {
 
649
          info->src_y += error;
 
650
          info->src = render_image_tile_fault (info);
 
651
          initial = TRUE;
 
652
        }
 
653
    }
 
654
}
 
655
 
 
656
static void
 
657
render_image_gray_a (RenderInfo *info)
 
658
{
 
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;
 
671
 
 
672
  y  = info->y;
 
673
  ye = info->y + info->h;
 
674
  xe = info->x + info->w;
 
675
 
 
676
  initial = TRUE;
 
677
  byte_order = info->byte_order;
 
678
  info->src = render_image_tile_fault (info);
 
679
 
 
680
  for (; y < ye; y++)
 
681
    {
 
682
      gint error = RINT (floor ((y + 1) / info->scaley)
 
683
                         - floor (y / info->scaley));
 
684
 
 
685
      if (!initial && (error == 0) && (y & check_mod))
 
686
        {
 
687
          memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
 
688
        }
 
689
      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
        }
 
716
 
 
717
      info->dest += info->dest_bpl;
 
718
 
 
719
      initial = FALSE;
 
720
 
 
721
      if (error >= 1)
 
722
        {
 
723
          info->src_y += error;
 
724
          info->src = render_image_tile_fault (info);
 
725
          initial = TRUE;
 
726
        }
 
727
    }
 
728
}
 
729
 
 
730
static void
 
731
render_image_rgb (RenderInfo *info)
 
732
{
 
733
  gint    byte_order;
 
734
  gint    y, ye;
 
735
  gint    xe;
 
736
  gint    initial;
 
737
 
 
738
  y  = info->y;
 
739
  ye = info->y + info->h;
 
740
  xe = info->x + info->w;
 
741
 
 
742
  initial = TRUE;
 
743
  byte_order = info->byte_order;
 
744
  info->src = render_image_tile_fault (info);
 
745
 
 
746
  for (; y < ye; y++)
 
747
    {
 
748
      gint error = RINT (floor ((y + 1) / info->scaley)
 
749
                         - floor (y / info->scaley));
 
750
 
 
751
      if (!initial && (error == 0))
 
752
        {
 
753
          memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
 
754
        }
 
755
      else
 
756
        {
 
757
          g_return_if_fail (info->src != NULL);
 
758
 
 
759
          memcpy (info->dest, info->src, 3 * info->w);
 
760
        }
 
761
 
 
762
      info->dest += info->dest_bpl;
 
763
 
 
764
      initial = FALSE;
 
765
 
 
766
      if (error >= 1)
 
767
        {
 
768
          info->src_y += error;
 
769
          info->src = render_image_tile_fault (info);
 
770
          initial = TRUE;
 
771
        }
 
772
    }
 
773
}
 
774
 
 
775
static void
 
776
render_image_rgb_a (RenderInfo *info)
 
777
{
 
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;
 
790
 
 
791
  y  = info->y;
 
792
  ye = info->y + info->h;
 
793
  xe = info->x + info->w;
 
794
 
 
795
  initial = TRUE;
 
796
  byte_order = info->byte_order;
 
797
  info->src = render_image_tile_fault (info);
 
798
 
 
799
  for (; y < ye; y++)
 
800
    {
 
801
      gint error = RINT (floor ((y + 1) / info->scaley)
 
802
                         - floor (y / info->scaley));
 
803
 
 
804
      if (!initial && (error == 0) && (y & check_mod))
 
805
        {
 
806
          memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
 
807
        }
 
808
      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
        }
 
844
 
 
845
      info->dest += info->dest_bpl;
 
846
 
 
847
      initial = FALSE;
 
848
 
 
849
      if (error >= 1)
 
850
        {
 
851
          info->src_y += error;
 
852
          info->src = render_image_tile_fault (info);
 
853
          initial = TRUE;
 
854
        }
 
855
    }
 
856
}
 
857
 
 
858
static void
 
859
render_image_init_info (RenderInfo       *info,
 
860
                        GimpDisplayShell *shell,
 
861
                        gint              x,
 
862
                        gint              y,
 
863
                        gint              w,
 
864
                        gint              h)
 
865
{
 
866
  GimpImage *gimage = shell->gdisp->gimage;
 
867
 
 
868
  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
  info->w          = w;
 
873
  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;
 
880
  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)))
 
889
    {
 
890
      info->alpha =
 
891
        render_image_init_alpha (gimp_projection_get_opacity (gimage->projection) * 255.999);
 
892
    }
 
893
}
 
894
 
 
895
static guint *
 
896
render_image_init_alpha (gint mult)
 
897
{
 
898
  static guint *alpha_mult = NULL;
 
899
  static gint   alpha_val  = -1;
 
900
 
 
901
  gint i;
 
902
 
 
903
  if (alpha_val != mult)
 
904
    {
 
905
      if (!alpha_mult)
 
906
        alpha_mult = g_new (guint, 256);
 
907
 
 
908
      alpha_val = mult;
 
909
      for (i = 0; i < 256; i++)
 
910
        alpha_mult[i] = ((mult * i) / 255) << 8;
 
911
    }
 
912
 
 
913
  return alpha_mult;
 
914
}
 
915
 
 
916
static guchar *
 
917
render_image_accelerate_scaling (gint    width,
 
918
                                 gint    start,
 
919
                                 gdouble scalex)
 
920
{
 
921
  static guchar *scale = NULL;
 
922
 
 
923
  gint  i;
 
924
 
 
925
  if (! scale)
 
926
    scale = g_new (guchar, GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH + 1);
 
927
 
 
928
  for (i = 0; i <= width; i++)
 
929
    {
 
930
      scale[i] = RINT (floor ((start + 1) / scalex) - floor (start / scalex));
 
931
      start++;
 
932
    }
 
933
 
 
934
  return scale;
 
935
}
 
936
 
 
937
static guchar *
 
938
render_image_tile_fault (RenderInfo *info)
 
939
{
 
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;
 
949
 
 
950
  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);
 
959
  scale = info->scale;
 
960
  dest  = tile_buf;
 
961
 
 
962
  x     = info->src_x;
 
963
  width = info->w;
 
964
 
 
965
  tilex = info->src_x / TILE_WIDTH;
 
966
 
 
967
  while (width--)
 
968
    {
 
969
      for (b = 0; b < bpp; b++)
 
970
        *dest++ = data[b];
 
971
 
 
972
      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
        }
 
995
    }
 
996
 
 
997
  tile_release (tile, FALSE);
 
998
 
 
999
  return tile_buf;
 
1000
}