1
1
mirror of https://gitlab.gnome.org/GNOME/gimp.git synced 2025-10-06 01:12:40 +02:00

path, tools, pdb: UX updates to vector layers

This patch improves vector layer UX based on feedback.
In summary:
* Makes vector layer editable from the Path tool
* Adds initial PDB for creating vector layers in scripts
* Size vector layers to the path size, rather than image
* Transform tools utilize the path for resizing
* Path tool automatically selects vector layer path
This commit is contained in:
Alx Sa
2025-07-12 21:56:50 -04:00
parent 60ed90e10a
commit a1cd2a2588
62 changed files with 4392 additions and 532 deletions

View File

@@ -33,7 +33,7 @@
#include "text/gimptextlayer.h"
#include "vectors/gimpvectorlayer.h"
#include "path/gimpvectorlayer.h"
#include "widgets/gimphelp-ids.h"
#include "widgets/gimpactiongroup.h"
@@ -999,7 +999,7 @@ layers_actions_update (GimpActionGroup *group,
gimp_action_group_set_action_active (group, action, TRUE);
text_layer = gimp_item_is_text_layer (GIMP_ITEM (layer));
vector_layer = gimp_drawable_is_vector_layer (GIMP_DRAWABLE (layer));
vector_layer = gimp_item_is_vector_layer (GIMP_ITEM (layer));
}
}

View File

@@ -74,8 +74,8 @@
#include "display/gimpdisplayshell.h"
#include "display/gimpimagewindow.h"
#include "tools/gimppathtool.h"
#include "tools/gimptexttool.h"
#include "tools/gimpvectortool.h"
#include "tools/tool_manager.h"
#include "dialogs/dialogs.h"
@@ -204,6 +204,10 @@ layers_edit_cmd_callback (GimpAction *action,
{
layers_edit_text_cmd_callback (action, value, data);
}
else if (gimp_item_is_vector_layer (GIMP_ITEM (layers->data)))
{
layers_vector_fill_stroke_cmd_callback (action, value, data);
}
else
{
layers_edit_attributes_cmd_callback (action, value, data);
@@ -273,7 +277,7 @@ layers_edit_vector_cmd_callback (GimpAction *action,
layer = layers->data;
if (! gimp_drawable_is_vector_layer (GIMP_DRAWABLE (layer)))
if (! gimp_item_is_vector_layer (GIMP_ITEM (layer)))
{
layers_edit_attributes_cmd_callback (action, value, data);
return;
@@ -281,13 +285,13 @@ layers_edit_vector_cmd_callback (GimpAction *action,
active_tool = tool_manager_get_active (image->gimp);
if (! GIMP_IS_VECTOR_TOOL (active_tool))
if (! GIMP_IS_PATH_TOOL (active_tool))
{
GimpToolInfo *tool_info;
tool_info = (GimpToolInfo *)
gimp_container_get_child_by_name (image->gimp->tool_info_list,
"gimp-vector-tool");
"gimp-path-tool");
if (GIMP_IS_TOOL_INFO (tool_info))
{
@@ -296,9 +300,9 @@ layers_edit_vector_cmd_callback (GimpAction *action,
}
}
if (GIMP_IS_VECTOR_TOOL (active_tool))
gimp_vector_tool_set_vectors (GIMP_VECTOR_TOOL (active_tool),
GIMP_VECTOR_LAYER (layer)->options->path);
if (GIMP_IS_PATH_TOOL (active_tool))
gimp_path_tool_set_path (GIMP_PATH_TOOL (active_tool),
GIMP_VECTOR_LAYER (layer)->options->path);
}
void

View File

@@ -470,6 +470,7 @@ paths_delete_cmd_callback (GimpAction *action,
{
GimpImage *image;
GList *paths;
gboolean attached_to_vector_layer = FALSE;
return_if_no_paths (image, paths, data);
paths = g_list_copy (paths);
@@ -479,11 +480,21 @@ paths_delete_cmd_callback (GimpAction *action,
_("Remove Paths"));
for (GList *iter = paths; iter; iter = iter->next)
gimp_image_remove_path (image, iter->data, TRUE, NULL);
{
/* Verify path is not attached to vector layer */
if (! gimp_path_attached_to_vector_layer (GIMP_PATH (iter->data), image))
gimp_image_remove_path (image, iter->data, TRUE, NULL);
else
attached_to_vector_layer = TRUE;
}
gimp_image_undo_group_end (image);
gimp_image_flush (image);
g_list_free (paths);
if (attached_to_vector_layer)
gimp_message_literal (image->gimp, NULL, GIMP_MESSAGE_WARNING,
_("Paths attached to vector layers weren't deleted"));
}
void

View File

@@ -1267,6 +1267,8 @@ gimp_undo_type_get_type (void)
{ GIMP_UNDO_TEXT_LAYER, "GIMP_UNDO_TEXT_LAYER", "text-layer" },
{ GIMP_UNDO_TEXT_LAYER_MODIFIED, "GIMP_UNDO_TEXT_LAYER_MODIFIED", "text-layer-modified" },
{ GIMP_UNDO_TEXT_LAYER_CONVERT, "GIMP_UNDO_TEXT_LAYER_CONVERT", "text-layer-convert" },
{ GIMP_UNDO_VECTOR_LAYER, "GIMP_UNDO_VECTOR_LAYER", "vector-layer" },
{ GIMP_UNDO_VECTOR_LAYER_MODIFIED, "GIMP_UNDO_VECTOR_LAYER_MODIFIED", "vector-layer-modified" },
{ GIMP_UNDO_LAYER_MASK_ADD, "GIMP_UNDO_LAYER_MASK_ADD", "layer-mask-add" },
{ GIMP_UNDO_LAYER_MASK_REMOVE, "GIMP_UNDO_LAYER_MASK_REMOVE", "layer-mask-remove" },
{ GIMP_UNDO_LAYER_MASK_APPLY, "GIMP_UNDO_LAYER_MASK_APPLY", "layer-mask-apply" },
@@ -1380,6 +1382,8 @@ gimp_undo_type_get_type (void)
{ GIMP_UNDO_TEXT_LAYER, NC_("undo-type", "Text layer"), NULL },
{ GIMP_UNDO_TEXT_LAYER_MODIFIED, NC_("undo-type", "Text layer modification"), NULL },
{ GIMP_UNDO_TEXT_LAYER_CONVERT, NC_("undo-type", "Convert text layer"), NULL },
{ GIMP_UNDO_VECTOR_LAYER, NC_("undo-type", "Vector layer"), NULL },
{ GIMP_UNDO_VECTOR_LAYER_MODIFIED, NC_("undo-type", "Vector layer modification"), NULL },
{ GIMP_UNDO_LAYER_MASK_ADD, NC_("undo-type", "Add layer masks"), NULL },
{ GIMP_UNDO_LAYER_MASK_REMOVE, NC_("undo-type", "Delete layer masks"), NULL },
{ GIMP_UNDO_LAYER_MASK_APPLY, NC_("undo-type", "Apply layer masks"), NULL },

View File

@@ -619,6 +619,8 @@ typedef enum /*< pdb-skip >*/
GIMP_UNDO_TEXT_LAYER, /*< desc="Text layer" >*/
GIMP_UNDO_TEXT_LAYER_MODIFIED, /*< desc="Text layer modification" >*/
GIMP_UNDO_TEXT_LAYER_CONVERT, /*< desc="Convert text layer" >*/
GIMP_UNDO_VECTOR_LAYER, /*< desc="Vector layer" >*/
GIMP_UNDO_VECTOR_LAYER_MODIFIED, /*< desc="Vector layer modification" >*/
GIMP_UNDO_LAYER_MASK_ADD, /*< desc="Add layer masks" >*/
GIMP_UNDO_LAYER_MASK_REMOVE, /*< desc="Delete layer masks" >*/
GIMP_UNDO_LAYER_MASK_APPLY, /*< desc="Apply layer masks" >*/

View File

@@ -57,6 +57,8 @@
#include "path/gimppathmodundo.h"
#include "path/gimppathpropundo.h"
#include "path/gimppathundo.h"
#include "path/gimpvectorlayer.h"
#include "path/gimpvectorlayerundo.h"
#include "text/gimptextlayer.h"
#include "text/gimptextundo.h"
@@ -877,6 +879,45 @@ gimp_image_undo_push_text_layer_convert (GimpImage *image,
}
/************************/
/* Vector Layer Undos */
/************************/
GimpUndo *
gimp_image_undo_push_vector_layer (GimpImage *image,
const gchar *undo_desc,
GimpVectorLayer *layer,
const GParamSpec *pspec)
{
g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
g_return_val_if_fail (GIMP_IS_VECTOR_LAYER (layer), NULL);
g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (layer)), NULL);
return gimp_image_undo_push (image, GIMP_TYPE_VECTOR_LAYER_UNDO,
GIMP_UNDO_VECTOR_LAYER, undo_desc,
GIMP_DIRTY_ITEM | GIMP_DIRTY_DRAWABLE,
"item", layer,
"param", pspec,
NULL);
}
GimpUndo *
gimp_image_undo_push_vector_layer_modified (GimpImage *image,
const gchar *undo_desc,
GimpVectorLayer *layer)
{
g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
g_return_val_if_fail (GIMP_IS_VECTOR_LAYER (layer), NULL);
g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (layer)), NULL);
return gimp_image_undo_push (image, GIMP_TYPE_VECTOR_LAYER_UNDO,
GIMP_UNDO_VECTOR_LAYER_MODIFIED, undo_desc,
GIMP_DIRTY_ITEM_META,
"item", layer,
NULL);
}
/**********************/
/* Layer Mask Undos */
/**********************/

View File

@@ -215,6 +215,17 @@ GimpUndo * gimp_image_undo_push_text_layer_convert (GimpImage *image,
GimpTextLayer *layer);
/* vector layer undos */
GimpUndo * gimp_image_undo_push_vector_layer (GimpImage *image,
const gchar *undo_desc,
GimpVectorLayer *layer,
const GParamSpec *pspec);
GimpUndo * gimp_image_undo_push_vector_layer_modified
(GimpImage *image,
const gchar *undo_desc,
GimpVectorLayer *layer);
/* layer mask undos */
GimpUndo * gimp_image_undo_push_layer_mask_add (GimpImage *image,

View File

@@ -87,6 +87,7 @@
#include "text/gimptextlayer.h"
#include "path/gimppath.h"
#include "path/gimpvectorlayer.h"
#include "gimp-log.h"
#include "gimp-intl.h"
@@ -5457,6 +5458,17 @@ gimp_image_add_layer (GimpImage *image,
gimp_drawable_attach_floating_sel (gimp_layer_get_floating_sel_drawable (layer),
layer);
/* If the layer is a vector layer, also add its path to the image */
if (gimp_item_is_vector_layer (GIMP_ITEM (layer)))
{
GimpPath *path = gimp_vector_layer_get_path (GIMP_VECTOR_LAYER (layer));
if (path &&
(! gimp_item_is_attached (GIMP_ITEM (path))) &&
gimp_item_get_image (GIMP_ITEM (path)) == image)
gimp_image_add_path (image, path, NULL, -1, FALSE);
}
if (old_has_alpha != gimp_image_has_alpha (image))
private->flush_accum.alpha_changed = TRUE;

View File

@@ -42,6 +42,7 @@
#include "gimpselection.h"
#include "path/gimppath.h"
#include "path/gimpvectorlayer.h"
#include "text/gimpfont.h"
#include "text/gimptextlayer.h"

View File

@@ -1,248 +1,326 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* vector-layer-options-dialog.h
*
* Copyright 2006 Hendrik Boom
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gegl.h>
#include <gtk/gtk.h>
#include "libgimpconfig/gimpconfig.h"
#include "libgimpwidgets/gimpwidgets.h"
#include "dialogs-types.h"
#include "core/gimp.h"
#include "core/gimpdrawable.h"
#include "core/gimpimage.h"
#include "core/gimpimage-undo-push.h"
#include "core/gimpstrokeoptions.h"
#include "widgets/gimpcolorpanel.h"
#include "widgets/gimppropwidgets.h"
#include "widgets/gimpviewabledialog.h"
#include "widgets/gimpstrokeeditor.h"
#include "vectors/gimpvectorlayer.h"
#include "vectors/gimpvectorlayeroptions.h"
#include "vector-layer-options-dialog.h"
#include "gimp-intl.h"
#define RESPONSE_RESET 1
/* local functions */
static void vector_layer_options_dialog_notify (GObject *options,
const GParamSpec *pspec,
GtkWidget *dialog);
static void vector_layer_options_dialog_response (GtkWidget *widget,
gint response_id,
GtkWidget *dialog);
/* public function */
GtkWidget *
vector_layer_options_dialog_new (GimpVectorLayer *layer,
GimpContext *context,
const gchar *title,
const gchar *icon_name,
const gchar *help_id,
GtkWidget *parent)
{
GimpVectorLayerOptions *saved_options;
GimpFillOptions *fill_options;
GimpStrokeOptions *stroke_options;
GtkWidget *dialog;
GtkWidget *main_vbox;
g_return_val_if_fail (GIMP_IS_VECTOR_LAYER (layer), NULL);
g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
g_return_val_if_fail (icon_name != NULL, NULL);
g_return_val_if_fail (parent == NULL || GTK_IS_WIDGET (parent), NULL);
saved_options = gimp_config_duplicate (GIMP_CONFIG (layer->options));
fill_options = gimp_config_duplicate (GIMP_CONFIG (saved_options->fill_options));
stroke_options = gimp_config_duplicate (GIMP_CONFIG (saved_options->stroke_options));
dialog = gimp_viewable_dialog_new (g_list_prepend (NULL, GIMP_VIEWABLE (layer)),
context,
title, "gimp-vectorlayer-options",
icon_name,
_("Choose vector layer options"),
parent,
gimp_standard_help_func,
help_id,
_("_Reset"), RESPONSE_RESET,
_("_Cancel"), GTK_RESPONSE_CANCEL,
_("_Apply"), GTK_RESPONSE_OK,
NULL);
gimp_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
RESPONSE_RESET,
GTK_RESPONSE_OK,
GTK_RESPONSE_CANCEL,
-1);
gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
g_signal_connect (dialog, "response",
G_CALLBACK (vector_layer_options_dialog_response),
dialog);
g_object_set_data (G_OBJECT (dialog), "layer", layer);
g_object_set_data_full (G_OBJECT (dialog), "saved-options",
saved_options,
(GDestroyNotify) g_object_unref);
g_object_set_data_full (G_OBJECT (dialog), "fill-options",
fill_options,
(GDestroyNotify) g_object_unref);
g_object_set_data_full (G_OBJECT (dialog), "stroke-options",
stroke_options,
(GDestroyNotify) g_object_unref);
g_signal_connect_object (fill_options, "notify",
G_CALLBACK (vector_layer_options_dialog_notify),
dialog, 0);
g_signal_connect_object (stroke_options, "notify",
G_CALLBACK (vector_layer_options_dialog_notify),
dialog, 0);
main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
main_vbox, TRUE, TRUE, 0);
gtk_widget_set_visible (main_vbox, TRUE);
/* The fill editor */
{
GtkWidget *frame;
GtkWidget *fill_editor;
frame = gimp_frame_new (_("Fill Style"));
gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
gtk_widget_set_visible (frame, TRUE);
fill_editor = gimp_fill_editor_new (fill_options, TRUE, TRUE);
gtk_container_add (GTK_CONTAINER (frame), fill_editor);
gtk_widget_set_visible (fill_editor, TRUE);
}
/* The stroke editor */
{
GtkWidget *frame;
GtkWidget *stroke_editor;
gdouble xres;
gdouble yres;
frame = gimp_frame_new (_("Stroke Style"));
gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
gtk_widget_set_visible (frame, TRUE);
gimp_image_get_resolution (gimp_item_get_image (GIMP_ITEM (layer)),
&xres, &yres);
stroke_editor = gimp_stroke_editor_new (stroke_options, yres, TRUE, TRUE);
gtk_container_add (GTK_CONTAINER (frame), stroke_editor);
gtk_widget_set_visible (stroke_editor, TRUE);
}
return dialog;
}
static void
vector_layer_options_dialog_notify (GObject *options,
const GParamSpec *pspec,
GtkWidget *dialog)
{
GimpVectorLayer *layer;
GimpFillOptions *fill_options;
GimpStrokeOptions *stroke_options;
layer = g_object_get_data (G_OBJECT (dialog), "layer");
fill_options = g_object_get_data (G_OBJECT (dialog), "fill-options");
stroke_options = g_object_get_data (G_OBJECT (dialog), "stroke-options");
gimp_config_sync (G_OBJECT (fill_options),
G_OBJECT (layer->options->fill_options), 0);
gimp_config_sync (G_OBJECT (stroke_options),
G_OBJECT (layer->options->stroke_options), 0);
gimp_vector_layer_refresh (layer);
gimp_image_flush (gimp_item_get_image (GIMP_ITEM (layer)));
}
static void
vector_layer_options_dialog_response (GtkWidget *widget,
gint response_id,
GtkWidget *dialog)
{
GimpVectorLayer *layer;
GimpVectorLayerOptions *saved_options;
GimpFillOptions *fill_options;
GimpStrokeOptions *stroke_options;
layer = g_object_get_data (G_OBJECT (dialog), "layer");
saved_options = g_object_get_data (G_OBJECT (dialog), "saved-options");
fill_options = g_object_get_data (G_OBJECT (dialog), "fill-options");
stroke_options = g_object_get_data (G_OBJECT (dialog), "stroke-options");
switch (response_id)
{
case GTK_RESPONSE_OK:
if (layer && layer->options )
{
gimp_config_sync (G_OBJECT (saved_options->fill_options),
G_OBJECT (layer->options->fill_options), 0);
gimp_config_sync (G_OBJECT (saved_options->stroke_options),
G_OBJECT (layer->options->stroke_options), 0);
gimp_image_undo_push_vector_layer (gimp_item_get_image (GIMP_ITEM (layer)),
_("Fill/Stroke Vector Layer"),
layer, NULL);
gimp_config_sync (G_OBJECT (fill_options),
G_OBJECT (layer->options->fill_options), 0);
gimp_config_sync (G_OBJECT (stroke_options),
G_OBJECT (layer->options->stroke_options), 0);
}
gtk_widget_destroy (dialog);
break;
default:
gimp_config_sync (G_OBJECT (saved_options->fill_options),
G_OBJECT (fill_options), 0);
gimp_config_sync (G_OBJECT (saved_options->stroke_options),
G_OBJECT (stroke_options), 0);
if (response_id != RESPONSE_RESET)
gtk_widget_destroy (dialog);
break;
}
}
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* vector-layer-options-dialog.h
*
* Copyright 2006 Hendrik Boom
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gegl.h>
#include <gtk/gtk.h>
#include "libgimpconfig/gimpconfig.h"
#include "libgimpwidgets/gimpwidgets.h"
#include "dialogs-types.h"
#include "core/gimp.h"
#include "core/gimpdrawable.h"
#include "core/gimpimage.h"
#include "core/gimpimage-undo-push.h"
#include "core/gimpstrokeoptions.h"
#include "path/gimppath.h"
#include "path/gimpvectorlayer.h"
#include "path/gimpvectorlayeroptions.h"
#include "widgets/gimpcolorpanel.h"
#include "widgets/gimpcontainercombobox.h"
#include "widgets/gimpcontainerview.h"
#include "widgets/gimppropwidgets.h"
#include "widgets/gimpviewabledialog.h"
#include "widgets/gimpstrokeeditor.h"
#include "vector-layer-options-dialog.h"
#include "gimp-intl.h"
#define RESPONSE_RESET 1
/* local functions */
static void vector_layer_options_dialog_notify (GObject *options,
const GParamSpec *pspec,
GtkWidget *dialog);
static void vector_layer_options_dialog_response (GtkWidget *widget,
gint response_id,
GtkWidget *dialog);
static void vector_layer_options_dialog_path_selected (GimpContainerView *view,
GtkWidget *dialog);
/* public function */
GtkWidget *
vector_layer_options_dialog_new (GimpVectorLayer *layer,
GimpContext *context,
const gchar *title,
const gchar *icon_name,
const gchar *help_id,
GtkWidget *parent)
{
GimpVectorLayerOptions *saved_options;
GimpFillOptions *fill_options;
GimpStrokeOptions *stroke_options;
GtkWidget *dialog;
GtkWidget *main_vbox;
GtkWidget *combo;
g_return_val_if_fail (GIMP_IS_VECTOR_LAYER (layer), NULL);
g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
g_return_val_if_fail (icon_name != NULL, NULL);
g_return_val_if_fail (parent == NULL || GTK_IS_WIDGET (parent), NULL);
saved_options = gimp_config_duplicate (GIMP_CONFIG (layer->options));
fill_options = gimp_config_duplicate (GIMP_CONFIG (saved_options->fill_options));
stroke_options = gimp_config_duplicate (GIMP_CONFIG (saved_options->stroke_options));
dialog = gimp_viewable_dialog_new (g_list_prepend (NULL, GIMP_VIEWABLE (layer)),
context,
title, "gimp-vectorlayer-options",
icon_name,
_("Edit Vector Layer Attributes"),
parent,
gimp_standard_help_func,
help_id,
_("_Reset"), RESPONSE_RESET,
_("_Cancel"), GTK_RESPONSE_CANCEL,
_("_Apply"), GTK_RESPONSE_OK,
NULL);
gimp_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
RESPONSE_RESET,
GTK_RESPONSE_OK,
GTK_RESPONSE_CANCEL,
-1);
gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
g_signal_connect (dialog, "response",
G_CALLBACK (vector_layer_options_dialog_response),
dialog);
g_object_set_data (G_OBJECT (dialog), "layer", layer);
g_object_set_data_full (G_OBJECT (dialog), "saved-options",
saved_options,
(GDestroyNotify) g_object_unref);
g_object_set_data_full (G_OBJECT (dialog), "fill-options",
fill_options,
(GDestroyNotify) g_object_unref);
g_object_set_data_full (G_OBJECT (dialog), "stroke-options",
stroke_options,
(GDestroyNotify) g_object_unref);
g_signal_connect_object (saved_options, "notify::enable-fill",
G_CALLBACK (vector_layer_options_dialog_notify),
dialog, 0);
g_signal_connect_object (saved_options, "notify::enable-stroke",
G_CALLBACK (vector_layer_options_dialog_notify),
dialog, 0);
g_signal_connect_object (fill_options, "notify",
G_CALLBACK (vector_layer_options_dialog_notify),
dialog, 0);
g_signal_connect_object (stroke_options, "notify",
G_CALLBACK (vector_layer_options_dialog_notify),
dialog, 0);
main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
main_vbox, TRUE, TRUE, 0);
gtk_widget_set_visible (main_vbox, TRUE);
combo = gimp_container_combo_box_new (gimp_image_get_paths (gimp_item_get_image (GIMP_ITEM (layer))),
context,
GIMP_VIEW_SIZE_SMALL, 1);
gimp_container_view_set_1_selected (GIMP_CONTAINER_VIEW (combo),
GIMP_VIEWABLE (saved_options->path));
g_signal_connect_object (combo, "selection-changed",
G_CALLBACK (vector_layer_options_dialog_path_selected),
dialog, 0);
gtk_box_pack_start (GTK_BOX (main_vbox), combo, FALSE, FALSE, 0);
gtk_widget_set_visible (combo, TRUE);
/* The fill editor */
{
GtkWidget *frame;
GtkWidget *fill_editor;
fill_editor = gimp_fill_editor_new (fill_options, TRUE, TRUE);
gtk_widget_set_visible (fill_editor, TRUE);
frame = gimp_prop_expanding_frame_new (G_OBJECT (saved_options),
"enable-fill", NULL, fill_editor,
NULL);
gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
}
/* The stroke editor */
{
GtkWidget *frame;
GtkWidget *stroke_editor;
gdouble xres;
gdouble yres;
gimp_image_get_resolution (gimp_item_get_image (GIMP_ITEM (layer)),
&xres, &yres);
stroke_editor = gimp_stroke_editor_new (stroke_options, yres, TRUE, TRUE);
gtk_widget_set_visible (stroke_editor, TRUE);
frame = gimp_prop_expanding_frame_new (G_OBJECT (saved_options),
"enable-stroke", NULL, stroke_editor,
NULL);
gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
}
return dialog;
}
static void
vector_layer_options_dialog_notify (GObject *options,
const GParamSpec *pspec,
GtkWidget *dialog)
{
GimpVectorLayer *layer;
GimpFillOptions *fill_options;
GimpStrokeOptions *stroke_options;
gboolean enable_fill;
gboolean enable_stroke;
layer = g_object_get_data (G_OBJECT (dialog), "layer");
enable_fill = layer->options->enable_fill;
enable_stroke = layer->options->enable_stroke;
fill_options = g_object_get_data (G_OBJECT (dialog), "fill-options");
stroke_options = g_object_get_data (G_OBJECT (dialog), "stroke-options");
gimp_config_sync (G_OBJECT (fill_options),
G_OBJECT (layer->options->fill_options), 0);
gimp_config_sync (G_OBJECT (stroke_options),
G_OBJECT (layer->options->stroke_options), 0);
if (! strcmp (pspec->name, "enable-fill") ||
! strcmp (pspec->name, "enable-stroke"))
{
GimpVectorLayerOptions *vector_options;
vector_options = GIMP_VECTOR_LAYER_OPTIONS (options);
layer->options->enable_fill = vector_options->enable_fill;
layer->options->enable_stroke = vector_options->enable_stroke;
}
gimp_vector_layer_refresh (layer);
gimp_image_flush (gimp_item_get_image (GIMP_ITEM (layer)));
layer->options->enable_fill = enable_fill;
layer->options->enable_stroke = enable_stroke;
}
static void
vector_layer_options_dialog_response (GtkWidget *widget,
gint response_id,
GtkWidget *dialog)
{
GimpVectorLayer *layer;
GimpPath *path;
GimpVectorLayerOptions *saved_options;
GimpFillOptions *fill_options;
GimpStrokeOptions *stroke_options;
layer = g_object_get_data (G_OBJECT (dialog), "layer");
saved_options = g_object_get_data (G_OBJECT (dialog), "saved-options");
fill_options = g_object_get_data (G_OBJECT (dialog), "fill-options");
stroke_options = g_object_get_data (G_OBJECT (dialog), "stroke-options");
switch (response_id)
{
case GTK_RESPONSE_OK:
if (layer && layer->options)
{
layer->options->enable_fill = saved_options->enable_fill;
gimp_config_sync (G_OBJECT (saved_options->fill_options),
G_OBJECT (layer->options->fill_options), 0);
layer->options->enable_stroke = saved_options->enable_stroke;
gimp_config_sync (G_OBJECT (saved_options->stroke_options),
G_OBJECT (layer->options->stroke_options), 0);
gimp_image_undo_push_vector_layer (gimp_item_get_image (GIMP_ITEM (layer)),
_("Fill/Stroke Vector Layer"),
layer, NULL);
gimp_config_sync (G_OBJECT (fill_options),
G_OBJECT (layer->options->fill_options), 0);
gimp_config_sync (G_OBJECT (stroke_options),
G_OBJECT (layer->options->stroke_options), 0);
}
gtk_widget_destroy (dialog);
break;
default:
gimp_config_sync (G_OBJECT (saved_options->fill_options),
G_OBJECT (fill_options), 0);
gimp_config_sync (G_OBJECT (saved_options->stroke_options),
G_OBJECT (stroke_options), 0);
if (layer && layer->options)
{
g_object_get (saved_options, "path", &path, NULL);
g_object_set (layer->options, "path", path, NULL);
gimp_vector_layer_refresh (layer);
gimp_image_flush (gimp_item_get_image (GIMP_ITEM (layer)));
}
if (response_id != RESPONSE_RESET)
gtk_widget_destroy (dialog);
break;
}
}
static void
vector_layer_options_dialog_path_selected (GimpContainerView *view,
GtkWidget *dialog)
{
GimpViewable *item = gimp_container_view_get_1_selected (view);
GimpPath *path = NULL;
GimpVectorLayer *layer;
layer = g_object_get_data (G_OBJECT (dialog), "layer");
if (item)
path = GIMP_PATH (item);
if (path && GIMP_IS_PATH (path))
{
g_object_set (layer->options, "path", path, NULL);
gimp_vector_layer_refresh (layer);
gimp_image_flush (gimp_item_get_image (GIMP_ITEM (layer)));
}
}

View File

@@ -1,34 +1,34 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* vector-layer-options-dialog.h
*
* Copyright 2006 Hendrik Boom
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __VECTOR_LAYER_OPTIONS_DIALOG_H__
#define __VECTOR_LAYER_OPTIONS_DIALOG_H__
GtkWidget * vector_layer_options_dialog_new (GimpVectorLayer *layer,
GimpContext *context,
const gchar *title,
const gchar *icon_name,
const gchar *help_id,
GtkWidget *parent);
#endif /* __VECTOR_LAYER_OPTIONS_DIALOG_H__ */
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* vector-layer-options-dialog.h
*
* Copyright 2006 Hendrik Boom
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __VECTOR_LAYER_OPTIONS_DIALOG_H__
#define __VECTOR_LAYER_OPTIONS_DIALOG_H__
GtkWidget * vector_layer_options_dialog_new (GimpVectorLayer *layer,
GimpContext *context,
const gchar *title,
const gchar *icon_name,
const gchar *help_id,
GtkWidget *parent);
#endif /* __VECTOR_LAYER_OPTIONS_DIALOG_H__ */

View File

@@ -34,6 +34,8 @@
#include "core/gimpgrid.h"
#include "core/gimplayer.h"
#include "path/gimpvectorlayer.h"
#include "gimpcanvas.h"
#include "gimpcanvas-style.h"
@@ -431,6 +433,15 @@ gimp_canvas_set_layer_style (GtkWidget *canvas,
pattern = gimp_cairo_pattern_create_stipple (layer_group_fg, layer_group_bg, 0,
offset_x, offset_y, render_space);
}
else if (gimp_item_is_vector_layer (GIMP_ITEM (layer)))
{
GeglColor *transparent = gegl_color_new ("transparent");
pattern = gimp_cairo_pattern_create_stipple (transparent, transparent, 0,
offset_x, offset_y, render_space);
g_clear_object (&transparent);
}
else
{
pattern = gimp_cairo_pattern_create_stipple (layer_fg, layer_bg, 0,

View File

@@ -398,6 +398,7 @@ EXPORTS
gimp_item_get_visible
gimp_item_height
gimp_item_is_text_layer
gimp_item_is_vector_layer
gimp_item_offsets
gimp_item_rename
gimp_item_resize
@@ -450,7 +451,7 @@ EXPORTS
gimp_marshal_VOID__OBJECT_OBJECT
gimp_marshal_VOID__OBJECT_POINTER
gimp_marshal_VOID__POINTER_BOXED
gimp_marshal_VOID__POINTER_ENUM
gimp_marshal_VOID__POINTER_ENUM
gimp_marshal_VOID__STRING_BOOLEAN_UINT_FLAGS
gimp_marshal_VOID__STRING_FLAGS
gimp_message

View File

@@ -40,6 +40,7 @@
#include "core/gimperror.h"
#include "core/gimpimage.h"
#include "core/gimpimage-undo-push.h"
#include "core/gimpitemstack.h"
#include "core/gimppaintinfo.h"
#include "core/gimpstrokeoptions.h"
@@ -50,6 +51,8 @@
#include "gimppath.h"
#include "gimppath-preview.h"
#include "gimpstroke.h"
#include "gimpvectorlayer.h"
#include "gimpvectorlayeroptions.h"
#include "gimp-intl.h"
@@ -164,6 +167,10 @@ static gint gimp_path_real_interpolate (GimpPath *path,
gint max_points,
GimpCoords *ret_coords);
static gboolean gimp_path_attached_to_vector_layer_rec
(GimpPath *path,
GList *layers);
static GimpBezierDesc * gimp_path_make_bezier (GimpPath *path);
static GimpBezierDesc * gimp_path_real_make_bezier (GimpPath *path);
@@ -1200,6 +1207,84 @@ gimp_path_real_interpolate (GimpPath *path,
return 0;
}
gboolean
gimp_path_attached_to_vector_layer (GimpPath *path,
GimpImage *image)
{
GList *layers;
GList *list;
g_return_val_if_fail (GIMP_IS_PATH (path), FALSE);
g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
layers = gimp_image_get_layer_iter (image);
for (list = layers; list; list = g_list_next (list))
{
if (GIMP_IS_VECTOR_LAYER (list->data))
{
GimpVectorLayer *vector_layer = GIMP_VECTOR_LAYER (list->data);
if (vector_layer->options &&
vector_layer->options->path &&
(path == vector_layer->options->path))
return TRUE;
}
if (gimp_viewable_get_children (GIMP_VIEWABLE (list->data)))
{
GimpContainer *container;
GList *iter2;
container = gimp_viewable_get_children (GIMP_VIEWABLE (list->data));
iter2 =
gimp_item_stack_get_item_iter (GIMP_ITEM_STACK (container));
if (gimp_path_attached_to_vector_layer_rec (path, iter2))
return TRUE;
}
}
return FALSE;
}
static gboolean
gimp_path_attached_to_vector_layer_rec (GimpPath *path,
GList *layers)
{
GList *list;
for (list = layers; list; list = g_list_next (list))
{
if (GIMP_IS_VECTOR_LAYER (list->data))
{
GimpVectorLayer *vector_layer = GIMP_VECTOR_LAYER (list->data);
if (vector_layer->options &&
vector_layer->options->path &&
(path == vector_layer->options->path))
return TRUE;
}
if (gimp_viewable_get_children (GIMP_VIEWABLE (list->data)))
{
GimpContainer *container;
GList *iter2;
container = gimp_viewable_get_children (GIMP_VIEWABLE (list->data));
iter2 =
gimp_item_stack_get_item_iter (GIMP_ITEM_STACK (container));
if (gimp_path_attached_to_vector_layer_rec (path, iter2))
return TRUE;
}
}
return FALSE;
}
const GimpBezierDesc *
gimp_path_get_bezier (GimpPath *path)
{

View File

@@ -175,6 +175,9 @@ gint gimp_path_interpolate (GimpPath *path,
gint max_points,
GimpCoords *ret_coords);
gboolean gimp_path_attached_to_vector_layer
(GimpPath *path,
GimpImage *image);
/* usually overloaded */
/* returns a bezier representation */

View File

@@ -0,0 +1,172 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpvectorlayer-xcf.c
*
* Copyright 2006 Hendrik Boom
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gio/gio.h>
#include <gegl.h>
#include "libgimpbase/gimpbase.h"
#include "path-types.h"
#include "core/gimp.h"
#include "core/gimpimage.h"
#include "core/gimpparasitelist.h"
#include "gimpvectorlayeroptions.h"
#include "gimpvectorlayeroptions-parasite.h"
#include "gimpvectorlayer.h"
#include "gimpvectorlayer-xcf.h"
#include "gimp-intl.h"
static GimpLayer * gimp_vector_layer_from_layer (GimpLayer *layer,
GimpVectorLayerOptions *options);
gboolean
gimp_vector_layer_xcf_load_hack (GimpLayer **layer)
{
const gchar *name;
GimpVectorLayerOptions *options = NULL;
const GimpParasite *parasite;
g_return_val_if_fail (layer != NULL, FALSE);
g_return_val_if_fail (GIMP_IS_LAYER (*layer), FALSE);
name = gimp_vector_layer_options_parasite_name ();
parasite = gimp_item_parasite_find (GIMP_ITEM (*layer), name);
if (parasite)
{
GError *error = NULL;
options = gimp_vector_layer_options_from_parasite (
parasite, &error, gimp_item_get_image (GIMP_ITEM (*layer))->gimp);
g_object_set (G_OBJECT (options),
"path", gimp_image_get_path_by_tattoo (
gimp_item_get_image (GIMP_ITEM (*layer)),
options->path_tattoo),
NULL);
if (error)
{
g_message (_("Problems parsing the vector layer parasite for layer '%s':\n"
"%s\n\n"
"Some vector layer properties may be wrong. "),
gimp_object_get_name (GIMP_OBJECT (*layer)),
error->message);
g_error_free (error);
}
}
if (options)
{
*layer = gimp_vector_layer_from_layer (*layer, options);
/* let the text layer know what parasite was used to create it */
GIMP_VECTOR_LAYER (*layer)->parasite = name;
}
return (options != NULL);
}
void
gimp_vector_layer_xcf_save_prepare (GimpVectorLayer *layer)
{
GimpVectorLayerOptions *options;
g_return_if_fail (GIMP_IS_VECTOR_LAYER (layer));
/* If the layer has a text parasite already, it wasn't changed and we
* can simply save the original parasite back which is still attached.
*/
if (layer->parasite)
return;
g_object_get (layer, "vector-layer-options", &options, NULL);
if (options)
{
GimpParasite *parasite = gimp_vector_layer_options_to_parasite (options);
gimp_parasite_list_add (gimp_item_get_parasites (GIMP_ITEM (layer)), parasite);
}
}
/**
* gimp_vector_layer_from_layer:
* @layer: a #GimpLayer object
* @options: a #GimpVectorLayerOptions object
*
* Converts a standard #GimpLayer and a #GimpVectorLayerOptions object
* into a #GimpVectorLayer. The new vector layer takes ownership of the
* @options and @layer objects. The @layer object is rendered unusable
* by this function. Don't even try to use it afterwards!
*
* This is a gross hack that is needed in order to load vector layers
* from XCF files in a backwards-compatible way. Please don't use it
* for anything else!
*
* Return value: a newly allocated #GimpVectorLayer object
**/
static GimpLayer *
gimp_vector_layer_from_layer (GimpLayer *layer,
GimpVectorLayerOptions *options)
{
GimpVectorLayer *vector_layer;
GimpDrawable *drawable;
g_return_val_if_fail (GIMP_IS_LAYER (layer), NULL);
g_return_val_if_fail (GIMP_IS_VECTOR_LAYER_OPTIONS (options), NULL);
vector_layer = g_object_new (GIMP_TYPE_VECTOR_LAYER,
"image", gimp_item_get_image (GIMP_ITEM (layer)),
"vector-layer-options", options,
NULL);
gimp_item_replace_item (GIMP_ITEM (vector_layer), GIMP_ITEM (layer));
drawable = GIMP_DRAWABLE (vector_layer);
gimp_drawable_steal_buffer (drawable, GIMP_DRAWABLE (layer));
gimp_layer_set_opacity (GIMP_LAYER (vector_layer),
gimp_layer_get_opacity (layer), FALSE);
gimp_layer_set_mode (GIMP_LAYER (vector_layer),
gimp_layer_get_mode (layer), FALSE);
gimp_layer_set_blend_space (GIMP_LAYER (vector_layer),
gimp_layer_get_blend_space (layer), FALSE);
gimp_layer_set_composite_space (GIMP_LAYER (vector_layer),
gimp_layer_get_composite_space (layer), FALSE);
gimp_layer_set_composite_mode (GIMP_LAYER (vector_layer),
gimp_layer_get_composite_mode (layer), FALSE);
gimp_layer_set_lock_alpha (GIMP_LAYER (vector_layer),
gimp_layer_get_lock_alpha (layer), FALSE);
g_object_unref (options);
g_object_unref (layer);
return GIMP_LAYER (vector_layer);
}

View File

@@ -0,0 +1,33 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpvectorlayer-xcf.h
*
* Copyright 2006 Hendrik Boom
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __GIMP_VECTOR_LAYER_XCF_H__
#define __GIMP_VECTOR_LAYER_XCF_H__
const gchar * gimp_vector_layer_vector_parasite_name (void) G_GNUC_CONST;
const gchar * gimp_vector_layer_fill_parasite_name (void) G_GNUC_CONST;
const gchar * gimp_vector_layer_stroke_parasite_name (void) G_GNUC_CONST;
gboolean gimp_vector_layer_xcf_load_hack (GimpLayer **layer);
void gimp_vector_layer_xcf_save_prepare (GimpVectorLayer *layer);
#endif /* __GIMP_VECTOR_LAYER_XCF_H__ */

801
app/path/gimpvectorlayer.c Normal file
View File

@@ -0,0 +1,801 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpvectorlayer.c
*
* Copyright 2006 Hendrik Boom
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <stdio.h>
#include <cairo.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gegl.h>
#include "libgimpcolor/gimpcolor.h"
#include "libgimpconfig/gimpconfig.h"
#include "path-types.h"
#include "core/gimp.h"
#include "core/gimpdrawable-fill.h"
#include "core/gimpdrawable-stroke.h"
#include "core/gimpimage.h"
#include "core/gimpselection.h"
#include "core/gimpimage-undo.h"
#include "core/gimpimage-undo-push.h"
#include "core/gimpstrokeoptions.h"
#include "core/gimpparasitelist.h"
#include "gimpvectorlayer.h"
#include "gimpvectorlayeroptions.h"
#include "gimppath.h"
#include "gimp-intl.h"
enum
{
PROP_0,
PROP_VECTOR_LAYER_OPTIONS,
PROP_MODIFIED
};
/* local function declarations */
static void gimp_vector_layer_finalize (GObject *object);
static void gimp_vector_layer_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
static void gimp_vector_layer_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_vector_layer_set_vector_options
(GimpVectorLayer *layer,
GimpVectorLayerOptions *options);
static void gimp_vector_layer_set_buffer (GimpDrawable *drawable,
gboolean push_undo,
const gchar *undo_desc,
GeglBuffer *buffer,
const GeglRectangle *bounds);
static void gimp_vector_layer_push_undo (GimpDrawable *drawable,
const gchar *undo_desc,
GeglBuffer *buffer,
gint x,
gint y,
gint width,
gint height);
static gint64 gimp_vector_layer_get_memsize (GimpObject *object,
gint64 *gui_size);
static GimpItem * gimp_vector_layer_duplicate (GimpItem *item,
GType new_type);
static void gimp_vector_layer_translate (GimpLayer *layer,
gint offset_x,
gint offset_y);
static void gimp_vector_layer_scale (GimpItem *item,
gint new_width,
gint new_height,
gint new_offset_x,
gint new_offset_y,
GimpInterpolationType interp_type,
GimpProgress *progress);
static void gimp_vector_layer_flip (GimpItem *item,
GimpContext *context,
GimpOrientationType flip_type,
gdouble axis,
gboolean clip_result);
static void gimp_vector_layer_rotate (GimpItem *item,
GimpContext *context,
GimpRotationType rotate_type,
gdouble center_x,
gdouble center_y,
gboolean clip_result);
static void gimp_vector_layer_transform (GimpItem *item,
GimpContext *context,
const GimpMatrix3 *matrix,
GimpTransformDirection direction,
GimpInterpolationType interp_type,
GimpTransformResize clip_result,
GimpProgress *progress);
static gboolean gimp_vector_layer_render (GimpVectorLayer *layer);
static void gimp_vector_layer_render_path (GimpVectorLayer *layer);
static void gimp_vector_layer_changed_options (GimpVectorLayer *layer);
static void gimp_vector_layer_removed (GimpItem *item);
static void gimp_vector_layer_removed_options_path
(GimpVectorLayer *layer);
G_DEFINE_TYPE (GimpVectorLayer, gimp_vector_layer, GIMP_TYPE_LAYER)
#define parent_class gimp_vector_layer_parent_class
static void
gimp_vector_layer_class_init (GimpVectorLayerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass);
GimpViewableClass *viewable_class = GIMP_VIEWABLE_CLASS (klass);
GimpItemClass *item_class = GIMP_ITEM_CLASS (klass);
GimpDrawableClass *drawable_class = GIMP_DRAWABLE_CLASS (klass);
GimpLayerClass *layer_class = GIMP_LAYER_CLASS (klass);
drawable_class->set_buffer = gimp_vector_layer_set_buffer;
drawable_class->push_undo = gimp_vector_layer_push_undo;
object_class->finalize = gimp_vector_layer_finalize;
object_class->set_property = gimp_vector_layer_set_property;
object_class->get_property = gimp_vector_layer_get_property;
gimp_object_class->get_memsize = gimp_vector_layer_get_memsize;
viewable_class->default_icon_name = "gimp-vector-layer";
viewable_class->default_name = _("Vector Layer");
layer_class->translate = gimp_vector_layer_translate;
item_class->removed = gimp_vector_layer_removed;
item_class->duplicate = gimp_vector_layer_duplicate;
item_class->scale = gimp_vector_layer_scale;
item_class->flip = gimp_vector_layer_flip;
item_class->rotate = gimp_vector_layer_rotate;
item_class->transform = gimp_vector_layer_transform;
item_class->rename_desc = _("Rename Vector Layer");
item_class->translate_desc = _("Move Vector Layer");
item_class->scale_desc = _("Scale Vector Layer");
item_class->resize_desc = _("Resize Vector Layer");
item_class->flip_desc = _("Flip Vector Layer");
item_class->rotate_desc = _("Rotate Vector Layer");
item_class->transform_desc = _("Transform Vector Layer");
GIMP_CONFIG_PROP_OBJECT (object_class, PROP_VECTOR_LAYER_OPTIONS,
"vector-layer-options", NULL, NULL,
GIMP_TYPE_VECTOR_LAYER_OPTIONS,
G_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_MODIFIED,
"modified",
NULL, NULL,
FALSE,
GIMP_PARAM_STATIC_STRINGS);
}
static void
gimp_vector_layer_init (GimpVectorLayer *layer)
{
layer->options = NULL;
layer->parasite = NULL;
layer->modified = FALSE;
}
static void
gimp_vector_layer_finalize (GObject *object)
{
GimpVectorLayer *layer = GIMP_VECTOR_LAYER (object);
if (layer->options)
{
g_object_unref (layer->options);
layer->options = NULL;
}
if (layer->parasite)
{
gimp_parasite_list_remove (gimp_item_get_parasites (GIMP_ITEM (layer)),
layer->parasite);
layer->parasite = NULL;
}
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
gimp_vector_layer_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GimpVectorLayer *vector_layer = GIMP_VECTOR_LAYER (object);
switch (property_id)
{
case PROP_VECTOR_LAYER_OPTIONS:
g_value_set_object (value, vector_layer->options);
break;
case PROP_MODIFIED:
g_value_set_boolean (value, vector_layer->modified);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gimp_vector_layer_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
GimpVectorLayer *vector_layer = GIMP_VECTOR_LAYER (object);
switch (property_id)
{
case PROP_VECTOR_LAYER_OPTIONS:
if (vector_layer->options)
{
g_signal_handlers_disconnect_by_func (vector_layer->options,
G_CALLBACK (gimp_vector_layer_changed_options),
vector_layer);
if (vector_layer->options->path)
g_signal_handlers_disconnect_by_func (vector_layer->options->path,
G_CALLBACK (gimp_vector_layer_removed_options_path),
vector_layer);
g_object_unref (vector_layer->options);
}
vector_layer->options = g_value_dup_object (value);
if (vector_layer->options)
{
if (vector_layer->options->path)
g_signal_connect_object (vector_layer->options->path, "removed",
G_CALLBACK (gimp_vector_layer_removed_options_path),
vector_layer, G_CONNECT_SWAPPED);
g_signal_connect_object (vector_layer->options, "notify",
G_CALLBACK (gimp_vector_layer_changed_options),
vector_layer, G_CONNECT_SWAPPED);
}
break;
case PROP_MODIFIED:
vector_layer->modified = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gimp_vector_layer_set_vector_options (GimpVectorLayer *layer,
GimpVectorLayerOptions *options)
{
if (layer->options)
{
g_signal_handlers_disconnect_by_func (layer->options,
G_CALLBACK (gimp_vector_layer_changed_options),
layer);
g_object_unref (layer->options);
}
layer->options = options;
gimp_vector_layer_changed_options (layer);
if (layer->options)
g_signal_connect_object (layer->options, "notify",
G_CALLBACK (gimp_vector_layer_changed_options),
layer, G_CONNECT_SWAPPED);
}
static void
gimp_vector_layer_set_buffer (GimpDrawable *drawable,
gboolean push_undo,
const gchar *undo_desc,
GeglBuffer *buffer,
const GeglRectangle *bounds)
{
GimpVectorLayer *layer = GIMP_VECTOR_LAYER (drawable);
GimpImage *image = gimp_item_get_image (GIMP_ITEM (layer));
if (push_undo && ! layer->modified)
gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_DRAWABLE_MOD,
undo_desc);
GIMP_DRAWABLE_CLASS (parent_class)->set_buffer (drawable,
push_undo, undo_desc,
buffer, bounds);
if (push_undo && ! layer->modified)
{
gimp_image_undo_push_vector_layer_modified (image, NULL, layer);
g_object_set (drawable, "modified", TRUE, NULL);
gimp_image_undo_group_end (image);
}
}
static void
gimp_vector_layer_push_undo (GimpDrawable *drawable,
const gchar *undo_desc,
GeglBuffer *buffer,
gint x,
gint y,
gint width,
gint height)
{
GimpVectorLayer *layer = GIMP_VECTOR_LAYER (drawable);
GimpImage *image = gimp_item_get_image (GIMP_ITEM (layer));
if (! layer->modified)
gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_DRAWABLE, undo_desc);
GIMP_DRAWABLE_CLASS (parent_class)->push_undo (drawable, undo_desc,
buffer,
x, y, width, height);
if (! layer->modified)
{
gimp_image_undo_push_vector_layer_modified (image, NULL, layer);
g_object_set (drawable, "modified", TRUE, NULL);
gimp_image_undo_group_end (image);
}
}
static gint64
gimp_vector_layer_get_memsize (GimpObject *object,
gint64 *gui_size)
{
GimpVectorLayer *vector_layer = GIMP_VECTOR_LAYER (object);
gint64 memsize = 0;
memsize += gimp_object_get_memsize (GIMP_OBJECT (vector_layer->options),
gui_size);
return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
gui_size);
}
static GimpItem *
gimp_vector_layer_duplicate (GimpItem *item,
GType new_type)
{
GimpItem *new_item;
g_return_val_if_fail (g_type_is_a (new_type, GIMP_TYPE_DRAWABLE), NULL);
new_item = GIMP_ITEM_CLASS (parent_class)->duplicate (item, new_type);
if (GIMP_IS_VECTOR_LAYER (new_item))
{
GimpVectorLayer *vector_layer = GIMP_VECTOR_LAYER (item);
GimpVectorLayer *new_vector_layer = GIMP_VECTOR_LAYER (new_item);
if (vector_layer->options)
{
GimpVectorLayerOptions *new_options =
gimp_config_duplicate (GIMP_CONFIG (vector_layer->options));
if (vector_layer->options->path)
{
GimpPath *path = gimp_vector_layer_get_path (vector_layer);
GimpPath *new_path;
new_path = GIMP_PATH (gimp_item_duplicate (GIMP_ITEM (path),
G_TYPE_FROM_INSTANCE (GIMP_ITEM (path))));
g_object_set (new_options, "path", new_path, NULL);
}
g_object_set (new_vector_layer,
"vector-layer-options", new_options,
NULL);
g_object_unref (new_options);
}
}
return new_item;
}
static void
gimp_vector_layer_translate (GimpLayer *layer,
gint offset_x,
gint offset_y)
{
GimpVectorLayer *vector_layer = GIMP_VECTOR_LAYER (layer);
if (vector_layer->options && vector_layer->options->path)
{
gimp_item_translate (GIMP_ITEM (vector_layer->options->path),
offset_x, offset_y, FALSE);
}
else
{
GIMP_LAYER_CLASS (parent_class)->translate (layer, offset_x, offset_y);
}
}
static void
gimp_vector_layer_scale (GimpItem *item,
gint new_width,
gint new_height,
gint new_offset_x,
gint new_offset_y,
GimpInterpolationType interp_type,
GimpProgress *progress)
{
GimpVectorLayer *vector_layer = GIMP_VECTOR_LAYER (item);
if (vector_layer->options && vector_layer->options->path)
{
gimp_item_scale (GIMP_ITEM (vector_layer->options->path),
new_width, new_height, new_offset_x, new_offset_y,
interp_type, progress);
}
else
{
GIMP_ITEM_CLASS (parent_class)->scale (item, new_width, new_height,
new_offset_x, new_offset_y,
interp_type, progress);
}
}
static void
gimp_vector_layer_flip (GimpItem *item,
GimpContext *context,
GimpOrientationType flip_type,
gdouble axis,
gboolean clip_result)
{
GimpVectorLayer *vector_layer = GIMP_VECTOR_LAYER (item);
if (vector_layer->options && vector_layer->options->path)
{
gimp_item_flip (GIMP_ITEM (vector_layer->options->path),
context, flip_type, axis, clip_result);
}
else
{
GIMP_ITEM_CLASS (parent_class)->flip (item, context, flip_type,
axis, clip_result);
}
}
static void
gimp_vector_layer_rotate (GimpItem *item,
GimpContext *context,
GimpRotationType rotate_type,
gdouble center_x,
gdouble center_y,
gboolean clip_result)
{
GimpVectorLayer *vector_layer = GIMP_VECTOR_LAYER (item);
if (vector_layer->options && vector_layer->options->path)
{
gimp_item_rotate (GIMP_ITEM (vector_layer->options->path),
context, rotate_type, center_x, center_y, clip_result);
}
else
{
GIMP_ITEM_CLASS (parent_class)->rotate (item, context, rotate_type,
center_x, center_y, clip_result);
}
}
static void
gimp_vector_layer_transform (GimpItem *item,
GimpContext *context,
const GimpMatrix3 *matrix,
GimpTransformDirection direction,
GimpInterpolationType interp_type,
GimpTransformResize clip_result,
GimpProgress *progress)
{
GimpVectorLayer *vector_layer = GIMP_VECTOR_LAYER (item);
if (vector_layer->options && vector_layer->options->path)
{
gimp_item_transform (GIMP_ITEM (vector_layer->options->path),
context, matrix, direction, interp_type,
clip_result, progress);
}
else
{
GIMP_ITEM_CLASS (parent_class)->transform (item, context, matrix,
direction, interp_type,
clip_result, progress);
}
}
static void
gimp_vector_layer_removed_options_path (GimpVectorLayer *layer)
{
if (layer->options)
{
gimp_image_undo_push_vector_layer (gimp_item_get_image (GIMP_ITEM (layer)),
_("Discard Vector Informations"),
layer, NULL);
g_object_set (layer->options, "path", NULL, NULL);
}
}
static void
gimp_vector_layer_removed (GimpItem *item)
{
GimpVectorLayer *vector_layer = GIMP_VECTOR_LAYER (item);
if (vector_layer->options && vector_layer->options->path)
g_signal_handlers_disconnect_by_func (vector_layer->options->path,
G_CALLBACK (gimp_vector_layer_removed_options_path),
vector_layer);
GIMP_ITEM_CLASS (parent_class)->removed (item);
}
/* public functions */
/**
* gimp_vector_layer_new:
* @image: the #GimpImage the layer should belong to
* @path: the #GimpPath object the layer should render
* @context: the #GimpContext from which to pull context properties
*
* Creates a new vector layer.
*
* Return value: a new #GimpVectorLayer or %NULL in case of a problem
**/
GimpVectorLayer *
gimp_vector_layer_new (GimpImage *image,
GimpPath *path,
GimpContext *context)
{
GimpVectorLayer *layer;
GimpVectorLayerOptions *options;
gint x = 0;
gint y = 0;
gint width = gimp_image_get_width (image);
gint height = gimp_image_get_height (image);
g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
g_return_val_if_fail (GIMP_IS_PATH (path), NULL);
g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
options = gimp_vector_layer_options_new (image, path, context);
gimp_item_bounds (GIMP_ITEM (path), &x, &y, &width, &height);
/* Set boundaries to image size if it's a blank path */
if (width == 0 || height == 0)
{
width = gimp_image_get_width (image);
height = gimp_image_get_height (image);
}
layer =
GIMP_VECTOR_LAYER (gimp_drawable_new (GIMP_TYPE_VECTOR_LAYER,
image, NULL,
x, y, width, height,
gimp_image_get_layer_format (image,
TRUE)));
gimp_object_set_name (GIMP_OBJECT (layer),
gimp_object_get_name (GIMP_OBJECT (path)));
gimp_layer_set_mode (GIMP_LAYER (layer),
gimp_image_get_default_new_layer_mode (image),
FALSE);
gimp_vector_layer_set_vector_options (layer, options);
return layer;
}
/**
* gimp_vector_layer_get_path:
* @layer: a #GimpVectorLayer
*
* Gets the path from @layer if one is associated with it.
*
* Return value: a #GimpPath or %NULL if no path is set.
*/
GimpPath *
gimp_vector_layer_get_path (GimpVectorLayer *layer)
{
g_return_val_if_fail (GIMP_IS_VECTOR_LAYER (layer), NULL);
if (gimp_item_is_vector_layer (GIMP_ITEM (layer)))
return layer->options->path;
return NULL;
}
void
gimp_vector_layer_refresh (GimpVectorLayer *layer)
{
if (layer->options)
gimp_vector_layer_render (layer);
}
/**
* gimp_vector_layer_discard:
* @layer: a #GimpVectorLayer
*
* Discards the vector information. This makes @layer behave like a
* normal layer.
*/
void
gimp_vector_layer_discard (GimpVectorLayer *layer)
{
g_return_if_fail (GIMP_IS_VECTOR_LAYER (layer));
g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (layer)));
if (! layer->options)
return;
if (layer->options->path)
gimp_image_undo_push_vector_layer (gimp_item_get_image (GIMP_ITEM (layer)),
_("Discard Vector Information"),
layer, NULL);
g_object_set (layer, "vector-layer-options", NULL, NULL);
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (layer));
gimp_image_flush (gimp_item_get_image (GIMP_ITEM (layer)));
}
gboolean
gimp_item_is_vector_layer (GimpItem *item)
{
return (GIMP_IS_VECTOR_LAYER (item) &&
GIMP_VECTOR_LAYER (item)->options);
}
/* private functions */
static gboolean
gimp_vector_layer_render (GimpVectorLayer *layer)
{
GimpDrawable *drawable = GIMP_DRAWABLE (layer);
GeglBuffer *buffer = NULL;
GimpItem *item = GIMP_ITEM (layer);
GimpImage *image = gimp_item_get_image (item);
gint layer_x = 0;
gint layer_y = 0;
gint x = 0;
gint y = 0;
gint width = gimp_image_get_width (image);
gint height = gimp_image_get_height (image);
gdouble stroke = 0;
g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), FALSE);
g_object_freeze_notify (G_OBJECT (drawable));
if (layer->options->enable_stroke)
stroke = gimp_stroke_options_get_width (layer->options->stroke_options);
/* Resize layer according to path size */
gimp_item_get_offset (GIMP_ITEM (layer), &layer_x, &layer_y);
gimp_item_bounds (GIMP_ITEM (layer->options->path), &x, &y, &width, &height);
buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0,
width + stroke, height + stroke),
gimp_drawable_get_format (drawable));
gimp_drawable_set_buffer (drawable, FALSE, NULL, buffer);
g_object_unref (buffer);
gimp_item_set_offset (GIMP_ITEM (layer), x - (stroke / 2), y - (stroke / 2));
/* make the layer background transparent */
gimp_drawable_fill (GIMP_DRAWABLE (layer),
gimp_get_user_context (image->gimp),
GIMP_FILL_TRANSPARENT);
/* render path to the layer */
gimp_vector_layer_render_path (layer);
g_object_thaw_notify (G_OBJECT (drawable));
return TRUE;
}
static void
gimp_vector_layer_render_path (GimpVectorLayer *layer)
{
GimpImage *image = gimp_item_get_image (GIMP_ITEM (layer));
GimpVectorLayerOptions *options = layer->options;
GimpPath *path = NULL;
GimpChannel *selection = gimp_image_get_mask (image);
GList *drawables;
GimpCustomStyle style;
if (options)
path = options->path;
/* Don't mask these fill/stroke operations */
gimp_selection_suspend (GIMP_SELECTION (selection));
/* Convert from custom to standard styles */
style = gimp_fill_options_get_custom_style (options->fill_options);
if (style == GIMP_CUSTOM_STYLE_SOLID_COLOR ||
! gimp_context_get_pattern (GIMP_CONTEXT (options->fill_options)))
gimp_fill_options_set_style (options->fill_options,
GIMP_FILL_STYLE_FG_COLOR);
else
gimp_fill_options_set_style (options->fill_options,
GIMP_FILL_STYLE_PATTERN);
style =
gimp_fill_options_get_custom_style (GIMP_FILL_OPTIONS (options->stroke_options));
if (style == GIMP_CUSTOM_STYLE_SOLID_COLOR ||
! gimp_context_get_pattern (GIMP_CONTEXT (options->stroke_options)))
gimp_fill_options_set_style (GIMP_FILL_OPTIONS (options->stroke_options),
GIMP_FILL_STYLE_FG_COLOR);
else
gimp_fill_options_set_style (GIMP_FILL_OPTIONS (options->stroke_options),
GIMP_FILL_STYLE_PATTERN);
/* Fill the path object onto the layer */
if (options->enable_fill)
gimp_drawable_fill_path (GIMP_DRAWABLE (layer),
options->fill_options,
path, FALSE, NULL);
drawables = g_list_prepend (NULL, GIMP_DRAWABLE (layer));
/* stroke the path object onto the layer */
if (options->enable_stroke && gimp_item_is_attached (GIMP_ITEM (path)))
gimp_item_stroke (GIMP_ITEM (path), drawables,
gimp_get_user_context (image->gimp),
options->stroke_options,
FALSE, FALSE,
NULL, NULL);
g_list_free (drawables);
gimp_selection_resume (GIMP_SELECTION (selection));
}
static void
gimp_vector_layer_changed_options (GimpVectorLayer *layer)
{
GimpItem *item = GIMP_ITEM (layer);
if (layer->parasite)
{
/* parasite is out of date, discard it */
gimp_parasite_list_remove (gimp_item_get_parasites (GIMP_ITEM (layer)),
layer->parasite);
layer->parasite = NULL;
}
if (layer->options && !layer->options->path)
gimp_vector_layer_discard (layer);
else if (gimp_item_is_attached (item))
gimp_vector_layer_refresh (layer);
}

View File

@@ -0,0 +1,69 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpvectorlayer.h
*
* Copyright 2006 Hendrik Boom
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __GIMP_VECTOR_LAYER_H__
#define __GIMP_VECTOR_LAYER_H__
#include "core/gimplayer.h"
#define GIMP_TYPE_VECTOR_LAYER (gimp_vector_layer_get_type ())
#define GIMP_VECTOR_LAYER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_VECTOR_LAYER, GimpVectorLayer))
#define GIMP_VECTOR_LAYER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_VECTOR_LAYER, GimpVectorLayerClass))
#define GIMP_IS_VECTOR_LAYER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_VECTOR_LAYER))
#define GIMP_IS_VECTOR_LAYER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_VECTOR_LAYER))
#define GIMP_VECTOR_LAYER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_VECTOR_LAYER, GimpVectorLayerClass))
typedef struct _GimpVectorLayerClass GimpVectorLayerClass;
struct _GimpVectorLayer
{
GimpLayer parent_instance;
GimpVectorLayerOptions *options;
const gchar *parasite;
gboolean modified;
};
struct _GimpVectorLayerClass
{
GimpLayerClass parent_class;
};
GType gimp_vector_layer_get_type (void) G_GNUC_CONST;
GimpVectorLayer * gimp_vector_layer_new (GimpImage *image,
GimpPath *path,
GimpContext *context);
GimpPath * gimp_vector_layer_get_path (GimpVectorLayer *layer);
void gimp_vector_layer_refresh (GimpVectorLayer *layer);
void gimp_vector_layer_discard (GimpVectorLayer *layer);
gboolean gimp_item_is_vector_layer (GimpItem *item);
#endif /* __GIMP_VECTOR_LAYER_H__ */

View File

@@ -0,0 +1,95 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpvectorlayeroptions-parasite.c
*
* Copyright 2006 Hendrik Boom
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <string.h>
#include <stdlib.h>
#include <glib-object.h>
#include <gio/gio.h>
#include "libgimpbase/gimpbase.h"
#include "libgimpconfig/gimpconfig.h"
#include "path-types.h"
#include "gimpvectorlayeroptions.h"
#include "gimpvectorlayeroptions-parasite.h"
#include "gimp-intl.h"
const gchar *
gimp_vector_layer_options_parasite_name (void)
{
return "gimp-vector-layer-options";
}
GimpParasite *
gimp_vector_layer_options_to_parasite (GimpVectorLayerOptions *options)
{
GimpParasite *parasite;
gchar *str;
g_return_val_if_fail (GIMP_IS_VECTOR_LAYER_OPTIONS (options), NULL);
str = gimp_config_serialize_to_string (GIMP_CONFIG (options), NULL);
g_return_val_if_fail (str != NULL, NULL);
parasite = gimp_parasite_new (gimp_vector_layer_options_parasite_name (),
GIMP_PARASITE_PERSISTENT,
strlen (str) + 1, str);
g_free (str);
return parasite;
}
GimpVectorLayerOptions *
gimp_vector_layer_options_from_parasite (const GimpParasite *parasite,
GError **error,
Gimp *gimp)
{
GimpVectorLayerOptions *options;
const gchar *str;
guint32 parasite_length;
g_return_val_if_fail (parasite != NULL, NULL);
g_return_val_if_fail (strcmp (gimp_parasite_get_name (parasite),
gimp_vector_layer_options_parasite_name ()) == 0,
NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
str = gimp_parasite_get_data (parasite, &parasite_length);
g_return_val_if_fail (str != NULL, NULL);
options = g_object_new (GIMP_TYPE_VECTOR_LAYER_OPTIONS,
"gimp", gimp,
NULL);
gimp_config_deserialize_string (GIMP_CONFIG (options),
str,
parasite_length,
NULL,
error);
return options;
}

View File

@@ -0,0 +1,33 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpvectorlayeroptions-parasite.h
*
* Copyright 2006 Hendrik Boom
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __GIMP_VECTOR_LAYER_OPTIONS_PARASITE_H__
#define __GIMP_VECTOR_LAYER_OPTIONS_PARASITE_H__
const gchar * gimp_vector_layer_options_parasite_name (void) G_GNUC_CONST;
GimpParasite * gimp_vector_layer_options_to_parasite (GimpVectorLayerOptions *text);
GimpVectorLayerOptions * gimp_vector_layer_options_from_parasite (const GimpParasite *parasite,
GError **error,
Gimp *gimp);
#endif /* __GIMP_VECTOR_LAYER_OPTIONS_PARASITE_H__ */

View File

@@ -0,0 +1,364 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpvectorlayers.c
*
* Copyright 2006 Hendrik Boom
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <cairo.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gegl.h>
#include "libgimpbase/gimpbase.h"
#include "libgimpconfig/gimpconfig.h"
#include "libgimpcolor/gimpcolor.h"
#include "path-types.h"
#include "core/gimp.h"
#include "core/gimpimage.h"
#include "core/gimpstrokeoptions.h"
#include "gimppath.h"
#include "gimpvectorlayer.h"
#include "gimpvectorlayeroptions.h"
#include "gimp-intl.h"
enum
{
PROP_0,
PROP_GIMP,
PROP_PATH,
PROP_PATH_TATTOO,
PROP_ENABLE_FILL,
PROP_FILL_OPTIONS,
PROP_ENABLE_STROKE,
PROP_STROKE_OPTIONS
};
/* local function declarations */
static GObject *gimp_vector_layer_options_constructor (GType type,
guint n_params,
GObjectConstructParam *params);
static void gimp_vector_layer_options_finalize (GObject *object);
static void gimp_vector_layer_options_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
static void gimp_vector_layer_options_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_vector_layer_options_path_changed (GimpVectorLayerOptions *options);
G_DEFINE_TYPE_WITH_CODE (GimpVectorLayerOptions,
gimp_vector_layer_options,
GIMP_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (GIMP_TYPE_CONFIG, NULL))
#define parent_class gimp_vector_layer_options_parent_class
static void
gimp_vector_layer_options_class_init (GimpVectorLayerOptionsClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->constructor = gimp_vector_layer_options_constructor;
object_class->finalize = gimp_vector_layer_options_finalize;
object_class->set_property = gimp_vector_layer_options_set_property;
object_class->get_property = gimp_vector_layer_options_get_property;
g_object_class_install_property (object_class, PROP_GIMP,
g_param_spec_object ("gimp",
NULL, NULL,
GIMP_TYPE_GIMP,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
GIMP_CONFIG_PROP_OBJECT (object_class, PROP_PATH,
"path", NULL, NULL,
GIMP_TYPE_PATH,
GIMP_PARAM_READWRITE |
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_UINT (object_class, PROP_PATH_TATTOO,
"path-tattoo", NULL, NULL,
0, G_MAXUINT32, 0,
G_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_ENABLE_FILL,
"enable-fill",
_("Fill Style"), NULL,
TRUE,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_OBJECT (object_class, PROP_FILL_OPTIONS,
"fill-options", NULL, NULL,
GIMP_TYPE_FILL_OPTIONS,
G_PARAM_STATIC_STRINGS |
GIMP_CONFIG_PARAM_AGGREGATE);
GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_ENABLE_STROKE,
"enable-stroke",
_("Stroke Style"), NULL,
TRUE,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_OBJECT (object_class, PROP_STROKE_OPTIONS,
"stroke-options", NULL, NULL,
GIMP_TYPE_STROKE_OPTIONS,
G_PARAM_STATIC_STRINGS |
GIMP_CONFIG_PARAM_AGGREGATE);
}
static void
gimp_vector_layer_options_init (GimpVectorLayerOptions *options)
{
options->path = NULL;
options->path_tattoo = 0;
}
static GObject *
gimp_vector_layer_options_constructor (GType type,
guint n_params,
GObjectConstructParam *params)
{
GObject *object;
GimpVectorLayerOptions *options;
object = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params);
options = GIMP_VECTOR_LAYER_OPTIONS (object);
g_assert (GIMP_IS_GIMP (options->gimp));
options->fill_options = gimp_fill_options_new (options->gimp, NULL, FALSE);
options->stroke_options = gimp_stroke_options_new (options->gimp, NULL, FALSE);
return object;
}
static void
gimp_vector_layer_options_finalize (GObject *object)
{
GimpVectorLayerOptions *options = GIMP_VECTOR_LAYER_OPTIONS (object);
if (options->path)
{
g_object_unref (options->path);
options->path = NULL;
}
if (options->fill_options)
{
g_object_unref (options->fill_options);
options->fill_options = NULL;
}
if (options->stroke_options)
{
g_object_unref (options->stroke_options);
options->stroke_options = NULL;
}
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
gimp_vector_layer_options_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GimpVectorLayerOptions *options = GIMP_VECTOR_LAYER_OPTIONS (object);
switch (property_id)
{
case PROP_GIMP:
g_value_set_object (value, options->gimp);
break;
case PROP_PATH:
g_value_set_object (value, options->path);
break;
case PROP_PATH_TATTOO:
g_value_set_uint (value, options->path_tattoo);
break;
case PROP_ENABLE_FILL:
g_value_set_boolean (value, options->enable_fill);
break;
case PROP_FILL_OPTIONS:
g_value_set_object (value, options->fill_options);
break;
case PROP_ENABLE_STROKE:
g_value_set_boolean (value, options->enable_stroke);
break;
case PROP_STROKE_OPTIONS:
g_value_set_object (value, options->stroke_options);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gimp_vector_layer_options_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
GimpVectorLayerOptions *options = GIMP_VECTOR_LAYER_OPTIONS (object);
switch (property_id)
{
case PROP_GIMP:
options->gimp = g_value_get_object (value);
break;
case PROP_PATH:
if (options->path)
{
g_signal_handlers_disconnect_by_func (options->path,
G_CALLBACK (gimp_vector_layer_options_path_changed),
options);
g_object_unref (options->path);
}
options->path = g_value_dup_object (value);
if (options->path)
{
g_signal_connect_object (options->path, "invalidate-preview",
G_CALLBACK (gimp_vector_layer_options_path_changed),
options, G_CONNECT_SWAPPED);
g_signal_connect_object (options->path, "name-changed",
G_CALLBACK (gimp_vector_layer_options_path_changed),
options, G_CONNECT_SWAPPED);
/* update the tattoo */
options->path_tattoo = gimp_item_get_tattoo (GIMP_ITEM (options->path));
}
break;
case PROP_PATH_TATTOO:
options->path_tattoo = g_value_get_uint (value);
if (options->path &&
gimp_item_get_tattoo (GIMP_ITEM (options->path)) != options->path_tattoo)
{
GimpImage *image = gimp_item_get_image (GIMP_ITEM (options->path));
g_object_set (options,
"path", gimp_image_get_path_by_tattoo
(image, options->path_tattoo),
NULL);
}
break;
case PROP_ENABLE_FILL:
options->enable_fill = g_value_get_boolean (value);
break;
case PROP_FILL_OPTIONS:
if (g_value_get_object (value))
gimp_config_sync (g_value_get_object (value),
G_OBJECT (options->fill_options), 0);
break;
case PROP_ENABLE_STROKE:
options->enable_stroke = g_value_get_boolean (value);
break;
case PROP_STROKE_OPTIONS:
if (g_value_get_object (value))
{
if (options->stroke_options)
g_object_unref (options->stroke_options);
options->stroke_options = gimp_config_duplicate (g_value_get_object (value));
}
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gimp_vector_layer_options_path_changed (GimpVectorLayerOptions *options)
{
g_object_notify (G_OBJECT (options), "path");
}
/* public functions */
/**
* gimp_vector_layer_options_new:
* @image: the #GimpImage the layer belongs to
* @path: the #GimpPath object for the layer to render
* @context: the #GimpContext from which to pull context properties
*
* Creates a new vector layer options.
*
* Return value: a new #GimpVectorLayerOptions or %NULL in case of a problem
**/
GimpVectorLayerOptions *
gimp_vector_layer_options_new (GimpImage *image,
GimpPath *path,
GimpContext *context)
{
GimpVectorLayerOptions *options;
GimpPattern *pattern;
GeglColor *stroke_color;
GeglColor *fill_color;
g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
g_return_val_if_fail (GIMP_IS_PATH (path), NULL);
g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
options = g_object_new (GIMP_TYPE_VECTOR_LAYER_OPTIONS,
"gimp", image->gimp,
NULL);
stroke_color = gimp_context_get_foreground (context);
fill_color = gimp_context_get_background (context);
pattern = gimp_context_get_pattern (context);
gimp_context_set_foreground (GIMP_CONTEXT (options->fill_options),
fill_color);
gimp_context_set_pattern (GIMP_CONTEXT (options->fill_options), pattern);
gimp_context_set_foreground (GIMP_CONTEXT (options->stroke_options),
stroke_color);
gimp_context_set_pattern (GIMP_CONTEXT (options->stroke_options), pattern);
g_object_set (options,
"path", path,
NULL);
return options;
}

View File

@@ -0,0 +1,66 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpvectorlayeroptions.h
*
* Copyright 2006 Hendrik Boom
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __GIMP_VECTOR_LAYER_OPTIONS_H__
#define __GIMP_VECTOR_LAYER_OPTIONS_H__
#include "core/gimpobject.h"
#define GIMP_TYPE_VECTOR_LAYER_OPTIONS (gimp_vector_layer_options_get_type ())
#define GIMP_VECTOR_LAYER_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_VECTOR_LAYER_OPTIONS, GimpVectorLayerOptions))
#define GIMP_VECTOR_LAYER_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_VECTOR_LAYER_OPTIONS, GimpVectorLayerOptionsClass))
#define GIMP_IS_VECTOR_LAYER_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_VECTOR_LAYER_OPTIONS))
#define GIMP_IS_VECTOR_LAYER_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_VECTOR_LAYER_OPTIONS))
#define GIMP_VECTOR_LAYER_OPTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_VECTOR_LAYER_OPTIONS, GimpVectorLayerOptionsClass))
typedef struct _GimpVectorLayerOptionsClass GimpVectorLayerOptionsClass;
struct _GimpVectorLayerOptions
{
GimpObject parent_instance;
Gimp *gimp;
GimpTattoo path_tattoo;
GimpPath *path;
gboolean enable_fill;
gboolean enable_stroke;
GimpFillOptions *fill_options;
GimpStrokeOptions *stroke_options;
};
struct _GimpVectorLayerOptionsClass
{
GimpObjectClass parent_class;
};
GType gimp_vector_layer_options_get_type (void) G_GNUC_CONST;
GimpVectorLayerOptions * gimp_vector_layer_options_new (GimpImage *image,
GimpPath *path,
GimpContext *context);
#endif /* __GIMP_VECTOR_LAYER_OPTIONS_H__ */

View File

@@ -0,0 +1,288 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpvectorlayerundo.h
*
* Copyright 2006 Hendrik Boom
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gio/gio.h>
#include <gegl.h>
#include "libgimpconfig/gimpconfig.h"
#include "path-types.h"
#include "core/gimp-memsize.h"
#include "core/gimpitem.h"
#include "core/gimpitemundo.h"
#include "core/gimp-utils.h"
#include "gimpvectorlayer.h"
#include "gimpvectorlayeroptions.h"
#include "gimpvectorlayerundo.h"
enum
{
PROP_0,
PROP_PARAM
};
static void gimp_vector_layer_undo_constructed (GObject *object);
static void gimp_vector_layer_undo_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_vector_layer_undo_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
static gint64 gimp_vector_layer_undo_get_memsize (GimpObject *object,
gint64 *gui_size);
static void gimp_vector_layer_undo_pop (GimpUndo *undo,
GimpUndoMode undo_mode,
GimpUndoAccumulator *accum);
static void gimp_vector_layer_undo_free (GimpUndo *undo,
GimpUndoMode undo_mode);
G_DEFINE_TYPE (GimpVectorLayerUndo, gimp_vector_layer_undo, GIMP_TYPE_ITEM_UNDO)
#define parent_class gimp_vector_layer_undo_parent_class
static void
gimp_vector_layer_undo_class_init (GimpVectorLayerUndoClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass);
GimpUndoClass *undo_class = GIMP_UNDO_CLASS (klass);
object_class->constructed = gimp_vector_layer_undo_constructed;
object_class->set_property = gimp_vector_layer_undo_set_property;
object_class->get_property = gimp_vector_layer_undo_get_property;
gimp_object_class->get_memsize = gimp_vector_layer_undo_get_memsize;
undo_class->pop = gimp_vector_layer_undo_pop;
undo_class->free = gimp_vector_layer_undo_free;
g_object_class_install_property (object_class, PROP_PARAM,
g_param_spec_param ("param", NULL, NULL,
G_TYPE_PARAM,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
}
static void
gimp_vector_layer_undo_init (GimpVectorLayerUndo *undo)
{
}
static void
gimp_vector_layer_undo_constructed (GObject *object)
{
GimpVectorLayerUndo *vector_undo = GIMP_VECTOR_LAYER_UNDO (object);
GimpVectorLayer *vector_layer;
G_OBJECT_CLASS (parent_class)->constructed (object);
g_assert (GIMP_IS_VECTOR_LAYER (GIMP_ITEM_UNDO (vector_undo)->item));
vector_layer = GIMP_VECTOR_LAYER (GIMP_ITEM_UNDO (vector_undo)->item);
switch (GIMP_UNDO (object)->undo_type)
{
case GIMP_UNDO_VECTOR_LAYER:
if (vector_undo->pspec)
{
g_assert (vector_undo->pspec->owner_type == GIMP_TYPE_VECTOR_LAYER_OPTIONS);
vector_undo->value = g_slice_new0 (GValue);
g_value_init (vector_undo->value, vector_undo->pspec->value_type);
g_object_get_property (G_OBJECT (vector_layer->options),
vector_undo->pspec->name, vector_undo->value);
}
else if (vector_layer->options)
{
vector_undo->vector_layer_options = gimp_config_duplicate (GIMP_CONFIG (vector_layer->options));
}
break;
case GIMP_UNDO_VECTOR_LAYER_MODIFIED:
vector_undo->modified = vector_layer->modified;
break;
default:
g_assert_not_reached ();
}
}
static void
gimp_vector_layer_undo_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
GimpVectorLayerUndo *vector_undo = GIMP_VECTOR_LAYER_UNDO (object);
switch (property_id)
{
case PROP_PARAM:
vector_undo->pspec = g_value_get_param (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gimp_vector_layer_undo_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GimpVectorLayerUndo *vector_undo = GIMP_VECTOR_LAYER_UNDO (object);
switch (property_id)
{
case PROP_PARAM:
g_value_set_param (value, (GParamSpec *) vector_undo->pspec);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static gint64
gimp_vector_layer_undo_get_memsize (GimpObject *object,
gint64 *gui_size)
{
GimpVectorLayerUndo *undo = GIMP_VECTOR_LAYER_UNDO (object);
gint64 memsize = 0;
memsize += gimp_g_value_get_memsize (undo->value);
memsize += gimp_object_get_memsize (GIMP_OBJECT (undo->vector_layer_options), NULL);
return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
gui_size);
}
static void
gimp_vector_layer_undo_pop (GimpUndo *undo,
GimpUndoMode undo_mode,
GimpUndoAccumulator *accum)
{
GimpVectorLayerUndo *vector_undo = GIMP_VECTOR_LAYER_UNDO (undo);
GimpVectorLayer *vector_layer = GIMP_VECTOR_LAYER (GIMP_ITEM_UNDO (undo)->item);
GIMP_UNDO_CLASS (parent_class)->pop (undo, undo_mode, accum);
switch (undo->undo_type)
{
case GIMP_UNDO_VECTOR_LAYER:
if (vector_undo->pspec)
{
GValue *value;
g_return_if_fail (vector_layer->options != NULL);
value = g_slice_new0 (GValue);
g_value_init (value, vector_undo->pspec->value_type);
g_object_get_property (G_OBJECT (vector_layer->options),
vector_undo->pspec->name, value);
g_object_set_property (G_OBJECT (vector_layer->options),
vector_undo->pspec->name, vector_undo->value);
g_value_unset (vector_undo->value);
g_slice_free (GValue, vector_undo->value);
vector_undo->value = value;
}
else
{
GimpVectorLayerOptions *vector_layer_options;
vector_layer_options = (vector_layer->options ?
gimp_config_duplicate (GIMP_CONFIG (vector_layer->options)) : NULL);
if (vector_layer->options && vector_undo->vector_layer_options)
gimp_config_sync (G_OBJECT (vector_undo->vector_layer_options),
G_OBJECT (vector_layer->options), 0);
else
g_object_set (vector_layer,
"vector-layer-options", vector_undo->vector_layer_options,
NULL);
if (vector_undo->vector_layer_options)
g_object_unref (vector_undo->vector_layer_options);
vector_undo->vector_layer_options = vector_layer_options;
}
break;
case GIMP_UNDO_VECTOR_LAYER_MODIFIED:
{
gboolean modified;
modified = vector_layer->modified;
g_object_set (vector_layer, "modified", vector_undo->modified, NULL);
vector_undo->modified = modified;
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (vector_layer));
}
break;
default:
g_assert_not_reached ();
}
}
static void
gimp_vector_layer_undo_free (GimpUndo *undo,
GimpUndoMode undo_mode)
{
GimpVectorLayerUndo *vector_undo = GIMP_VECTOR_LAYER_UNDO (undo);
if (vector_undo->vector_layer_options)
{
g_object_unref (vector_undo->vector_layer_options);
vector_undo->vector_layer_options = NULL;
}
if (vector_undo->pspec)
{
g_value_unset (vector_undo->value);
g_slice_free (GValue, vector_undo->value);
vector_undo->value = NULL;
vector_undo->pspec = NULL;
}
GIMP_UNDO_CLASS (parent_class)->free (undo, undo_mode);
}

View File

@@ -0,0 +1,58 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpvectorlayerundo.h
*
* Copyright 2006 Hendrik Boom
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __GIMP_VECTOR_LAYER_UNDO_H__
#define __GIMP_VECTOR_LAYER_UNDO_H__
#include "core/gimpitemundo.h"
#define GIMP_TYPE_VECTOR_LAYER_UNDO (gimp_vector_layer_undo_get_type ())
#define GIMP_VECTOR_LAYER_UNDO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_VECTOR_LAYER_UNDO, GimpVectorLayerUndo))
#define GIMP_VECTOR_LAYER_UNDO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_VECTOR_LAYER_UNDO, GimpVectorLayerUndoClass))
#define GIMP_IS_VECTOR_LAYER_UNDO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_VECTOR_LAYER_UNDO))
#define GIMP_IS_VECTOR_LAYER_UNDO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_VECTOR_LAYER_UNDO))
#define GIMP_VECTOR_LAYER_UNDO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_VECTOR_LAYER_UNDO, GimpVectorLayerUndoClass))
typedef struct _GimpVectorLayerUndoClass GimpVectorLayerUndoClass;
struct _GimpVectorLayerUndo
{
GimpItemUndo parent_instance;
GimpVectorLayerOptions *vector_layer_options;
const GParamSpec *pspec;
GValue *value;
gboolean modified;
};
struct _GimpVectorLayerUndoClass
{
GimpItemClass parent_class;
};
GType gimp_vector_layer_undo_get_type (void) G_GNUC_CONST;
#endif /* __GIMP_VECTOR_LAYER_UNDO_H__ */

View File

@@ -12,6 +12,11 @@ libapppath_sources = [
'gimppathundo.c',
'gimpstroke-new.c',
'gimpstroke.c',
'gimpvectorlayer.c',
'gimpvectorlayer-xcf.c',
'gimpvectorlayeroptions.c',
'gimpvectorlayeroptions-parasite.c',
'gimpvectorlayerundo.c',
]
libapppath = static_library('apppath',

View File

@@ -25,8 +25,12 @@
#include "path-enums.h"
typedef struct _GimpAnchor GimpAnchor;
typedef struct _GimpAnchor GimpAnchor;
typedef struct _GimpPath GimpPath;
typedef struct _GimpStroke GimpStroke;
typedef struct _GimpBezierStroke GimpBezierStroke;
typedef struct _GimpPath GimpPath;
typedef struct _GimpStroke GimpStroke;
typedef struct _GimpBezierStroke GimpBezierStroke;
typedef struct _GimpVectorLayer GimpVectorLayer;
typedef struct _GimpVectorLayerOptions GimpVectorLayerOptions;
typedef struct _GimpVectorLayerUndo GimpVectorLayerUndo;

View File

@@ -30,7 +30,7 @@
#include "internal-procs.h"
/* 721 procedures registered total */
/* 725 procedures registered total */
void
internal_procs_init (GimpPDB *pdb)
@@ -94,4 +94,5 @@ internal_procs_init (GimpPDB *pdb)
register_text_layer_procs (pdb);
register_text_tool_procs (pdb);
register_unit_procs (pdb);
register_vector_layer_procs (pdb);
}

View File

@@ -81,3 +81,4 @@ void register_selection_procs (GimpPDB *pdb);
void register_text_layer_procs (GimpPDB *pdb);
void register_text_tool_procs (GimpPDB *pdb);
void register_unit_procs (GimpPDB *pdb);
void register_vector_layer_procs (GimpPDB *pdb);

View File

@@ -39,6 +39,7 @@
#include "core/gimpparamspecs.h"
#include "core/gimpselection.h"
#include "path/gimppath.h"
#include "path/gimpvectorlayer.h"
#include "text/gimptextlayer.h"
#include "gimppdb.h"
@@ -179,6 +180,39 @@ item_id_is_text_layer_invoker (GimpProcedure *procedure,
return return_vals;
}
static GimpValueArray *
item_id_is_vector_layer_invoker (GimpProcedure *procedure,
Gimp *gimp,
GimpContext *context,
GimpProgress *progress,
const GimpValueArray *args,
GError **error)
{
gboolean success = TRUE;
GimpValueArray *return_vals;
gint item_id;
gboolean vector_layer = FALSE;
item_id = g_value_get_int (gimp_value_array_index (args, 0));
if (success)
{
GimpItem *item = gimp_item_get_by_id (gimp, item_id);
vector_layer = (GIMP_IS_LAYER (item) &&
! gimp_item_is_removed (item) &&
gimp_item_is_vector_layer (item));
}
return_vals = gimp_procedure_get_return_values (procedure, success,
error ? *error : NULL);
if (success)
g_value_set_boolean (gimp_value_array_index (return_vals, 1), vector_layer);
return return_vals;
}
static GimpValueArray *
item_id_is_group_layer_invoker (GimpProcedure *procedure,
Gimp *gimp,
@@ -1191,6 +1225,37 @@ register_item_procs (GimpPDB *pdb)
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);
/*
* gimp-item-id-is-vector-layer
*/
procedure = gimp_procedure_new (item_id_is_vector_layer_invoker, FALSE);
gimp_object_set_static_name (GIMP_OBJECT (procedure),
"gimp-item-id-is-vector-layer");
gimp_procedure_set_static_help (procedure,
"Returns whether the item ID is a vector layer.",
"This procedure returns %TRUE if the specified item ID is a vector layer.\n"
"\n"
"*Note*: in most use cases, you should not use this function. See [func@Gimp.Item.id_is_layer] for a discussion on alternatives.",
NULL);
gimp_procedure_set_static_attribution (procedure,
"Alex S.",
"Alex S.",
"2025");
gimp_procedure_add_argument (procedure,
g_param_spec_int ("item-id",
"item id",
"The item ID",
G_MININT32, G_MAXINT32, 0,
GIMP_PARAM_READWRITE));
gimp_procedure_add_return_value (procedure,
g_param_spec_boolean ("vector-layer",
"vector layer",
"TRUE if the item is a vector layer, FALSE otherwise.",
FALSE,
GIMP_PARAM_READWRITE));
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);
/*
* gimp-item-id-is-group-layer
*/

View File

@@ -66,6 +66,7 @@ libappinternalprocs_sources = [
'text-layer-cmds.c',
'text-tool-cmds.c',
'unit-cmds.c',
'vector-layer-cmds.c',
]
libapppdb = static_library('apppdb',

232
app/pdb/vector-layer-cmds.c Normal file
View File

@@ -0,0 +1,232 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995-2003 Spencer Kimball and Peter Mattis
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/* NOTE: This file is auto-generated by pdbgen.pl. */
#include "config.h"
#include "stamp-pdbgen.h"
#include <gegl.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include "libgimpbase/gimpbase.h"
#include "libgimpbase/gimpbase.h"
#include "pdb-types.h"
#include "core/gimpcontext.h"
#include "core/gimpimage.h"
#include "core/gimpparamspecs.h"
#include "path/gimppath.h"
#include "path/gimpvectorlayer.h"
#include "gimppdb.h"
#include "gimppdberror.h"
#include "gimppdb-utils.h"
#include "gimpprocedure.h"
#include "internal-procs.h"
#include "gimp-intl.h"
static GimpValueArray *
vector_layer_new_invoker (GimpProcedure *procedure,
Gimp *gimp,
GimpContext *context,
GimpProgress *progress,
const GimpValueArray *args,
GError **error)
{
gboolean success = TRUE;
GimpValueArray *return_vals;
GimpImage *image;
GimpPath *path;
GimpVectorLayer *layer = NULL;
image = g_value_get_object (gimp_value_array_index (args, 0));
path = g_value_get_object (gimp_value_array_index (args, 1));
if (success)
{
if (path == NULL)
{
g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_ERROR_INVALID_ARGUMENT,
_("Failed to create vector layer"));
success = FALSE;
}
if (success)
{
layer = GIMP_VECTOR_LAYER (gimp_vector_layer_new (image, path, context));
if (! layer)
{
g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_ERROR_INVALID_ARGUMENT,
_("Failed to create vector layer"));
success = FALSE;
}
}
}
return_vals = gimp_procedure_get_return_values (procedure, success,
error ? *error : NULL);
if (success)
g_value_set_object (gimp_value_array_index (return_vals, 1), layer);
return return_vals;
}
static GimpValueArray *
vector_layer_refresh_invoker (GimpProcedure *procedure,
Gimp *gimp,
GimpContext *context,
GimpProgress *progress,
const GimpValueArray *args,
GError **error)
{
gboolean success = TRUE;
GimpVectorLayer *layer;
layer = g_value_get_object (gimp_value_array_index (args, 0));
if (success)
{
gimp_vector_layer_refresh (layer);
}
return gimp_procedure_get_return_values (procedure, success,
error ? *error : NULL);
}
static GimpValueArray *
vector_layer_discard_invoker (GimpProcedure *procedure,
Gimp *gimp,
GimpContext *context,
GimpProgress *progress,
const GimpValueArray *args,
GError **error)
{
gboolean success = TRUE;
GimpVectorLayer *layer;
layer = g_value_get_object (gimp_value_array_index (args, 0));
if (success)
{
gimp_vector_layer_discard (layer);
}
return gimp_procedure_get_return_values (procedure, success,
error ? *error : NULL);
}
void
register_vector_layer_procs (GimpPDB *pdb)
{
GimpProcedure *procedure;
/*
* gimp-vector-layer-new
*/
procedure = gimp_procedure_new (vector_layer_new_invoker, FALSE);
gimp_object_set_static_name (GIMP_OBJECT (procedure),
"gimp-vector-layer-new");
gimp_procedure_set_static_help (procedure,
"Creates a new vector layer.",
"This procedure creates a new path layer displaying the specified @path. By default, the fill and stroke properties will be defined by the context.\n"
"\n"
"The new layer still needs to be added to the image as this is not automatic. Add the new layer with the [method@Image.insert_layer] method.\n"
"\n"
"The arguments are kept as simple as necessary for the basic case. All vector attributes, however, can be modified with the appropriate `gimp_vector_layer_set_*()` procedures.",
NULL);
gimp_procedure_set_static_attribution (procedure,
"Alex S.",
"Alex S.",
"2025");
gimp_procedure_add_argument (procedure,
gimp_param_spec_image ("image",
"image",
"The image",
FALSE,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
gimp_param_spec_path ("path",
"path",
"The path to create the layer from",
FALSE,
GIMP_PARAM_READWRITE));
gimp_procedure_add_return_value (procedure,
gimp_param_spec_vector_layer ("layer",
"layer",
"The new vector layer. The object belongs to libgimp and you should not free it.",
FALSE,
GIMP_PARAM_READWRITE));
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);
/*
* gimp-vector-layer-refresh
*/
procedure = gimp_procedure_new (vector_layer_refresh_invoker, FALSE);
gimp_object_set_static_name (GIMP_OBJECT (procedure),
"gimp-vector-layer-refresh");
gimp_procedure_set_static_help (procedure,
"Rerender the vector layer",
"This procedure causes the vector layer to refresh itself after changes.",
NULL);
gimp_procedure_set_static_attribution (procedure,
"Alex S.",
"Alex S.",
"2025");
gimp_procedure_add_argument (procedure,
gimp_param_spec_vector_layer ("layer",
"layer",
"The vector layer",
FALSE,
GIMP_PARAM_READWRITE));
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);
/*
* gimp-vector-layer-discard
*/
procedure = gimp_procedure_new (vector_layer_discard_invoker, FALSE);
gimp_object_set_static_name (GIMP_OBJECT (procedure),
"gimp-vector-layer-discard");
gimp_procedure_set_static_help (procedure,
"Discard the vector layer information.",
"Discards the vector information. This makes the layer behave like a normal layer.",
NULL);
gimp_procedure_set_static_attribution (procedure,
"Alex S.",
"Alex S.",
"2025");
gimp_procedure_add_argument (procedure,
gimp_param_spec_vector_layer ("layer",
"layer",
"The vector layer",
FALSE,
GIMP_PARAM_READWRITE));
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);
}

View File

@@ -46,6 +46,7 @@
#include "core/gimpunit.h"
#include "path/gimppath.h"
#include "path/gimpvectorlayer.h"
#include "text/gimpfont.h"
#include "text/gimptextlayer.h"

View File

@@ -41,6 +41,8 @@
#include "paint/gimppaintcore.h"
#include "paint/gimppaintoptions.h"
#include "path/gimpvectorlayer.h"
#include "widgets/gimpdevices.h"
#include "widgets/gimpwidgets-utils.h"
@@ -342,6 +344,24 @@ gimp_paint_tool_button_press (GimpTool *tool,
}
}
if (gimp_item_is_vector_layer (GIMP_ITEM (drawable)))
{
gboolean constrain_only;
/* Allow vector layers to be set as sources */
constrain_only = (state & gimp_get_constrain_behavior_mask () &&
! (state & gimp_get_extend_selection_mask ()));
if (! (GIMP_IS_SOURCE_TOOL (tool) && constrain_only))
{
gimp_tool_message_literal (tool, display,
_("Vector layers must be rasterized "
"before they can be painted on."));
g_list_free (drawables);
return;
}
}
if (! gimp_paint_tool_check_alpha (paint_tool, drawable, display, &error))
{
GtkWidget *options_gui;

View File

@@ -24,12 +24,21 @@
#include <gtk/gtk.h>
#include "libgimpbase/gimpbase.h"
#include "libgimpcolor/gimpcolor.h"
#include "libgimpconfig/gimpconfig.h"
#include "libgimpwidgets/gimpwidgets.h"
#include "tools-types.h"
#include "core/gimp.h"
#include "core/gimpcontainer.h"
#include "core/gimpdatafactory.h"
#include "core/gimppattern.h"
#include "core/gimpstrokeoptions.h"
#include "widgets/gimphelp-ids.h"
#include "widgets/gimppropwidgets.h"
#include "widgets/gimpstrokeeditor.h"
#include "widgets/gimpwidgets-utils.h"
#include "gimppathoptions.h"
@@ -42,28 +51,68 @@ enum
{
PROP_0,
PROP_PATH_EDIT_MODE,
PROP_PATH_POLYGONAL
PROP_PATH_POLYGONAL,
PROP_ENABLE_FILL,
PROP_ENABLE_STROKE,
PROP_FILL_STYLE,
PROP_FILL_FOREGROUND,
PROP_FILL_PATTERN,
PROP_FILL_ANTIALIAS,
PROP_STROKE_STYLE,
PROP_STROKE_FOREGROUND,
PROP_STROKE_PATTERN,
PROP_STROKE_WIDTH,
PROP_STROKE_UNIT,
PROP_STROKE_ANTIALIAS,
PROP_STROKE_CAP_STYLE,
PROP_STROKE_JOIN_STYLE,
PROP_STROKE_MITER_LIMIT,
PROP_STROKE_DASH_OFFSET
};
static void gimp_path_options_config_iface_init (GimpConfigInterface *config_iface);
static gboolean gimp_path_options_serialize_property (GimpConfig *config,
guint property_id,
const GValue *value,
GParamSpec *pspec,
GimpConfigWriter *writer);
static gboolean gimp_path_options_deserialize_property (GimpConfig *config,
guint property_id,
GValue *value,
GParamSpec *pspec,
GScanner *scanner,
GTokenType *expected);
static void gimp_path_options_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_path_options_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
static void gimp_path_options_finalize (GObject *object);
static void gimp_path_options_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_path_options_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
G_DEFINE_TYPE (GimpPathOptions, gimp_path_options, GIMP_TYPE_TOOL_OPTIONS)
G_DEFINE_TYPE_WITH_CODE (GimpPathOptions, gimp_path_options,
GIMP_TYPE_TOOL_OPTIONS,
G_IMPLEMENT_INTERFACE (GIMP_TYPE_CONFIG,
gimp_path_options_config_iface_init))
#define parent_class gimp_path_options_parent_class
static GimpConfigInterface *parent_config_iface = NULL;
static void
gimp_path_options_class_init (GimpPathOptionsClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GeglColor *black = gegl_color_new ("black");
GeglColor *white = gegl_color_new ("white");
object_class->finalize = gimp_path_options_finalize;
object_class->set_property = gimp_path_options_set_property;
object_class->get_property = gimp_path_options_get_property;
@@ -81,11 +130,140 @@ gimp_path_options_class_init (GimpPathOptionsClass *klass)
_("Restrict editing to polygons"),
FALSE,
GIMP_PARAM_STATIC_STRINGS);
/* Vector layer specific properties */
GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_ENABLE_FILL,
"enable-fill",
_("Enable Fill"), NULL,
TRUE,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_ENABLE_STROKE,
"enable-stroke",
_("Enable Stroke"), NULL,
TRUE,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_ENUM (object_class, PROP_FILL_STYLE,
"fill-custom-style",
NULL, NULL,
GIMP_TYPE_CUSTOM_STYLE,
GIMP_CUSTOM_STYLE_SOLID_COLOR,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_COLOR (object_class, PROP_FILL_FOREGROUND,
"fill-foreground",
NULL, NULL,
TRUE, white,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_OBJECT (object_class, PROP_FILL_PATTERN,
"fill-pattern",
NULL, NULL,
GIMP_TYPE_PATTERN,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_FILL_ANTIALIAS,
"fill-antialias",
NULL, NULL,
TRUE,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_ENUM (object_class, PROP_STROKE_STYLE,
"stroke-custom-style",
NULL, NULL,
GIMP_TYPE_CUSTOM_STYLE,
GIMP_CUSTOM_STYLE_SOLID_COLOR,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_COLOR (object_class, PROP_STROKE_FOREGROUND,
"stroke-foreground",
NULL, NULL,
TRUE, black,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_OBJECT (object_class, PROP_STROKE_PATTERN,
"stroke-pattern",
NULL, NULL,
GIMP_TYPE_PATTERN,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_STROKE_WIDTH,
"stroke-width",
NULL, NULL,
0.0, 2000.0, 6.0,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_UNIT (object_class, PROP_STROKE_UNIT,
"stroke-unit",
NULL, NULL,
TRUE, FALSE, gimp_unit_pixel (),
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_STROKE_ANTIALIAS,
"stroke-antialias",
NULL, NULL,
TRUE,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_ENUM (object_class, PROP_STROKE_CAP_STYLE,
"stroke-cap-style",
NULL, NULL,
GIMP_TYPE_CAP_STYLE, GIMP_CAP_BUTT,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_ENUM (object_class, PROP_STROKE_JOIN_STYLE,
"stroke-join-style",
NULL, NULL,
GIMP_TYPE_JOIN_STYLE, GIMP_JOIN_MITER,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_STROKE_MITER_LIMIT,
"stroke-miter-limit",
NULL, NULL,
0.0, 100.0, 10.0,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_STROKE_DASH_OFFSET,
"stroke-dash-offset",
NULL, NULL,
0.0, 2000.0, 0.0,
GIMP_PARAM_STATIC_STRINGS);
g_clear_object (&white);
g_clear_object (&black);
}
static void
gimp_path_options_config_iface_init (GimpConfigInterface *config_iface)
{
parent_config_iface = g_type_interface_peek_parent (config_iface);
config_iface->serialize_property = gimp_path_options_serialize_property;
config_iface->deserialize_property = gimp_path_options_deserialize_property;
}
static void
gimp_path_options_init (GimpPathOptions *options)
{
GeglColor *black = gegl_color_new ("black");
GeglColor *white = gegl_color_new ("white");
options->fill_foreground = white;
options->stroke_foreground = black;
}
static void
gimp_path_options_finalize (GObject *object)
{
GimpPathOptions *options = GIMP_PATH_OPTIONS (object);
g_clear_object (&options->fill_options);
g_clear_object (&options->stroke_options);
g_clear_object (&options->fill_foreground);
g_clear_object (&options->stroke_foreground);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
@@ -104,13 +282,84 @@ gimp_path_options_set_property (GObject *object,
case PROP_PATH_POLYGONAL:
options->polygonal = g_value_get_boolean (value);
break;
case PROP_ENABLE_FILL:
options->enable_fill = g_value_get_boolean (value);
break;
case PROP_ENABLE_STROKE:
options->enable_stroke = g_value_get_boolean (value);
break;
case PROP_FILL_STYLE:
options->fill_style = g_value_get_enum (value);
break;
case PROP_FILL_FOREGROUND:
g_set_object (&options->fill_foreground, g_value_get_object (value));
break;
case PROP_FILL_PATTERN:
{
GimpPattern *pattern = g_value_get_object (value);
if (options->fill_pattern != pattern)
{
if (options->fill_pattern)
g_object_unref (options->fill_pattern);
options->fill_pattern = pattern ? g_object_ref (pattern) : pattern;
}
break;
}
case PROP_FILL_ANTIALIAS:
options->fill_antialias = g_value_get_boolean (value);
break;
case PROP_STROKE_STYLE:
options->stroke_style = g_value_get_enum (value);
break;
case PROP_STROKE_FOREGROUND:
g_set_object (&options->stroke_foreground, g_value_get_object (value));
break;
case PROP_STROKE_PATTERN:
{
GimpPattern *pattern = g_value_get_object (value);
if (options->stroke_pattern != pattern)
{
if (options->stroke_pattern)
g_object_unref (options->stroke_pattern);
options->stroke_pattern = pattern ?
g_object_ref (pattern) : pattern;
}
break;
}
case PROP_STROKE_WIDTH:
options->stroke_width = g_value_get_double (value);
break;
case PROP_STROKE_UNIT:
options->stroke_unit = g_value_get_object (value);
break;
case PROP_STROKE_ANTIALIAS:
options->stroke_antialias = g_value_get_boolean (value);
break;
case PROP_STROKE_CAP_STYLE:
options->stroke_cap_style = g_value_get_enum (value);
break;
case PROP_STROKE_JOIN_STYLE:
options->stroke_join_style = g_value_get_enum (value);
break;
case PROP_STROKE_MITER_LIMIT:
options->stroke_miter_limit = g_value_get_double (value);
break;
case PROP_STROKE_DASH_OFFSET:
options->stroke_dash_offset = g_value_get_double (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gimp_path_options_get_property (GObject *object,
guint property_id,
@@ -127,12 +376,138 @@ gimp_path_options_get_property (GObject *object,
case PROP_PATH_POLYGONAL:
g_value_set_boolean (value, options->polygonal);
break;
case PROP_ENABLE_FILL:
g_value_set_boolean (value, options->enable_fill);
break;
case PROP_ENABLE_STROKE:
g_value_set_boolean (value, options->enable_stroke);
break;
case PROP_FILL_STYLE:
g_value_set_enum (value, options->fill_style);
break;
case PROP_FILL_FOREGROUND:
g_value_set_object (value, options->fill_foreground);
break;
case PROP_FILL_PATTERN:
g_value_set_object (value, options->fill_pattern);
break;
case PROP_FILL_ANTIALIAS:
g_value_set_boolean (value, options->fill_antialias);
break;
case PROP_STROKE_STYLE:
g_value_set_enum (value, options->stroke_style);
break;
case PROP_STROKE_FOREGROUND:
g_value_set_object (value, options->stroke_foreground);
break;
case PROP_STROKE_PATTERN:
g_value_set_object (value, options->stroke_pattern);
break;
case PROP_STROKE_WIDTH:
g_value_set_double (value, options->stroke_width);
break;
case PROP_STROKE_UNIT:
g_value_set_object (value, options->stroke_unit);
break;
case PROP_STROKE_ANTIALIAS:
g_value_set_boolean (value, options->stroke_antialias);
break;
case PROP_STROKE_CAP_STYLE:
g_value_set_enum (value, options->stroke_cap_style);
break;
case PROP_STROKE_JOIN_STYLE:
g_value_set_enum (value, options->stroke_join_style);
break;
case PROP_STROKE_MITER_LIMIT:
g_value_set_double (value, options->stroke_miter_limit);
break;
case PROP_STROKE_DASH_OFFSET:
g_value_set_double (value, options->stroke_dash_offset);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static gboolean
gimp_path_options_serialize_property (GimpConfig *config,
guint property_id,
const GValue *value,
GParamSpec *pspec,
GimpConfigWriter *writer)
{
if (property_id == PROP_FILL_PATTERN ||
property_id == PROP_STROKE_PATTERN)
{
GimpObject *serialize_obj = g_value_get_object (value);
gimp_config_writer_open (writer, pspec->name);
if (serialize_obj)
gimp_config_writer_string (writer,
gimp_object_get_name (serialize_obj));
else
gimp_config_writer_print (writer, "NULL", 4);
gimp_config_writer_close (writer);
return TRUE;
}
return FALSE;
}
static gboolean
gimp_path_options_deserialize_property (GimpConfig *object,
guint property_id,
GValue *value,
GParamSpec *pspec,
GScanner *scanner,
GTokenType *expected)
{
if (property_id == PROP_FILL_PATTERN ||
property_id == PROP_STROKE_PATTERN)
{
gchar *object_name;
if (gimp_scanner_parse_identifier (scanner, "NULL"))
{
g_value_set_object (value, NULL);
}
else if (gimp_scanner_parse_string (scanner, &object_name))
{
GimpContext *context = GIMP_CONTEXT (object);
GimpContainer *container;
GimpObject *deserialize_obj;
if (! object_name)
object_name = g_strdup ("");
container =
gimp_data_factory_get_container (context->gimp->pattern_factory);
deserialize_obj = gimp_container_get_child_by_name (container,
object_name);
g_value_set_object (value, deserialize_obj);
g_free (object_name);
}
else
{
*expected = G_TOKEN_STRING;
}
return TRUE;
}
return FALSE;
}
static void
button_append_modifier (GtkWidget *button,
GdkModifierType modifiers)
@@ -149,7 +524,7 @@ GtkWidget *
gimp_path_options_gui (GimpToolOptions *tool_options)
{
GObject *config = G_OBJECT (tool_options);
GimpPathOptions *options = GIMP_PATH_OPTIONS (tool_options);
GimpPathOptions *options = GIMP_PATH_OPTIONS (tool_options);
GtkWidget *vbox = gimp_tool_options_gui (tool_options);
GtkWidget *frame;
GtkWidget *button;
@@ -198,23 +573,7 @@ gimp_path_options_gui (GimpToolOptions *tool_options)
options->to_selection_button = button;
button = gtk_button_new_with_label (_("Fill Path"));
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_widget_set_sensitive (button, FALSE);
gimp_help_set_help_data (button, NULL, GIMP_HELP_PATH_FILL);
gtk_widget_set_visible (button, TRUE);
options->fill_button = button;
button = gtk_button_new_with_label (_("Stroke Path"));
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_widget_set_sensitive (button, FALSE);
gimp_help_set_help_data (button, NULL, GIMP_HELP_PATH_STROKE);
gtk_widget_set_visible (button, TRUE);
options->stroke_button = button;
button = gtk_button_new_with_label (_("Create Vector Layer"));
button = gtk_button_new_with_label (_("Create New Vector Layer"));
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_widget_set_sensitive (button, FALSE);
gimp_help_set_help_data (button, NULL, NULL);
@@ -222,5 +581,64 @@ gimp_path_options_gui (GimpToolOptions *tool_options)
options->vector_layer_button = button;
/* The fill editor */
{
GtkWidget *frame;
GtkWidget *fill_editor;
options->fill_options =
gimp_fill_options_new (GIMP_CONTEXT (options)->gimp,
NULL, FALSE);
#define FILL_BIND(a) \
g_object_bind_property (options, "fill-" #a, \
options->fill_options, #a, \
G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE)
FILL_BIND (custom-style);
FILL_BIND (foreground);
FILL_BIND (pattern);
fill_editor = gimp_fill_editor_new (options->fill_options,
TRUE, TRUE);
gtk_widget_set_visible (fill_editor, TRUE);
frame = gimp_prop_expanding_frame_new (config, "enable-fill", NULL,
fill_editor, NULL);
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
}
/* The stroke editor */
{
GtkWidget *frame;
GtkWidget *stroke_editor;
options->stroke_options =
gimp_stroke_options_new (GIMP_CONTEXT (options)->gimp,
NULL, FALSE);
#define STROKE_BIND(a) \
g_object_bind_property (options, "stroke-" #a, \
options->stroke_options, #a, \
G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE)
STROKE_BIND (custom-style);
STROKE_BIND (foreground);
STROKE_BIND (pattern);
STROKE_BIND (width);
STROKE_BIND (unit);
STROKE_BIND (cap-style);
STROKE_BIND (join-style);
STROKE_BIND (miter-limit);
STROKE_BIND (antialias);
STROKE_BIND (dash-offset);
stroke_editor = gimp_stroke_editor_new (options->stroke_options, 72.0,
TRUE, TRUE);
gtk_widget_set_visible (stroke_editor, TRUE);
frame = gimp_prop_expanding_frame_new (config, "enable-stroke", NULL,
stroke_editor, NULL);
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
}
return vbox;
}

View File

@@ -28,20 +28,41 @@
#define GIMP_PATH_OPTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_PATH_OPTIONS, GimpPathOptionsClass))
typedef struct _GimpPathOptions GimpPathOptions;
typedef struct _GimpPathOptions GimpPathOptions;
typedef struct _GimpToolOptionsClass GimpPathOptionsClass;
struct _GimpPathOptions
{
GimpToolOptions parent_instance;
GimpToolOptions parent_instance;
GimpPathMode edit_mode;
gboolean polygonal;
GimpPathMode edit_mode;
gboolean polygonal;
/* vector layer */
gboolean enable_fill;
gboolean enable_stroke;
GimpFillOptions *fill_options;
GimpStrokeOptions *stroke_options;
GimpCustomStyle fill_style;
GeglColor *fill_foreground;
GimpPattern *fill_pattern;
gboolean fill_antialias;
GimpCustomStyle stroke_style;
GeglColor *stroke_foreground;
GimpPattern *stroke_pattern;
gboolean stroke_antialias;
gdouble stroke_width;
GimpUnit *stroke_unit;
GimpCapStyle stroke_cap_style;
GimpJoinStyle stroke_join_style;
gdouble stroke_miter_limit;
gdouble stroke_dash_offset;
/* options gui */
GtkWidget *to_selection_button;
GtkWidget *fill_button;
GtkWidget *stroke_button;
GtkWidget *to_selection_button;
GtkWidget *vector_layer_button;
};

View File

@@ -35,12 +35,15 @@
#include "core/gimpimage-pick-item.h"
#include "core/gimpimage-undo.h"
#include "core/gimpimage-undo-push.h"
#include "core/gimpstrokeoptions.h"
#include "core/gimptoolinfo.h"
#include "core/gimpundostack.h"
#include "paint/gimppaintoptions.h" /* GIMP_PAINT_OPTIONS_CONTEXT_MASK */
#include "path/gimppath.h"
#include "path/gimpvectorlayer.h"
#include "path/gimpvectorlayeroptions.h"
#include "widgets/gimpdialogfactory.h"
#include "widgets/gimpdockcontainer.h"
@@ -70,6 +73,7 @@
/* local function prototypes */
static void gimp_path_tool_constructed (GObject *object);
static void gimp_path_tool_dispose (GObject *object);
static void gimp_path_tool_control (GimpTool *tool,
@@ -106,6 +110,12 @@ static void gimp_path_tool_start (GimpPathTool *path_t
GimpDisplay *display);
static void gimp_path_tool_halt (GimpPathTool *path_tool);
static void gimp_path_tool_image_changed (GimpPathTool *path_tool,
GimpImage *image,
GimpContext *context);
static void gimp_path_tool_image_selected_layers_changed
(GimpPathTool *path_tool);
static void gimp_path_tool_tool_path_changed (GimpToolWidget *tool_path,
GimpPathTool *path_tool);
static void gimp_path_tool_tool_path_begin_change
@@ -130,23 +140,12 @@ static void gimp_path_tool_to_selection_extended
(GimpPathTool *path_tool,
GdkModifierType state);
static void gimp_path_tool_fill_path (GimpPathTool *path_tool,
GtkWidget *button);
static void gimp_path_tool_fill_callback (GtkWidget *dialog,
GList *items,
GList *drawables,
GimpContext *context,
GimpFillOptions *options,
gpointer data);
static void gimp_path_tool_stroke_path (GimpPathTool *path_tool,
GtkWidget *button);
static void gimp_path_tool_stroke_callback (GtkWidget *dialog,
GList *items,
GList *drawables,
GimpContext *context,
GimpStrokeOptions *options,
gpointer data);
static void gimp_path_tool_create_vector_layer(GimpPathTool *path_tool,
GtkWidget *button);
static void gimp_path_tool_vector_change_notify
(GObject *options,
const GParamSpec *pspec,
GimpVectorLayer *layer);
G_DEFINE_TYPE (GimpPathTool, gimp_path_tool, GIMP_TYPE_DRAW_TOOL)
@@ -179,6 +178,7 @@ gimp_path_tool_class_init (GimpPathToolClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GimpToolClass *tool_class = GIMP_TOOL_CLASS (klass);
object_class->constructed = gimp_path_tool_constructed;
object_class->dispose = gimp_path_tool_dispose;
tool_class->control = gimp_path_tool_control;
@@ -203,6 +203,28 @@ gimp_path_tool_init (GimpPathTool *path_tool)
path_tool->saved_mode = GIMP_PATH_MODE_DESIGN;
}
static void
gimp_path_tool_constructed (GObject *object)
{
GimpPathTool *path_tool = GIMP_PATH_TOOL (object);
GimpContext *context;
GimpToolInfo *tool_info;
G_OBJECT_CLASS (parent_class)->constructed (object);
tool_info = GIMP_TOOL (path_tool)->tool_info;
context = gimp_get_user_context (tool_info->gimp);
g_signal_connect_object (context, "image-changed",
G_CALLBACK (gimp_path_tool_image_changed),
path_tool, G_CONNECT_SWAPPED);
gimp_path_tool_image_changed (path_tool,
gimp_context_get_image (context),
context);
}
static void
gimp_path_tool_dispose (GObject *object)
{
@@ -211,6 +233,8 @@ gimp_path_tool_dispose (GObject *object)
gimp_path_tool_set_path (path_tool, NULL);
g_clear_object (&path_tool->widget);
gimp_path_tool_image_changed (path_tool, NULL, NULL);
G_OBJECT_CLASS (parent_class)->dispose (object);
}
@@ -445,6 +469,87 @@ gimp_path_tool_halt (GimpPathTool *path_tool)
tool->display = NULL;
}
static void
gimp_path_tool_image_changed (GimpPathTool *path_tool,
GimpImage *image,
GimpContext *context)
{
if (path_tool->current_image)
g_signal_handlers_disconnect_by_func (path_tool->current_image,
gimp_path_tool_image_selected_layers_changed,
NULL);
g_set_weak_pointer (&path_tool->current_image, image);
if (path_tool->current_image)
g_signal_connect_object (path_tool->current_image, "selected-layers-changed",
G_CALLBACK (gimp_path_tool_image_selected_layers_changed),
path_tool, G_CONNECT_SWAPPED);
gimp_path_tool_image_selected_layers_changed (path_tool);
}
static void
gimp_path_tool_image_selected_layers_changed (GimpPathTool *path_tool)
{
GimpPathOptions *options = GIMP_PATH_TOOL_GET_OPTIONS (path_tool);
GList *current_layers = NULL;
if (path_tool->current_vector_layer)
{
g_signal_handlers_disconnect_by_func (options,
gimp_path_tool_vector_change_notify,
path_tool->current_vector_layer);
g_signal_handlers_disconnect_by_func (options->fill_options,
gimp_path_tool_vector_change_notify,
path_tool->current_vector_layer);
g_signal_handlers_disconnect_by_func (options->stroke_options,
gimp_path_tool_vector_change_notify,
path_tool->current_vector_layer);
path_tool->current_vector_layer = NULL;
gimp_path_tool_set_path (path_tool, NULL);
}
if (path_tool->current_image)
current_layers = gimp_image_get_selected_layers (path_tool->current_image);
/* If we've selected a single vector layer, make its path editable */
if (current_layers &&
g_list_length (current_layers) == 1 &&
gimp_item_is_vector_layer (GIMP_ITEM (current_layers->data)))
{
GimpVectorLayer *vector_layer = current_layers->data;
gimp_path_tool_set_path (path_tool,
gimp_vector_layer_get_path (vector_layer));
g_object_set (options,
"enable-fill", vector_layer->options->enable_fill,
"enable_stroke", vector_layer->options->enable_stroke,
NULL);
gimp_config_sync (G_OBJECT (vector_layer->options->stroke_options),
G_OBJECT (options->stroke_options), 0);
gimp_config_sync (G_OBJECT (vector_layer->options->fill_options),
G_OBJECT (options->fill_options), 0);
g_signal_connect_object (options, "notify::enable-fill",
G_CALLBACK (gimp_path_tool_vector_change_notify),
vector_layer, 0);
g_signal_connect_object (options, "notify::enable-stroke",
G_CALLBACK (gimp_path_tool_vector_change_notify),
vector_layer, 0);
g_signal_connect_object (options->fill_options, "notify",
G_CALLBACK (gimp_path_tool_vector_change_notify),
vector_layer, 0);
g_signal_connect_object (options->stroke_options, "notify",
G_CALLBACK (gimp_path_tool_vector_change_notify),
vector_layer, 0);
path_tool->current_vector_layer = vector_layer;
}
}
static void
gimp_path_tool_tool_path_changed (GimpToolWidget *tool_path,
GimpPathTool *path_tool)
@@ -453,9 +558,7 @@ gimp_path_tool_tool_path_changed (GimpToolWidget *tool_path,
GimpImage *image = gimp_display_get_image (shell->display);
GimpPath *path;
g_object_get (tool_path,
"path", &path,
NULL);
g_object_get (tool_path, "path", &path, NULL);
if (path != path_tool->path)
{
@@ -595,19 +698,11 @@ gimp_path_tool_set_path (GimpPathTool *path_tool,
tool);
}
if (options->fill_button)
if (options->vector_layer_button)
{
gtk_widget_set_sensitive (options->fill_button, FALSE);
g_signal_handlers_disconnect_by_func (options->fill_button,
gimp_path_tool_fill_path,
tool);
}
if (options->stroke_button)
{
gtk_widget_set_sensitive (options->stroke_button, FALSE);
g_signal_handlers_disconnect_by_func (options->stroke_button,
gimp_path_tool_stroke_path,
gtk_widget_set_sensitive (options->vector_layer_button, FALSE);
g_signal_handlers_disconnect_by_func (options->vector_layer_button,
gimp_path_tool_create_vector_layer,
tool);
}
}
@@ -642,20 +737,13 @@ gimp_path_tool_set_path (GimpPathTool *path_tool,
gtk_widget_set_sensitive (options->to_selection_button, TRUE);
}
if (options->fill_button)
if (options->vector_layer_button)
{
g_signal_connect_swapped (options->fill_button, "clicked",
G_CALLBACK (gimp_path_tool_fill_path),
tool);
gtk_widget_set_sensitive (options->fill_button, TRUE);
}
g_signal_connect_swapped (options->vector_layer_button, "clicked",
G_CALLBACK (gimp_path_tool_create_vector_layer),
tool);
if (options->stroke_button)
{
g_signal_connect_swapped (options->stroke_button, "clicked",
G_CALLBACK (gimp_path_tool_stroke_path),
tool);
gtk_widget_set_sensitive (options->stroke_button, TRUE);
gtk_widget_set_sensitive (options->vector_layer_button, TRUE);
}
if (tool->display)
@@ -722,180 +810,126 @@ gimp_path_tool_to_selection_extended (GimpPathTool *path_tool,
gimp_image_flush (image);
}
static void
gimp_path_tool_fill_path (GimpPathTool *path_tool,
GtkWidget *button)
gimp_path_tool_create_vector_layer (GimpPathTool *path_tool,
GtkWidget *button)
{
GimpDialogConfig *config;
GimpImage *image;
GList *drawables;
GList *path_list = NULL;
GtkWidget *dialog;
GimpImage *image;
GimpVectorLayer *layer;
GimpPathOptions *options = GIMP_PATH_TOOL_GET_OPTIONS (path_tool);
if (! path_tool->path)
return;
image = gimp_item_get_image (GIMP_ITEM (path_tool->path));
config = GIMP_DIALOG_CONFIG (image->gimp->config);
g_signal_handlers_block_by_func (image,
gimp_path_tool_image_selected_layers_changed,
path_tool);
drawables = gimp_image_get_selected_drawables (image);
if (! drawables)
/* If there's already an active vector layer, create a new blank path */
if (path_tool->current_vector_layer)
{
gimp_tool_message (GIMP_TOOL (path_tool),
GIMP_TOOL (path_tool)->display,
_("There are no selected layers or channels to fill."));
return;
GimpPath *new_path = gimp_path_new (image, _("Vector Layer"));
gimp_image_add_path (image, new_path, GIMP_IMAGE_ACTIVE_PARENT, -1,
TRUE);
g_signal_handlers_disconnect_by_func (options,
gimp_path_tool_vector_change_notify,
path_tool->current_vector_layer);
g_signal_handlers_disconnect_by_func (options->fill_options,
gimp_path_tool_vector_change_notify,
path_tool->current_vector_layer);
g_signal_handlers_disconnect_by_func (options->stroke_options,
gimp_path_tool_vector_change_notify,
path_tool->current_vector_layer);
}
if (g_list_length (drawables) == 1 &&
gimp_item_is_content_locked (GIMP_ITEM (drawables->data), NULL))
{
gimp_tool_message (GIMP_TOOL (path_tool),
GIMP_TOOL (path_tool)->display,
_("A selected layer's pixels are locked."));
return;
}
layer = gimp_vector_layer_new (image, path_tool->path,
gimp_get_user_context (image->gimp));
path_tool->current_vector_layer = layer;
path_list = g_list_prepend (NULL, path_tool->path);
dialog = fill_dialog_new (path_list, drawables,
GIMP_CONTEXT (GIMP_TOOL_GET_OPTIONS (path_tool)),
_("Fill Path"),
GIMP_ICON_TOOL_BUCKET_FILL,
GIMP_HELP_PATH_FILL,
button,
config->fill_options,
gimp_path_tool_fill_callback,
path_tool);
gtk_widget_show (dialog);
g_list_free (path_list);
g_list_free (drawables);
}
gimp_image_add_layer (image,
GIMP_LAYER (layer),
GIMP_IMAGE_ACTIVE_PARENT,
-1,
TRUE);
static void
gimp_path_tool_fill_callback (GtkWidget *dialog,
GList *items,
GList *drawables,
GimpContext *context,
GimpFillOptions *options,
gpointer data)
{
GimpDialogConfig *config = GIMP_DIALOG_CONFIG (context->gimp->config);
GimpImage *image = gimp_item_get_image (items->data);
GError *error = NULL;
g_object_set (layer->options,
"enable-fill", options->enable_fill,
"enable-stroke", options->enable_stroke,
NULL);
gimp_config_sync (G_OBJECT (options),
G_OBJECT (config->fill_options), 0);
gimp_config_sync (G_OBJECT (options->fill_options),
G_OBJECT (layer->options->fill_options), 0);
gimp_config_sync (G_OBJECT (options->stroke_options),
G_OBJECT (layer->options->stroke_options), 0);
gimp_image_undo_group_start (image,
GIMP_UNDO_GROUP_DRAWABLE_MOD,
"Fill");
g_signal_connect_object (options, "notify::enable-fill",
G_CALLBACK (gimp_path_tool_vector_change_notify),
layer, 0);
g_signal_connect_object (options, "notify::enable-stroke",
G_CALLBACK (gimp_path_tool_vector_change_notify),
layer, 0);
g_signal_connect_object (options->fill_options, "notify",
G_CALLBACK (gimp_path_tool_vector_change_notify),
layer, 0);
g_signal_connect_object (options->stroke_options, "notify",
G_CALLBACK (gimp_path_tool_vector_change_notify),
layer, 0);
for (GList *iter = items; iter; iter = iter->next)
if (! gimp_item_fill (iter->data, drawables, options,
TRUE, NULL, &error))
{
gimp_message_literal (context->gimp,
G_OBJECT (dialog),
GIMP_MESSAGE_WARNING,
error ? error->message : "NULL");
g_clear_error (&error);
break;
}
gimp_image_undo_group_end (image);
gimp_vector_layer_refresh (layer);
gimp_image_flush (image);
gtk_widget_destroy (dialog);
}
static void
gimp_path_tool_stroke_path (GimpPathTool *path_tool,
GtkWidget *button)
{
GimpDialogConfig *config;
GimpImage *image;
GList *drawables;
GList *path_list = NULL;
GtkWidget *dialog;
if (! path_tool->path)
return;
image = gimp_item_get_image (GIMP_ITEM (path_tool->path));
config = GIMP_DIALOG_CONFIG (image->gimp->config);
drawables = gimp_image_get_selected_drawables (image);
if (! drawables)
{
gimp_tool_message (GIMP_TOOL (path_tool),
GIMP_TOOL (path_tool)->display,
_("There are no selected layers or channels to stroke to."));
return;
}
if (g_list_length (drawables) == 1 &&
gimp_item_is_content_locked (GIMP_ITEM (drawables->data), NULL))
{
gimp_tool_message (GIMP_TOOL (path_tool),
GIMP_TOOL (path_tool)->display,
_("A selected layer's pixels are locked."));
return;
}
path_list = g_list_prepend (NULL, path_tool->path);
dialog = stroke_dialog_new (path_list, drawables,
GIMP_CONTEXT (GIMP_TOOL_GET_OPTIONS (path_tool)),
_("Stroke Path"),
GIMP_ICON_PATH_STROKE,
GIMP_HELP_PATH_STROKE,
button,
config->stroke_options,
gimp_path_tool_stroke_callback,
path_tool);
gtk_widget_show (dialog);
g_list_free (path_list);
g_list_free (drawables);
g_signal_handlers_unblock_by_func (image,
gimp_path_tool_image_selected_layers_changed,
path_tool);
}
static void
gimp_path_tool_stroke_callback (GtkWidget *dialog,
GList *items,
GList *drawables,
GimpContext *context,
GimpStrokeOptions *options,
gpointer data)
gimp_path_tool_vector_change_notify (GObject *options,
const GParamSpec *pspec,
GimpVectorLayer *layer)
{
GimpDialogConfig *config = GIMP_DIALOG_CONFIG (context->gimp->config);
GimpImage *image = gimp_item_get_image (items->data);
GError *error = NULL;
GimpImage *image;
gboolean needs_update = FALSE;
gimp_config_sync (G_OBJECT (options),
G_OBJECT (config->stroke_options), 0);
image = gimp_item_get_image (GIMP_ITEM (layer));
gimp_image_undo_group_start (image,
GIMP_UNDO_GROUP_DRAWABLE_MOD,
"Stroke");
if (GIMP_IS_STROKE_OPTIONS (options))
{
GimpStrokeOptions *stroke_options = GIMP_STROKE_OPTIONS (options);
for (GList *iter = items; iter; iter = iter->next)
if (! gimp_item_stroke (iter->data, drawables, context, options, NULL,
TRUE, NULL, &error))
{
gimp_message_literal (context->gimp,
G_OBJECT (dialog),
GIMP_MESSAGE_WARNING,
error ? error->message : "NULL");
gimp_config_sync (G_OBJECT (stroke_options),
G_OBJECT (layer->options->stroke_options), 0);
g_clear_error (&error);
break;
}
needs_update = TRUE;
}
else if (GIMP_IS_FILL_OPTIONS (options))
{
GimpFillOptions *fill_options = GIMP_FILL_OPTIONS (options);
gimp_image_undo_group_end (image);
gimp_image_flush (image);
gtk_widget_destroy (dialog);
gimp_config_sync (G_OBJECT (fill_options),
G_OBJECT (layer->options->fill_options), 0);
needs_update = TRUE;
}
else if (GIMP_IS_PATH_OPTIONS (options))
{
GimpPathOptions *path_options = GIMP_PATH_OPTIONS (options);
g_object_set (layer->options,
"enable-fill", path_options->enable_fill,
"enable-stroke", path_options->enable_stroke,
NULL);
needs_update = TRUE;
}
if (needs_update)
{
gimp_vector_layer_refresh (layer);
gimp_image_flush (image);
}
}

View File

@@ -38,13 +38,16 @@ typedef struct _GimpPathToolClass GimpPathToolClass;
struct _GimpPathTool
{
GimpDrawTool parent_instance;
GimpDrawTool parent_instance;
GimpPath *path; /* the current Path data */
GimpPathMode saved_mode; /* used by modifier_key() */
GimpImage *current_image;
GimpVectorLayer *current_vector_layer;
GimpToolWidget *widget;
GimpToolWidget *grab_widget;
GimpPath *path; /* the current Path data */
GimpPathMode saved_mode; /* used by modifier_key() */
GimpToolWidget *widget;
GimpToolWidget *grab_widget;
};
struct _GimpPathToolClass

View File

@@ -449,6 +449,7 @@ gimp_main (GType plug_in_type,
GIMP_TYPE_DRAWABLE, GIMP_TYPE_PARAM_DRAWABLE,
GIMP_TYPE_LAYER, GIMP_TYPE_PARAM_LAYER,
GIMP_TYPE_TEXT_LAYER, GIMP_TYPE_PARAM_TEXT_LAYER,
GIMP_TYPE_VECTOR_LAYER, GIMP_TYPE_PARAM_VECTOR_LAYER,
GIMP_TYPE_GROUP_LAYER, GIMP_TYPE_PARAM_GROUP_LAYER,
GIMP_TYPE_CHANNEL, GIMP_TYPE_PARAM_CHANNEL,
GIMP_TYPE_LAYER_MASK, GIMP_TYPE_PARAM_LAYER_MASK,

View File

@@ -601,6 +601,7 @@ EXPORTS
gimp_item_id_is_selection
gimp_item_id_is_text_layer
gimp_item_id_is_valid
gimp_item_id_is_vector_layer
gimp_item_is_channel
gimp_item_is_drawable
gimp_item_is_group
@@ -749,7 +750,9 @@ EXPORTS
gimp_param_spec_resource_none_allowed
gimp_param_spec_selection
gimp_param_spec_text_layer
gimp_param_spec_vector_layer
gimp_param_text_layer_get_type
gimp_param_vector_layer_get_type
gimp_path_bezier_stroke_conicto
gimp_path_bezier_stroke_cubicto
gimp_path_bezier_stroke_lineto
@@ -912,6 +915,9 @@ EXPORTS
gimp_procedure_add_unit_argument
gimp_procedure_add_unit_aux_argument
gimp_procedure_add_unit_return_value
gimp_procedure_add_vector_layer_argument
gimp_procedure_add_vector_layer_aux_argument
gimp_procedure_add_vector_layer_return_value
gimp_procedure_config_get_choice_id
gimp_procedure_config_get_color_array
gimp_procedure_config_get_core_object_array
@@ -1063,6 +1069,11 @@ EXPORTS
gimp_unit_new
gimp_update_metadata
gimp_user_time
gimp_vector_layer_discard
gimp_vector_layer_get_by_id
gimp_vector_layer_get_type
gimp_vector_layer_new
gimp_vector_layer_refresh
gimp_vector_load_procedure_extract_dimensions
gimp_vector_load_procedure_get_type
gimp_vector_load_procedure_new

View File

@@ -71,6 +71,7 @@
#include <libgimp/gimpselection.h>
#include <libgimp/gimptextlayer.h>
#include <libgimp/gimpthumbnailprocedure.h>
#include <libgimp/gimpvectorlayer.h>
#include <libgimp/gimpvectorloadprocedure.h>
#include <libgimp/gimp_pdb_headers.h>

View File

@@ -82,5 +82,6 @@
#include <libgimp/gimptextlayer_pdb.h>
#include <libgimp/gimptexttool_pdb.h>
#include <libgimp/gimpunit_pdb.h>
#include <libgimp/gimpvectorlayer_pdb.h>
#endif /* __GIMP_PDB_HEADERS_H__ */

View File

@@ -284,6 +284,11 @@ _gimp_gp_param_def_to_param_spec (const GPParamDef *param_def)
param_def->meta.m_id.none_ok,
flags);
if (! strcmp (param_def->type_name, "GimpParamVectorLayer"))
return gimp_param_spec_vector_layer (name, nick, blurb,
param_def->meta.m_id.none_ok,
flags);
if (! strcmp (param_def->type_name, "GimpParamGroupLayer"))
return gimp_param_spec_group_layer (name, nick, blurb,
param_def->meta.m_id.none_ok,
@@ -716,6 +721,10 @@ _gimp_param_spec_to_gp_param_def (GParamSpec *pspec,
{
type_name = "GimpParamTextLayer";
}
else if (value_type == GIMP_TYPE_VECTOR_LAYER)
{
type_name = "GimpParamVectorLayer";
}
else if (value_type == GIMP_TYPE_GROUP_LAYER)
{
type_name = "GimpParamGroupLayer";

View File

@@ -211,6 +211,46 @@ gimp_item_id_is_text_layer (gint item_id)
return text_layer;
}
/**
* gimp_item_id_is_vector_layer:
* @item_id: The item ID.
*
* Returns whether the item ID is a vector layer.
*
* This procedure returns %TRUE if the specified item ID is a vector
* layer.
*
* *Note*: in most use cases, you should not use this function. See
* [func@Gimp.Item.id_is_layer] for a discussion on alternatives.
*
* Returns: TRUE if the item is a vector layer, FALSE otherwise.
*
* Since: 3.2
**/
gboolean
gimp_item_id_is_vector_layer (gint item_id)
{
GimpValueArray *args;
GimpValueArray *return_vals;
gboolean vector_layer = FALSE;
args = gimp_value_array_new_from_types (NULL,
G_TYPE_INT, item_id,
G_TYPE_NONE);
return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (),
"gimp-item-id-is-vector-layer",
args);
gimp_value_array_unref (args);
if (GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS)
vector_layer = GIMP_VALUES_GET_BOOLEAN (return_vals, 1);
gimp_value_array_unref (return_vals);
return vector_layer;
}
/**
* gimp_item_id_is_group_layer:
* @item_id: The item ID.

View File

@@ -36,6 +36,7 @@ gboolean gimp_item_id_is_valid (gint item_id);
gboolean gimp_item_id_is_drawable (gint item_id);
gboolean gimp_item_id_is_layer (gint item_id);
gboolean gimp_item_id_is_text_layer (gint item_id);
gboolean gimp_item_id_is_vector_layer (gint item_id);
gboolean gimp_item_id_is_group_layer (gint item_id);
gboolean gimp_item_id_is_channel (gint item_id);
gboolean gimp_item_id_is_layer_mask (gint item_id);

View File

@@ -532,6 +532,86 @@ gimp_param_spec_text_layer (const gchar *name,
}
/*
* GIMP_TYPE_PARAM_VECTOR_LAYER
*/
static void gimp_param_vector_layer_class_init (GParamSpecClass *klass);
static void gimp_param_vector_layer_init (GParamSpec *pspec);
GType
gimp_param_vector_layer_get_type (void)
{
static GType type = 0;
if (! type)
{
const GTypeInfo info =
{
sizeof (GParamSpecClass),
NULL, NULL,
(GClassInitFunc) gimp_param_vector_layer_class_init,
NULL, NULL,
sizeof (GimpParamSpecItem),
0,
(GInstanceInitFunc) gimp_param_vector_layer_init
};
type = g_type_register_static (GIMP_TYPE_PARAM_LAYER,
"GimpParamVectorLayer", &info, 0);
}
return type;
}
static void
gimp_param_vector_layer_class_init (GParamSpecClass *klass)
{
klass->value_type = GIMP_TYPE_VECTOR_LAYER;
}
static void
gimp_param_vector_layer_init (GParamSpec *pspec)
{
}
/**
* gimp_param_spec_vector_layer:
* @name: Canonical name of the property specified.
* @nick: Nick name of the property specified.
* @blurb: Description of the property specified.
* @none_ok: Whether no is a valid value.
* @flags: Flags for the property specified.
*
* Creates a new #GimpParamSpecVectorLayer specifying a
* [type@VectorLayer] property.
*
* See g_param_spec_internal() for details on property names.
*
* Returns: (transfer floating): The newly created #GimpParamSpecVectorLayer.
*
* Since: 3.2
**/
GParamSpec *
gimp_param_spec_vector_layer (const gchar *name,
const gchar *nick,
const gchar *blurb,
gboolean none_ok,
GParamFlags flags)
{
GimpParamSpecItem *ispec;
ispec = g_param_spec_internal (GIMP_TYPE_PARAM_VECTOR_LAYER,
name, nick, blurb, flags);
g_return_val_if_fail (ispec, NULL);
ispec->none_ok = none_ok ? TRUE : FALSE;
return G_PARAM_SPEC (ispec);
}
/*
* GIMP_TYPE_PARAM_GROUP_LAYER
*/

View File

@@ -129,6 +129,25 @@ GParamSpec * gimp_param_spec_text_layer (const gchar *name,
GParamFlags flags);
/*
* GIMP_TYPE_PARAM_VECTOR_LAYER
*/
#define GIMP_VALUE_HOLDS_VECTOR_LAYER(value) (G_TYPE_CHECK_VALUE_TYPE ((value),\
GIMP_TYPE_VECTOR_LAYER))
#define GIMP_TYPE_PARAM_VECTOR_LAYER (gimp_param_vector_layer_get_type ())
#define GIMP_IS_PARAM_SPEC_VECTOR_LAYER(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), GIMP_TYPE_PARAM_VECTOR_LAYER))
GType gimp_param_vector_layer_get_type (void) G_GNUC_CONST;
GParamSpec * gimp_param_spec_vector_layer (const gchar *name,
const gchar *nick,
const gchar *blurb,
gboolean none_ok,
GParamFlags flags);
/*
* GIMP_TYPE_PARAM_GROUP_LAYER
*/

View File

@@ -1801,6 +1801,12 @@ _gimp_plug_in_get_item (GimpPlugIn *plug_in,
"id", item_id,
NULL);
}
else if (gimp_item_id_is_vector_layer (item_id))
{
item = g_object_new (GIMP_TYPE_VECTOR_LAYER,
"id", item_id,
NULL);
}
else if (gimp_item_id_is_group_layer (item_id))
{
item = g_object_new (GIMP_TYPE_GROUP_LAYER,

View File

@@ -1884,6 +1884,84 @@ gimp_procedure_add_text_layer_return_value (GimpProcedure *procedure,
none_ok, flags));
}
/**
* gimp_procedure_add_vector_layer_argument:
* @procedure: the #GimpProcedure.
* @name: the name of the argument to be created.
* @nick: the label used in #GimpProcedureDialog.
* @blurb: (nullable): a more detailed help description.
* @none_ok: Whether no is a valid value.
* @flags: argument flags.
*
* Add a new #GimpVectorLayer argument to @procedure.
*
* Since: 3.0
**/
void
gimp_procedure_add_vector_layer_argument (GimpProcedure *procedure,
const gchar *name,
const gchar *nick,
const gchar *blurb,
gboolean none_ok,
GParamFlags flags)
{
_gimp_procedure_add_argument (procedure,
gimp_param_spec_vector_layer (name, nick, blurb,
none_ok, flags));
}
/**
* gimp_procedure_add_vector_layer_aux_argument:
* @procedure: the #GimpProcedure.
* @name: the name of the argument to be created.
* @nick: the label used in #GimpProcedureDialog.
* @blurb: (nullable): a more detailed help description.
* @none_ok: Whether no is a valid value.
* @flags: argument flags.
*
* Add a new #GimpVectorLayer auxiliary argument to @procedure.
*
* Since: 3.0
**/
void
gimp_procedure_add_vector_layer_aux_argument (GimpProcedure *procedure,
const gchar *name,
const gchar *nick,
const gchar *blurb,
gboolean none_ok,
GParamFlags flags)
{
_gimp_procedure_add_aux_argument (procedure,
gimp_param_spec_vector_layer (name, nick, blurb,
none_ok, flags));
}
/**
* gimp_procedure_add_vector_layer_return_value:
* @procedure: the #GimpProcedure.
* @name: the name of the argument to be created.
* @nick: the label used in #GimpProcedureDialog.
* @blurb: (nullable): a more detailed help description.
* @none_ok: Whether no is a valid value.
* @flags: argument flags.
*
* Add a new #GimpVectorLayer return value to @procedure.
*
* Since: 3.0
**/
void
gimp_procedure_add_vector_layer_return_value (GimpProcedure *procedure,
const gchar *name,
const gchar *nick,
const gchar *blurb,
gboolean none_ok,
GParamFlags flags)
{
_gimp_procedure_add_return_value (procedure,
gimp_param_spec_vector_layer (name, nick, blurb,
none_ok, flags));
}
/**
* gimp_procedure_add_group_layer_argument:
* @procedure: the #GimpProcedure.

View File

@@ -313,6 +313,18 @@ G_BEGIN_DECLS
g_value_set_object (gimp_value_array_index (args, n), value)
/* vector layer */
#define GIMP_VALUES_GET_VECTOR_LAYER(args, n) \
g_value_get_object (gimp_value_array_index (args, n))
#define GIMP_VALUES_GET_VECTOR_LAYER_ID(args, n) \
gimp_item_get_id (g_value_get_object (gimp_value_array_index (args, n)))
#define GIMP_VALUES_SET_VECTOR_LAYER(args, n, value) \
g_value_set_object (gimp_value_array_index (args, n), value)
/* group layer */
#define GIMP_VALUES_GET_GROUP_LAYER(args, n) \
@@ -899,6 +911,25 @@ void gimp_procedure_add_text_layer_return_value (GimpProcedure *procedure
gboolean none_ok,
GParamFlags flags);
void gimp_procedure_add_vector_layer_argument (GimpProcedure *procedure,
const gchar *name,
const gchar *nick,
const gchar *blurb,
gboolean none_ok,
GParamFlags flags);
void gimp_procedure_add_vector_layer_aux_argument (GimpProcedure *procedure,
const gchar *name,
const gchar *nick,
const gchar *blurb,
gboolean none_ok,
GParamFlags flags);
void gimp_procedure_add_vector_layer_return_value (GimpProcedure *procedure,
const gchar *name,
const gchar *nick,
const gchar *blurb,
gboolean none_ok,
GParamFlags flags);
void gimp_procedure_add_group_layer_argument (GimpProcedure *procedure,
const gchar *name,
const gchar *nick,

View File

@@ -52,6 +52,7 @@ typedef struct _GimpTextLayer GimpTextLayer;
typedef struct _GimpPath GimpPath;
typedef struct _GimpDrawableFilter GimpDrawableFilter;
typedef struct _GimpDrawableFilterConfig GimpDrawableFilterConfig;
typedef struct _GimpVectorLayer GimpVectorLayer;
typedef struct _GimpDisplay GimpDisplay;

75
libgimp/gimpvectorlayer.c Normal file
View File

@@ -0,0 +1,75 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-2000 Peter Mattis and Spencer Kimball
*
* gimpvectorlayer.c
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gimp.h"
struct _GimpVectorLayer
{
GimpLayer parent_instance;
};
G_DEFINE_TYPE (GimpVectorLayer, gimp_vector_layer, GIMP_TYPE_LAYER)
#define parent_class gimp_vector_layer_parent_class
static void
gimp_vector_layer_class_init (GimpVectorLayerClass *klass)
{
}
static void
gimp_vector_layer_init (GimpVectorLayer *layer)
{
}
/* Public API. */
/**
* gimp_vector_layer_get_by_id:
* @layer_id: The layer id.
*
* Returns a #GimpVectorLayer representing @layer_id. This function calls
* gimp_item_get_by_id() and returns the item if it is layer or %NULL
* otherwise.
*
* Returns: (nullable) (transfer none): a #GimpVectorLayer for @layer_id or
* %NULL if @layer_id does not represent a valid layer. The
* object belongs to libgimp and you must not modify or unref
* it.
*
* Since: 3.0
**/
GimpVectorLayer *
gimp_vector_layer_get_by_id (gint32 layer_id)
{
GimpItem *item = gimp_item_get_by_id (layer_id);
if (GIMP_IS_VECTOR_LAYER (item))
return (GimpVectorLayer *) item;
return NULL;
}

45
libgimp/gimpvectorlayer.h Normal file
View File

@@ -0,0 +1,45 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-2000 Peter Mattis and Spencer Kimball
*
* gimpvectorlayer.h
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
#if !defined (__GIMP_H_INSIDE__) && !defined (GIMP_COMPILATION)
#error "Only <libgimp/gimp.h> can be included directly."
#endif
#ifndef __GIMP_VECTOR_LAYER_H__
#define __GIMP_VECTOR_LAYER_H__
G_BEGIN_DECLS
/* For information look into the C source or the html documentation */
#include <libgimp/gimplayer.h>
#define GIMP_TYPE_VECTOR_LAYER (gimp_vector_layer_get_type ())
G_DECLARE_FINAL_TYPE (GimpVectorLayer, gimp_vector_layer, GIMP, VECTOR_LAYER, GimpLayer)
GimpVectorLayer * gimp_vector_layer_get_by_id (gint32 layer_id);
G_END_DECLS
#endif /* __GIMP_VECTOR_LAYER_H__ */

View File

@@ -0,0 +1,159 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-2003 Peter Mattis and Spencer Kimball
*
* gimpvectorlayer_pdb.c
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
/* NOTE: This file is auto-generated by pdbgen.pl */
#include "config.h"
#include "stamp-pdbgen.h"
#include "gimp.h"
/**
* SECTION: gimpvectorlayer
* @title: gimpvectorlayer
* @short_description: Functions for querying and manipulating vector layers.
*
* Functions for querying and manipulating vector layers.
**/
/**
* gimp_vector_layer_new:
* @image: The image.
* @path: The path to create the layer from.
*
* Creates a new vector layer.
*
* This procedure creates a new path layer displaying the specified
* @path. By default, the fill and stroke properties will be defined by
* the context.
*
* The new layer still needs to be added to the image as this is not
* automatic. Add the new layer with the [method@Image.insert_layer]
* method.
*
* The arguments are kept as simple as necessary for the basic case.
* All vector attributes, however, can be modified with the appropriate
* `gimp_vector_layer_set_*()` procedures.
*
* Returns: (transfer none):
* The new vector layer. The object belongs to libgimp and you should not free it.
*
* Since: 3.2
**/
GimpVectorLayer *
gimp_vector_layer_new (GimpImage *image,
GimpPath *path)
{
GimpValueArray *args;
GimpValueArray *return_vals;
GimpVectorLayer *layer = NULL;
args = gimp_value_array_new_from_types (NULL,
GIMP_TYPE_IMAGE, image,
GIMP_TYPE_PATH, path,
G_TYPE_NONE);
return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (),
"gimp-vector-layer-new",
args);
gimp_value_array_unref (args);
if (GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS)
layer = GIMP_VALUES_GET_VECTOR_LAYER (return_vals, 1);
gimp_value_array_unref (return_vals);
return layer;
}
/**
* gimp_vector_layer_refresh:
* @layer: The vector layer.
*
* Rerender the vector layer
*
* This procedure causes the vector layer to refresh itself after
* changes.
*
* Returns: TRUE on success.
*
* Since: 3.2
**/
gboolean
gimp_vector_layer_refresh (GimpVectorLayer *layer)
{
GimpValueArray *args;
GimpValueArray *return_vals;
gboolean success = TRUE;
args = gimp_value_array_new_from_types (NULL,
GIMP_TYPE_VECTOR_LAYER, layer,
G_TYPE_NONE);
return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (),
"gimp-vector-layer-refresh",
args);
gimp_value_array_unref (args);
success = GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS;
gimp_value_array_unref (return_vals);
return success;
}
/**
* gimp_vector_layer_discard:
* @layer: The vector layer.
*
* Discard the vector layer information.
*
* Discards the vector information. This makes the layer behave like a
* normal layer.
*
* Returns: TRUE on success.
*
* Since: 3.2
**/
gboolean
gimp_vector_layer_discard (GimpVectorLayer *layer)
{
GimpValueArray *args;
GimpValueArray *return_vals;
gboolean success = TRUE;
args = gimp_value_array_new_from_types (NULL,
GIMP_TYPE_VECTOR_LAYER, layer,
G_TYPE_NONE);
return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (),
"gimp-vector-layer-discard",
args);
gimp_value_array_unref (args);
success = GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS;
gimp_value_array_unref (return_vals);
return success;
}

View File

@@ -0,0 +1,43 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-2003 Peter Mattis and Spencer Kimball
*
* gimpvectorlayer_pdb.h
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
/* NOTE: This file is auto-generated by pdbgen.pl */
#if !defined (__GIMP_H_INSIDE__) && !defined (GIMP_COMPILATION)
#error "Only <libgimp/gimp.h> can be included directly."
#endif
#ifndef __GIMP_VECTOR_LAYER_PDB_H__
#define __GIMP_VECTOR_LAYER_PDB_H__
G_BEGIN_DECLS
/* For information look into the C source or the html documentation */
GimpVectorLayer* gimp_vector_layer_new (GimpImage *image,
GimpPath *path);
gboolean gimp_vector_layer_refresh (GimpVectorLayer *layer);
gboolean gimp_vector_layer_discard (GimpVectorLayer *layer);
G_END_DECLS
#endif /* __GIMP_VECTOR_LAYER_PDB_H__ */

View File

@@ -114,6 +114,7 @@ pdb_wrappers_sources = [
'gimptextlayer_pdb.c',
'gimptexttool_pdb.c',
'gimpunit_pdb.c',
'gimpvectorlayer_pdb.c',
]
pdb_wrappers_headers = [
@@ -173,6 +174,7 @@ pdb_wrappers_headers = [
'gimptextlayer_pdb.h',
'gimptexttool_pdb.h',
'gimpunit_pdb.h',
'gimpvectorlayer_pdb.h',
]
libgimp_sources_introspectable = [
@@ -214,6 +216,7 @@ libgimp_sources_introspectable = [
'gimpselection.c',
'gimptextlayer.c',
'gimpthumbnailprocedure.c',
'gimpvectorlayer.c',
'gimpvectorloadprocedure.c',
gimpenums,
pdb_wrappers_sources,
@@ -276,6 +279,7 @@ libgimp_headers_introspectable = [
'gimpselection.h',
'gimptextlayer.h',
'gimpthumbnailprocedure.h',
'gimpvectorlayer.h',
'gimpvectorloadprocedure.h',
pdb_wrappers_headers,
]

View File

@@ -381,6 +381,16 @@ gimp_param_spec_text_layer ("$name",
"$blurb",
$none_ok,
$flags)
CODE
}
elsif ($pdbtype eq 'vector_layer') {
$none_ok = exists $arg->{none_ok} ? 'TRUE' : 'FALSE';
$pspec = <<CODE;
gimp_param_spec_vector_layer ("$name",
"$nick",
"$blurb",
$none_ok,
$flags)
CODE
}
elsif ($pdbtype eq 'layer') {

View File

@@ -57,4 +57,5 @@
text_layer
text_tool
unit
vector_layer
);

View File

@@ -178,6 +178,42 @@ CODE
);
}
sub item_id_is_vector_layer {
$blurb = 'Returns whether the item ID is a vector layer.';
$help = <<'HELP';
This procedure returns %TRUE if the specified item ID is a vector layer.
*Note*: in most use cases, you should not use this function. See
[func@Gimp.Item.id_is_layer] for a discussion on alternatives.
HELP
&alxsa_pdb_misc('2025', '3.2');
@inargs = (
{ name => 'item_id', type => 'int32',
desc => 'The item ID' }
);
@outargs = (
{ name => 'vector_layer', type => 'boolean',
desc => 'TRUE if the item is a vector layer, FALSE otherwise.' }
);
%invoke = (
code => <<'CODE'
{
GimpItem *item = gimp_item_get_by_id (gimp, item_id);
vector_layer = (GIMP_IS_LAYER (item) &&
! gimp_item_is_removed (item) &&
gimp_item_is_vector_layer (item));
}
CODE
);
}
sub item_id_is_group_layer {
$blurb = 'Returns whether the item ID is a group layer.';
@@ -1056,7 +1092,8 @@ CODE
"core/gimplayermask.h"
"core/gimplist.h"
"core/gimpselection.h"
"path/gimppath.h"
"path/gimppath.h"
"path/gimpvectorlayer.h"
"text/gimptextlayer.h"
"gimppdb-utils.h"
"gimppdbcontext.h"
@@ -1066,6 +1103,7 @@ CODE
item_id_is_drawable
item_id_is_layer
item_id_is_text_layer
item_id_is_vector_layer
item_id_is_group_layer
item_id_is_channel
item_id_is_layer_mask

144
pdb/groups/vector_layer.pdb Normal file
View File

@@ -0,0 +1,144 @@
# GIMP - The GNU Image Manipulation Program
# Copyright (C) 1995 Spencer Kimball and Peter Mattis
# New Vector Layer PDB API
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
sub vector_layer_new {
$blurb = 'Creates a new vector layer.';
$help = <<'HELP';
This procedure creates a new path layer displaying the specified @path. By
default, the fill and stroke properties will be defined by the context.
The new layer still needs to be added to the image as this is not
automatic. Add the new layer with the [method@Image.insert_layer]
method.
The arguments are kept as simple as necessary for the basic case. All
vector attributes, however, can be modified with the appropriate
`gimp_vector_layer_set_*()` procedures.
HELP
&alxsa_pdb_misc('2025', '3.2');
@inargs = (
{ name => 'image', type => 'image',
desc => 'The image' },
{ name => 'path', type => 'path',
desc => 'The path to create the layer from' }
);
@outargs = (
{ name => 'layer', type => 'vector_layer',
desc => 'The new vector layer. The object belongs to libgimp and you should not free it.' }
);
%invoke = (
code => <<'CODE'
{
if (path == NULL)
{
g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_ERROR_INVALID_ARGUMENT,
_("Failed to create vector layer"));
success = FALSE;
}
if (success)
{
layer = GIMP_VECTOR_LAYER (gimp_vector_layer_new (image, path, context));
if (! layer)
{
g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_ERROR_INVALID_ARGUMENT,
_("Failed to create vector layer"));
success = FALSE;
}
}
}
CODE
);
}
sub vector_layer_refresh {
$blurb = 'Rerender the vector layer';
$help = <<'HELP';
This procedure causes the vector layer to refresh itself after changes.
HELP
&alxsa_pdb_misc('2025', '3.2');
@inargs = (
{ name => 'layer', type => 'vector_layer',
desc => 'The vector layer' }
);
%invoke = (
code => <<'CODE'
{
gimp_vector_layer_refresh (layer);
}
CODE
);
}
sub vector_layer_discard {
$blurb = 'Discard the vector layer information.';
$help = <<'HELP';
Discards the vector information. This makes the layer behave like a normal layer.
HELP
&alxsa_pdb_misc('2025', '3.2');
@inargs = (
{ name => 'layer', type => 'vector_layer',
desc => 'The vector layer' }
);
%invoke = (
code => <<'CODE'
{
gimp_vector_layer_discard (layer);
}
CODE
);
}
@headers = qw("libgimpbase/gimpbase.h"
"core/gimpcontext.h"
"path/gimpvectorlayer.h"
"gimppdb-utils.h"
"gimppdberror.h"
"gimp-intl.h");
@procs = qw(vector_layer_new
vector_layer_refresh
vector_layer_discard);
%exports = (app => [@procs], lib => [@procs]);
$desc = 'Vector layer procedures';
$doc_title = 'gimpvectorlayer';
$doc_short_desc = 'Functions for querying and manipulating vector layers.';
$doc_long_desc = 'Functions for querying and manipulating vector layers.';
1;

View File

@@ -59,6 +59,7 @@ pdb_names = [
'text_layer',
'text_tool',
'unit',
'vector_layer',
]
pdb_sources = []

View File

@@ -371,6 +371,18 @@ package Gimp::CodeGen::pdb;
take_value_func => 'g_value_set_object ($value, $var)',
headers => [ qw("text/gimptextlayer.h") ] },
vector_layer => { name => 'VECTOR_LAYER',
gtype => 'GIMP_TYPE_VECTOR_LAYER',
type => 'GimpVectorLayer *',
const_type => 'GimpVectorLayer *',
init_value => 'NULL',
out_annotate => '(transfer none)',
get_value_func => '$var = g_value_get_object ($value)',
dup_value_func => '$var = GIMP_VALUES_GET_VECTOR_LAYER ($value)',
set_value_func => 'g_value_set_object ($value, $var)',
take_value_func => 'g_value_set_object ($value, $var)',
headers => [ qw("path/gimpvectorlayer.h") ] },
group_layer => { name => 'GROUP_LAYER',
gtype => 'GIMP_TYPE_GROUP_LAYER',
type => 'GimpGroupLayer *',