diff --git a/ChangeLog b/ChangeLog index f9a271a21b..a59c978faa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +2002-01-31 Michael Natterer + + * app/core/gimplayer.[ch]: removed gimp_layer_has_alpha(), use + gimp_drawable_has_alpha() instead. + + * app/core/gimpimage-convert.c + * app/core/gimpimage-merge.c + * app/core/gimpimage-projection.c + * app/display/gimpdisplayshell.c + * app/gui/layers-commands.c: changed accordingly. + + * app/core/gimpimage.[ch]: added gimp_image_has_alphe(), made some + variable names more verbose and use enum types instead of "gint" + in functions calling initial_region() and combine_regions(). + + * app/widgets/gimpchannellistview.c: show an alpha channel preview + only if the image has alpha. + + * app/widgets/gimppreview.c: reordered functions, + gimp_preview_render_and_flush(): fixed channel preview rendering, + calculate the component byte offsets before entering the render + loop instead of duplicating the render code for the gray/alpha + case. + 2002-01-31 Sven Neumann * app/widgets/gimpfontselection-dialog.c: use GtkTreeViews instead of diff --git a/app/actions/layers-commands.c b/app/actions/layers-commands.c index bbc9fcf701..fe3095531c 100644 --- a/app/actions/layers-commands.c +++ b/app/actions/layers-commands.c @@ -1287,7 +1287,7 @@ layers_menu_update (GtkItemFactory *factory, fs = (gimp_image_floating_sel (gimage) != NULL); ac = (gimp_image_get_active_channel (gimage) != NULL); - alpha = layer && gimp_layer_has_alpha (layer); + alpha = layer && gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)); lp = ! gimp_image_is_empty (gimage); indexed = (gimp_image_base_type (gimage) == GIMP_INDEXED); @@ -1305,7 +1305,7 @@ layers_menu_update (GtkItemFactory *factory, } if (next) - next_alpha = gimp_layer_has_alpha (GIMP_LAYER (next->data)); + next_alpha = gimp_drawable_has_alpha (GIMP_DRAWABLE (next->data)); else next_alpha = FALSE; diff --git a/app/core/gimpimage-convert.c b/app/core/gimpimage-convert.c index 47ac70daf8..f660762119 100644 --- a/app/core/gimpimage-convert.c +++ b/app/core/gimpimage-convert.c @@ -627,7 +627,7 @@ remap_indexed_layer (GimpLayer *layer, unsigned char* src; unsigned char* dest; - has_alpha = gimp_layer_has_alpha (layer) ? 1 : 0; + has_alpha = gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)) ? 1 : 0; pixel_region_init (&srcPR, GIMP_DRAWABLE(layer)->tiles, 0, 0, GIMP_DRAWABLE(layer)->width, GIMP_DRAWABLE(layer)->height, @@ -804,7 +804,7 @@ gimp_image_convert (GimpImage *gimage, new_layer_type = GIMP_IMAGE_TYPE_FROM_BASE_TYPE (new_type); - if (gimp_layer_has_alpha (layer)) + if (gimp_drawable_has_alpha (GIMP_DRAWABLE (layer))) new_layer_type = GIMP_IMAGE_TYPE_WITH_ALPHA (new_layer_type); new_tiles = tile_manager_new (GIMP_DRAWABLE (layer)->width, @@ -1130,7 +1130,7 @@ generate_histogram_gray (CFHistogram histogram, void *pr; gboolean has_alpha; - has_alpha = gimp_layer_has_alpha (layer); + has_alpha = gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)); pixel_region_init (&srcPR, GIMP_DRAWABLE(layer)->tiles, 0, 0, GIMP_DRAWABLE(layer)->width, GIMP_DRAWABLE(layer)->height, FALSE); for (pr = pixel_regions_register (1, &srcPR); @@ -1164,7 +1164,7 @@ generate_histogram_rgb (CFHistogram histogram, int row, col, coledge; int offsetx, offsety; - has_alpha = gimp_layer_has_alpha (layer); + has_alpha = gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)); gimp_drawable_offsets (GIMP_DRAWABLE(layer), &offsetx, &offsety); @@ -2505,7 +2505,8 @@ median_cut_pass2_no_dither_gray (QuantizeObj *quantobj, gimp_drawable_offsets (GIMP_DRAWABLE(layer), &offsetx, &offsety); - has_alpha = gimp_layer_has_alpha (layer); + has_alpha = gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)); + pixel_region_init (&srcPR, GIMP_DRAWABLE(layer)->tiles, 0, 0, GIMP_DRAWABLE(layer)->width, GIMP_DRAWABLE(layer)->height, FALSE); pixel_region_init (&destPR, new_tiles, 0, 0, GIMP_DRAWABLE(layer)->width, GIMP_DRAWABLE(layer)->height, TRUE); for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr)) @@ -2568,7 +2569,8 @@ median_cut_pass2_fixed_dither_gray (QuantizeObj *quantobj, gimp_drawable_offsets (GIMP_DRAWABLE(layer), &offsetx, &offsety); - has_alpha = gimp_layer_has_alpha (layer); + has_alpha = gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)); + pixel_region_init (&srcPR, GIMP_DRAWABLE(layer)->tiles, 0, 0, GIMP_DRAWABLE(layer)->width, GIMP_DRAWABLE(layer)->height, FALSE); pixel_region_init (&destPR, new_tiles, 0, 0, GIMP_DRAWABLE(layer)->width, GIMP_DRAWABLE(layer)->height, TRUE); for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr)) @@ -2653,7 +2655,8 @@ median_cut_pass2_no_dither_rgb (QuantizeObj *quantobj, if (gimp_drawable_is_gray (GIMP_DRAWABLE(layer))) red_pix = green_pix = blue_pix = GRAY_PIX; - has_alpha = gimp_layer_has_alpha (layer); + has_alpha = gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)); + pixel_region_init (&srcPR, GIMP_DRAWABLE(layer)->tiles, 0, 0, GIMP_DRAWABLE(layer)->width, GIMP_DRAWABLE(layer)->height, FALSE); pixel_region_init (&destPR, new_tiles, 0, 0, GIMP_DRAWABLE(layer)->width, GIMP_DRAWABLE(layer)->height, TRUE); for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr)) @@ -2730,7 +2733,8 @@ median_cut_pass2_fixed_dither_rgb (QuantizeObj *quantobj, if (gimp_drawable_is_gray (GIMP_DRAWABLE (layer))) red_pix = green_pix = blue_pix = GRAY_PIX; - has_alpha = gimp_layer_has_alpha (layer); + has_alpha = gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)); + pixel_region_init (&srcPR, GIMP_DRAWABLE(layer)->tiles, 0, 0, GIMP_DRAWABLE(layer)->width, GIMP_DRAWABLE(layer)->height, FALSE); pixel_region_init (&destPR, new_tiles, 0, 0, GIMP_DRAWABLE(layer)->width, GIMP_DRAWABLE(layer)->height, TRUE); for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr)) @@ -2829,7 +2833,8 @@ median_cut_pass2_nodestruct_dither_rgb (QuantizeObj *quantobj, gimp_drawable_offsets (GIMP_DRAWABLE(layer), &offsetx, &offsety); - has_alpha = gimp_layer_has_alpha (layer); + has_alpha = gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)); + pixel_region_init (&srcPR, GIMP_DRAWABLE(layer)->tiles, 0, 0, GIMP_DRAWABLE(layer)->width, GIMP_DRAWABLE(layer)->height, FALSE); pixel_region_init (&destPR, new_tiles, 0, 0, GIMP_DRAWABLE(layer)->width, GIMP_DRAWABLE(layer)->height, TRUE); for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr)) @@ -3013,7 +3018,8 @@ median_cut_pass2_fs_dither_gray (QuantizeObj *quantobj, gimp_drawable_offsets (GIMP_DRAWABLE(layer), &offsetx, &offsety); - has_alpha = gimp_layer_has_alpha (layer); + has_alpha = gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)); + pixel_region_init (&srcPR, GIMP_DRAWABLE(layer)->tiles, 0, 0, GIMP_DRAWABLE(layer)->width, GIMP_DRAWABLE(layer)->height, FALSE); pixel_region_init (&destPR, new_tiles, 0, 0, GIMP_DRAWABLE(layer)->width, GIMP_DRAWABLE(layer)->height, TRUE); src_bytes = GIMP_DRAWABLE(layer)->bytes; @@ -3223,7 +3229,8 @@ median_cut_pass2_fs_dither_rgb (QuantizeObj *quantobj, if (gimp_drawable_is_gray (GIMP_DRAWABLE(layer))) red_pix = green_pix = blue_pix = GRAY_PIX; - has_alpha = gimp_layer_has_alpha (layer); + has_alpha = gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)); + pixel_region_init (&srcPR, GIMP_DRAWABLE(layer)->tiles, 0, 0, GIMP_DRAWABLE(layer)->width, GIMP_DRAWABLE(layer)->height, FALSE); pixel_region_init (&destPR, new_tiles, 0, 0, GIMP_DRAWABLE(layer)->width, GIMP_DRAWABLE(layer)->height, TRUE); src_bytes = GIMP_DRAWABLE(layer)->bytes; diff --git a/app/core/gimpimage-merge.c b/app/core/gimpimage-merge.c index 6b784f7287..b5c03dedec 100644 --- a/app/core/gimpimage-merge.c +++ b/app/core/gimpimage-merge.c @@ -215,9 +215,9 @@ gimp_image_merge_layers (GimpImage *gimage, gint count; gint x1, y1, x2, y2; gint x3, y3, x4, y4; - gint operation; + CombinationMode operation; gint position; - gint active[MAX_CHANNELS] = {1, 1, 1, 1}; + gboolean active[MAX_CHANNELS] = { TRUE, TRUE, TRUE, TRUE }; gint off_x, off_y; gchar *name; diff --git a/app/core/gimpimage-projection.c b/app/core/gimpimage-projection.c index 3a7f85eedf..5d12a37770 100644 --- a/app/core/gimpimage-projection.c +++ b/app/core/gimpimage-projection.c @@ -543,7 +543,7 @@ gimp_image_initialize_projection (GimpImage *gimage, gimp_drawable_offsets (GIMP_DRAWABLE (layer), &off_x, &off_y); if (gimp_drawable_get_visible (GIMP_DRAWABLE (layer)) && - ! gimp_layer_has_alpha (layer) && + ! gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)) && (off_x <= x) && (off_y <= y) && (off_x + gimp_drawable_width (GIMP_DRAWABLE (layer)) >= x + w) && @@ -588,7 +588,7 @@ gimp_image_construct (GimpImage *gimage, if ((gimage->layers) && /* There's a layer. */ (! g_slist_next (gimage->layers)) && /* It's the only layer. */ - (gimp_layer_has_alpha ((GimpLayer *) (gimage->layers->data))) && + (gimp_drawable_has_alpha (GIMP_DRAWABLE (gimage->layers->data))) && /* It's !flat. */ (gimp_drawable_get_visible (GIMP_DRAWABLE (gimage->layers->data))) && /* It's visible. */ diff --git a/app/core/gimpimage.c b/app/core/gimpimage.c index d0512409b9..111780ac49 100644 --- a/app/core/gimpimage.c +++ b/app/core/gimpimage.c @@ -691,7 +691,7 @@ gimp_image_get_new_preview (GimpViewable *viewable, gint x1, y1, x2, y2; gint bytes; gboolean construct_flag; - gint visible[MAX_CHANNELS] = { 1, 1, 1, 1 }; + gboolean visible_components[MAX_CHANNELS] = { TRUE, TRUE, TRUE, TRUE }; gint off_x, off_y; gimage = GIMP_IMAGE (viewable); @@ -815,23 +815,35 @@ gimp_image_get_new_preview (GimpViewable *viewable, { if (! construct_flag) initial_region (&src2PR, &src1PR, - mask, NULL, layer->opacity, - layer->mode, visible, INITIAL_INTENSITY_ALPHA); + mask, NULL, + layer->opacity, + layer->mode, + visible_components, + INITIAL_INTENSITY_ALPHA); else combine_regions (&src1PR, &src2PR, &src1PR, - mask, NULL, layer->opacity, - layer->mode, visible, COMBINE_INTEN_A_INTEN_A); + mask, NULL, + layer->opacity, + layer->mode, + visible_components, + COMBINE_INTEN_A_INTEN_A); } else { if (! construct_flag) initial_region (&src2PR, &src1PR, - mask, NULL, layer->opacity, - layer->mode, visible, INITIAL_INTENSITY); + mask, NULL, + layer->opacity, + layer->mode, + visible_components, + INITIAL_INTENSITY); else combine_regions (&src1PR, &src2PR, &src1PR, - mask, NULL, layer->opacity, - layer->mode, visible, COMBINE_INTEN_A_INTEN); + mask, NULL, + layer->opacity, + layer->mode, + visible_components, + COMBINE_INTEN_A_INTEN); } construct_flag = TRUE; @@ -1100,6 +1112,19 @@ gimp_image_get_height (const GimpImage *gimage) return gimage->height; } +gboolean +gimp_image_has_alpha (const GimpImage *gimage) +{ + GimpLayer *layer; + + g_return_val_if_fail (GIMP_IS_IMAGE (gimage), TRUE); + + layer = (GimpLayer *) gimp_container_get_child_by_index (gimage->layers, 0); + + return ((gimp_container_num_children (gimage->layers) > 1) || + (layer && gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)))); +} + gboolean gimp_image_is_empty (const GimpImage *gimage) { @@ -1238,8 +1263,7 @@ gimp_image_get_active_components (const GimpImage *gimage, const GimpDrawable *drawable, gint *active) { - GimpLayer *layer; - gint i; + gint i; /* first, blindly copy the gimage active channels */ for (i = 0; i < MAX_CHANNELS; i++) @@ -1259,8 +1283,11 @@ gimp_image_get_active_components (const GimpImage *gimage, */ if (GIMP_IS_LAYER (drawable)) { + GimpLayer *layer; + layer = GIMP_LAYER (drawable); - if (gimp_layer_has_alpha (layer) && layer->preserve_trans) + + if (gimp_drawable_has_alpha (drawable) && layer->preserve_trans) active[gimp_drawable_bytes (drawable) - 1] = 0; } } @@ -1713,12 +1740,12 @@ gimp_image_apply_image (GimpImage *gimage, gint x, gint y) { - GimpChannel *mask; - gint x1, y1, x2, y2; - gint offset_x, offset_y; - PixelRegion src1PR, destPR, maskPR; - gint operation; - gint active [MAX_CHANNELS]; + GimpChannel *mask; + gint x1, y1, x2, y2; + gint offset_x, offset_y; + PixelRegion src1PR, destPR, maskPR; + CombinationMode operation; + gboolean active_components[MAX_CHANNELS]; g_return_if_fail (GIMP_IS_IMAGE (gimage)); @@ -1727,7 +1754,7 @@ gimp_image_apply_image (GimpImage *gimage, NULL : gimp_image_get_mask (gimage)); /* configure the active channel array */ - gimp_image_get_active_components (gimage, drawable, active); + gimp_image_get_active_components (gimage, drawable, active_components); /* determine what sort of operation is being attempted and * if it's actually legal... @@ -1797,12 +1824,12 @@ gimp_image_apply_image (GimpImage *gimage, (x2 - x1), (y2 - y1), FALSE); combine_regions (&src1PR, src2PR, &destPR, &maskPR, NULL, - opacity, mode, active, operation); + opacity, mode, active_components, operation); } else { combine_regions (&src1PR, src2PR, &destPR, NULL, NULL, - opacity, mode, active, operation); + opacity, mode, active_components, operation); } } @@ -1822,14 +1849,14 @@ gimp_image_replace_image (GimpImage *gimage, gint x, gint y) { - GimpChannel *mask; - gint x1, y1, x2, y2; - gint offset_x, offset_y; - PixelRegion src1PR, destPR; - PixelRegion mask2PR, tempPR; - guchar *temp_data; - gint operation; - gint active [MAX_CHANNELS]; + GimpChannel *mask; + gint x1, y1, x2, y2; + gint offset_x, offset_y; + PixelRegion src1PR, destPR; + PixelRegion mask2PR, tempPR; + guchar *temp_data; + CombinationMode operation; + gboolean active_components[MAX_CHANNELS]; g_return_if_fail (GIMP_IS_IMAGE (gimage)); @@ -1837,7 +1864,7 @@ gimp_image_replace_image (GimpImage *gimage, mask = (gimp_image_mask_is_empty (gimage)) ? NULL : gimp_image_get_mask (gimage); /* configure the active channel array */ - gimp_image_get_active_components (gimage, drawable, active); + gimp_image_get_active_components (gimage, drawable, active_components); /* determine what sort of operation is being attempted and * if it's actually legal... @@ -1930,14 +1957,14 @@ gimp_image_replace_image (GimpImage *gimage, tempPR.data = temp_data; combine_regions_replace (&src1PR, src2PR, &destPR, &tempPR, NULL, - opacity, active, operation); + opacity, active_components, operation); g_free (temp_data); } else { combine_regions_replace (&src1PR, src2PR, &destPR, maskPR, NULL, - opacity, active, operation); + opacity, active_components, operation); } } @@ -2619,7 +2646,7 @@ gimp_image_raise_layer_to_top (GimpImage *gimage, return FALSE; } - if (! gimp_layer_has_alpha (layer)) + if (! gimp_drawable_has_alpha (GIMP_DRAWABLE (layer))) { g_message (_("Cannot raise a layer without alpha.")); return FALSE; @@ -2690,7 +2717,7 @@ gimp_image_position_layer (GimpImage *gimage, num_layers - 1); if (new_index == num_layers - 1 && - ! gimp_layer_has_alpha (tmp)) + ! gimp_drawable_has_alpha (GIMP_DRAWABLE (tmp))) { g_message (_("Layer \"%s\" has no alpha.\nLayer was placed above it."), GIMP_OBJECT (tmp)->name); diff --git a/app/core/gimpimage.h b/app/core/gimpimage.h index b60ca42852..369eea4f75 100644 --- a/app/core/gimpimage.h +++ b/app/core/gimpimage.h @@ -244,6 +244,7 @@ void gimp_image_unit_changed (GimpImage *gimage); gint gimp_image_get_width (const GimpImage *gimage); gint gimp_image_get_height (const GimpImage *gimage); +gboolean gimp_image_has_alpha (const GimpImage *gimage); gboolean gimp_image_is_empty (const GimpImage *gimage); GimpLayer * gimp_image_floating_sel (const GimpImage *gimage); diff --git a/app/core/gimplayer.c b/app/core/gimplayer.c index 08f1006cdd..af3d491cd1 100644 --- a/app/core/gimplayer.c +++ b/app/core/gimplayer.c @@ -562,7 +562,7 @@ gimp_layer_add_mask (GimpLayer *layer, return NULL; } - if (! gimp_layer_has_alpha (layer)) + if (! gimp_drawable_has_alpha (GIMP_DRAWABLE (layer))) { g_message (_("Cannot add layer mask to a layer\n" "with no alpha channel.")); @@ -648,7 +648,7 @@ gimp_layer_create_mask (const GimpLayer *layer, case ADD_ALPHA_MASK: /* Extract the layer's alpha channel */ - if (gimp_layer_has_alpha (layer)) + if (gimp_drawable_has_alpha (GIMP_DRAWABLE (layer))) { pixel_region_init (&layerPR, GIMP_DRAWABLE (layer)->tiles, 0, 0, @@ -706,7 +706,7 @@ gimp_layer_apply_mask (GimpLayer *layer, return; /* this operation can only be done to layers with an alpha channel */ - if (! gimp_layer_has_alpha (layer)) + if (! gimp_drawable_has_alpha (GIMP_DRAWABLE (layer))) return; gimage = gimp_drawable_gimage (GIMP_DRAWABLE (layer)); @@ -1171,7 +1171,7 @@ gimp_layer_resize (GimpLayer *layer, TRUE); /* fill with the fill color */ - if (gimp_layer_has_alpha (layer)) + if (gimp_drawable_has_alpha (GIMP_DRAWABLE (layer))) { /* Set to transparent and black */ guchar bg[4] = {0, 0, 0, 0}; @@ -1358,7 +1358,7 @@ gimp_layer_pick_correlate (GimpLayer *layer, /* If the point is inside, and the layer has no * alpha channel, success! */ - if (! gimp_layer_has_alpha (layer)) + if (! gimp_drawable_has_alpha (GIMP_DRAWABLE (layer))) return TRUE; /* Otherwise, determine if the alpha value at @@ -1404,14 +1404,6 @@ gimp_layer_get_mask (const GimpLayer *layer) return layer->mask; } -gboolean -gimp_layer_has_alpha (const GimpLayer *layer) -{ - g_return_val_if_fail (GIMP_IS_LAYER (layer), FALSE); - - return GIMP_IMAGE_TYPE_HAS_ALPHA (GIMP_DRAWABLE (layer)->type); -} - gboolean gimp_layer_is_floating_sel (const GimpLayer *layer) { diff --git a/app/core/gimplayer.h b/app/core/gimplayer.h index d0fc352b15..0aa8e3c591 100644 --- a/app/core/gimplayer.h +++ b/app/core/gimplayer.h @@ -146,7 +146,6 @@ gint gimp_layer_pick_correlate (GimpLayer *layer, GimpLayerMask * gimp_layer_get_mask (const GimpLayer *layer); -gboolean gimp_layer_has_alpha (const GimpLayer *layer); gboolean gimp_layer_is_floating_sel (const GimpLayer *layer); void gimp_layer_set_opacity (GimpLayer *layer, diff --git a/app/core/gimpprojection-construct.c b/app/core/gimpprojection-construct.c index 3a7f85eedf..5d12a37770 100644 --- a/app/core/gimpprojection-construct.c +++ b/app/core/gimpprojection-construct.c @@ -543,7 +543,7 @@ gimp_image_initialize_projection (GimpImage *gimage, gimp_drawable_offsets (GIMP_DRAWABLE (layer), &off_x, &off_y); if (gimp_drawable_get_visible (GIMP_DRAWABLE (layer)) && - ! gimp_layer_has_alpha (layer) && + ! gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)) && (off_x <= x) && (off_y <= y) && (off_x + gimp_drawable_width (GIMP_DRAWABLE (layer)) >= x + w) && @@ -588,7 +588,7 @@ gimp_image_construct (GimpImage *gimage, if ((gimage->layers) && /* There's a layer. */ (! g_slist_next (gimage->layers)) && /* It's the only layer. */ - (gimp_layer_has_alpha ((GimpLayer *) (gimage->layers->data))) && + (gimp_drawable_has_alpha (GIMP_DRAWABLE (gimage->layers->data))) && /* It's !flat. */ (gimp_drawable_get_visible (GIMP_DRAWABLE (gimage->layers->data))) && /* It's visible. */ diff --git a/app/display/gimpdisplayshell-draw.c b/app/display/gimpdisplayshell-draw.c index 852e9d8437..424891361a 100644 --- a/app/display/gimpdisplayshell-draw.c +++ b/app/display/gimpdisplayshell-draw.c @@ -925,7 +925,7 @@ gimp_display_shell_set_menu_sensitivity (GimpDisplayShell *shell) if (layer) { lm = gimp_layer_get_mask (layer) ? TRUE : FALSE; - alpha = gimp_layer_has_alpha (layer); + alpha = gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)); lind = gimp_image_get_layer_index (gimage, layer); } diff --git a/app/display/gimpdisplayshell.c b/app/display/gimpdisplayshell.c index 852e9d8437..424891361a 100644 --- a/app/display/gimpdisplayshell.c +++ b/app/display/gimpdisplayshell.c @@ -925,7 +925,7 @@ gimp_display_shell_set_menu_sensitivity (GimpDisplayShell *shell) if (layer) { lm = gimp_layer_get_mask (layer) ? TRUE : FALSE; - alpha = gimp_layer_has_alpha (layer); + alpha = gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)); lind = gimp_image_get_layer_index (gimage, layer); } diff --git a/app/gui/layers-commands.c b/app/gui/layers-commands.c index bbc9fcf701..fe3095531c 100644 --- a/app/gui/layers-commands.c +++ b/app/gui/layers-commands.c @@ -1287,7 +1287,7 @@ layers_menu_update (GtkItemFactory *factory, fs = (gimp_image_floating_sel (gimage) != NULL); ac = (gimp_image_get_active_channel (gimage) != NULL); - alpha = layer && gimp_layer_has_alpha (layer); + alpha = layer && gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)); lp = ! gimp_image_is_empty (gimage); indexed = (gimp_image_base_type (gimage) == GIMP_INDEXED); @@ -1305,7 +1305,7 @@ layers_menu_update (GtkItemFactory *factory, } if (next) - next_alpha = gimp_layer_has_alpha (GIMP_LAYER (next->data)); + next_alpha = gimp_drawable_has_alpha (GIMP_DRAWABLE (next->data)); else next_alpha = FALSE; diff --git a/app/widgets/gimpchannellistview.c b/app/widgets/gimpchannellistview.c index bc95a74c98..ef455bd902 100644 --- a/app/widgets/gimpchannellistview.c +++ b/app/widgets/gimpchannellistview.c @@ -406,7 +406,10 @@ gimp_channel_list_view_create_components (GimpChannelListView *view) break; } - components[n_components++] = GIMP_ALPHA_CHANNEL; + if (gimp_image_has_alpha (gimage)) + { + components[n_components++] = GIMP_ALPHA_CHANNEL; + } for (i = 0; i < n_components; i++) { @@ -451,7 +454,8 @@ static void gimp_channel_list_view_alpha_changed (GimpImage *gimage, GimpChannelListView *view) { - g_print ("gimp_channel_list_view_alpha_changed()\n"); + gimp_channel_list_view_clear_components (view); + gimp_channel_list_view_create_components (view); } static void diff --git a/app/widgets/gimpchanneltreeview.c b/app/widgets/gimpchanneltreeview.c index bc95a74c98..ef455bd902 100644 --- a/app/widgets/gimpchanneltreeview.c +++ b/app/widgets/gimpchanneltreeview.c @@ -406,7 +406,10 @@ gimp_channel_list_view_create_components (GimpChannelListView *view) break; } - components[n_components++] = GIMP_ALPHA_CHANNEL; + if (gimp_image_has_alpha (gimage)) + { + components[n_components++] = GIMP_ALPHA_CHANNEL; + } for (i = 0; i < n_components; i++) { @@ -451,7 +454,8 @@ static void gimp_channel_list_view_alpha_changed (GimpImage *gimage, GimpChannelListView *view) { - g_print ("gimp_channel_list_view_alpha_changed()\n"); + gimp_channel_list_view_clear_components (view); + gimp_channel_list_view_create_components (view); } static void diff --git a/app/widgets/gimppreview.c b/app/widgets/gimppreview.c index 0071d9780f..cb4668ac81 100644 --- a/app/widgets/gimppreview.c +++ b/app/widgets/gimppreview.c @@ -60,6 +60,8 @@ #include "gimptoolinfopreview.h" +#define PREVIEW_BYTES 3 + #define PREVIEW_POPUP_DELAY 150 #define PREVIEW_EVENT_MASK (GDK_BUTTON_PRESS_MASK | \ @@ -84,7 +86,7 @@ static void gimp_preview_init (GimpPreview *preview) static void gimp_preview_destroy (GtkObject *object); static void gimp_preview_size_allocate (GtkWidget *widget, GtkAllocation *allocation); -static gboolean gimp_preview_expose (GtkWidget *widget, +static gboolean gimp_preview_expose_event (GtkWidget *widget, GdkEventExpose *event); static gboolean gimp_preview_button_press_event (GtkWidget *widget, GdkEventButton *bevent); @@ -113,6 +115,8 @@ static void gimp_preview_popup_show (GimpPreview *preview, gint x, gint y); static void gimp_preview_popup_hide (GimpPreview *preview); +static gboolean gimp_preview_popup_timeout (GimpPreview *preview); + static void gimp_preview_size_changed (GimpPreview *preview, GimpViewable *viewable); static void gimp_preview_paint (GimpPreview *preview); @@ -205,7 +209,7 @@ gimp_preview_class_init (GimpPreviewClass *klass) object_class->destroy = gimp_preview_destroy; widget_class->size_allocate = gimp_preview_size_allocate; - widget_class->expose_event = gimp_preview_expose; + widget_class->expose_event = gimp_preview_expose_event; widget_class->button_press_event = gimp_preview_button_press_event; widget_class->button_release_event = gimp_preview_button_release_event; widget_class->enter_notify_event = gimp_preview_enter_notify_event; @@ -272,55 +276,263 @@ gimp_preview_destroy (GtkObject *object) GTK_OBJECT_CLASS (parent_class)->destroy (object); } -static GimpPreview * -gimp_preview_new_by_type (GimpViewable *viewable) +static void +gimp_preview_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) { GimpPreview *preview; - if (GIMP_IS_BRUSH (viewable)) + preview = GIMP_PREVIEW (widget); + + allocation->width = preview->width + 2 * preview->border_width; + allocation->height = preview->height + 2 * preview->border_width; + + if (GTK_WIDGET_CLASS (parent_class)->size_allocate) + GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation); + + gimp_preview_paint (GIMP_PREVIEW (widget)); +} + +static gboolean +gimp_preview_expose_event (GtkWidget *widget, + GdkEventExpose *event) +{ + GimpPreview *preview; + guchar *buf; + GdkRectangle buf_rect = { 0, 0, 0, 0 }; + GdkRectangle render_rect; + + preview = GIMP_PREVIEW (widget); + + if (! GTK_WIDGET_DRAWABLE (widget) || ! preview->buffer) + return FALSE; + + buf_rect.width = preview->width + 2 * preview->border_width; + buf_rect.height = preview->height + 2 * preview->border_width; + + if (widget->allocation.width > buf_rect.width) + buf_rect.x = (widget->allocation.width - buf_rect.width) / 2; + + if (widget->allocation.height >buf_rect.height) + buf_rect.y = (widget->allocation.height - buf_rect.height) / 2; + + if (gdk_rectangle_intersect (&event->area, &buf_rect, &render_rect)) { - preview = g_object_new (GIMP_TYPE_BRUSH_PREVIEW, NULL); + buf = (preview->buffer + + (render_rect.y - buf_rect.y) * preview->rowstride + + (render_rect.x - buf_rect.x) * PREVIEW_BYTES); + + gdk_draw_rgb_image_dithalign (widget->window, + widget->style->black_gc, + render_rect.x, + render_rect.y, + render_rect.width, + render_rect.height, + GDK_RGB_DITHER_NORMAL, + buf, + preview->rowstride, + event->area.x, + event->area.y); } - else if (GIMP_IS_DRAWABLE (viewable)) + + return FALSE; +} + +static gint +gimp_preview_button_press_event (GtkWidget *widget, + GdkEventButton *bevent) +{ + GimpPreview *preview; + + preview = GIMP_PREVIEW (widget); + +#define DEBUG_MEMSIZE 1 + +#ifdef DEBUG_MEMSIZE + if (bevent->type == GDK_BUTTON_PRESS && bevent->button == 2) { - preview = g_object_new (GIMP_TYPE_DRAWABLE_PREVIEW, NULL); + gimp_object_get_memsize (GIMP_OBJECT (preview->viewable)); } - else if (GIMP_IS_IMAGE (viewable)) +#endif /* DEBUG_MEMSIZE */ + + if (! preview->clickable && + ! preview->show_popup) + return FALSE; + + if (bevent->type == GDK_BUTTON_PRESS) { - preview = g_object_new (GIMP_TYPE_IMAGE_PREVIEW, NULL); + if (bevent->button == 1) + { + gtk_grab_add (widget); + + preview->press_state = bevent->state; + + if (preview->show_popup && gimp_preview_needs_popup (preview)) + { + gimp_preview_popup_show (preview, + bevent->x, + bevent->y); + } + } + else + { + preview->press_state = 0; + + if (bevent->button == 3) + { + g_signal_emit (G_OBJECT (widget), preview_signals[CONTEXT], 0); + } + else + { + return FALSE; + } + } } - else if (GIMP_IS_PATTERN (viewable)) + else if (bevent->type == GDK_2BUTTON_PRESS) { - preview = g_object_new (GIMP_TYPE_PATTERN_PREVIEW, NULL); + if (bevent->button == 1) + { + g_signal_emit (G_OBJECT (widget), preview_signals[DOUBLE_CLICKED], 0); + } } - else if (GIMP_IS_GRADIENT (viewable)) + + return TRUE; +} + +static gint +gimp_preview_button_release_event (GtkWidget *widget, + GdkEventButton *bevent) +{ + GimpPreview *preview; + gboolean click = TRUE; + + preview = GIMP_PREVIEW (widget); + + if (! preview->clickable && + ! preview->show_popup) + return FALSE; + + if (bevent->button == 1) { - preview = g_object_new (GIMP_TYPE_GRADIENT_PREVIEW, NULL); - } - else if (GIMP_IS_PALETTE (viewable)) - { - preview = g_object_new (GIMP_TYPE_PALETTE_PREVIEW, NULL); - } - else if (GIMP_IS_BUFFER (viewable)) - { - preview = g_object_new (GIMP_TYPE_BUFFER_PREVIEW, NULL); - } - else if (GIMP_IS_TOOL_INFO (viewable)) - { - preview = g_object_new (GIMP_TYPE_TOOL_INFO_PREVIEW, NULL); - } - else if (GIMP_IS_IMAGEFILE (viewable)) - { - preview = g_object_new (GIMP_TYPE_IMAGEFILE_PREVIEW, NULL); + if (preview->show_popup && gimp_preview_needs_popup (preview)) + { + click = (preview->popup_id != 0); + } + + gimp_preview_popup_hide (preview); + + /* remove the grab _after_ hiding the popup */ + gtk_grab_remove (widget); + + if (preview->clickable && click && preview->in_button) + { + if (preview->press_state & + (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK)) + { + g_signal_emit (G_OBJECT (widget), + preview_signals[EXTENDED_CLICKED], 0, + preview->press_state); + } + else + { + g_signal_emit (G_OBJECT (widget), preview_signals[CLICKED], 0); + } + } } else { - preview = g_object_new (GIMP_TYPE_PREVIEW, NULL); + return FALSE; } - return preview; + return TRUE; } +static gint +gimp_preview_enter_notify_event (GtkWidget *widget, + GdkEventCrossing *event) +{ + GimpPreview *preview; + GtkWidget *event_widget; + + preview = GIMP_PREVIEW (widget); + event_widget = gtk_get_event_widget ((GdkEvent *) event); + + if ((event_widget == widget) && + (event->detail != GDK_NOTIFY_INFERIOR)) + { + preview->in_button = TRUE; + } + + return FALSE; +} + +static gint +gimp_preview_leave_notify_event (GtkWidget *widget, + GdkEventCrossing *event) +{ + GimpPreview *preview; + GtkWidget *event_widget; + + preview = GIMP_PREVIEW (widget); + event_widget = gtk_get_event_widget ((GdkEvent *) event); + + if ((event_widget == widget) && + (event->detail != GDK_NOTIFY_INFERIOR)) + { + preview->in_button = FALSE; + } + + return FALSE; +} + +static GimpPreview * +gimp_preview_new_by_type (GimpViewable *viewable) +{ + GType type = GIMP_TYPE_PREVIEW; + + if (GIMP_IS_BRUSH (viewable)) + { + type = GIMP_TYPE_BRUSH_PREVIEW; + } + else if (GIMP_IS_DRAWABLE (viewable)) + { + type = GIMP_TYPE_DRAWABLE_PREVIEW; + } + else if (GIMP_IS_IMAGE (viewable)) + { + type = GIMP_TYPE_IMAGE_PREVIEW; + } + else if (GIMP_IS_PATTERN (viewable)) + { + type = GIMP_TYPE_PATTERN_PREVIEW; + } + else if (GIMP_IS_GRADIENT (viewable)) + { + type = GIMP_TYPE_GRADIENT_PREVIEW; + } + else if (GIMP_IS_PALETTE (viewable)) + { + type = GIMP_TYPE_PALETTE_PREVIEW; + } + else if (GIMP_IS_BUFFER (viewable)) + { + type = GIMP_TYPE_BUFFER_PREVIEW; + } + else if (GIMP_IS_TOOL_INFO (viewable)) + { + type = GIMP_TYPE_TOOL_INFO_PREVIEW; + } + else if (GIMP_IS_IMAGEFILE (viewable)) + { + type = GIMP_TYPE_IMAGEFILE_PREVIEW; + } + + return g_object_new (type, NULL); +} + + +/* public functions */ + GtkWidget * gimp_preview_new (GimpViewable *viewable, gint size, @@ -485,7 +697,7 @@ gimp_preview_set_size_full (GimpPreview *preview, GTK_WIDGET (preview)->requisition.height = height + 2 * border_width; preview->rowstride = - ((preview->width + 2 * preview->border_width) * 3 + 3) & ~3; + ((preview->width + 2 * preview->border_width) * PREVIEW_BYTES + 3) & ~3; if (preview->buffer) { @@ -541,152 +753,8 @@ gimp_preview_render (GimpPreview *preview) GIMP_PREVIEW_GET_CLASS (preview)->render (preview); } -static gint -gimp_preview_button_press_event (GtkWidget *widget, - GdkEventButton *bevent) -{ - GimpPreview *preview; - preview = GIMP_PREVIEW (widget); - -#define DEBUG_MEMSIZE 1 - -#ifdef DEBUG_MEMSIZE - if (bevent->type == GDK_BUTTON_PRESS && bevent->button == 2) - { - gimp_object_get_memsize (GIMP_OBJECT (preview->viewable)); - } -#endif /* DEBUG_MEMSIZE */ - - if (! preview->clickable && - ! preview->show_popup) - return FALSE; - - if (bevent->type == GDK_BUTTON_PRESS) - { - if (bevent->button == 1) - { - gtk_grab_add (widget); - - preview->press_state = bevent->state; - - if (preview->show_popup && gimp_preview_needs_popup (preview)) - { - gimp_preview_popup_show (preview, - bevent->x, - bevent->y); - } - } - else - { - preview->press_state = 0; - - if (bevent->button == 3) - { - g_signal_emit (G_OBJECT (widget), preview_signals[CONTEXT], 0); - } - else - { - return FALSE; - } - } - } - else if (bevent->type == GDK_2BUTTON_PRESS) - { - if (bevent->button == 1) - { - g_signal_emit (G_OBJECT (widget), preview_signals[DOUBLE_CLICKED], 0); - } - } - - return TRUE; -} - -static gint -gimp_preview_button_release_event (GtkWidget *widget, - GdkEventButton *bevent) -{ - GimpPreview *preview; - gboolean click = TRUE; - - preview = GIMP_PREVIEW (widget); - - if (! preview->clickable && - ! preview->show_popup) - return FALSE; - - if (bevent->button == 1) - { - if (preview->show_popup && gimp_preview_needs_popup (preview)) - { - click = (preview->popup_id != 0); - } - - gimp_preview_popup_hide (preview); - - /* remove the grab _after_ hiding the popup */ - gtk_grab_remove (widget); - - if (preview->clickable && click && preview->in_button) - { - if (preview->press_state & - (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK)) - { - g_signal_emit (G_OBJECT (widget), - preview_signals[EXTENDED_CLICKED], 0, - preview->press_state); - } - else - { - g_signal_emit (G_OBJECT (widget), preview_signals[CLICKED], 0); - } - } - } - else - { - return FALSE; - } - - return TRUE; -} - -static gint -gimp_preview_enter_notify_event (GtkWidget *widget, - GdkEventCrossing *event) -{ - GimpPreview *preview; - GtkWidget *event_widget; - - preview = GIMP_PREVIEW (widget); - event_widget = gtk_get_event_widget ((GdkEvent *) event); - - if ((event_widget == widget) && - (event->detail != GDK_NOTIFY_INFERIOR)) - { - preview->in_button = TRUE; - } - - return FALSE; -} - -static gint -gimp_preview_leave_notify_event (GtkWidget *widget, - GdkEventCrossing *event) -{ - GimpPreview *preview; - GtkWidget *event_widget; - - preview = GIMP_PREVIEW (widget); - event_widget = gtk_get_event_widget ((GdkEvent *) event); - - if ((event_widget == widget) && - (event->detail != GDK_NOTIFY_INFERIOR)) - { - preview->in_button = FALSE; - } - - return FALSE; -} +/* private functions */ static void gimp_preview_real_render (GimpPreview *preview) @@ -766,6 +834,34 @@ gimp_preview_real_create_popup (GimpPreview *preview) TRUE, FALSE, FALSE); } +static void +gimp_preview_popup_show (GimpPreview *preview, + gint x, + gint y) +{ + preview->popup_x = x; + preview->popup_y = y; + + preview->popup_id = g_timeout_add (PREVIEW_POPUP_DELAY, + (GSourceFunc) gimp_preview_popup_timeout, + preview); +} + +static void +gimp_preview_popup_hide (GimpPreview *preview) +{ + if (preview->popup_id) + { + g_source_remove (preview->popup_id); + + preview->popup_id = 0; + preview->popup_x = 0; + preview->popup_y = 0; + } + + g_object_set_data (G_OBJECT (preview), "gimp-preview-popup", NULL); +} + static gboolean gimp_preview_popup_timeout (GimpPreview *preview) { @@ -820,102 +916,12 @@ gimp_preview_popup_timeout (GimpPreview *preview) gtk_window_move (GTK_WINDOW (window), x, y); gtk_widget_show (window); - g_object_set_data_full (G_OBJECT (preview), "preview_popup_window", window, + g_object_set_data_full (G_OBJECT (preview), "gimp-preview-popup", window, (GDestroyNotify) gtk_widget_destroy); return FALSE; } -static void -gimp_preview_popup_show (GimpPreview *preview, - gint x, - gint y) -{ - preview->popup_x = x; - preview->popup_y = y; - - preview->popup_id = g_timeout_add (PREVIEW_POPUP_DELAY, - (GSourceFunc) gimp_preview_popup_timeout, - preview); -} - -static void -gimp_preview_popup_hide (GimpPreview *preview) -{ - if (preview->popup_id) - { - g_source_remove (preview->popup_id); - - preview->popup_id = 0; - preview->popup_x = 0; - preview->popup_y = 0; - } - - g_object_set_data (G_OBJECT (preview), "preview_popup_window", NULL); -} - -static void -gimp_preview_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - GimpPreview *preview; - - preview = GIMP_PREVIEW (widget); - - allocation->width = preview->width + 2 * preview->border_width; - allocation->height = preview->height + 2 * preview->border_width; - - if (GTK_WIDGET_CLASS (parent_class)->size_allocate) - GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation); - - gimp_preview_paint (GIMP_PREVIEW (widget)); -} - -static gboolean -gimp_preview_expose (GtkWidget *widget, - GdkEventExpose *event) -{ - GimpPreview *preview; - guchar *buf; - GdkRectangle buf_rect = { 0, 0, 0, 0 }; - GdkRectangle render_rect; - - preview = GIMP_PREVIEW (widget); - - if (! GTK_WIDGET_DRAWABLE (widget) || ! preview->buffer) - return FALSE; - - buf_rect.width = preview->width + 2 * preview->border_width; - buf_rect.height = preview->height + 2 * preview->border_width; - - if (widget->allocation.width > buf_rect.width) - buf_rect.x = (widget->allocation.width - buf_rect.width) / 2; - - if (widget->allocation.height >buf_rect.height) - buf_rect.y = (widget->allocation.height - buf_rect.height) / 2; - - if (gdk_rectangle_intersect (&event->area, &buf_rect, &render_rect)) - { - buf = (preview->buffer + - (render_rect.y - buf_rect.y) * preview->rowstride + - (render_rect.x - buf_rect.x) * 3); - - gdk_draw_rgb_image_dithalign (widget->window, - widget->style->black_gc, - render_rect.x, - render_rect.y, - render_rect.width, - render_rect.height, - GDK_RGB_DITHER_NORMAL, - buf, - preview->rowstride, - event->area.x, - event->area.y); - } - - return FALSE; -} - static void gimp_preview_size_changed (GimpPreview *preview, GimpViewable *viewable) @@ -957,6 +963,16 @@ gimp_preview_idle_paint (GimpPreview *preview) return FALSE; } +static GimpViewable * +gimp_preview_drag_viewable (GtkWidget *widget, + gpointer data) +{ + return GIMP_PREVIEW (widget)->viewable; +} + + +/* protected functions */ + void gimp_preview_calc_size (GimpPreview *preview, gint aspect_width, @@ -1014,13 +1030,15 @@ gimp_preview_render_and_flush (GimpPreview *preview, gint x1, y1, x2, y2; gint rowstride; gboolean color; - gint alpha; gboolean has_alpha; gboolean render_composite; - gint image_bytes; + gint red_component; + gint green_component; + gint blue_component; + gint alpha_component; gint offset; gint border; - guchar border_color[3]; + guchar border_color[PREVIEW_BYTES]; width = preview->width; height = preview->height; @@ -1038,8 +1056,6 @@ gimp_preview_render_and_flush (GimpPreview *preview, &border_color[1], &border_color[2]); - alpha = ALPHA_PIX; - /* Here are the different cases this functions handles correctly: * 1) Offset temp_buf which does not necessarily cover full image area * 2) Color conversion of temp_buf if it is gray and image is color @@ -1051,34 +1067,43 @@ gimp_preview_render_and_flush (GimpPreview *preview, * 2) Color temp_bufs have bytes == {3, 4} * 3) If image is gray, then temp_buf should have bytes == {1, 2} */ - image_bytes = 3; - has_alpha = (temp_buf->bytes == 2 || temp_buf->bytes == 4); - rowstride = temp_buf->width * temp_buf->bytes; - /* Determine if the preview buf supplied is color - * Generally, if the bytes == {3, 4}, this is true. - * However, if the channel argument supplied is not -1, then - * the preview buf is assumed to be gray despite the number of - * channels it contains - */ - color = ((channel == -1) && - (temp_buf->bytes == 3 || temp_buf->bytes == 4)); + color = (temp_buf->bytes == 3 || temp_buf->bytes == 4); + has_alpha = (temp_buf->bytes == 2 || temp_buf->bytes == 4); + render_composite = (channel == -1); + rowstride = temp_buf->width * temp_buf->bytes; /* render the checkerboard only if the temp_buf has alpha *and* - * we render a composite preview (channel == -1) + * we render a composite preview */ - if (has_alpha && (channel == -1)) + if (has_alpha && render_composite) + buf = render_check_buf; + else + buf = render_empty_buf; + + if (render_composite) { - buf = render_check_buf; - render_composite = TRUE; - alpha = ((color) ? ALPHA_PIX : - ((channel != -1) ? (temp_buf->bytes - 1) : - ALPHA_G_PIX)); + if (color) + { + red_component = RED_PIX; + green_component = GREEN_PIX; + blue_component = BLUE_PIX; + alpha_component = ALPHA_PIX; + } + else + { + red_component = GRAY_PIX; + green_component = GRAY_PIX; + blue_component = GRAY_PIX; + alpha_component = ALPHA_G_PIX; + } } else { - buf = render_empty_buf; - render_composite = FALSE; + red_component = channel; + green_component = channel; + blue_component = channel; + alpha_component = 0; } x1 = CLAMP (temp_buf->x, 0, width); @@ -1089,27 +1114,23 @@ gimp_preview_render_and_flush (GimpPreview *preview, src = temp_buf_data (temp_buf) + ((y1 - temp_buf->y) * rowstride + (x1 - temp_buf->x) * temp_buf->bytes); - /* One last thing for efficiency's sake: */ - if (channel == -1) - channel = 0; - /* Set the border color once before rendering */ for (j = 0; j < width + border * 2; j++) - for (b = 0; b < image_bytes; b++) - render_temp_buf[j * image_bytes + b] = border_color[b]; + for (b = 0; b < PREVIEW_BYTES; b++) + render_temp_buf[j * PREVIEW_BYTES + b] = border_color[b]; for (i = 0; i < border; i++) { memcpy (preview->buffer + i * preview->rowstride, render_temp_buf, - (width + 2 * border) * image_bytes); + (width + 2 * border) * PREVIEW_BYTES); } for (i = border + height; i < 2 * border + height; i++) { memcpy (preview->buffer + i * preview->rowstride, render_temp_buf, - (width + 2 * border) * image_bytes); + (width + 2 * border) * PREVIEW_BYTES); } for (i = 0; i < height; i++) @@ -1132,106 +1153,64 @@ gimp_preview_render_and_flush (GimpPreview *preview, { /* Handle the leading transparency */ for (j = 0; j < x1; j++) - for (b = 0; b < image_bytes; b++) - render_temp_buf[(border + j) * image_bytes + b] = cb[j * 3 + b]; + for (b = 0; b < PREVIEW_BYTES; b++) + render_temp_buf[(border + j) * PREVIEW_BYTES + b] = cb[j * 3 + b]; /* The stuff in the middle */ s = src; for (j = x1; j < x2; j++) { - if (color) - { - if (has_alpha && render_composite) - { - a = s[alpha] << 8; + if (has_alpha && render_composite) + { + a = s[alpha_component] << 8; - if ((j + offset) & 0x4) - { - render_temp_buf[(border + j) * 3 + 0] = - render_blend_dark_check [(a | s[RED_PIX])]; - render_temp_buf[(border + j) * 3 + 1] = - render_blend_dark_check [(a | s[GREEN_PIX])]; - render_temp_buf[(border + j) * 3 + 2] = - render_blend_dark_check [(a | s[BLUE_PIX])]; - } - else - { - render_temp_buf[(border + j) * 3 + 0] = - render_blend_light_check [(a | s[RED_PIX])]; - render_temp_buf[(border + j) * 3 + 1] = - render_blend_light_check [(a | s[GREEN_PIX])]; - render_temp_buf[(border + j) * 3 + 2] = - render_blend_light_check [(a | s[BLUE_PIX])]; - } - } - else - { - render_temp_buf[(border + j) * 3 + 0] = s[RED_PIX]; - render_temp_buf[(border + j) * 3 + 1] = s[GREEN_PIX]; - render_temp_buf[(border + j) * 3 + 2] = s[BLUE_PIX]; - } - } - else - { - if (has_alpha && render_composite) - { - a = s[alpha] << 8; - - if ((j + offset) & 0x4) - { - render_temp_buf[(border + j) * 3 + 0] = - render_blend_dark_check [(a | s[GRAY_PIX])]; - render_temp_buf[(border + j) * 3 + 1] = - render_blend_dark_check [(a | s[GRAY_PIX])]; - render_temp_buf[(border + j) * 3 + 2] = - render_blend_dark_check [(a | s[GRAY_PIX])]; - } - else - { - render_temp_buf[(border + j) * 3 + 0] = - render_blend_light_check [(a | s[GRAY_PIX])]; - render_temp_buf[(border + j) * 3 + 1] = - render_blend_light_check [(a | s[GRAY_PIX])]; - render_temp_buf[(border + j) * 3 + 2] = - render_blend_light_check [(a | s[GRAY_PIX])]; - } - } - else - { - render_temp_buf[(border + j) * 3 + 0] = s[GRAY_PIX]; - render_temp_buf[(border + j) * 3 + 1] = s[GRAY_PIX]; - render_temp_buf[(border + j) * 3 + 2] = s[GRAY_PIX]; - } - } + if ((j + offset) & 0x4) + { + render_temp_buf[(border + j) * 3 + 0] = + render_blend_dark_check [(a | s[red_component])]; + render_temp_buf[(border + j) * 3 + 1] = + render_blend_dark_check [(a | s[green_component])]; + render_temp_buf[(border + j) * 3 + 2] = + render_blend_dark_check [(a | s[blue_component])]; + } + else + { + render_temp_buf[(border + j) * 3 + 0] = + render_blend_light_check [(a | s[red_component])]; + render_temp_buf[(border + j) * 3 + 1] = + render_blend_light_check [(a | s[green_component])]; + render_temp_buf[(border + j) * 3 + 2] = + render_blend_light_check [(a | s[blue_component])]; + } + } + else + { + render_temp_buf[(border + j) * 3 + 0] = s[red_component]; + render_temp_buf[(border + j) * 3 + 1] = s[green_component]; + render_temp_buf[(border + j) * 3 + 2] = s[blue_component]; + } s += temp_buf->bytes; } /* Handle the trailing transparency */ for (j = x2; j < width; j++) - for (b = 0; b < image_bytes; b++) - render_temp_buf[(border + j) * image_bytes + b] = cb[j * 3 + b]; + for (b = 0; b < PREVIEW_BYTES; b++) + render_temp_buf[(border + j) * PREVIEW_BYTES + b] = cb[j * 3 + b]; src += rowstride; } else { for (j = 0; j < width; j++) - for (b = 0; b < image_bytes; b++) - render_temp_buf[(border + j) * image_bytes + b] = cb[j * 3 + b]; + for (b = 0; b < PREVIEW_BYTES; b++) + render_temp_buf[(border + j) * PREVIEW_BYTES + b] = cb[j * 3 + b]; } memcpy (preview->buffer + (i + border) * preview->rowstride, render_temp_buf, - (width + 2 * border) * image_bytes); + (width + 2 * border) * PREVIEW_BYTES); } gtk_widget_queue_draw (GTK_WIDGET (preview)); } - -static GimpViewable * -gimp_preview_drag_viewable (GtkWidget *widget, - gpointer data) -{ - return GIMP_PREVIEW (widget)->viewable; -} diff --git a/app/widgets/gimppreviewrenderer.c b/app/widgets/gimppreviewrenderer.c index 0071d9780f..cb4668ac81 100644 --- a/app/widgets/gimppreviewrenderer.c +++ b/app/widgets/gimppreviewrenderer.c @@ -60,6 +60,8 @@ #include "gimptoolinfopreview.h" +#define PREVIEW_BYTES 3 + #define PREVIEW_POPUP_DELAY 150 #define PREVIEW_EVENT_MASK (GDK_BUTTON_PRESS_MASK | \ @@ -84,7 +86,7 @@ static void gimp_preview_init (GimpPreview *preview) static void gimp_preview_destroy (GtkObject *object); static void gimp_preview_size_allocate (GtkWidget *widget, GtkAllocation *allocation); -static gboolean gimp_preview_expose (GtkWidget *widget, +static gboolean gimp_preview_expose_event (GtkWidget *widget, GdkEventExpose *event); static gboolean gimp_preview_button_press_event (GtkWidget *widget, GdkEventButton *bevent); @@ -113,6 +115,8 @@ static void gimp_preview_popup_show (GimpPreview *preview, gint x, gint y); static void gimp_preview_popup_hide (GimpPreview *preview); +static gboolean gimp_preview_popup_timeout (GimpPreview *preview); + static void gimp_preview_size_changed (GimpPreview *preview, GimpViewable *viewable); static void gimp_preview_paint (GimpPreview *preview); @@ -205,7 +209,7 @@ gimp_preview_class_init (GimpPreviewClass *klass) object_class->destroy = gimp_preview_destroy; widget_class->size_allocate = gimp_preview_size_allocate; - widget_class->expose_event = gimp_preview_expose; + widget_class->expose_event = gimp_preview_expose_event; widget_class->button_press_event = gimp_preview_button_press_event; widget_class->button_release_event = gimp_preview_button_release_event; widget_class->enter_notify_event = gimp_preview_enter_notify_event; @@ -272,55 +276,263 @@ gimp_preview_destroy (GtkObject *object) GTK_OBJECT_CLASS (parent_class)->destroy (object); } -static GimpPreview * -gimp_preview_new_by_type (GimpViewable *viewable) +static void +gimp_preview_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) { GimpPreview *preview; - if (GIMP_IS_BRUSH (viewable)) + preview = GIMP_PREVIEW (widget); + + allocation->width = preview->width + 2 * preview->border_width; + allocation->height = preview->height + 2 * preview->border_width; + + if (GTK_WIDGET_CLASS (parent_class)->size_allocate) + GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation); + + gimp_preview_paint (GIMP_PREVIEW (widget)); +} + +static gboolean +gimp_preview_expose_event (GtkWidget *widget, + GdkEventExpose *event) +{ + GimpPreview *preview; + guchar *buf; + GdkRectangle buf_rect = { 0, 0, 0, 0 }; + GdkRectangle render_rect; + + preview = GIMP_PREVIEW (widget); + + if (! GTK_WIDGET_DRAWABLE (widget) || ! preview->buffer) + return FALSE; + + buf_rect.width = preview->width + 2 * preview->border_width; + buf_rect.height = preview->height + 2 * preview->border_width; + + if (widget->allocation.width > buf_rect.width) + buf_rect.x = (widget->allocation.width - buf_rect.width) / 2; + + if (widget->allocation.height >buf_rect.height) + buf_rect.y = (widget->allocation.height - buf_rect.height) / 2; + + if (gdk_rectangle_intersect (&event->area, &buf_rect, &render_rect)) { - preview = g_object_new (GIMP_TYPE_BRUSH_PREVIEW, NULL); + buf = (preview->buffer + + (render_rect.y - buf_rect.y) * preview->rowstride + + (render_rect.x - buf_rect.x) * PREVIEW_BYTES); + + gdk_draw_rgb_image_dithalign (widget->window, + widget->style->black_gc, + render_rect.x, + render_rect.y, + render_rect.width, + render_rect.height, + GDK_RGB_DITHER_NORMAL, + buf, + preview->rowstride, + event->area.x, + event->area.y); } - else if (GIMP_IS_DRAWABLE (viewable)) + + return FALSE; +} + +static gint +gimp_preview_button_press_event (GtkWidget *widget, + GdkEventButton *bevent) +{ + GimpPreview *preview; + + preview = GIMP_PREVIEW (widget); + +#define DEBUG_MEMSIZE 1 + +#ifdef DEBUG_MEMSIZE + if (bevent->type == GDK_BUTTON_PRESS && bevent->button == 2) { - preview = g_object_new (GIMP_TYPE_DRAWABLE_PREVIEW, NULL); + gimp_object_get_memsize (GIMP_OBJECT (preview->viewable)); } - else if (GIMP_IS_IMAGE (viewable)) +#endif /* DEBUG_MEMSIZE */ + + if (! preview->clickable && + ! preview->show_popup) + return FALSE; + + if (bevent->type == GDK_BUTTON_PRESS) { - preview = g_object_new (GIMP_TYPE_IMAGE_PREVIEW, NULL); + if (bevent->button == 1) + { + gtk_grab_add (widget); + + preview->press_state = bevent->state; + + if (preview->show_popup && gimp_preview_needs_popup (preview)) + { + gimp_preview_popup_show (preview, + bevent->x, + bevent->y); + } + } + else + { + preview->press_state = 0; + + if (bevent->button == 3) + { + g_signal_emit (G_OBJECT (widget), preview_signals[CONTEXT], 0); + } + else + { + return FALSE; + } + } } - else if (GIMP_IS_PATTERN (viewable)) + else if (bevent->type == GDK_2BUTTON_PRESS) { - preview = g_object_new (GIMP_TYPE_PATTERN_PREVIEW, NULL); + if (bevent->button == 1) + { + g_signal_emit (G_OBJECT (widget), preview_signals[DOUBLE_CLICKED], 0); + } } - else if (GIMP_IS_GRADIENT (viewable)) + + return TRUE; +} + +static gint +gimp_preview_button_release_event (GtkWidget *widget, + GdkEventButton *bevent) +{ + GimpPreview *preview; + gboolean click = TRUE; + + preview = GIMP_PREVIEW (widget); + + if (! preview->clickable && + ! preview->show_popup) + return FALSE; + + if (bevent->button == 1) { - preview = g_object_new (GIMP_TYPE_GRADIENT_PREVIEW, NULL); - } - else if (GIMP_IS_PALETTE (viewable)) - { - preview = g_object_new (GIMP_TYPE_PALETTE_PREVIEW, NULL); - } - else if (GIMP_IS_BUFFER (viewable)) - { - preview = g_object_new (GIMP_TYPE_BUFFER_PREVIEW, NULL); - } - else if (GIMP_IS_TOOL_INFO (viewable)) - { - preview = g_object_new (GIMP_TYPE_TOOL_INFO_PREVIEW, NULL); - } - else if (GIMP_IS_IMAGEFILE (viewable)) - { - preview = g_object_new (GIMP_TYPE_IMAGEFILE_PREVIEW, NULL); + if (preview->show_popup && gimp_preview_needs_popup (preview)) + { + click = (preview->popup_id != 0); + } + + gimp_preview_popup_hide (preview); + + /* remove the grab _after_ hiding the popup */ + gtk_grab_remove (widget); + + if (preview->clickable && click && preview->in_button) + { + if (preview->press_state & + (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK)) + { + g_signal_emit (G_OBJECT (widget), + preview_signals[EXTENDED_CLICKED], 0, + preview->press_state); + } + else + { + g_signal_emit (G_OBJECT (widget), preview_signals[CLICKED], 0); + } + } } else { - preview = g_object_new (GIMP_TYPE_PREVIEW, NULL); + return FALSE; } - return preview; + return TRUE; } +static gint +gimp_preview_enter_notify_event (GtkWidget *widget, + GdkEventCrossing *event) +{ + GimpPreview *preview; + GtkWidget *event_widget; + + preview = GIMP_PREVIEW (widget); + event_widget = gtk_get_event_widget ((GdkEvent *) event); + + if ((event_widget == widget) && + (event->detail != GDK_NOTIFY_INFERIOR)) + { + preview->in_button = TRUE; + } + + return FALSE; +} + +static gint +gimp_preview_leave_notify_event (GtkWidget *widget, + GdkEventCrossing *event) +{ + GimpPreview *preview; + GtkWidget *event_widget; + + preview = GIMP_PREVIEW (widget); + event_widget = gtk_get_event_widget ((GdkEvent *) event); + + if ((event_widget == widget) && + (event->detail != GDK_NOTIFY_INFERIOR)) + { + preview->in_button = FALSE; + } + + return FALSE; +} + +static GimpPreview * +gimp_preview_new_by_type (GimpViewable *viewable) +{ + GType type = GIMP_TYPE_PREVIEW; + + if (GIMP_IS_BRUSH (viewable)) + { + type = GIMP_TYPE_BRUSH_PREVIEW; + } + else if (GIMP_IS_DRAWABLE (viewable)) + { + type = GIMP_TYPE_DRAWABLE_PREVIEW; + } + else if (GIMP_IS_IMAGE (viewable)) + { + type = GIMP_TYPE_IMAGE_PREVIEW; + } + else if (GIMP_IS_PATTERN (viewable)) + { + type = GIMP_TYPE_PATTERN_PREVIEW; + } + else if (GIMP_IS_GRADIENT (viewable)) + { + type = GIMP_TYPE_GRADIENT_PREVIEW; + } + else if (GIMP_IS_PALETTE (viewable)) + { + type = GIMP_TYPE_PALETTE_PREVIEW; + } + else if (GIMP_IS_BUFFER (viewable)) + { + type = GIMP_TYPE_BUFFER_PREVIEW; + } + else if (GIMP_IS_TOOL_INFO (viewable)) + { + type = GIMP_TYPE_TOOL_INFO_PREVIEW; + } + else if (GIMP_IS_IMAGEFILE (viewable)) + { + type = GIMP_TYPE_IMAGEFILE_PREVIEW; + } + + return g_object_new (type, NULL); +} + + +/* public functions */ + GtkWidget * gimp_preview_new (GimpViewable *viewable, gint size, @@ -485,7 +697,7 @@ gimp_preview_set_size_full (GimpPreview *preview, GTK_WIDGET (preview)->requisition.height = height + 2 * border_width; preview->rowstride = - ((preview->width + 2 * preview->border_width) * 3 + 3) & ~3; + ((preview->width + 2 * preview->border_width) * PREVIEW_BYTES + 3) & ~3; if (preview->buffer) { @@ -541,152 +753,8 @@ gimp_preview_render (GimpPreview *preview) GIMP_PREVIEW_GET_CLASS (preview)->render (preview); } -static gint -gimp_preview_button_press_event (GtkWidget *widget, - GdkEventButton *bevent) -{ - GimpPreview *preview; - preview = GIMP_PREVIEW (widget); - -#define DEBUG_MEMSIZE 1 - -#ifdef DEBUG_MEMSIZE - if (bevent->type == GDK_BUTTON_PRESS && bevent->button == 2) - { - gimp_object_get_memsize (GIMP_OBJECT (preview->viewable)); - } -#endif /* DEBUG_MEMSIZE */ - - if (! preview->clickable && - ! preview->show_popup) - return FALSE; - - if (bevent->type == GDK_BUTTON_PRESS) - { - if (bevent->button == 1) - { - gtk_grab_add (widget); - - preview->press_state = bevent->state; - - if (preview->show_popup && gimp_preview_needs_popup (preview)) - { - gimp_preview_popup_show (preview, - bevent->x, - bevent->y); - } - } - else - { - preview->press_state = 0; - - if (bevent->button == 3) - { - g_signal_emit (G_OBJECT (widget), preview_signals[CONTEXT], 0); - } - else - { - return FALSE; - } - } - } - else if (bevent->type == GDK_2BUTTON_PRESS) - { - if (bevent->button == 1) - { - g_signal_emit (G_OBJECT (widget), preview_signals[DOUBLE_CLICKED], 0); - } - } - - return TRUE; -} - -static gint -gimp_preview_button_release_event (GtkWidget *widget, - GdkEventButton *bevent) -{ - GimpPreview *preview; - gboolean click = TRUE; - - preview = GIMP_PREVIEW (widget); - - if (! preview->clickable && - ! preview->show_popup) - return FALSE; - - if (bevent->button == 1) - { - if (preview->show_popup && gimp_preview_needs_popup (preview)) - { - click = (preview->popup_id != 0); - } - - gimp_preview_popup_hide (preview); - - /* remove the grab _after_ hiding the popup */ - gtk_grab_remove (widget); - - if (preview->clickable && click && preview->in_button) - { - if (preview->press_state & - (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK)) - { - g_signal_emit (G_OBJECT (widget), - preview_signals[EXTENDED_CLICKED], 0, - preview->press_state); - } - else - { - g_signal_emit (G_OBJECT (widget), preview_signals[CLICKED], 0); - } - } - } - else - { - return FALSE; - } - - return TRUE; -} - -static gint -gimp_preview_enter_notify_event (GtkWidget *widget, - GdkEventCrossing *event) -{ - GimpPreview *preview; - GtkWidget *event_widget; - - preview = GIMP_PREVIEW (widget); - event_widget = gtk_get_event_widget ((GdkEvent *) event); - - if ((event_widget == widget) && - (event->detail != GDK_NOTIFY_INFERIOR)) - { - preview->in_button = TRUE; - } - - return FALSE; -} - -static gint -gimp_preview_leave_notify_event (GtkWidget *widget, - GdkEventCrossing *event) -{ - GimpPreview *preview; - GtkWidget *event_widget; - - preview = GIMP_PREVIEW (widget); - event_widget = gtk_get_event_widget ((GdkEvent *) event); - - if ((event_widget == widget) && - (event->detail != GDK_NOTIFY_INFERIOR)) - { - preview->in_button = FALSE; - } - - return FALSE; -} +/* private functions */ static void gimp_preview_real_render (GimpPreview *preview) @@ -766,6 +834,34 @@ gimp_preview_real_create_popup (GimpPreview *preview) TRUE, FALSE, FALSE); } +static void +gimp_preview_popup_show (GimpPreview *preview, + gint x, + gint y) +{ + preview->popup_x = x; + preview->popup_y = y; + + preview->popup_id = g_timeout_add (PREVIEW_POPUP_DELAY, + (GSourceFunc) gimp_preview_popup_timeout, + preview); +} + +static void +gimp_preview_popup_hide (GimpPreview *preview) +{ + if (preview->popup_id) + { + g_source_remove (preview->popup_id); + + preview->popup_id = 0; + preview->popup_x = 0; + preview->popup_y = 0; + } + + g_object_set_data (G_OBJECT (preview), "gimp-preview-popup", NULL); +} + static gboolean gimp_preview_popup_timeout (GimpPreview *preview) { @@ -820,102 +916,12 @@ gimp_preview_popup_timeout (GimpPreview *preview) gtk_window_move (GTK_WINDOW (window), x, y); gtk_widget_show (window); - g_object_set_data_full (G_OBJECT (preview), "preview_popup_window", window, + g_object_set_data_full (G_OBJECT (preview), "gimp-preview-popup", window, (GDestroyNotify) gtk_widget_destroy); return FALSE; } -static void -gimp_preview_popup_show (GimpPreview *preview, - gint x, - gint y) -{ - preview->popup_x = x; - preview->popup_y = y; - - preview->popup_id = g_timeout_add (PREVIEW_POPUP_DELAY, - (GSourceFunc) gimp_preview_popup_timeout, - preview); -} - -static void -gimp_preview_popup_hide (GimpPreview *preview) -{ - if (preview->popup_id) - { - g_source_remove (preview->popup_id); - - preview->popup_id = 0; - preview->popup_x = 0; - preview->popup_y = 0; - } - - g_object_set_data (G_OBJECT (preview), "preview_popup_window", NULL); -} - -static void -gimp_preview_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - GimpPreview *preview; - - preview = GIMP_PREVIEW (widget); - - allocation->width = preview->width + 2 * preview->border_width; - allocation->height = preview->height + 2 * preview->border_width; - - if (GTK_WIDGET_CLASS (parent_class)->size_allocate) - GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation); - - gimp_preview_paint (GIMP_PREVIEW (widget)); -} - -static gboolean -gimp_preview_expose (GtkWidget *widget, - GdkEventExpose *event) -{ - GimpPreview *preview; - guchar *buf; - GdkRectangle buf_rect = { 0, 0, 0, 0 }; - GdkRectangle render_rect; - - preview = GIMP_PREVIEW (widget); - - if (! GTK_WIDGET_DRAWABLE (widget) || ! preview->buffer) - return FALSE; - - buf_rect.width = preview->width + 2 * preview->border_width; - buf_rect.height = preview->height + 2 * preview->border_width; - - if (widget->allocation.width > buf_rect.width) - buf_rect.x = (widget->allocation.width - buf_rect.width) / 2; - - if (widget->allocation.height >buf_rect.height) - buf_rect.y = (widget->allocation.height - buf_rect.height) / 2; - - if (gdk_rectangle_intersect (&event->area, &buf_rect, &render_rect)) - { - buf = (preview->buffer + - (render_rect.y - buf_rect.y) * preview->rowstride + - (render_rect.x - buf_rect.x) * 3); - - gdk_draw_rgb_image_dithalign (widget->window, - widget->style->black_gc, - render_rect.x, - render_rect.y, - render_rect.width, - render_rect.height, - GDK_RGB_DITHER_NORMAL, - buf, - preview->rowstride, - event->area.x, - event->area.y); - } - - return FALSE; -} - static void gimp_preview_size_changed (GimpPreview *preview, GimpViewable *viewable) @@ -957,6 +963,16 @@ gimp_preview_idle_paint (GimpPreview *preview) return FALSE; } +static GimpViewable * +gimp_preview_drag_viewable (GtkWidget *widget, + gpointer data) +{ + return GIMP_PREVIEW (widget)->viewable; +} + + +/* protected functions */ + void gimp_preview_calc_size (GimpPreview *preview, gint aspect_width, @@ -1014,13 +1030,15 @@ gimp_preview_render_and_flush (GimpPreview *preview, gint x1, y1, x2, y2; gint rowstride; gboolean color; - gint alpha; gboolean has_alpha; gboolean render_composite; - gint image_bytes; + gint red_component; + gint green_component; + gint blue_component; + gint alpha_component; gint offset; gint border; - guchar border_color[3]; + guchar border_color[PREVIEW_BYTES]; width = preview->width; height = preview->height; @@ -1038,8 +1056,6 @@ gimp_preview_render_and_flush (GimpPreview *preview, &border_color[1], &border_color[2]); - alpha = ALPHA_PIX; - /* Here are the different cases this functions handles correctly: * 1) Offset temp_buf which does not necessarily cover full image area * 2) Color conversion of temp_buf if it is gray and image is color @@ -1051,34 +1067,43 @@ gimp_preview_render_and_flush (GimpPreview *preview, * 2) Color temp_bufs have bytes == {3, 4} * 3) If image is gray, then temp_buf should have bytes == {1, 2} */ - image_bytes = 3; - has_alpha = (temp_buf->bytes == 2 || temp_buf->bytes == 4); - rowstride = temp_buf->width * temp_buf->bytes; - /* Determine if the preview buf supplied is color - * Generally, if the bytes == {3, 4}, this is true. - * However, if the channel argument supplied is not -1, then - * the preview buf is assumed to be gray despite the number of - * channels it contains - */ - color = ((channel == -1) && - (temp_buf->bytes == 3 || temp_buf->bytes == 4)); + color = (temp_buf->bytes == 3 || temp_buf->bytes == 4); + has_alpha = (temp_buf->bytes == 2 || temp_buf->bytes == 4); + render_composite = (channel == -1); + rowstride = temp_buf->width * temp_buf->bytes; /* render the checkerboard only if the temp_buf has alpha *and* - * we render a composite preview (channel == -1) + * we render a composite preview */ - if (has_alpha && (channel == -1)) + if (has_alpha && render_composite) + buf = render_check_buf; + else + buf = render_empty_buf; + + if (render_composite) { - buf = render_check_buf; - render_composite = TRUE; - alpha = ((color) ? ALPHA_PIX : - ((channel != -1) ? (temp_buf->bytes - 1) : - ALPHA_G_PIX)); + if (color) + { + red_component = RED_PIX; + green_component = GREEN_PIX; + blue_component = BLUE_PIX; + alpha_component = ALPHA_PIX; + } + else + { + red_component = GRAY_PIX; + green_component = GRAY_PIX; + blue_component = GRAY_PIX; + alpha_component = ALPHA_G_PIX; + } } else { - buf = render_empty_buf; - render_composite = FALSE; + red_component = channel; + green_component = channel; + blue_component = channel; + alpha_component = 0; } x1 = CLAMP (temp_buf->x, 0, width); @@ -1089,27 +1114,23 @@ gimp_preview_render_and_flush (GimpPreview *preview, src = temp_buf_data (temp_buf) + ((y1 - temp_buf->y) * rowstride + (x1 - temp_buf->x) * temp_buf->bytes); - /* One last thing for efficiency's sake: */ - if (channel == -1) - channel = 0; - /* Set the border color once before rendering */ for (j = 0; j < width + border * 2; j++) - for (b = 0; b < image_bytes; b++) - render_temp_buf[j * image_bytes + b] = border_color[b]; + for (b = 0; b < PREVIEW_BYTES; b++) + render_temp_buf[j * PREVIEW_BYTES + b] = border_color[b]; for (i = 0; i < border; i++) { memcpy (preview->buffer + i * preview->rowstride, render_temp_buf, - (width + 2 * border) * image_bytes); + (width + 2 * border) * PREVIEW_BYTES); } for (i = border + height; i < 2 * border + height; i++) { memcpy (preview->buffer + i * preview->rowstride, render_temp_buf, - (width + 2 * border) * image_bytes); + (width + 2 * border) * PREVIEW_BYTES); } for (i = 0; i < height; i++) @@ -1132,106 +1153,64 @@ gimp_preview_render_and_flush (GimpPreview *preview, { /* Handle the leading transparency */ for (j = 0; j < x1; j++) - for (b = 0; b < image_bytes; b++) - render_temp_buf[(border + j) * image_bytes + b] = cb[j * 3 + b]; + for (b = 0; b < PREVIEW_BYTES; b++) + render_temp_buf[(border + j) * PREVIEW_BYTES + b] = cb[j * 3 + b]; /* The stuff in the middle */ s = src; for (j = x1; j < x2; j++) { - if (color) - { - if (has_alpha && render_composite) - { - a = s[alpha] << 8; + if (has_alpha && render_composite) + { + a = s[alpha_component] << 8; - if ((j + offset) & 0x4) - { - render_temp_buf[(border + j) * 3 + 0] = - render_blend_dark_check [(a | s[RED_PIX])]; - render_temp_buf[(border + j) * 3 + 1] = - render_blend_dark_check [(a | s[GREEN_PIX])]; - render_temp_buf[(border + j) * 3 + 2] = - render_blend_dark_check [(a | s[BLUE_PIX])]; - } - else - { - render_temp_buf[(border + j) * 3 + 0] = - render_blend_light_check [(a | s[RED_PIX])]; - render_temp_buf[(border + j) * 3 + 1] = - render_blend_light_check [(a | s[GREEN_PIX])]; - render_temp_buf[(border + j) * 3 + 2] = - render_blend_light_check [(a | s[BLUE_PIX])]; - } - } - else - { - render_temp_buf[(border + j) * 3 + 0] = s[RED_PIX]; - render_temp_buf[(border + j) * 3 + 1] = s[GREEN_PIX]; - render_temp_buf[(border + j) * 3 + 2] = s[BLUE_PIX]; - } - } - else - { - if (has_alpha && render_composite) - { - a = s[alpha] << 8; - - if ((j + offset) & 0x4) - { - render_temp_buf[(border + j) * 3 + 0] = - render_blend_dark_check [(a | s[GRAY_PIX])]; - render_temp_buf[(border + j) * 3 + 1] = - render_blend_dark_check [(a | s[GRAY_PIX])]; - render_temp_buf[(border + j) * 3 + 2] = - render_blend_dark_check [(a | s[GRAY_PIX])]; - } - else - { - render_temp_buf[(border + j) * 3 + 0] = - render_blend_light_check [(a | s[GRAY_PIX])]; - render_temp_buf[(border + j) * 3 + 1] = - render_blend_light_check [(a | s[GRAY_PIX])]; - render_temp_buf[(border + j) * 3 + 2] = - render_blend_light_check [(a | s[GRAY_PIX])]; - } - } - else - { - render_temp_buf[(border + j) * 3 + 0] = s[GRAY_PIX]; - render_temp_buf[(border + j) * 3 + 1] = s[GRAY_PIX]; - render_temp_buf[(border + j) * 3 + 2] = s[GRAY_PIX]; - } - } + if ((j + offset) & 0x4) + { + render_temp_buf[(border + j) * 3 + 0] = + render_blend_dark_check [(a | s[red_component])]; + render_temp_buf[(border + j) * 3 + 1] = + render_blend_dark_check [(a | s[green_component])]; + render_temp_buf[(border + j) * 3 + 2] = + render_blend_dark_check [(a | s[blue_component])]; + } + else + { + render_temp_buf[(border + j) * 3 + 0] = + render_blend_light_check [(a | s[red_component])]; + render_temp_buf[(border + j) * 3 + 1] = + render_blend_light_check [(a | s[green_component])]; + render_temp_buf[(border + j) * 3 + 2] = + render_blend_light_check [(a | s[blue_component])]; + } + } + else + { + render_temp_buf[(border + j) * 3 + 0] = s[red_component]; + render_temp_buf[(border + j) * 3 + 1] = s[green_component]; + render_temp_buf[(border + j) * 3 + 2] = s[blue_component]; + } s += temp_buf->bytes; } /* Handle the trailing transparency */ for (j = x2; j < width; j++) - for (b = 0; b < image_bytes; b++) - render_temp_buf[(border + j) * image_bytes + b] = cb[j * 3 + b]; + for (b = 0; b < PREVIEW_BYTES; b++) + render_temp_buf[(border + j) * PREVIEW_BYTES + b] = cb[j * 3 + b]; src += rowstride; } else { for (j = 0; j < width; j++) - for (b = 0; b < image_bytes; b++) - render_temp_buf[(border + j) * image_bytes + b] = cb[j * 3 + b]; + for (b = 0; b < PREVIEW_BYTES; b++) + render_temp_buf[(border + j) * PREVIEW_BYTES + b] = cb[j * 3 + b]; } memcpy (preview->buffer + (i + border) * preview->rowstride, render_temp_buf, - (width + 2 * border) * image_bytes); + (width + 2 * border) * PREVIEW_BYTES); } gtk_widget_queue_draw (GTK_WIDGET (preview)); } - -static GimpViewable * -gimp_preview_drag_viewable (GtkWidget *widget, - gpointer data) -{ - return GIMP_PREVIEW (widget)->viewable; -} diff --git a/app/widgets/gimpview.c b/app/widgets/gimpview.c index 0071d9780f..cb4668ac81 100644 --- a/app/widgets/gimpview.c +++ b/app/widgets/gimpview.c @@ -60,6 +60,8 @@ #include "gimptoolinfopreview.h" +#define PREVIEW_BYTES 3 + #define PREVIEW_POPUP_DELAY 150 #define PREVIEW_EVENT_MASK (GDK_BUTTON_PRESS_MASK | \ @@ -84,7 +86,7 @@ static void gimp_preview_init (GimpPreview *preview) static void gimp_preview_destroy (GtkObject *object); static void gimp_preview_size_allocate (GtkWidget *widget, GtkAllocation *allocation); -static gboolean gimp_preview_expose (GtkWidget *widget, +static gboolean gimp_preview_expose_event (GtkWidget *widget, GdkEventExpose *event); static gboolean gimp_preview_button_press_event (GtkWidget *widget, GdkEventButton *bevent); @@ -113,6 +115,8 @@ static void gimp_preview_popup_show (GimpPreview *preview, gint x, gint y); static void gimp_preview_popup_hide (GimpPreview *preview); +static gboolean gimp_preview_popup_timeout (GimpPreview *preview); + static void gimp_preview_size_changed (GimpPreview *preview, GimpViewable *viewable); static void gimp_preview_paint (GimpPreview *preview); @@ -205,7 +209,7 @@ gimp_preview_class_init (GimpPreviewClass *klass) object_class->destroy = gimp_preview_destroy; widget_class->size_allocate = gimp_preview_size_allocate; - widget_class->expose_event = gimp_preview_expose; + widget_class->expose_event = gimp_preview_expose_event; widget_class->button_press_event = gimp_preview_button_press_event; widget_class->button_release_event = gimp_preview_button_release_event; widget_class->enter_notify_event = gimp_preview_enter_notify_event; @@ -272,55 +276,263 @@ gimp_preview_destroy (GtkObject *object) GTK_OBJECT_CLASS (parent_class)->destroy (object); } -static GimpPreview * -gimp_preview_new_by_type (GimpViewable *viewable) +static void +gimp_preview_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) { GimpPreview *preview; - if (GIMP_IS_BRUSH (viewable)) + preview = GIMP_PREVIEW (widget); + + allocation->width = preview->width + 2 * preview->border_width; + allocation->height = preview->height + 2 * preview->border_width; + + if (GTK_WIDGET_CLASS (parent_class)->size_allocate) + GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation); + + gimp_preview_paint (GIMP_PREVIEW (widget)); +} + +static gboolean +gimp_preview_expose_event (GtkWidget *widget, + GdkEventExpose *event) +{ + GimpPreview *preview; + guchar *buf; + GdkRectangle buf_rect = { 0, 0, 0, 0 }; + GdkRectangle render_rect; + + preview = GIMP_PREVIEW (widget); + + if (! GTK_WIDGET_DRAWABLE (widget) || ! preview->buffer) + return FALSE; + + buf_rect.width = preview->width + 2 * preview->border_width; + buf_rect.height = preview->height + 2 * preview->border_width; + + if (widget->allocation.width > buf_rect.width) + buf_rect.x = (widget->allocation.width - buf_rect.width) / 2; + + if (widget->allocation.height >buf_rect.height) + buf_rect.y = (widget->allocation.height - buf_rect.height) / 2; + + if (gdk_rectangle_intersect (&event->area, &buf_rect, &render_rect)) { - preview = g_object_new (GIMP_TYPE_BRUSH_PREVIEW, NULL); + buf = (preview->buffer + + (render_rect.y - buf_rect.y) * preview->rowstride + + (render_rect.x - buf_rect.x) * PREVIEW_BYTES); + + gdk_draw_rgb_image_dithalign (widget->window, + widget->style->black_gc, + render_rect.x, + render_rect.y, + render_rect.width, + render_rect.height, + GDK_RGB_DITHER_NORMAL, + buf, + preview->rowstride, + event->area.x, + event->area.y); } - else if (GIMP_IS_DRAWABLE (viewable)) + + return FALSE; +} + +static gint +gimp_preview_button_press_event (GtkWidget *widget, + GdkEventButton *bevent) +{ + GimpPreview *preview; + + preview = GIMP_PREVIEW (widget); + +#define DEBUG_MEMSIZE 1 + +#ifdef DEBUG_MEMSIZE + if (bevent->type == GDK_BUTTON_PRESS && bevent->button == 2) { - preview = g_object_new (GIMP_TYPE_DRAWABLE_PREVIEW, NULL); + gimp_object_get_memsize (GIMP_OBJECT (preview->viewable)); } - else if (GIMP_IS_IMAGE (viewable)) +#endif /* DEBUG_MEMSIZE */ + + if (! preview->clickable && + ! preview->show_popup) + return FALSE; + + if (bevent->type == GDK_BUTTON_PRESS) { - preview = g_object_new (GIMP_TYPE_IMAGE_PREVIEW, NULL); + if (bevent->button == 1) + { + gtk_grab_add (widget); + + preview->press_state = bevent->state; + + if (preview->show_popup && gimp_preview_needs_popup (preview)) + { + gimp_preview_popup_show (preview, + bevent->x, + bevent->y); + } + } + else + { + preview->press_state = 0; + + if (bevent->button == 3) + { + g_signal_emit (G_OBJECT (widget), preview_signals[CONTEXT], 0); + } + else + { + return FALSE; + } + } } - else if (GIMP_IS_PATTERN (viewable)) + else if (bevent->type == GDK_2BUTTON_PRESS) { - preview = g_object_new (GIMP_TYPE_PATTERN_PREVIEW, NULL); + if (bevent->button == 1) + { + g_signal_emit (G_OBJECT (widget), preview_signals[DOUBLE_CLICKED], 0); + } } - else if (GIMP_IS_GRADIENT (viewable)) + + return TRUE; +} + +static gint +gimp_preview_button_release_event (GtkWidget *widget, + GdkEventButton *bevent) +{ + GimpPreview *preview; + gboolean click = TRUE; + + preview = GIMP_PREVIEW (widget); + + if (! preview->clickable && + ! preview->show_popup) + return FALSE; + + if (bevent->button == 1) { - preview = g_object_new (GIMP_TYPE_GRADIENT_PREVIEW, NULL); - } - else if (GIMP_IS_PALETTE (viewable)) - { - preview = g_object_new (GIMP_TYPE_PALETTE_PREVIEW, NULL); - } - else if (GIMP_IS_BUFFER (viewable)) - { - preview = g_object_new (GIMP_TYPE_BUFFER_PREVIEW, NULL); - } - else if (GIMP_IS_TOOL_INFO (viewable)) - { - preview = g_object_new (GIMP_TYPE_TOOL_INFO_PREVIEW, NULL); - } - else if (GIMP_IS_IMAGEFILE (viewable)) - { - preview = g_object_new (GIMP_TYPE_IMAGEFILE_PREVIEW, NULL); + if (preview->show_popup && gimp_preview_needs_popup (preview)) + { + click = (preview->popup_id != 0); + } + + gimp_preview_popup_hide (preview); + + /* remove the grab _after_ hiding the popup */ + gtk_grab_remove (widget); + + if (preview->clickable && click && preview->in_button) + { + if (preview->press_state & + (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK)) + { + g_signal_emit (G_OBJECT (widget), + preview_signals[EXTENDED_CLICKED], 0, + preview->press_state); + } + else + { + g_signal_emit (G_OBJECT (widget), preview_signals[CLICKED], 0); + } + } } else { - preview = g_object_new (GIMP_TYPE_PREVIEW, NULL); + return FALSE; } - return preview; + return TRUE; } +static gint +gimp_preview_enter_notify_event (GtkWidget *widget, + GdkEventCrossing *event) +{ + GimpPreview *preview; + GtkWidget *event_widget; + + preview = GIMP_PREVIEW (widget); + event_widget = gtk_get_event_widget ((GdkEvent *) event); + + if ((event_widget == widget) && + (event->detail != GDK_NOTIFY_INFERIOR)) + { + preview->in_button = TRUE; + } + + return FALSE; +} + +static gint +gimp_preview_leave_notify_event (GtkWidget *widget, + GdkEventCrossing *event) +{ + GimpPreview *preview; + GtkWidget *event_widget; + + preview = GIMP_PREVIEW (widget); + event_widget = gtk_get_event_widget ((GdkEvent *) event); + + if ((event_widget == widget) && + (event->detail != GDK_NOTIFY_INFERIOR)) + { + preview->in_button = FALSE; + } + + return FALSE; +} + +static GimpPreview * +gimp_preview_new_by_type (GimpViewable *viewable) +{ + GType type = GIMP_TYPE_PREVIEW; + + if (GIMP_IS_BRUSH (viewable)) + { + type = GIMP_TYPE_BRUSH_PREVIEW; + } + else if (GIMP_IS_DRAWABLE (viewable)) + { + type = GIMP_TYPE_DRAWABLE_PREVIEW; + } + else if (GIMP_IS_IMAGE (viewable)) + { + type = GIMP_TYPE_IMAGE_PREVIEW; + } + else if (GIMP_IS_PATTERN (viewable)) + { + type = GIMP_TYPE_PATTERN_PREVIEW; + } + else if (GIMP_IS_GRADIENT (viewable)) + { + type = GIMP_TYPE_GRADIENT_PREVIEW; + } + else if (GIMP_IS_PALETTE (viewable)) + { + type = GIMP_TYPE_PALETTE_PREVIEW; + } + else if (GIMP_IS_BUFFER (viewable)) + { + type = GIMP_TYPE_BUFFER_PREVIEW; + } + else if (GIMP_IS_TOOL_INFO (viewable)) + { + type = GIMP_TYPE_TOOL_INFO_PREVIEW; + } + else if (GIMP_IS_IMAGEFILE (viewable)) + { + type = GIMP_TYPE_IMAGEFILE_PREVIEW; + } + + return g_object_new (type, NULL); +} + + +/* public functions */ + GtkWidget * gimp_preview_new (GimpViewable *viewable, gint size, @@ -485,7 +697,7 @@ gimp_preview_set_size_full (GimpPreview *preview, GTK_WIDGET (preview)->requisition.height = height + 2 * border_width; preview->rowstride = - ((preview->width + 2 * preview->border_width) * 3 + 3) & ~3; + ((preview->width + 2 * preview->border_width) * PREVIEW_BYTES + 3) & ~3; if (preview->buffer) { @@ -541,152 +753,8 @@ gimp_preview_render (GimpPreview *preview) GIMP_PREVIEW_GET_CLASS (preview)->render (preview); } -static gint -gimp_preview_button_press_event (GtkWidget *widget, - GdkEventButton *bevent) -{ - GimpPreview *preview; - preview = GIMP_PREVIEW (widget); - -#define DEBUG_MEMSIZE 1 - -#ifdef DEBUG_MEMSIZE - if (bevent->type == GDK_BUTTON_PRESS && bevent->button == 2) - { - gimp_object_get_memsize (GIMP_OBJECT (preview->viewable)); - } -#endif /* DEBUG_MEMSIZE */ - - if (! preview->clickable && - ! preview->show_popup) - return FALSE; - - if (bevent->type == GDK_BUTTON_PRESS) - { - if (bevent->button == 1) - { - gtk_grab_add (widget); - - preview->press_state = bevent->state; - - if (preview->show_popup && gimp_preview_needs_popup (preview)) - { - gimp_preview_popup_show (preview, - bevent->x, - bevent->y); - } - } - else - { - preview->press_state = 0; - - if (bevent->button == 3) - { - g_signal_emit (G_OBJECT (widget), preview_signals[CONTEXT], 0); - } - else - { - return FALSE; - } - } - } - else if (bevent->type == GDK_2BUTTON_PRESS) - { - if (bevent->button == 1) - { - g_signal_emit (G_OBJECT (widget), preview_signals[DOUBLE_CLICKED], 0); - } - } - - return TRUE; -} - -static gint -gimp_preview_button_release_event (GtkWidget *widget, - GdkEventButton *bevent) -{ - GimpPreview *preview; - gboolean click = TRUE; - - preview = GIMP_PREVIEW (widget); - - if (! preview->clickable && - ! preview->show_popup) - return FALSE; - - if (bevent->button == 1) - { - if (preview->show_popup && gimp_preview_needs_popup (preview)) - { - click = (preview->popup_id != 0); - } - - gimp_preview_popup_hide (preview); - - /* remove the grab _after_ hiding the popup */ - gtk_grab_remove (widget); - - if (preview->clickable && click && preview->in_button) - { - if (preview->press_state & - (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK)) - { - g_signal_emit (G_OBJECT (widget), - preview_signals[EXTENDED_CLICKED], 0, - preview->press_state); - } - else - { - g_signal_emit (G_OBJECT (widget), preview_signals[CLICKED], 0); - } - } - } - else - { - return FALSE; - } - - return TRUE; -} - -static gint -gimp_preview_enter_notify_event (GtkWidget *widget, - GdkEventCrossing *event) -{ - GimpPreview *preview; - GtkWidget *event_widget; - - preview = GIMP_PREVIEW (widget); - event_widget = gtk_get_event_widget ((GdkEvent *) event); - - if ((event_widget == widget) && - (event->detail != GDK_NOTIFY_INFERIOR)) - { - preview->in_button = TRUE; - } - - return FALSE; -} - -static gint -gimp_preview_leave_notify_event (GtkWidget *widget, - GdkEventCrossing *event) -{ - GimpPreview *preview; - GtkWidget *event_widget; - - preview = GIMP_PREVIEW (widget); - event_widget = gtk_get_event_widget ((GdkEvent *) event); - - if ((event_widget == widget) && - (event->detail != GDK_NOTIFY_INFERIOR)) - { - preview->in_button = FALSE; - } - - return FALSE; -} +/* private functions */ static void gimp_preview_real_render (GimpPreview *preview) @@ -766,6 +834,34 @@ gimp_preview_real_create_popup (GimpPreview *preview) TRUE, FALSE, FALSE); } +static void +gimp_preview_popup_show (GimpPreview *preview, + gint x, + gint y) +{ + preview->popup_x = x; + preview->popup_y = y; + + preview->popup_id = g_timeout_add (PREVIEW_POPUP_DELAY, + (GSourceFunc) gimp_preview_popup_timeout, + preview); +} + +static void +gimp_preview_popup_hide (GimpPreview *preview) +{ + if (preview->popup_id) + { + g_source_remove (preview->popup_id); + + preview->popup_id = 0; + preview->popup_x = 0; + preview->popup_y = 0; + } + + g_object_set_data (G_OBJECT (preview), "gimp-preview-popup", NULL); +} + static gboolean gimp_preview_popup_timeout (GimpPreview *preview) { @@ -820,102 +916,12 @@ gimp_preview_popup_timeout (GimpPreview *preview) gtk_window_move (GTK_WINDOW (window), x, y); gtk_widget_show (window); - g_object_set_data_full (G_OBJECT (preview), "preview_popup_window", window, + g_object_set_data_full (G_OBJECT (preview), "gimp-preview-popup", window, (GDestroyNotify) gtk_widget_destroy); return FALSE; } -static void -gimp_preview_popup_show (GimpPreview *preview, - gint x, - gint y) -{ - preview->popup_x = x; - preview->popup_y = y; - - preview->popup_id = g_timeout_add (PREVIEW_POPUP_DELAY, - (GSourceFunc) gimp_preview_popup_timeout, - preview); -} - -static void -gimp_preview_popup_hide (GimpPreview *preview) -{ - if (preview->popup_id) - { - g_source_remove (preview->popup_id); - - preview->popup_id = 0; - preview->popup_x = 0; - preview->popup_y = 0; - } - - g_object_set_data (G_OBJECT (preview), "preview_popup_window", NULL); -} - -static void -gimp_preview_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - GimpPreview *preview; - - preview = GIMP_PREVIEW (widget); - - allocation->width = preview->width + 2 * preview->border_width; - allocation->height = preview->height + 2 * preview->border_width; - - if (GTK_WIDGET_CLASS (parent_class)->size_allocate) - GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation); - - gimp_preview_paint (GIMP_PREVIEW (widget)); -} - -static gboolean -gimp_preview_expose (GtkWidget *widget, - GdkEventExpose *event) -{ - GimpPreview *preview; - guchar *buf; - GdkRectangle buf_rect = { 0, 0, 0, 0 }; - GdkRectangle render_rect; - - preview = GIMP_PREVIEW (widget); - - if (! GTK_WIDGET_DRAWABLE (widget) || ! preview->buffer) - return FALSE; - - buf_rect.width = preview->width + 2 * preview->border_width; - buf_rect.height = preview->height + 2 * preview->border_width; - - if (widget->allocation.width > buf_rect.width) - buf_rect.x = (widget->allocation.width - buf_rect.width) / 2; - - if (widget->allocation.height >buf_rect.height) - buf_rect.y = (widget->allocation.height - buf_rect.height) / 2; - - if (gdk_rectangle_intersect (&event->area, &buf_rect, &render_rect)) - { - buf = (preview->buffer + - (render_rect.y - buf_rect.y) * preview->rowstride + - (render_rect.x - buf_rect.x) * 3); - - gdk_draw_rgb_image_dithalign (widget->window, - widget->style->black_gc, - render_rect.x, - render_rect.y, - render_rect.width, - render_rect.height, - GDK_RGB_DITHER_NORMAL, - buf, - preview->rowstride, - event->area.x, - event->area.y); - } - - return FALSE; -} - static void gimp_preview_size_changed (GimpPreview *preview, GimpViewable *viewable) @@ -957,6 +963,16 @@ gimp_preview_idle_paint (GimpPreview *preview) return FALSE; } +static GimpViewable * +gimp_preview_drag_viewable (GtkWidget *widget, + gpointer data) +{ + return GIMP_PREVIEW (widget)->viewable; +} + + +/* protected functions */ + void gimp_preview_calc_size (GimpPreview *preview, gint aspect_width, @@ -1014,13 +1030,15 @@ gimp_preview_render_and_flush (GimpPreview *preview, gint x1, y1, x2, y2; gint rowstride; gboolean color; - gint alpha; gboolean has_alpha; gboolean render_composite; - gint image_bytes; + gint red_component; + gint green_component; + gint blue_component; + gint alpha_component; gint offset; gint border; - guchar border_color[3]; + guchar border_color[PREVIEW_BYTES]; width = preview->width; height = preview->height; @@ -1038,8 +1056,6 @@ gimp_preview_render_and_flush (GimpPreview *preview, &border_color[1], &border_color[2]); - alpha = ALPHA_PIX; - /* Here are the different cases this functions handles correctly: * 1) Offset temp_buf which does not necessarily cover full image area * 2) Color conversion of temp_buf if it is gray and image is color @@ -1051,34 +1067,43 @@ gimp_preview_render_and_flush (GimpPreview *preview, * 2) Color temp_bufs have bytes == {3, 4} * 3) If image is gray, then temp_buf should have bytes == {1, 2} */ - image_bytes = 3; - has_alpha = (temp_buf->bytes == 2 || temp_buf->bytes == 4); - rowstride = temp_buf->width * temp_buf->bytes; - /* Determine if the preview buf supplied is color - * Generally, if the bytes == {3, 4}, this is true. - * However, if the channel argument supplied is not -1, then - * the preview buf is assumed to be gray despite the number of - * channels it contains - */ - color = ((channel == -1) && - (temp_buf->bytes == 3 || temp_buf->bytes == 4)); + color = (temp_buf->bytes == 3 || temp_buf->bytes == 4); + has_alpha = (temp_buf->bytes == 2 || temp_buf->bytes == 4); + render_composite = (channel == -1); + rowstride = temp_buf->width * temp_buf->bytes; /* render the checkerboard only if the temp_buf has alpha *and* - * we render a composite preview (channel == -1) + * we render a composite preview */ - if (has_alpha && (channel == -1)) + if (has_alpha && render_composite) + buf = render_check_buf; + else + buf = render_empty_buf; + + if (render_composite) { - buf = render_check_buf; - render_composite = TRUE; - alpha = ((color) ? ALPHA_PIX : - ((channel != -1) ? (temp_buf->bytes - 1) : - ALPHA_G_PIX)); + if (color) + { + red_component = RED_PIX; + green_component = GREEN_PIX; + blue_component = BLUE_PIX; + alpha_component = ALPHA_PIX; + } + else + { + red_component = GRAY_PIX; + green_component = GRAY_PIX; + blue_component = GRAY_PIX; + alpha_component = ALPHA_G_PIX; + } } else { - buf = render_empty_buf; - render_composite = FALSE; + red_component = channel; + green_component = channel; + blue_component = channel; + alpha_component = 0; } x1 = CLAMP (temp_buf->x, 0, width); @@ -1089,27 +1114,23 @@ gimp_preview_render_and_flush (GimpPreview *preview, src = temp_buf_data (temp_buf) + ((y1 - temp_buf->y) * rowstride + (x1 - temp_buf->x) * temp_buf->bytes); - /* One last thing for efficiency's sake: */ - if (channel == -1) - channel = 0; - /* Set the border color once before rendering */ for (j = 0; j < width + border * 2; j++) - for (b = 0; b < image_bytes; b++) - render_temp_buf[j * image_bytes + b] = border_color[b]; + for (b = 0; b < PREVIEW_BYTES; b++) + render_temp_buf[j * PREVIEW_BYTES + b] = border_color[b]; for (i = 0; i < border; i++) { memcpy (preview->buffer + i * preview->rowstride, render_temp_buf, - (width + 2 * border) * image_bytes); + (width + 2 * border) * PREVIEW_BYTES); } for (i = border + height; i < 2 * border + height; i++) { memcpy (preview->buffer + i * preview->rowstride, render_temp_buf, - (width + 2 * border) * image_bytes); + (width + 2 * border) * PREVIEW_BYTES); } for (i = 0; i < height; i++) @@ -1132,106 +1153,64 @@ gimp_preview_render_and_flush (GimpPreview *preview, { /* Handle the leading transparency */ for (j = 0; j < x1; j++) - for (b = 0; b < image_bytes; b++) - render_temp_buf[(border + j) * image_bytes + b] = cb[j * 3 + b]; + for (b = 0; b < PREVIEW_BYTES; b++) + render_temp_buf[(border + j) * PREVIEW_BYTES + b] = cb[j * 3 + b]; /* The stuff in the middle */ s = src; for (j = x1; j < x2; j++) { - if (color) - { - if (has_alpha && render_composite) - { - a = s[alpha] << 8; + if (has_alpha && render_composite) + { + a = s[alpha_component] << 8; - if ((j + offset) & 0x4) - { - render_temp_buf[(border + j) * 3 + 0] = - render_blend_dark_check [(a | s[RED_PIX])]; - render_temp_buf[(border + j) * 3 + 1] = - render_blend_dark_check [(a | s[GREEN_PIX])]; - render_temp_buf[(border + j) * 3 + 2] = - render_blend_dark_check [(a | s[BLUE_PIX])]; - } - else - { - render_temp_buf[(border + j) * 3 + 0] = - render_blend_light_check [(a | s[RED_PIX])]; - render_temp_buf[(border + j) * 3 + 1] = - render_blend_light_check [(a | s[GREEN_PIX])]; - render_temp_buf[(border + j) * 3 + 2] = - render_blend_light_check [(a | s[BLUE_PIX])]; - } - } - else - { - render_temp_buf[(border + j) * 3 + 0] = s[RED_PIX]; - render_temp_buf[(border + j) * 3 + 1] = s[GREEN_PIX]; - render_temp_buf[(border + j) * 3 + 2] = s[BLUE_PIX]; - } - } - else - { - if (has_alpha && render_composite) - { - a = s[alpha] << 8; - - if ((j + offset) & 0x4) - { - render_temp_buf[(border + j) * 3 + 0] = - render_blend_dark_check [(a | s[GRAY_PIX])]; - render_temp_buf[(border + j) * 3 + 1] = - render_blend_dark_check [(a | s[GRAY_PIX])]; - render_temp_buf[(border + j) * 3 + 2] = - render_blend_dark_check [(a | s[GRAY_PIX])]; - } - else - { - render_temp_buf[(border + j) * 3 + 0] = - render_blend_light_check [(a | s[GRAY_PIX])]; - render_temp_buf[(border + j) * 3 + 1] = - render_blend_light_check [(a | s[GRAY_PIX])]; - render_temp_buf[(border + j) * 3 + 2] = - render_blend_light_check [(a | s[GRAY_PIX])]; - } - } - else - { - render_temp_buf[(border + j) * 3 + 0] = s[GRAY_PIX]; - render_temp_buf[(border + j) * 3 + 1] = s[GRAY_PIX]; - render_temp_buf[(border + j) * 3 + 2] = s[GRAY_PIX]; - } - } + if ((j + offset) & 0x4) + { + render_temp_buf[(border + j) * 3 + 0] = + render_blend_dark_check [(a | s[red_component])]; + render_temp_buf[(border + j) * 3 + 1] = + render_blend_dark_check [(a | s[green_component])]; + render_temp_buf[(border + j) * 3 + 2] = + render_blend_dark_check [(a | s[blue_component])]; + } + else + { + render_temp_buf[(border + j) * 3 + 0] = + render_blend_light_check [(a | s[red_component])]; + render_temp_buf[(border + j) * 3 + 1] = + render_blend_light_check [(a | s[green_component])]; + render_temp_buf[(border + j) * 3 + 2] = + render_blend_light_check [(a | s[blue_component])]; + } + } + else + { + render_temp_buf[(border + j) * 3 + 0] = s[red_component]; + render_temp_buf[(border + j) * 3 + 1] = s[green_component]; + render_temp_buf[(border + j) * 3 + 2] = s[blue_component]; + } s += temp_buf->bytes; } /* Handle the trailing transparency */ for (j = x2; j < width; j++) - for (b = 0; b < image_bytes; b++) - render_temp_buf[(border + j) * image_bytes + b] = cb[j * 3 + b]; + for (b = 0; b < PREVIEW_BYTES; b++) + render_temp_buf[(border + j) * PREVIEW_BYTES + b] = cb[j * 3 + b]; src += rowstride; } else { for (j = 0; j < width; j++) - for (b = 0; b < image_bytes; b++) - render_temp_buf[(border + j) * image_bytes + b] = cb[j * 3 + b]; + for (b = 0; b < PREVIEW_BYTES; b++) + render_temp_buf[(border + j) * PREVIEW_BYTES + b] = cb[j * 3 + b]; } memcpy (preview->buffer + (i + border) * preview->rowstride, render_temp_buf, - (width + 2 * border) * image_bytes); + (width + 2 * border) * PREVIEW_BYTES); } gtk_widget_queue_draw (GTK_WIDGET (preview)); } - -static GimpViewable * -gimp_preview_drag_viewable (GtkWidget *widget, - gpointer data) -{ - return GIMP_PREVIEW (widget)->viewable; -} diff --git a/app/widgets/gimpviewrenderer.c b/app/widgets/gimpviewrenderer.c index 0071d9780f..cb4668ac81 100644 --- a/app/widgets/gimpviewrenderer.c +++ b/app/widgets/gimpviewrenderer.c @@ -60,6 +60,8 @@ #include "gimptoolinfopreview.h" +#define PREVIEW_BYTES 3 + #define PREVIEW_POPUP_DELAY 150 #define PREVIEW_EVENT_MASK (GDK_BUTTON_PRESS_MASK | \ @@ -84,7 +86,7 @@ static void gimp_preview_init (GimpPreview *preview) static void gimp_preview_destroy (GtkObject *object); static void gimp_preview_size_allocate (GtkWidget *widget, GtkAllocation *allocation); -static gboolean gimp_preview_expose (GtkWidget *widget, +static gboolean gimp_preview_expose_event (GtkWidget *widget, GdkEventExpose *event); static gboolean gimp_preview_button_press_event (GtkWidget *widget, GdkEventButton *bevent); @@ -113,6 +115,8 @@ static void gimp_preview_popup_show (GimpPreview *preview, gint x, gint y); static void gimp_preview_popup_hide (GimpPreview *preview); +static gboolean gimp_preview_popup_timeout (GimpPreview *preview); + static void gimp_preview_size_changed (GimpPreview *preview, GimpViewable *viewable); static void gimp_preview_paint (GimpPreview *preview); @@ -205,7 +209,7 @@ gimp_preview_class_init (GimpPreviewClass *klass) object_class->destroy = gimp_preview_destroy; widget_class->size_allocate = gimp_preview_size_allocate; - widget_class->expose_event = gimp_preview_expose; + widget_class->expose_event = gimp_preview_expose_event; widget_class->button_press_event = gimp_preview_button_press_event; widget_class->button_release_event = gimp_preview_button_release_event; widget_class->enter_notify_event = gimp_preview_enter_notify_event; @@ -272,55 +276,263 @@ gimp_preview_destroy (GtkObject *object) GTK_OBJECT_CLASS (parent_class)->destroy (object); } -static GimpPreview * -gimp_preview_new_by_type (GimpViewable *viewable) +static void +gimp_preview_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) { GimpPreview *preview; - if (GIMP_IS_BRUSH (viewable)) + preview = GIMP_PREVIEW (widget); + + allocation->width = preview->width + 2 * preview->border_width; + allocation->height = preview->height + 2 * preview->border_width; + + if (GTK_WIDGET_CLASS (parent_class)->size_allocate) + GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation); + + gimp_preview_paint (GIMP_PREVIEW (widget)); +} + +static gboolean +gimp_preview_expose_event (GtkWidget *widget, + GdkEventExpose *event) +{ + GimpPreview *preview; + guchar *buf; + GdkRectangle buf_rect = { 0, 0, 0, 0 }; + GdkRectangle render_rect; + + preview = GIMP_PREVIEW (widget); + + if (! GTK_WIDGET_DRAWABLE (widget) || ! preview->buffer) + return FALSE; + + buf_rect.width = preview->width + 2 * preview->border_width; + buf_rect.height = preview->height + 2 * preview->border_width; + + if (widget->allocation.width > buf_rect.width) + buf_rect.x = (widget->allocation.width - buf_rect.width) / 2; + + if (widget->allocation.height >buf_rect.height) + buf_rect.y = (widget->allocation.height - buf_rect.height) / 2; + + if (gdk_rectangle_intersect (&event->area, &buf_rect, &render_rect)) { - preview = g_object_new (GIMP_TYPE_BRUSH_PREVIEW, NULL); + buf = (preview->buffer + + (render_rect.y - buf_rect.y) * preview->rowstride + + (render_rect.x - buf_rect.x) * PREVIEW_BYTES); + + gdk_draw_rgb_image_dithalign (widget->window, + widget->style->black_gc, + render_rect.x, + render_rect.y, + render_rect.width, + render_rect.height, + GDK_RGB_DITHER_NORMAL, + buf, + preview->rowstride, + event->area.x, + event->area.y); } - else if (GIMP_IS_DRAWABLE (viewable)) + + return FALSE; +} + +static gint +gimp_preview_button_press_event (GtkWidget *widget, + GdkEventButton *bevent) +{ + GimpPreview *preview; + + preview = GIMP_PREVIEW (widget); + +#define DEBUG_MEMSIZE 1 + +#ifdef DEBUG_MEMSIZE + if (bevent->type == GDK_BUTTON_PRESS && bevent->button == 2) { - preview = g_object_new (GIMP_TYPE_DRAWABLE_PREVIEW, NULL); + gimp_object_get_memsize (GIMP_OBJECT (preview->viewable)); } - else if (GIMP_IS_IMAGE (viewable)) +#endif /* DEBUG_MEMSIZE */ + + if (! preview->clickable && + ! preview->show_popup) + return FALSE; + + if (bevent->type == GDK_BUTTON_PRESS) { - preview = g_object_new (GIMP_TYPE_IMAGE_PREVIEW, NULL); + if (bevent->button == 1) + { + gtk_grab_add (widget); + + preview->press_state = bevent->state; + + if (preview->show_popup && gimp_preview_needs_popup (preview)) + { + gimp_preview_popup_show (preview, + bevent->x, + bevent->y); + } + } + else + { + preview->press_state = 0; + + if (bevent->button == 3) + { + g_signal_emit (G_OBJECT (widget), preview_signals[CONTEXT], 0); + } + else + { + return FALSE; + } + } } - else if (GIMP_IS_PATTERN (viewable)) + else if (bevent->type == GDK_2BUTTON_PRESS) { - preview = g_object_new (GIMP_TYPE_PATTERN_PREVIEW, NULL); + if (bevent->button == 1) + { + g_signal_emit (G_OBJECT (widget), preview_signals[DOUBLE_CLICKED], 0); + } } - else if (GIMP_IS_GRADIENT (viewable)) + + return TRUE; +} + +static gint +gimp_preview_button_release_event (GtkWidget *widget, + GdkEventButton *bevent) +{ + GimpPreview *preview; + gboolean click = TRUE; + + preview = GIMP_PREVIEW (widget); + + if (! preview->clickable && + ! preview->show_popup) + return FALSE; + + if (bevent->button == 1) { - preview = g_object_new (GIMP_TYPE_GRADIENT_PREVIEW, NULL); - } - else if (GIMP_IS_PALETTE (viewable)) - { - preview = g_object_new (GIMP_TYPE_PALETTE_PREVIEW, NULL); - } - else if (GIMP_IS_BUFFER (viewable)) - { - preview = g_object_new (GIMP_TYPE_BUFFER_PREVIEW, NULL); - } - else if (GIMP_IS_TOOL_INFO (viewable)) - { - preview = g_object_new (GIMP_TYPE_TOOL_INFO_PREVIEW, NULL); - } - else if (GIMP_IS_IMAGEFILE (viewable)) - { - preview = g_object_new (GIMP_TYPE_IMAGEFILE_PREVIEW, NULL); + if (preview->show_popup && gimp_preview_needs_popup (preview)) + { + click = (preview->popup_id != 0); + } + + gimp_preview_popup_hide (preview); + + /* remove the grab _after_ hiding the popup */ + gtk_grab_remove (widget); + + if (preview->clickable && click && preview->in_button) + { + if (preview->press_state & + (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK)) + { + g_signal_emit (G_OBJECT (widget), + preview_signals[EXTENDED_CLICKED], 0, + preview->press_state); + } + else + { + g_signal_emit (G_OBJECT (widget), preview_signals[CLICKED], 0); + } + } } else { - preview = g_object_new (GIMP_TYPE_PREVIEW, NULL); + return FALSE; } - return preview; + return TRUE; } +static gint +gimp_preview_enter_notify_event (GtkWidget *widget, + GdkEventCrossing *event) +{ + GimpPreview *preview; + GtkWidget *event_widget; + + preview = GIMP_PREVIEW (widget); + event_widget = gtk_get_event_widget ((GdkEvent *) event); + + if ((event_widget == widget) && + (event->detail != GDK_NOTIFY_INFERIOR)) + { + preview->in_button = TRUE; + } + + return FALSE; +} + +static gint +gimp_preview_leave_notify_event (GtkWidget *widget, + GdkEventCrossing *event) +{ + GimpPreview *preview; + GtkWidget *event_widget; + + preview = GIMP_PREVIEW (widget); + event_widget = gtk_get_event_widget ((GdkEvent *) event); + + if ((event_widget == widget) && + (event->detail != GDK_NOTIFY_INFERIOR)) + { + preview->in_button = FALSE; + } + + return FALSE; +} + +static GimpPreview * +gimp_preview_new_by_type (GimpViewable *viewable) +{ + GType type = GIMP_TYPE_PREVIEW; + + if (GIMP_IS_BRUSH (viewable)) + { + type = GIMP_TYPE_BRUSH_PREVIEW; + } + else if (GIMP_IS_DRAWABLE (viewable)) + { + type = GIMP_TYPE_DRAWABLE_PREVIEW; + } + else if (GIMP_IS_IMAGE (viewable)) + { + type = GIMP_TYPE_IMAGE_PREVIEW; + } + else if (GIMP_IS_PATTERN (viewable)) + { + type = GIMP_TYPE_PATTERN_PREVIEW; + } + else if (GIMP_IS_GRADIENT (viewable)) + { + type = GIMP_TYPE_GRADIENT_PREVIEW; + } + else if (GIMP_IS_PALETTE (viewable)) + { + type = GIMP_TYPE_PALETTE_PREVIEW; + } + else if (GIMP_IS_BUFFER (viewable)) + { + type = GIMP_TYPE_BUFFER_PREVIEW; + } + else if (GIMP_IS_TOOL_INFO (viewable)) + { + type = GIMP_TYPE_TOOL_INFO_PREVIEW; + } + else if (GIMP_IS_IMAGEFILE (viewable)) + { + type = GIMP_TYPE_IMAGEFILE_PREVIEW; + } + + return g_object_new (type, NULL); +} + + +/* public functions */ + GtkWidget * gimp_preview_new (GimpViewable *viewable, gint size, @@ -485,7 +697,7 @@ gimp_preview_set_size_full (GimpPreview *preview, GTK_WIDGET (preview)->requisition.height = height + 2 * border_width; preview->rowstride = - ((preview->width + 2 * preview->border_width) * 3 + 3) & ~3; + ((preview->width + 2 * preview->border_width) * PREVIEW_BYTES + 3) & ~3; if (preview->buffer) { @@ -541,152 +753,8 @@ gimp_preview_render (GimpPreview *preview) GIMP_PREVIEW_GET_CLASS (preview)->render (preview); } -static gint -gimp_preview_button_press_event (GtkWidget *widget, - GdkEventButton *bevent) -{ - GimpPreview *preview; - preview = GIMP_PREVIEW (widget); - -#define DEBUG_MEMSIZE 1 - -#ifdef DEBUG_MEMSIZE - if (bevent->type == GDK_BUTTON_PRESS && bevent->button == 2) - { - gimp_object_get_memsize (GIMP_OBJECT (preview->viewable)); - } -#endif /* DEBUG_MEMSIZE */ - - if (! preview->clickable && - ! preview->show_popup) - return FALSE; - - if (bevent->type == GDK_BUTTON_PRESS) - { - if (bevent->button == 1) - { - gtk_grab_add (widget); - - preview->press_state = bevent->state; - - if (preview->show_popup && gimp_preview_needs_popup (preview)) - { - gimp_preview_popup_show (preview, - bevent->x, - bevent->y); - } - } - else - { - preview->press_state = 0; - - if (bevent->button == 3) - { - g_signal_emit (G_OBJECT (widget), preview_signals[CONTEXT], 0); - } - else - { - return FALSE; - } - } - } - else if (bevent->type == GDK_2BUTTON_PRESS) - { - if (bevent->button == 1) - { - g_signal_emit (G_OBJECT (widget), preview_signals[DOUBLE_CLICKED], 0); - } - } - - return TRUE; -} - -static gint -gimp_preview_button_release_event (GtkWidget *widget, - GdkEventButton *bevent) -{ - GimpPreview *preview; - gboolean click = TRUE; - - preview = GIMP_PREVIEW (widget); - - if (! preview->clickable && - ! preview->show_popup) - return FALSE; - - if (bevent->button == 1) - { - if (preview->show_popup && gimp_preview_needs_popup (preview)) - { - click = (preview->popup_id != 0); - } - - gimp_preview_popup_hide (preview); - - /* remove the grab _after_ hiding the popup */ - gtk_grab_remove (widget); - - if (preview->clickable && click && preview->in_button) - { - if (preview->press_state & - (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK)) - { - g_signal_emit (G_OBJECT (widget), - preview_signals[EXTENDED_CLICKED], 0, - preview->press_state); - } - else - { - g_signal_emit (G_OBJECT (widget), preview_signals[CLICKED], 0); - } - } - } - else - { - return FALSE; - } - - return TRUE; -} - -static gint -gimp_preview_enter_notify_event (GtkWidget *widget, - GdkEventCrossing *event) -{ - GimpPreview *preview; - GtkWidget *event_widget; - - preview = GIMP_PREVIEW (widget); - event_widget = gtk_get_event_widget ((GdkEvent *) event); - - if ((event_widget == widget) && - (event->detail != GDK_NOTIFY_INFERIOR)) - { - preview->in_button = TRUE; - } - - return FALSE; -} - -static gint -gimp_preview_leave_notify_event (GtkWidget *widget, - GdkEventCrossing *event) -{ - GimpPreview *preview; - GtkWidget *event_widget; - - preview = GIMP_PREVIEW (widget); - event_widget = gtk_get_event_widget ((GdkEvent *) event); - - if ((event_widget == widget) && - (event->detail != GDK_NOTIFY_INFERIOR)) - { - preview->in_button = FALSE; - } - - return FALSE; -} +/* private functions */ static void gimp_preview_real_render (GimpPreview *preview) @@ -766,6 +834,34 @@ gimp_preview_real_create_popup (GimpPreview *preview) TRUE, FALSE, FALSE); } +static void +gimp_preview_popup_show (GimpPreview *preview, + gint x, + gint y) +{ + preview->popup_x = x; + preview->popup_y = y; + + preview->popup_id = g_timeout_add (PREVIEW_POPUP_DELAY, + (GSourceFunc) gimp_preview_popup_timeout, + preview); +} + +static void +gimp_preview_popup_hide (GimpPreview *preview) +{ + if (preview->popup_id) + { + g_source_remove (preview->popup_id); + + preview->popup_id = 0; + preview->popup_x = 0; + preview->popup_y = 0; + } + + g_object_set_data (G_OBJECT (preview), "gimp-preview-popup", NULL); +} + static gboolean gimp_preview_popup_timeout (GimpPreview *preview) { @@ -820,102 +916,12 @@ gimp_preview_popup_timeout (GimpPreview *preview) gtk_window_move (GTK_WINDOW (window), x, y); gtk_widget_show (window); - g_object_set_data_full (G_OBJECT (preview), "preview_popup_window", window, + g_object_set_data_full (G_OBJECT (preview), "gimp-preview-popup", window, (GDestroyNotify) gtk_widget_destroy); return FALSE; } -static void -gimp_preview_popup_show (GimpPreview *preview, - gint x, - gint y) -{ - preview->popup_x = x; - preview->popup_y = y; - - preview->popup_id = g_timeout_add (PREVIEW_POPUP_DELAY, - (GSourceFunc) gimp_preview_popup_timeout, - preview); -} - -static void -gimp_preview_popup_hide (GimpPreview *preview) -{ - if (preview->popup_id) - { - g_source_remove (preview->popup_id); - - preview->popup_id = 0; - preview->popup_x = 0; - preview->popup_y = 0; - } - - g_object_set_data (G_OBJECT (preview), "preview_popup_window", NULL); -} - -static void -gimp_preview_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - GimpPreview *preview; - - preview = GIMP_PREVIEW (widget); - - allocation->width = preview->width + 2 * preview->border_width; - allocation->height = preview->height + 2 * preview->border_width; - - if (GTK_WIDGET_CLASS (parent_class)->size_allocate) - GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation); - - gimp_preview_paint (GIMP_PREVIEW (widget)); -} - -static gboolean -gimp_preview_expose (GtkWidget *widget, - GdkEventExpose *event) -{ - GimpPreview *preview; - guchar *buf; - GdkRectangle buf_rect = { 0, 0, 0, 0 }; - GdkRectangle render_rect; - - preview = GIMP_PREVIEW (widget); - - if (! GTK_WIDGET_DRAWABLE (widget) || ! preview->buffer) - return FALSE; - - buf_rect.width = preview->width + 2 * preview->border_width; - buf_rect.height = preview->height + 2 * preview->border_width; - - if (widget->allocation.width > buf_rect.width) - buf_rect.x = (widget->allocation.width - buf_rect.width) / 2; - - if (widget->allocation.height >buf_rect.height) - buf_rect.y = (widget->allocation.height - buf_rect.height) / 2; - - if (gdk_rectangle_intersect (&event->area, &buf_rect, &render_rect)) - { - buf = (preview->buffer + - (render_rect.y - buf_rect.y) * preview->rowstride + - (render_rect.x - buf_rect.x) * 3); - - gdk_draw_rgb_image_dithalign (widget->window, - widget->style->black_gc, - render_rect.x, - render_rect.y, - render_rect.width, - render_rect.height, - GDK_RGB_DITHER_NORMAL, - buf, - preview->rowstride, - event->area.x, - event->area.y); - } - - return FALSE; -} - static void gimp_preview_size_changed (GimpPreview *preview, GimpViewable *viewable) @@ -957,6 +963,16 @@ gimp_preview_idle_paint (GimpPreview *preview) return FALSE; } +static GimpViewable * +gimp_preview_drag_viewable (GtkWidget *widget, + gpointer data) +{ + return GIMP_PREVIEW (widget)->viewable; +} + + +/* protected functions */ + void gimp_preview_calc_size (GimpPreview *preview, gint aspect_width, @@ -1014,13 +1030,15 @@ gimp_preview_render_and_flush (GimpPreview *preview, gint x1, y1, x2, y2; gint rowstride; gboolean color; - gint alpha; gboolean has_alpha; gboolean render_composite; - gint image_bytes; + gint red_component; + gint green_component; + gint blue_component; + gint alpha_component; gint offset; gint border; - guchar border_color[3]; + guchar border_color[PREVIEW_BYTES]; width = preview->width; height = preview->height; @@ -1038,8 +1056,6 @@ gimp_preview_render_and_flush (GimpPreview *preview, &border_color[1], &border_color[2]); - alpha = ALPHA_PIX; - /* Here are the different cases this functions handles correctly: * 1) Offset temp_buf which does not necessarily cover full image area * 2) Color conversion of temp_buf if it is gray and image is color @@ -1051,34 +1067,43 @@ gimp_preview_render_and_flush (GimpPreview *preview, * 2) Color temp_bufs have bytes == {3, 4} * 3) If image is gray, then temp_buf should have bytes == {1, 2} */ - image_bytes = 3; - has_alpha = (temp_buf->bytes == 2 || temp_buf->bytes == 4); - rowstride = temp_buf->width * temp_buf->bytes; - /* Determine if the preview buf supplied is color - * Generally, if the bytes == {3, 4}, this is true. - * However, if the channel argument supplied is not -1, then - * the preview buf is assumed to be gray despite the number of - * channels it contains - */ - color = ((channel == -1) && - (temp_buf->bytes == 3 || temp_buf->bytes == 4)); + color = (temp_buf->bytes == 3 || temp_buf->bytes == 4); + has_alpha = (temp_buf->bytes == 2 || temp_buf->bytes == 4); + render_composite = (channel == -1); + rowstride = temp_buf->width * temp_buf->bytes; /* render the checkerboard only if the temp_buf has alpha *and* - * we render a composite preview (channel == -1) + * we render a composite preview */ - if (has_alpha && (channel == -1)) + if (has_alpha && render_composite) + buf = render_check_buf; + else + buf = render_empty_buf; + + if (render_composite) { - buf = render_check_buf; - render_composite = TRUE; - alpha = ((color) ? ALPHA_PIX : - ((channel != -1) ? (temp_buf->bytes - 1) : - ALPHA_G_PIX)); + if (color) + { + red_component = RED_PIX; + green_component = GREEN_PIX; + blue_component = BLUE_PIX; + alpha_component = ALPHA_PIX; + } + else + { + red_component = GRAY_PIX; + green_component = GRAY_PIX; + blue_component = GRAY_PIX; + alpha_component = ALPHA_G_PIX; + } } else { - buf = render_empty_buf; - render_composite = FALSE; + red_component = channel; + green_component = channel; + blue_component = channel; + alpha_component = 0; } x1 = CLAMP (temp_buf->x, 0, width); @@ -1089,27 +1114,23 @@ gimp_preview_render_and_flush (GimpPreview *preview, src = temp_buf_data (temp_buf) + ((y1 - temp_buf->y) * rowstride + (x1 - temp_buf->x) * temp_buf->bytes); - /* One last thing for efficiency's sake: */ - if (channel == -1) - channel = 0; - /* Set the border color once before rendering */ for (j = 0; j < width + border * 2; j++) - for (b = 0; b < image_bytes; b++) - render_temp_buf[j * image_bytes + b] = border_color[b]; + for (b = 0; b < PREVIEW_BYTES; b++) + render_temp_buf[j * PREVIEW_BYTES + b] = border_color[b]; for (i = 0; i < border; i++) { memcpy (preview->buffer + i * preview->rowstride, render_temp_buf, - (width + 2 * border) * image_bytes); + (width + 2 * border) * PREVIEW_BYTES); } for (i = border + height; i < 2 * border + height; i++) { memcpy (preview->buffer + i * preview->rowstride, render_temp_buf, - (width + 2 * border) * image_bytes); + (width + 2 * border) * PREVIEW_BYTES); } for (i = 0; i < height; i++) @@ -1132,106 +1153,64 @@ gimp_preview_render_and_flush (GimpPreview *preview, { /* Handle the leading transparency */ for (j = 0; j < x1; j++) - for (b = 0; b < image_bytes; b++) - render_temp_buf[(border + j) * image_bytes + b] = cb[j * 3 + b]; + for (b = 0; b < PREVIEW_BYTES; b++) + render_temp_buf[(border + j) * PREVIEW_BYTES + b] = cb[j * 3 + b]; /* The stuff in the middle */ s = src; for (j = x1; j < x2; j++) { - if (color) - { - if (has_alpha && render_composite) - { - a = s[alpha] << 8; + if (has_alpha && render_composite) + { + a = s[alpha_component] << 8; - if ((j + offset) & 0x4) - { - render_temp_buf[(border + j) * 3 + 0] = - render_blend_dark_check [(a | s[RED_PIX])]; - render_temp_buf[(border + j) * 3 + 1] = - render_blend_dark_check [(a | s[GREEN_PIX])]; - render_temp_buf[(border + j) * 3 + 2] = - render_blend_dark_check [(a | s[BLUE_PIX])]; - } - else - { - render_temp_buf[(border + j) * 3 + 0] = - render_blend_light_check [(a | s[RED_PIX])]; - render_temp_buf[(border + j) * 3 + 1] = - render_blend_light_check [(a | s[GREEN_PIX])]; - render_temp_buf[(border + j) * 3 + 2] = - render_blend_light_check [(a | s[BLUE_PIX])]; - } - } - else - { - render_temp_buf[(border + j) * 3 + 0] = s[RED_PIX]; - render_temp_buf[(border + j) * 3 + 1] = s[GREEN_PIX]; - render_temp_buf[(border + j) * 3 + 2] = s[BLUE_PIX]; - } - } - else - { - if (has_alpha && render_composite) - { - a = s[alpha] << 8; - - if ((j + offset) & 0x4) - { - render_temp_buf[(border + j) * 3 + 0] = - render_blend_dark_check [(a | s[GRAY_PIX])]; - render_temp_buf[(border + j) * 3 + 1] = - render_blend_dark_check [(a | s[GRAY_PIX])]; - render_temp_buf[(border + j) * 3 + 2] = - render_blend_dark_check [(a | s[GRAY_PIX])]; - } - else - { - render_temp_buf[(border + j) * 3 + 0] = - render_blend_light_check [(a | s[GRAY_PIX])]; - render_temp_buf[(border + j) * 3 + 1] = - render_blend_light_check [(a | s[GRAY_PIX])]; - render_temp_buf[(border + j) * 3 + 2] = - render_blend_light_check [(a | s[GRAY_PIX])]; - } - } - else - { - render_temp_buf[(border + j) * 3 + 0] = s[GRAY_PIX]; - render_temp_buf[(border + j) * 3 + 1] = s[GRAY_PIX]; - render_temp_buf[(border + j) * 3 + 2] = s[GRAY_PIX]; - } - } + if ((j + offset) & 0x4) + { + render_temp_buf[(border + j) * 3 + 0] = + render_blend_dark_check [(a | s[red_component])]; + render_temp_buf[(border + j) * 3 + 1] = + render_blend_dark_check [(a | s[green_component])]; + render_temp_buf[(border + j) * 3 + 2] = + render_blend_dark_check [(a | s[blue_component])]; + } + else + { + render_temp_buf[(border + j) * 3 + 0] = + render_blend_light_check [(a | s[red_component])]; + render_temp_buf[(border + j) * 3 + 1] = + render_blend_light_check [(a | s[green_component])]; + render_temp_buf[(border + j) * 3 + 2] = + render_blend_light_check [(a | s[blue_component])]; + } + } + else + { + render_temp_buf[(border + j) * 3 + 0] = s[red_component]; + render_temp_buf[(border + j) * 3 + 1] = s[green_component]; + render_temp_buf[(border + j) * 3 + 2] = s[blue_component]; + } s += temp_buf->bytes; } /* Handle the trailing transparency */ for (j = x2; j < width; j++) - for (b = 0; b < image_bytes; b++) - render_temp_buf[(border + j) * image_bytes + b] = cb[j * 3 + b]; + for (b = 0; b < PREVIEW_BYTES; b++) + render_temp_buf[(border + j) * PREVIEW_BYTES + b] = cb[j * 3 + b]; src += rowstride; } else { for (j = 0; j < width; j++) - for (b = 0; b < image_bytes; b++) - render_temp_buf[(border + j) * image_bytes + b] = cb[j * 3 + b]; + for (b = 0; b < PREVIEW_BYTES; b++) + render_temp_buf[(border + j) * PREVIEW_BYTES + b] = cb[j * 3 + b]; } memcpy (preview->buffer + (i + border) * preview->rowstride, render_temp_buf, - (width + 2 * border) * image_bytes); + (width + 2 * border) * PREVIEW_BYTES); } gtk_widget_queue_draw (GTK_WIDGET (preview)); } - -static GimpViewable * -gimp_preview_drag_viewable (GtkWidget *widget, - gpointer data) -{ - return GIMP_PREVIEW (widget)->viewable; -}