static void gimp_item_prop_undo_constructed (GObject *object) { GimpItemPropUndo *item_prop_undo = GIMP_ITEM_PROP_UNDO (object); GimpItem *item; G_OBJECT_CLASS (parent_class)->constructed (object); item = GIMP_ITEM_UNDO (object)->item; switch (GIMP_UNDO (object)->undo_type) { case GIMP_UNDO_ITEM_REORDER: item_prop_undo->parent = gimp_item_get_parent (item); item_prop_undo->position = gimp_item_get_index (item); break; case GIMP_UNDO_ITEM_RENAME: item_prop_undo->name = g_strdup (gimp_object_get_name (item)); break; case GIMP_UNDO_ITEM_DISPLACE: gimp_item_get_offset (item, &item_prop_undo->offset_x, &item_prop_undo->offset_y); break; case GIMP_UNDO_ITEM_VISIBILITY: item_prop_undo->visible = gimp_item_get_visible (item); break; case GIMP_UNDO_ITEM_LINKED: item_prop_undo->linked = gimp_item_get_linked (item); break; case GIMP_UNDO_ITEM_COLOR_TAG: item_prop_undo->color_tag = gimp_item_get_color_tag (item); break; case GIMP_UNDO_ITEM_LOCK_CONTENT: item_prop_undo->lock_content = gimp_item_get_lock_content (item); break; case GIMP_UNDO_ITEM_LOCK_POSITION: item_prop_undo->lock_position = gimp_item_get_lock_position (item); break; case GIMP_UNDO_PARASITE_ATTACH: case GIMP_UNDO_PARASITE_REMOVE: g_assert (item_prop_undo->parasite_name != NULL); item_prop_undo->parasite = gimp_parasite_copy (gimp_item_parasite_find (item, item_prop_undo->parasite_name)); break; default: g_assert_not_reached (); } }
/* ----------------------------------------------- * gap_image_get_parentpositions_as_int_stringlist * ----------------------------------------------- * returns the list of parent stackpositions as list of integer numbers * separated by the "/" delimiter. * example 2/3/2 * return NULL in case the specified drawable is invalid or has no perent item */ char * gap_image_get_parentpositions_as_int_stringlist(gint32 drawable_id) { char *parentpositions; gint32 l_parent_id; gint32 l_image_id; parentpositions = NULL; l_parent_id = gimp_item_get_parent(drawable_id); if (l_parent_id > 0) { gint l_position; l_image_id = gimp_item_get_image(drawable_id); l_position = gimp_image_get_item_position (l_image_id, l_parent_id); parentpositions = g_strdup_printf("%d", l_position); while(l_parent_id > 0) { l_parent_id = gimp_item_get_parent(l_parent_id); if (l_parent_id > 0) { char *new_parentpositions; l_position = gimp_image_get_item_position (l_image_id, l_parent_id); new_parentpositions = g_strdup_printf("%d/%s" , (int)l_position , parentpositions ); g_free(parentpositions); parentpositions = new_parentpositions; } } } if(gap_debug) { printf("parentpositions_as_int_stringlist: %s\n" , parentpositions == NULL ? "null" : parentpositions ); } return (parentpositions); } /* end gap_image_get_parentpositions_as_int_stringlist */
static PyObject * item_get_parent(PyGimpLayer *self, void *closure) { gint32 id = gimp_item_get_parent(self->ID); if (id == -1) { Py_INCREF(Py_None); return Py_None; } return pygimp_item_new(id); }
/* ----------------------------------------------- * gap_image_get_tree_position_list * ----------------------------------------------- * return a list that represents the stack positions * of the specified item_id (typically a layer) * which contains positions within the image * and within all its parent group layers. * * The 1st element in the stack position list refers to the stackposition * at toplevel of the image. * Note: * The caller shall g_free the returned list * after use by calling: gap_image_gfree_tree_position_list */ GapImageStackPositionsList * gap_image_get_tree_position_list(gint32 item_id) { gint32 l_image_id; gint32 l_curr_item_id; GapImageStackPositionsList *posRootPtr; posRootPtr = NULL; l_image_id = gimp_item_get_image (item_id); if(gap_debug) { printf("gap_image_get_tree_position_list Start image_id: %d\n" , (int)l_image_id ); } if (l_image_id < 0) { return (NULL); } l_curr_item_id = item_id; while(l_curr_item_id > 0) { GapImageStackPositionsList *posPtr; posPtr = g_new(GapImageStackPositionsList, 1); posPtr->stack_position = gimp_image_get_item_position (l_image_id, l_curr_item_id); if(gap_debug) { printf("item_id:%d stack_position: %d name:%s\n" , (int)l_curr_item_id , (int)posPtr->stack_position , gimp_item_get_name(l_curr_item_id) ); } posPtr->next = posRootPtr; posRootPtr = posPtr; l_curr_item_id = gimp_item_get_parent (l_curr_item_id); } return (posRootPtr); } /* end gap_image_get_tree_position_list */
/* ----------------------------- * gap_image_get_the_layer_below * ----------------------------- * returns the id of the layer below the specified layerId * * returns -1 in case there is no layer below the specified layerId * Note that -1 is alse returned * a) in case the specified layerId is not a valid layer (or not attached to an image) * b) in case the specified layerId is on bottom of a layergroup * c) in case the specified layerId is on bottom of the toplevel layerstack */ gint32 gap_image_get_the_layer_below(gint32 layerId) { gint32 lowerLayerId; gint32 l_parent_id; gint l_nlayers; gint32 *l_layers_list; gint l_ii; lowerLayerId = -1; l_parent_id = 0; if (layerId >= 0) { l_parent_id = gimp_item_get_parent(layerId); } if (l_parent_id > 0) { l_layers_list = gimp_item_get_children(l_parent_id, &l_nlayers); } else { /* use toplevel layers list of the image */ l_layers_list = gimp_image_get_layers(gimp_item_get_image(layerId), &l_nlayers); } if (l_layers_list == NULL) { return (-1); } for(l_ii = 0; l_ii < l_nlayers; l_ii++) { if (l_layers_list[l_ii] == layerId) { gint l_pos_below = l_ii + 1; if (l_pos_below < l_nlayers) { lowerLayerId = l_layers_list[l_pos_below]; break; } } } g_free(l_layers_list); return (lowerLayerId); } /* end gap_image_get_the_layer_below */
static void gimp_item_prop_undo_pop (GimpUndo *undo, GimpUndoMode undo_mode, GimpUndoAccumulator *accum) { GimpItemPropUndo *item_prop_undo = GIMP_ITEM_PROP_UNDO (undo); GimpItem *item = GIMP_ITEM_UNDO (undo)->item; GIMP_UNDO_CLASS (parent_class)->pop (undo, undo_mode, accum); switch (undo->undo_type) { case GIMP_UNDO_ITEM_REORDER: { GimpItem *parent; gint position; parent = gimp_item_get_parent (item); position = gimp_item_get_index (item); gimp_item_tree_reorder_item (gimp_item_get_tree (item), item, item_prop_undo->parent, item_prop_undo->position, FALSE, NULL); item_prop_undo->parent = parent; item_prop_undo->position = position; } break; case GIMP_UNDO_ITEM_RENAME: { gchar *name; name = g_strdup (gimp_object_get_name (item)); gimp_item_tree_rename_item (gimp_item_get_tree (item), item, item_prop_undo->name, FALSE, NULL); g_free (item_prop_undo->name); item_prop_undo->name = name; } break; case GIMP_UNDO_ITEM_DISPLACE: { gint offset_x; gint offset_y; gimp_item_get_offset (item, &offset_x, &offset_y); gimp_item_translate (item, item_prop_undo->offset_x - offset_x, item_prop_undo->offset_y - offset_y, FALSE); item_prop_undo->offset_x = offset_x; item_prop_undo->offset_y = offset_y; } break; case GIMP_UNDO_ITEM_VISIBILITY: { gboolean visible; visible = gimp_item_get_visible (item); gimp_item_set_visible (item, item_prop_undo->visible, FALSE); item_prop_undo->visible = visible; } break; case GIMP_UNDO_ITEM_LINKED: { gboolean linked; linked = gimp_item_get_linked (item); gimp_item_set_linked (item, item_prop_undo->linked, FALSE); item_prop_undo->linked = linked; } break; case GIMP_UNDO_ITEM_COLOR_TAG: { GimpColorTag color_tag; color_tag = gimp_item_get_color_tag (item); gimp_item_set_color_tag (item, item_prop_undo->color_tag, FALSE); item_prop_undo->color_tag = color_tag; } break; case GIMP_UNDO_ITEM_LOCK_CONTENT: { gboolean lock_content; lock_content = gimp_item_get_lock_content (item); gimp_item_set_lock_content (item, item_prop_undo->lock_content, FALSE); item_prop_undo->lock_content = lock_content; } break; case GIMP_UNDO_ITEM_LOCK_POSITION: { gboolean lock_position; lock_position = gimp_item_get_lock_position (item); gimp_item_set_lock_position (item, item_prop_undo->lock_position, FALSE); item_prop_undo->lock_position = lock_position; } break; case GIMP_UNDO_PARASITE_ATTACH: case GIMP_UNDO_PARASITE_REMOVE: { GimpParasite *parasite; parasite = item_prop_undo->parasite; item_prop_undo->parasite = gimp_parasite_copy (gimp_item_parasite_find (item, item_prop_undo->parasite_name)); if (parasite) gimp_item_parasite_attach (item, parasite, FALSE); else gimp_item_parasite_detach (item, item_prop_undo->parasite_name, FALSE); if (parasite) gimp_parasite_free (parasite); } break; default: g_assert_not_reached (); } }
static gint32 do_curl_effect (gint32 drawable_id) { gint x = 0; gint y = 0; gboolean color_image; gint x1, y1, k; guint alpha_pos, progress, max_progress; gdouble intensity, alpha; GimpVector2 v, dl, dr; gdouble dl_mag, dr_mag, angle, factor; guchar *pp, *dest, fore_grayval, back_grayval; guchar *gradsamp; GimpPixelRgn dest_rgn; gpointer pr; gint32 curl_layer_id; guchar *grad_samples = NULL; color_image = gimp_drawable_is_rgb (drawable_id); curl_layer = gimp_drawable_get (gimp_layer_new (image_id, _("Curl Layer"), true_sel_width, true_sel_height, color_image ? GIMP_RGBA_IMAGE : GIMP_GRAYA_IMAGE, 100, GIMP_NORMAL_MODE)); curl_layer_id = curl_layer->drawable_id; gimp_image_insert_layer (image_id, curl_layer->drawable_id, gimp_item_get_parent (drawable_id), drawable_position); gimp_drawable_fill (curl_layer->drawable_id, GIMP_FILL_TRANSPARENT); gimp_drawable_offsets (drawable_id, &x1, &y1); gimp_layer_set_offsets (curl_layer->drawable_id, sel_x + x1, sel_y + y1); gimp_tile_cache_ntiles (2 * (curl_layer->width / gimp_tile_width () + 1)); gimp_pixel_rgn_init (&dest_rgn, curl_layer, 0, 0, true_sel_width, true_sel_height, TRUE, TRUE); /* Init shade_under */ gimp_vector2_set (&dl, -sel_width, -sel_height); dl_mag = gimp_vector2_length (&dl); gimp_vector2_set (&dr, -(sel_width - right_tangent.x), -(sel_height - right_tangent.y)); dr_mag = gimp_vector2_length (&dr); alpha = acos (gimp_vector2_inner_product (&dl, &dr) / (dl_mag * dr_mag)); /* Init shade_curl */ fore_grayval = GIMP_RGB_LUMINANCE (fore_color[0], fore_color[1], fore_color[2]) + 0.5; back_grayval = GIMP_RGB_LUMINANCE (back_color[0], back_color[1], back_color[2]) + 0.5; /* Gradient Samples */ switch (curl.colors) { case CURL_COLORS_FG_BG: break; case CURL_COLORS_GRADIENT: grad_samples = get_gradient_samples (curl_layer->drawable_id, FALSE); break; case CURL_COLORS_GRADIENT_REVERSE: grad_samples = get_gradient_samples (curl_layer->drawable_id, TRUE); break; } max_progress = 2 * sel_width * sel_height; progress = 0; alpha_pos = dest_rgn.bpp - 1; /* Main loop */ for (pr = gimp_pixel_rgns_register (1, &dest_rgn); pr != NULL; pr = gimp_pixel_rgns_process (pr)) { dest = dest_rgn.data; for (y1 = dest_rgn.y; y1 < dest_rgn.y + dest_rgn.h; y1++) { pp = dest; for (x1 = dest_rgn.x; x1 < dest_rgn.x + dest_rgn.w; x1++) { /* Map coordinates to get the curl correct... */ switch (curl.orientation) { case CURL_ORIENTATION_VERTICAL: x = CURL_EDGE_RIGHT (curl.edge) ? x1 : sel_width - 1 - x1; y = CURL_EDGE_UPPER (curl.edge) ? y1 : sel_height - 1 - y1; break; case CURL_ORIENTATION_HORIZONTAL: x = CURL_EDGE_LOWER (curl.edge) ? y1 : sel_width - 1 - y1; y = CURL_EDGE_LEFT (curl.edge) ? x1 : sel_height - 1 - x1; break; } if (left_of_diagl (x, y)) { /* uncurled region */ for (k = 0; k <= alpha_pos; k++) pp[k] = 0; } else if (right_of_diagr (x, y) || (right_of_diagm (x, y) && below_diagb (x, y) && !inside_circle (x, y))) { /* curled region */ for (k = 0; k <= alpha_pos; k++) pp[k] = 0; } else { v.x = -(sel_width - x); v.y = -(sel_height - y); angle = acos (gimp_vector2_inner_product (&v, &dl) / (gimp_vector2_length (&v) * dl_mag)); if (inside_circle (x, y) || below_diagb (x, y)) { /* Below the curl. */ factor = angle / alpha; for (k = 0; k < alpha_pos; k++) pp[k] = 0; pp[alpha_pos] = (curl.shade ? (guchar) ((float) 255 * (float) factor) : 0); } else { /* On the curl */ switch (curl.colors) { case CURL_COLORS_FG_BG: intensity = pow (sin (G_PI * angle / alpha), 1.5); if (color_image) { pp[0] = (intensity * back_color[0] + (1.0 - intensity) * fore_color[0]); pp[1] = (intensity * back_color[1] + (1.0 - intensity) * fore_color[1]); pp[2] = (intensity * back_color[2] + (1.0 - intensity) * fore_color[2]); } else pp[0] = (intensity * back_grayval + (1 - intensity) * fore_grayval); pp[alpha_pos] = (guchar) ((double) 255.99 * (1.0 - intensity * (1.0 - curl.opacity))); break; case CURL_COLORS_GRADIENT: case CURL_COLORS_GRADIENT_REVERSE: /* Calculate position in Gradient */ intensity = (angle/alpha) + sin (G_PI*2 * angle/alpha) * 0.075; /* Check boundaries */ intensity = CLAMP (intensity, 0.0, 1.0); gradsamp = (grad_samples + ((guint) (intensity * NGRADSAMPLES)) * dest_rgn.bpp); if (color_image) { pp[0] = gradsamp[0]; pp[1] = gradsamp[1]; pp[2] = gradsamp[2]; } else pp[0] = gradsamp[0]; pp[alpha_pos] = (guchar) ((double) gradsamp[alpha_pos] * (1.0 - intensity * (1.0 - curl.opacity))); break; } } } pp += dest_rgn.bpp; } dest += dest_rgn.rowstride; } progress += dest_rgn.w * dest_rgn.h; gimp_progress_update ((double) progress / (double) max_progress); } gimp_progress_update (1.0); gimp_drawable_flush (curl_layer); gimp_drawable_merge_shadow (curl_layer->drawable_id, FALSE); gimp_drawable_update (curl_layer->drawable_id, 0, 0, curl_layer->width, curl_layer->height); gimp_drawable_detach (curl_layer); g_free (grad_samples); return curl_layer_id; }
static void dog (gint32 image_ID, GimpDrawable *drawable, gdouble inner, gdouble outer, gboolean show_progress) { GimpDrawable *drawable1; GimpDrawable *drawable2; gint32 drawable_id = drawable->drawable_id; gint32 layer1; gint32 layer2; gint width, height; gint x1, y1, x2, y2; guchar maxval = 255; gimp_drawable_mask_bounds (drawable_id, &x1, &y1, &x2, &y2); width = (x2 - x1); height = (y2 - y1); gimp_drawable_flush (drawable); layer1 = gimp_layer_copy (drawable_id); gimp_item_set_visible (layer1, FALSE); gimp_item_set_name (layer1, "dog_scratch_layer1"); gimp_image_insert_layer (image_ID, layer1, gimp_item_get_parent (drawable_id), 0); layer2 = gimp_layer_copy (drawable_id); gimp_item_set_visible (layer2, FALSE); gimp_item_set_name (layer2, "dog_scratch_layer2"); gimp_image_insert_layer (image_ID, layer2, gimp_item_get_parent (drawable_id), 0); drawable1 = gimp_drawable_get (layer1); drawable2 = gimp_drawable_get (layer2); gauss_rle (drawable1, inner, 0, show_progress); gauss_rle (drawable2, outer, 1, show_progress); compute_difference (drawable, drawable1, drawable2, &maxval); gimp_drawable_detach (drawable1); gimp_drawable_detach (drawable2); gimp_image_remove_layer (image_ID, layer1); gimp_image_remove_layer (image_ID, layer2); gimp_drawable_flush (drawable); gimp_drawable_merge_shadow (drawable_id, TRUE); gimp_drawable_update (drawable_id, x1, y1, width, height); if (dogvals.normalize || dogvals.invert) /* gimp_invert doesn't work properly with previews due to shadow handling * so reimplement it here - see Bug 557380 */ { normalize_invert (drawable, dogvals.normalize, maxval, dogvals.invert); gimp_drawable_flush (drawable); gimp_drawable_merge_shadow (drawable_id, TRUE); gimp_drawable_update (drawable_id, x1, y1, width, height); } }
/* ------------------------------------ * gap_image_merge_group_layer * ------------------------------------ * merge the specified group layer and return the id of the resulting layer. * * The merge strategy * o) create a temporary image of same size/type (l_tmp_img_id) * o) copy the specified grouplayer to the temporary image (l_tmp_img_id) * o) call gimp_image_merge_visible_layers on the temporary image (l_tmp_img_id, mode) * o) copy the merged layer back to the original image * to the same group at the position of the original layergroup * o) remove the temporary image * o) remove original layergroup * o) rename the resuling merged layer. * * returns 0 if all done OK * (or -1 on error) */ gint32 gap_image_merge_group_layer(gint32 image_id, gint32 group_layer_id, gint merge_mode) { gint32 l_tmp_img_id; gint32 l_new_layer_id; gint32 l_merged_layer_id; gint32 l_parent_id; gint32 l_position; gint l_src_offset_x; gint l_src_offset_y; gboolean l_visible; char *l_name; if (!gimp_item_is_group(group_layer_id)) { /* the specified group_layer_id is not a group * -- no merge is done, return its id as result -- */ return(group_layer_id); } l_visible = gimp_item_get_visible(group_layer_id); l_name = gimp_item_get_name(group_layer_id); /* create a temporary image */ l_tmp_img_id = gap_image_new_of_samesize(image_id); /* copy the grouplayer to the temporary image */ l_new_layer_id = gap_layer_copy_to_dest_image(l_tmp_img_id, group_layer_id, 100.0, /* full opacity */ 0, /* NORMAL paintmode */ &l_src_offset_x, &l_src_offset_y ); gimp_image_insert_layer (l_tmp_img_id, l_new_layer_id, 0, 0); gimp_layer_set_offsets(l_new_layer_id, l_src_offset_x, l_src_offset_y); gimp_item_set_visible(l_new_layer_id, TRUE); /* merge visible layers in the temporary image */ l_merged_layer_id = gimp_image_merge_visible_layers (l_tmp_img_id, merge_mode); l_new_layer_id = gap_layer_copy_to_dest_image(image_id, l_merged_layer_id, gimp_layer_get_opacity(group_layer_id), gimp_layer_get_mode(group_layer_id), &l_src_offset_x, &l_src_offset_y ); l_position = gimp_image_get_item_position (image_id, group_layer_id); l_parent_id = gimp_item_get_parent(group_layer_id); if (l_parent_id < 0) { l_parent_id = 0; } gimp_image_insert_layer (image_id, l_new_layer_id, l_parent_id, l_position); gimp_layer_set_offsets(l_new_layer_id, l_src_offset_x, l_src_offset_y); /* remove the original group layer from the original image */ gimp_image_remove_layer(image_id, group_layer_id); /* restore the original layer name */ if (l_name != NULL) { gimp_item_set_name(l_new_layer_id, l_name); g_free(l_name); } gimp_item_set_visible(l_new_layer_id, l_visible); /* remove the temporary image */ gap_image_delete_immediate(l_tmp_img_id); return(l_new_layer_id); } /* end gap_image_merge_group_layer */