2003-03-24 20:21:58 +08:00
|
|
|
/* The GIMP -- an image manipulation program
|
|
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <glib-object.h>
|
|
|
|
|
2006-08-29 22:46:32 +08:00
|
|
|
#include "libgimpbase/gimpbase.h"
|
|
|
|
|
2003-03-24 20:21:58 +08:00
|
|
|
#include "core-types.h"
|
|
|
|
|
|
|
|
#include "base/pixel-region.h"
|
|
|
|
#include "base/temp-buf.h"
|
|
|
|
|
|
|
|
#include "paint-funcs/paint-funcs.h"
|
|
|
|
|
|
|
|
#include "config/gimpcoreconfig.h"
|
|
|
|
|
|
|
|
#include "gimp.h"
|
2004-12-11 09:22:58 +08:00
|
|
|
#include "gimpdrawable-preview.h"
|
2003-03-24 20:21:58 +08:00
|
|
|
#include "gimpimage.h"
|
|
|
|
#include "gimpimage-preview.h"
|
|
|
|
#include "gimplayer.h"
|
|
|
|
#include "gimplayermask.h"
|
|
|
|
#include "gimplist.h"
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
gimp_image_get_preview_size (GimpViewable *viewable,
|
|
|
|
gint size,
|
|
|
|
gboolean is_popup,
|
|
|
|
gboolean dot_for_dot,
|
|
|
|
gint *width,
|
|
|
|
gint *height)
|
|
|
|
{
|
2006-03-29 01:08:36 +08:00
|
|
|
GimpImage *image = GIMP_IMAGE (viewable);
|
2003-03-24 20:21:58 +08:00
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
if (! image->gimp->config->layer_previews && ! is_popup)
|
2003-03-24 20:21:58 +08:00
|
|
|
{
|
|
|
|
*width = size;
|
|
|
|
*height = size;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
gimp_viewable_calc_preview_size (image->width,
|
|
|
|
image->height,
|
2003-03-24 20:21:58 +08:00
|
|
|
size,
|
|
|
|
size,
|
|
|
|
dot_for_dot,
|
2006-03-29 01:08:36 +08:00
|
|
|
image->xresolution,
|
|
|
|
image->yresolution,
|
2003-03-24 20:21:58 +08:00
|
|
|
width,
|
|
|
|
height,
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
gimp_image_get_popup_size (GimpViewable *viewable,
|
|
|
|
gint width,
|
|
|
|
gint height,
|
|
|
|
gboolean dot_for_dot,
|
|
|
|
gint *popup_width,
|
|
|
|
gint *popup_height)
|
|
|
|
{
|
2006-03-29 01:08:36 +08:00
|
|
|
GimpImage *image = GIMP_IMAGE (viewable);
|
2003-03-24 20:21:58 +08:00
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
if (! image->gimp->config->layer_previews)
|
2003-03-24 20:21:58 +08:00
|
|
|
return FALSE;
|
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
if (image->width > width || image->height > height)
|
2003-03-24 20:21:58 +08:00
|
|
|
{
|
|
|
|
gboolean scaling_up;
|
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
gimp_viewable_calc_preview_size (image->width,
|
|
|
|
image->height,
|
2003-10-09 20:26:46 +08:00
|
|
|
width * 2,
|
|
|
|
height * 2,
|
2003-03-24 20:21:58 +08:00
|
|
|
dot_for_dot, 1.0, 1.0,
|
|
|
|
popup_width,
|
|
|
|
popup_height,
|
|
|
|
&scaling_up);
|
|
|
|
|
|
|
|
if (scaling_up)
|
|
|
|
{
|
2006-03-29 01:08:36 +08:00
|
|
|
*popup_width = image->width;
|
|
|
|
*popup_height = image->height;
|
2003-03-24 20:21:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
TempBuf *
|
|
|
|
gimp_image_get_preview (GimpViewable *viewable,
|
2006-08-30 05:44:51 +08:00
|
|
|
GimpContext *context,
|
2006-04-12 20:49:29 +08:00
|
|
|
gint width,
|
|
|
|
gint height)
|
2003-03-24 20:21:58 +08:00
|
|
|
{
|
2006-03-29 01:08:36 +08:00
|
|
|
GimpImage *image = GIMP_IMAGE (viewable);
|
2003-03-24 20:21:58 +08:00
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
if (! image->gimp->config->layer_previews)
|
2003-03-24 20:21:58 +08:00
|
|
|
return NULL;
|
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
if (image->comp_preview_valid &&
|
|
|
|
image->comp_preview->width == width &&
|
|
|
|
image->comp_preview->height == height)
|
2003-03-24 20:21:58 +08:00
|
|
|
{
|
|
|
|
/* The easy way */
|
2006-03-29 01:08:36 +08:00
|
|
|
return image->comp_preview;
|
2003-03-24 20:21:58 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* The hard way */
|
2006-03-29 01:08:36 +08:00
|
|
|
if (image->comp_preview)
|
2006-04-12 20:49:29 +08:00
|
|
|
temp_buf_free (image->comp_preview);
|
2003-03-24 20:21:58 +08:00
|
|
|
|
|
|
|
/* Actually construct the composite preview from the layer previews!
|
|
|
|
* This might seem ridiculous, but it's actually the best way, given
|
|
|
|
* a number of unsavory alternatives.
|
|
|
|
*/
|
2006-08-30 05:44:51 +08:00
|
|
|
image->comp_preview = gimp_image_get_new_preview (viewable, context,
|
|
|
|
width, height);
|
2003-03-24 20:21:58 +08:00
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
image->comp_preview_valid = TRUE;
|
2003-03-24 20:21:58 +08:00
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
return image->comp_preview;
|
2003-03-24 20:21:58 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TempBuf *
|
|
|
|
gimp_image_get_new_preview (GimpViewable *viewable,
|
2006-08-30 05:44:51 +08:00
|
|
|
GimpContext *context,
|
2006-04-12 20:49:29 +08:00
|
|
|
gint width,
|
|
|
|
gint height)
|
2003-03-24 20:21:58 +08:00
|
|
|
{
|
2006-03-29 01:08:36 +08:00
|
|
|
GimpImage *image;
|
2003-03-24 20:21:58 +08:00
|
|
|
GimpLayer *layer;
|
|
|
|
GimpLayer *floating_sel;
|
|
|
|
PixelRegion src1PR, src2PR, maskPR;
|
|
|
|
PixelRegion *mask;
|
|
|
|
TempBuf *comp;
|
|
|
|
TempBuf *layer_buf;
|
|
|
|
TempBuf *mask_buf;
|
|
|
|
GList *list;
|
|
|
|
GSList *reverse_list = NULL;
|
|
|
|
gdouble ratio;
|
|
|
|
gint x, y, w, h;
|
|
|
|
gint x1, y1, x2, y2;
|
|
|
|
gint bytes;
|
|
|
|
gboolean construct_flag;
|
|
|
|
gboolean visible_components[MAX_CHANNELS] = { TRUE, TRUE, TRUE, TRUE };
|
|
|
|
gint off_x, off_y;
|
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
image = GIMP_IMAGE (viewable);
|
2003-03-24 20:21:58 +08:00
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
if (! image->gimp->config->layer_previews)
|
2003-03-24 20:21:58 +08:00
|
|
|
return NULL;
|
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
ratio = (gdouble) width / (gdouble) image->width;
|
2003-03-24 20:21:58 +08:00
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
switch (gimp_image_base_type (image))
|
2003-03-24 20:21:58 +08:00
|
|
|
{
|
|
|
|
case GIMP_RGB:
|
|
|
|
case GIMP_INDEXED:
|
|
|
|
bytes = 4;
|
|
|
|
break;
|
|
|
|
case GIMP_GRAY:
|
|
|
|
bytes = 2;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
bytes = 0;
|
|
|
|
g_assert_not_reached ();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The construction buffer */
|
|
|
|
comp = temp_buf_new (width, height, bytes, 0, 0, NULL);
|
|
|
|
temp_buf_data_clear (comp);
|
|
|
|
|
|
|
|
floating_sel = NULL;
|
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
for (list = GIMP_LIST (image->layers)->list;
|
2003-09-12 03:52:29 +08:00
|
|
|
list;
|
2003-03-24 20:21:58 +08:00
|
|
|
list = g_list_next (list))
|
|
|
|
{
|
|
|
|
layer = (GimpLayer *) list->data;
|
|
|
|
|
|
|
|
/* only add layers that are visible to the list */
|
2003-09-12 03:52:29 +08:00
|
|
|
if (gimp_item_get_visible (GIMP_ITEM (layer)))
|
2006-04-12 20:49:29 +08:00
|
|
|
{
|
|
|
|
/* floating selections are added right above the layer
|
|
|
|
* they are attached to
|
|
|
|
*/
|
|
|
|
if (gimp_layer_is_floating_sel (layer))
|
|
|
|
{
|
|
|
|
floating_sel = layer;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (floating_sel &&
|
|
|
|
floating_sel->fs.drawable == GIMP_DRAWABLE (layer))
|
|
|
|
{
|
|
|
|
reverse_list = g_slist_prepend (reverse_list, floating_sel);
|
|
|
|
}
|
|
|
|
|
|
|
|
reverse_list = g_slist_prepend (reverse_list, layer);
|
|
|
|
}
|
|
|
|
}
|
2003-03-24 20:21:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
construct_flag = FALSE;
|
|
|
|
|
|
|
|
for (; reverse_list; reverse_list = g_slist_next (reverse_list))
|
|
|
|
{
|
2004-12-11 09:22:58 +08:00
|
|
|
gint src_x, src_y;
|
|
|
|
gint src_width, src_height;
|
|
|
|
gboolean use_sub_preview = FALSE;
|
|
|
|
|
2003-03-24 20:21:58 +08:00
|
|
|
layer = (GimpLayer *) reverse_list->data;
|
|
|
|
|
2003-05-08 22:06:03 +08:00
|
|
|
gimp_item_offsets (GIMP_ITEM (layer), &off_x, &off_y);
|
2003-03-24 20:21:58 +08:00
|
|
|
|
2004-12-11 09:22:58 +08:00
|
|
|
if (! gimp_rectangle_intersect (0, 0,
|
|
|
|
gimp_item_width (GIMP_ITEM (layer)),
|
|
|
|
gimp_item_height (GIMP_ITEM (layer)),
|
|
|
|
-off_x, -off_y,
|
2006-03-29 01:08:36 +08:00
|
|
|
image->width, image->height,
|
2004-12-11 09:22:58 +08:00
|
|
|
&src_x, &src_y,
|
|
|
|
&src_width, &src_height))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2003-03-24 20:21:58 +08:00
|
|
|
x = (gint) RINT (ratio * off_x);
|
|
|
|
y = (gint) RINT (ratio * off_y);
|
2003-05-08 22:06:03 +08:00
|
|
|
w = (gint) RINT (ratio * gimp_item_width (GIMP_ITEM (layer)));
|
2003-05-08 21:12:46 +08:00
|
|
|
h = (gint) RINT (ratio * gimp_item_height (GIMP_ITEM (layer)));
|
2003-03-24 20:21:58 +08:00
|
|
|
|
|
|
|
if (w < 1 || h < 1)
|
2006-04-12 20:49:29 +08:00
|
|
|
continue;
|
2003-03-24 20:21:58 +08:00
|
|
|
|
2004-12-11 09:22:58 +08:00
|
|
|
if ((w * h) > (width * height * 4))
|
|
|
|
use_sub_preview = TRUE;
|
|
|
|
|
2003-03-24 20:21:58 +08:00
|
|
|
x1 = CLAMP (x, 0, width);
|
|
|
|
y1 = CLAMP (y, 0, height);
|
|
|
|
x2 = CLAMP (x + w, 0, width);
|
|
|
|
y2 = CLAMP (y + h, 0, height);
|
|
|
|
|
2005-08-14 07:55:52 +08:00
|
|
|
if (x2 == x1 || y2 == y1)
|
2006-04-12 20:49:29 +08:00
|
|
|
continue;
|
2005-08-14 07:55:52 +08:00
|
|
|
|
2005-09-04 01:16:58 +08:00
|
|
|
pixel_region_init_temp_buf (&src1PR, comp,
|
|
|
|
x1, y1, x2 - x1, y2 - y1);
|
2003-03-24 20:21:58 +08:00
|
|
|
|
2004-12-11 09:22:58 +08:00
|
|
|
if (use_sub_preview)
|
|
|
|
{
|
|
|
|
layer_buf = gimp_drawable_get_sub_preview (GIMP_DRAWABLE (layer),
|
|
|
|
src_x, src_y,
|
|
|
|
src_width, src_height,
|
|
|
|
(x2 - x1),
|
|
|
|
(y2 - y1));
|
|
|
|
|
|
|
|
g_assert (layer_buf);
|
|
|
|
g_assert (layer_buf->bytes <= comp->bytes);
|
|
|
|
|
2005-09-04 01:16:58 +08:00
|
|
|
pixel_region_init_temp_buf (&src2PR, layer_buf,
|
|
|
|
0, 0, src1PR.w, src1PR.h);
|
2004-12-11 09:22:58 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-08-30 05:44:51 +08:00
|
|
|
layer_buf = gimp_viewable_get_preview (GIMP_VIEWABLE (layer),
|
|
|
|
context, w, h);
|
2004-12-11 09:22:58 +08:00
|
|
|
|
|
|
|
g_assert (layer_buf);
|
|
|
|
g_assert (layer_buf->bytes <= comp->bytes);
|
|
|
|
|
2005-09-04 01:16:58 +08:00
|
|
|
pixel_region_init_temp_buf (&src2PR, layer_buf,
|
|
|
|
x1 - x, y1 - y, src1PR.w, src1PR.h);
|
2004-12-11 09:22:58 +08:00
|
|
|
}
|
2003-03-24 20:21:58 +08:00
|
|
|
|
|
|
|
if (layer->mask && layer->mask->apply_mask)
|
2006-04-12 20:49:29 +08:00
|
|
|
{
|
2004-12-11 09:22:58 +08:00
|
|
|
if (use_sub_preview)
|
|
|
|
{
|
|
|
|
mask_buf =
|
|
|
|
gimp_drawable_get_sub_preview (GIMP_DRAWABLE (layer->mask),
|
|
|
|
src_x, src_y,
|
|
|
|
src_width, src_height,
|
|
|
|
x2 - x1,
|
|
|
|
y2 - y1);
|
|
|
|
|
2005-09-04 01:16:58 +08:00
|
|
|
pixel_region_init_temp_buf (&maskPR, mask_buf,
|
|
|
|
0, 0, src1PR.w, maskPR.h);
|
2004-12-11 09:22:58 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mask_buf = gimp_viewable_get_preview (GIMP_VIEWABLE (layer->mask),
|
2006-08-30 05:44:51 +08:00
|
|
|
context, w, h);
|
2004-12-11 09:22:58 +08:00
|
|
|
|
2005-09-04 01:16:58 +08:00
|
|
|
pixel_region_init_temp_buf (&maskPR, mask_buf,
|
|
|
|
x1 - x, y1 - y, src1PR.w, maskPR.h);
|
2004-12-11 09:22:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
mask = &maskPR;
|
2006-04-12 20:49:29 +08:00
|
|
|
}
|
2003-03-24 20:21:58 +08:00
|
|
|
else
|
2006-04-12 20:49:29 +08:00
|
|
|
{
|
2004-12-11 09:22:58 +08:00
|
|
|
mask_buf = NULL;
|
2006-04-12 20:49:29 +08:00
|
|
|
mask = NULL;
|
|
|
|
}
|
2003-03-24 20:21:58 +08:00
|
|
|
|
|
|
|
/* Based on the type of the layer, project the layer onto the
|
|
|
|
* composite preview...
|
|
|
|
* Indexed images are actually already converted to RGB and RGBA,
|
|
|
|
* so just project them as if they were type "intensity"
|
|
|
|
* Send in all TRUE for visible since that info doesn't matter
|
|
|
|
* for previews
|
|
|
|
*/
|
|
|
|
if (gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)))
|
2006-04-12 20:49:29 +08:00
|
|
|
{
|
|
|
|
if (! construct_flag)
|
|
|
|
initial_region (&src2PR, &src1PR,
|
|
|
|
mask, NULL,
|
2003-03-24 20:21:58 +08:00
|
|
|
layer->opacity * 255.999,
|
2006-04-12 20:49:29 +08:00
|
|
|
layer->mode,
|
2003-03-24 20:21:58 +08:00
|
|
|
visible_components,
|
|
|
|
INITIAL_INTENSITY_ALPHA);
|
2006-04-12 20:49:29 +08:00
|
|
|
else
|
|
|
|
combine_regions (&src1PR, &src2PR, &src1PR,
|
|
|
|
mask, NULL,
|
2003-03-24 20:21:58 +08:00
|
|
|
layer->opacity * 255.999,
|
2006-04-12 20:49:29 +08:00
|
|
|
layer->mode,
|
2003-03-24 20:21:58 +08:00
|
|
|
visible_components,
|
|
|
|
COMBINE_INTEN_A_INTEN_A);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-04-12 20:49:29 +08:00
|
|
|
if (! construct_flag)
|
|
|
|
initial_region (&src2PR, &src1PR,
|
|
|
|
mask, NULL,
|
2003-03-24 20:21:58 +08:00
|
|
|
layer->opacity * 255.999,
|
2006-04-12 20:49:29 +08:00
|
|
|
layer->mode,
|
2003-03-24 20:21:58 +08:00
|
|
|
visible_components,
|
|
|
|
INITIAL_INTENSITY);
|
2006-04-12 20:49:29 +08:00
|
|
|
else
|
|
|
|
combine_regions (&src1PR, &src2PR, &src1PR,
|
|
|
|
mask, NULL,
|
2003-03-24 20:21:58 +08:00
|
|
|
layer->opacity * 255.999,
|
2006-04-12 20:49:29 +08:00
|
|
|
layer->mode,
|
2003-03-24 20:21:58 +08:00
|
|
|
visible_components,
|
|
|
|
COMBINE_INTEN_A_INTEN);
|
|
|
|
}
|
|
|
|
|
2004-12-11 09:22:58 +08:00
|
|
|
if (use_sub_preview)
|
|
|
|
{
|
|
|
|
temp_buf_free (layer_buf);
|
|
|
|
|
|
|
|
if (mask_buf)
|
|
|
|
temp_buf_free (mask_buf);
|
|
|
|
}
|
|
|
|
|
2003-03-24 20:21:58 +08:00
|
|
|
construct_flag = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_slist_free (reverse_list);
|
|
|
|
|
|
|
|
return comp;
|
|
|
|
}
|