1
/* The GIMP -- an image manipulation program
2
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
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.
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.
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.
21
#include <glib-object.h>
23
#include "libgimpcolor/gimpcolor.h"
25
#include "core-types.h"
27
#include "base/pixel-region.h"
28
#include "base/tile-manager.h"
30
#include "paint-funcs/paint-funcs.h"
32
#include "gimpimage.h"
33
#include "gimplayer.h"
34
#include "gimplayer-floating-sel.h"
35
#include "gimplayermask.h"
37
#include "gimpprojection.h"
38
#include "gimpprojection-construct.h"
41
/* local function prototypes */
43
static void gimp_projection_construct_layers (GimpProjection *proj,
48
static void gimp_projection_construct_channels (GimpProjection *proj,
53
static void gimp_projection_initialize (GimpProjection *proj,
59
static void project_intensity (GimpProjection *proj,
64
static void project_intensity_alpha (GimpProjection *proj,
69
static void project_indexed (GimpProjection *proj,
73
static void project_indexed_alpha (GimpProjection *proj,
78
static void project_channel (GimpProjection *proj,
84
/* public functions */
87
gimp_projection_construct (GimpProjection *proj,
93
g_return_if_fail (GIMP_IS_PROJECTION (proj));
99
/* set the construct flag, used to determine if anything
100
* has been written to the gimage raw image yet.
102
gimage->construct_flag = FALSE;
106
gimp_item_offsets (GIMP_ITEM (gimage->layers->data), &xoff, &yoff);
109
if ((gimage->layers) && /* There's a layer. */
110
(! g_slist_next (gimage->layers)) && /* It's the only layer. */
111
(gimp_drawable_has_alpha (GIMP_DRAWABLE (gimage->layers->data))) &&
113
(gimp_item_get_visible (GIMP_ITEM (gimage->layers->data))) &&
115
(gimp_item_width (GIMP_ITEM (gimage->layers->data)) ==
117
(gimp_item_height (GIMP_ITEM (gimage->layers->data)) ==
118
gimage->height) && /* Covers all. */
119
(!gimp_drawable_is_indexed (GIMP_DRAWABLE (gimage->layers->data))) &&
121
(((GimpLayer *)(gimage->layers->data))->opacity == GIMP_OPACITY_OPAQUE)
128
gimp_item_offsets (GIMP_ITEM (gimage->layers->data), &xoff, &yoff);
130
if ((xoff==0) && (yoff==0)) /* Starts at 0,0 */
132
PixelRegion srcPR, destPR;
135
g_warning("Can use cow-projection hack. Yay!");
137
pixel_region_init (&srcPR, gimp_drawable_data
138
(GIMP_DRAWABLE (gimage->layers->data)),
140
pixel_region_init (&destPR,
141
gimp_image_projection (gimage),
144
for (pr = pixel_regions_register (2, &srcPR, &destPR);
146
pr = pixel_regions_process (pr))
148
tile_manager_map_over_tile (destPR.tiles,
149
destPR.curtile, srcPR.curtile);
152
gimage->construct_flag = TRUE;
153
gimp_image_construct_channels (gimage, x, y, w, h);
159
proj->construct_flag = FALSE;
162
/* First, determine if the projection image needs to be
163
* initialized--this is the case when there are no visible
164
* layers that cover the entire canvas--either because layers
165
* are offset or only a floating selection is visible
167
gimp_projection_initialize (proj, x, y, w, h);
169
/* call functions which process the list of layers and
170
* the list of channels
172
gimp_projection_construct_layers (proj, x, y, w, h);
173
gimp_projection_construct_channels (proj, x, y, w, h);
177
/* private functions */
180
gimp_projection_construct_layers (GimpProjection *proj,
188
PixelRegion src1PR, src2PR, maskPR;
195
/* composite the floating selection if it exists */
196
if ((layer = gimp_image_floating_sel (proj->gimage)))
197
floating_sel_composite (layer, x, y, w, h, FALSE);
201
for (list = GIMP_LIST (proj->gimage->layers)->list;
203
list = g_list_next (list))
205
layer = (GimpLayer *) list->data;
207
/* only add layers that are visible and not floating selections
210
if (! gimp_layer_is_floating_sel (layer) &&
211
gimp_item_get_visible (GIMP_ITEM (layer)))
213
reverse_list = g_list_prepend (reverse_list, layer);
217
for (list = reverse_list; list; list = g_list_next (list))
219
layer = (GimpLayer *) list->data;
221
gimp_item_offsets (GIMP_ITEM (layer), &off_x, &off_y);
223
x1 = CLAMP (off_x, x, x + w);
224
y1 = CLAMP (off_y, y, y + h);
225
x2 = CLAMP (off_x + gimp_item_width (GIMP_ITEM (layer)), x, x + w);
226
y2 = CLAMP (off_y + gimp_item_height (GIMP_ITEM (layer)), y, y + h);
228
/* configure the pixel regions */
229
pixel_region_init (&src1PR, gimp_projection_get_tiles (proj),
230
x1, y1, (x2 - x1), (y2 - y1),
233
/* If we're showing the layer mask instead of the layer... */
234
if (layer->mask && layer->mask->show_mask)
236
pixel_region_init (&src2PR,
237
gimp_drawable_data (GIMP_DRAWABLE (layer->mask)),
238
(x1 - off_x), (y1 - off_y),
239
(x2 - x1), (y2 - y1), FALSE);
241
copy_gray_to_region (&src2PR, &src1PR);
243
/* Otherwise, normal */
246
pixel_region_init (&src2PR,
247
gimp_drawable_data (GIMP_DRAWABLE (layer)),
248
(x1 - off_x), (y1 - off_y),
249
(x2 - x1), (y2 - y1), FALSE);
251
if (layer->mask && layer->mask->apply_mask)
253
pixel_region_init (&maskPR,
254
gimp_drawable_data (GIMP_DRAWABLE (layer->mask)),
255
(x1 - off_x), (y1 - off_y),
256
(x2 - x1), (y2 - y1), FALSE);
262
/* Based on the type of the layer, project the layer onto the
263
* projection image...
265
switch (gimp_drawable_type (GIMP_DRAWABLE (layer)))
267
case GIMP_RGB_IMAGE: case GIMP_GRAY_IMAGE:
268
/* no mask possible */
269
project_intensity (proj, layer, &src2PR, &src1PR, mask);
272
case GIMP_RGBA_IMAGE: case GIMP_GRAYA_IMAGE:
273
project_intensity_alpha (proj, layer, &src2PR, &src1PR, mask);
276
case GIMP_INDEXED_IMAGE:
277
/* no mask possible */
278
project_indexed (proj, layer, &src2PR, &src1PR);
281
case GIMP_INDEXEDA_IMAGE:
282
project_indexed_alpha (proj, layer, &src2PR, &src1PR, mask);
290
proj->construct_flag = TRUE; /* something was projected */
293
g_list_free (reverse_list);
297
gimp_projection_construct_channels (GimpProjection *proj,
303
GimpChannel *channel;
307
GList *reverse_list = NULL;
309
/* reverse the channel list */
310
for (list = GIMP_LIST (proj->gimage->channels)->list;
312
list = g_list_next (list))
314
reverse_list = g_list_prepend (reverse_list, list->data);
317
for (list = reverse_list; list; list = g_list_next (list))
319
channel = (GimpChannel *) list->data;
321
if (gimp_item_get_visible (GIMP_ITEM (channel)))
323
/* configure the pixel regions */
324
pixel_region_init (&src1PR,
325
gimp_projection_get_tiles (proj),
328
pixel_region_init (&src2PR,
329
gimp_drawable_data (GIMP_DRAWABLE (channel)),
333
project_channel (proj, channel, &src1PR, &src2PR);
335
proj->construct_flag = TRUE;
339
g_list_free (reverse_list);
343
gimp_projection_initialize (GimpProjection *proj,
351
gboolean coverage = FALSE;
353
/* this function determines whether a visible layer
354
* provides complete coverage over the image. If not,
355
* the projection is initialized to transparent
358
for (list = GIMP_LIST (proj->gimage->layers)->list;
360
list = g_list_next (list))
362
GimpItem *item = list->data;
365
gimp_item_offsets (item, &off_x, &off_y);
367
if (gimp_item_get_visible (item) &&
368
! gimp_drawable_has_alpha (GIMP_DRAWABLE (item)) &&
371
(off_x + gimp_item_width (item) >= x + w) &&
372
(off_y + gimp_item_height (item) >= y + h))
382
guchar clear[4] = { 0, 0, 0, 0 };
384
pixel_region_init (&PR, gimp_projection_get_tiles (proj),
386
color_region (&PR, clear);
391
project_intensity (GimpProjection *proj,
397
if (! proj->construct_flag)
398
initial_region (src, dest, mask, NULL,
399
layer->opacity * 255.999,
401
proj->gimage->visible,
404
combine_regions (dest, src, dest, mask, NULL,
405
layer->opacity * 255.999,
407
proj->gimage->visible,
408
COMBINE_INTEN_A_INTEN);
412
project_intensity_alpha (GimpProjection *proj,
418
if (! proj->construct_flag)
419
initial_region (src, dest, mask, NULL,
420
layer->opacity * 255.999,
422
proj->gimage->visible,
423
INITIAL_INTENSITY_ALPHA);
425
combine_regions (dest, src, dest, mask, NULL,
426
layer->opacity * 255.999,
428
proj->gimage->visible,
429
COMBINE_INTEN_A_INTEN_A);
433
project_indexed (GimpProjection *proj,
438
g_return_if_fail (proj->gimage->cmap != NULL);
440
if (! proj->construct_flag)
441
initial_region (src, dest, NULL, proj->gimage->cmap,
442
layer->opacity * 255.999,
444
proj->gimage->visible,
447
g_warning ("%s: unable to project indexed image.", G_STRFUNC);
451
project_indexed_alpha (GimpProjection *proj,
457
g_return_if_fail (proj->gimage->cmap != NULL);
459
if (! proj->construct_flag)
460
initial_region (src, dest, mask, proj->gimage->cmap,
461
layer->opacity * 255.999,
463
proj->gimage->visible,
464
INITIAL_INDEXED_ALPHA);
466
combine_regions (dest, src, dest, mask, proj->gimage->cmap,
467
layer->opacity * 255.999,
469
proj->gimage->visible,
470
COMBINE_INTEN_A_INDEXED_A);
474
project_channel (GimpProjection *proj,
475
GimpChannel *channel,
483
gimp_rgba_get_uchar (&channel->color,
484
&col[0], &col[1], &col[2], &opacity);
486
if (! proj->construct_flag)
488
type = (channel->show_masked) ?
489
INITIAL_CHANNEL_MASK : INITIAL_CHANNEL_SELECTION;
491
initial_region (src2, src, NULL, col,
499
type = (channel->show_masked) ?
500
COMBINE_INTEN_A_CHANNEL_MASK : COMBINE_INTEN_A_CHANNEL_SELECTION;
502
combine_regions (src, src2, src, NULL, col,