static void gimp_ink_motion (GimpPaintCore *paint_core, GimpDrawable *drawable, GimpPaintOptions *paint_options, const GimpCoords *coords, guint32 time) { GimpInk *ink = GIMP_INK (paint_core); GimpInkOptions *options = GIMP_INK_OPTIONS (paint_options); GimpContext *context = GIMP_CONTEXT (paint_options); GimpBlob *blob_union = NULL; GimpBlob *blob_to_render; GeglBuffer *paint_buffer; gint paint_buffer_x; gint paint_buffer_y; GimpRGB foreground; GeglColor *color; if (! ink->last_blob) { ink->last_blob = ink_pen_ellipse (options, coords->x, coords->y, coords->pressure, coords->xtilt, coords->ytilt, 100); if (ink->start_blob) g_free (ink->start_blob); ink->start_blob = gimp_blob_duplicate (ink->last_blob); blob_to_render = ink->last_blob; } else { GimpBlob *blob = ink_pen_ellipse (options, coords->x, coords->y, coords->pressure, coords->xtilt, coords->ytilt, coords->velocity * 100); blob_union = gimp_blob_convex_union (ink->last_blob, blob); g_free (ink->last_blob); ink->last_blob = blob; blob_to_render = blob_union; } /* Get the buffer */ ink->cur_blob = blob_to_render; paint_buffer = gimp_paint_core_get_paint_buffer (paint_core, drawable, paint_options, coords, &paint_buffer_x, &paint_buffer_y); ink->cur_blob = NULL; if (! paint_buffer) return; gimp_context_get_foreground (context, &foreground); color = gimp_gegl_color_new (&foreground); gegl_buffer_set_color (paint_buffer, NULL, color); g_object_unref (color); /* draw the blob directly to the canvas_buffer */ render_blob (paint_core->canvas_buffer, GEGL_RECTANGLE (paint_core->paint_buffer_x, paint_core->paint_buffer_y, gegl_buffer_get_width (paint_core->paint_buffer), gegl_buffer_get_height (paint_core->paint_buffer)), blob_to_render); /* draw the paint_area using the just rendered canvas_buffer as mask */ gimp_paint_core_paste (paint_core, paint_core->canvas_buffer, GEGL_RECTANGLE (paint_core->paint_buffer_x, paint_core->paint_buffer_y, gegl_buffer_get_width (paint_core->paint_buffer), gegl_buffer_get_height (paint_core->paint_buffer)), drawable, GIMP_OPACITY_OPAQUE, gimp_context_get_opacity (context), gimp_context_get_paint_mode (context), GIMP_PAINT_CONSTANT); if (blob_union) g_free (blob_union); }
GtkWidget * gimp_ink_options_gui (GimpToolOptions *tool_options) { GObject *config = G_OBJECT (tool_options); GimpInkOptions *ink_options = GIMP_INK_OPTIONS (tool_options); GtkWidget *vbox = gimp_paint_options_gui (tool_options); GtkWidget *frame; GtkWidget *vbox2; GtkWidget *scale; GtkWidget *blob_box; GtkWidget *hbox; GtkWidget *editor; GtkSizeGroup *size_group; /* adjust sliders */ frame = gimp_frame_new (_("Adjustment")); gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0); gtk_widget_show (frame); vbox2 = gtk_vbox_new (FALSE, 2); gtk_container_add (GTK_CONTAINER (frame), vbox2); gtk_widget_show (vbox2); /* size slider */ scale = gimp_prop_spin_scale_new (config, "size", _("Size"), 1.0, 2.0, 1); gtk_box_pack_start (GTK_BOX (vbox2), scale, FALSE, FALSE, 0); gtk_widget_show (scale); /* angle adjust slider */ scale = gimp_prop_spin_scale_new (config, "tilt-angle", _("Angle"), 1.0, 10.0, 1); gtk_box_pack_start (GTK_BOX (vbox2), scale, FALSE, FALSE, 0); gtk_widget_show (scale); /* sens sliders */ frame = gimp_frame_new (_("Sensitivity")); gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0); gtk_widget_show (frame); vbox2 = gtk_vbox_new (FALSE, 2); gtk_container_add (GTK_CONTAINER (frame), vbox2); gtk_widget_show (vbox2); /* size sens slider */ scale = gimp_prop_spin_scale_new (config, "size-sensitivity", _("Size"), 0.01, 0.1, 2); gtk_box_pack_start (GTK_BOX (vbox2), scale, FALSE, FALSE, 0); gtk_widget_show (scale); /* tilt sens slider */ scale = gimp_prop_spin_scale_new (config, "tilt-sensitivity", _("Tilt"), 0.01, 0.1, 2); gtk_box_pack_start (GTK_BOX (vbox2), scale, FALSE, FALSE, 0); gtk_widget_show (scale); /* velocity sens slider */ scale = gimp_prop_spin_scale_new (config, "vel-sensitivity", _("Speed"), 0.01, 0.1, 2); gtk_box_pack_start (GTK_BOX (vbox2), scale, FALSE, FALSE, 0); gtk_widget_show (scale); /* Blob shape widgets */ frame = gimp_frame_new (_("Shape")); gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); gtk_widget_show (frame); hbox = gtk_hbox_new (FALSE, 2); gtk_container_add (GTK_CONTAINER (frame), hbox); gtk_widget_show (hbox); size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL); /* Blob type radiobuttons */ blob_box = gimp_prop_enum_stock_box_new (config, "blob-type", "gimp-shape", 0, 0); gtk_orientable_set_orientation (GTK_ORIENTABLE (blob_box), GTK_ORIENTATION_VERTICAL); gtk_box_pack_start (GTK_BOX (hbox), blob_box, FALSE, FALSE, 0); gtk_widget_show (blob_box); gtk_size_group_add_widget (size_group, blob_box); /* Blob editor */ frame = gtk_aspect_frame_new (NULL, 0.0, 0.5, 1.0, FALSE); gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0); gtk_widget_show (frame); gtk_size_group_add_widget (size_group, frame); editor = gimp_blob_editor_new (ink_options->blob_type, ink_options->blob_aspect, ink_options->blob_angle); gtk_container_add (GTK_CONTAINER (frame), editor); gtk_widget_show (editor); gimp_config_connect (config, G_OBJECT (editor), "blob-type"); gimp_config_connect (config, G_OBJECT (editor), "blob-aspect"); gimp_config_connect (config, G_OBJECT (editor), "blob-angle"); return vbox; }
static void gimp_ink_motion (GimpPaintCore *paint_core, GimpDrawable *drawable, GimpPaintOptions *paint_options, const GimpCoords *coords, guint32 time) { GimpInk *ink = GIMP_INK (paint_core); GimpInkOptions *options = GIMP_INK_OPTIONS (paint_options); GimpContext *context = GIMP_CONTEXT (paint_options); GimpImage *image; GimpBlob *blob_union = NULL; GimpBlob *blob_to_render; TempBuf *area; guchar col[MAX_CHANNELS]; PixelRegion blob_maskPR; image = gimp_item_get_image (GIMP_ITEM (drawable)); if (! ink->last_blob) { ink->last_blob = ink_pen_ellipse (options, coords->x, coords->y, coords->pressure, coords->xtilt, coords->ytilt, 100); if (ink->start_blob) g_free (ink->start_blob); ink->start_blob = gimp_blob_duplicate (ink->last_blob); blob_to_render = ink->last_blob; } else { GimpBlob *blob = ink_pen_ellipse (options, coords->x, coords->y, coords->pressure, coords->xtilt, coords->ytilt, coords->velocity * 100); blob_union = gimp_blob_convex_union (ink->last_blob, blob); g_free (ink->last_blob); ink->last_blob = blob; blob_to_render = blob_union; } /* Get the buffer */ ink->cur_blob = blob_to_render; area = gimp_paint_core_get_paint_area (paint_core, drawable, paint_options, coords); ink->cur_blob = NULL; if (! area) return; gimp_image_get_foreground (image, context, gimp_drawable_type (drawable), col); /* set the alpha channel */ col[paint_core->canvas_buf->bytes - 1] = OPAQUE_OPACITY; /* color the pixels */ color_pixels (temp_buf_get_data (paint_core->canvas_buf), col, area->width * area->height, area->bytes); gimp_paint_core_validate_canvas_tiles (paint_core, paint_core->canvas_buf->x, paint_core->canvas_buf->y, paint_core->canvas_buf->width, paint_core->canvas_buf->height); /* draw the blob directly to the canvas_tiles */ pixel_region_init (&blob_maskPR, paint_core->canvas_tiles, paint_core->canvas_buf->x, paint_core->canvas_buf->y, paint_core->canvas_buf->width, paint_core->canvas_buf->height, TRUE); render_blob (blob_to_render, &blob_maskPR); /* draw the canvas_buf using the just rendered canvas_tiles as mask */ pixel_region_init (&blob_maskPR, paint_core->canvas_tiles, paint_core->canvas_buf->x, paint_core->canvas_buf->y, paint_core->canvas_buf->width, paint_core->canvas_buf->height, FALSE); gimp_paint_core_paste (paint_core, &blob_maskPR, drawable, GIMP_OPACITY_OPAQUE, gimp_context_get_opacity (context), gimp_context_get_paint_mode (context), GIMP_PAINT_CONSTANT); if (blob_union) g_free (blob_union); }
GtkWidget * gimp_ink_options_gui (GimpToolOptions *tool_options) { GObject *config = G_OBJECT (tool_options); GimpInkOptions *ink_options = GIMP_INK_OPTIONS (tool_options); GtkWidget *vbox = gimp_paint_options_gui (tool_options); GtkWidget *frame; GtkWidget *table; GtkWidget *blob_vbox; GtkWidget *hbox; GtkWidget *editor; GtkObject *adj; /* adjust sliders */ frame = gimp_frame_new (_("Adjustment")); gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0); gtk_widget_show (frame); table = gtk_table_new (2, 3, FALSE); gtk_table_set_col_spacings (GTK_TABLE (table), 2); gtk_container_add (GTK_CONTAINER (frame), table); gtk_widget_show (table); /* size slider */ adj = gimp_prop_scale_entry_new (config, "size", GTK_TABLE (table), 0, 0, _("Size:"), 1.0, 2.0, 1, FALSE, 0.0, 0.0); gimp_scale_entry_set_logarithmic (adj, TRUE); /* angle adjust slider */ gimp_prop_scale_entry_new (config, "tilt-angle", GTK_TABLE (table), 0, 1, _("Angle:"), 1.0, 10.0, 1, FALSE, 0.0, 0.0); /* sens sliders */ frame = gimp_frame_new (_("Sensitivity")); gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0); gtk_widget_show (frame); table = gtk_table_new (3, 3, FALSE); gtk_table_set_col_spacings (GTK_TABLE (table), 2); gtk_container_add (GTK_CONTAINER (frame), table); gtk_widget_show (table); /* size sens slider */ gimp_prop_scale_entry_new (config, "size-sensitivity", GTK_TABLE (table), 0, 0, _("Size:"), 0.01, 0.1, 1, FALSE, 0.0, 0.0); /* tilt sens slider */ gimp_prop_scale_entry_new (config, "tilt-sensitivity", GTK_TABLE (table), 0, 1, _("Tilt:"), 0.01, 0.1, 1, FALSE, 0.0, 0.0); /* velocity sens slider */ gimp_prop_scale_entry_new (config, "vel-sensitivity", GTK_TABLE (table), 0, 2, _("Speed:"), 0.01, 0.1, 1, FALSE, 0.0, 0.0); /* bottom hbox */ hbox = gtk_hbox_new (FALSE, 2); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); gtk_widget_show (hbox); /* Blob type radiobuttons */ frame = gimp_prop_enum_radio_frame_new (config, "blob-type", _("Type"), 0, 0); gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0); gtk_widget_show (frame); { GtkWidget *frame_child = gtk_bin_get_child (GTK_BIN (frame)); GList *children; GList *list; GimpInkBlobType blob_type; children = gtk_container_get_children (GTK_CONTAINER (frame_child)); for (list = children, blob_type = GIMP_INK_BLOB_TYPE_ELLIPSE; list; list = g_list_next (list), blob_type++) { GtkWidget *radio = GTK_WIDGET (list->data); GtkWidget *blob; gtk_container_remove (GTK_CONTAINER (radio), gtk_bin_get_child (GTK_BIN (radio))); blob = blob_image_new (blob_type); gtk_container_add (GTK_CONTAINER (radio), blob); gtk_widget_show (blob); } g_list_free (children); } /* Blob shape widget */ frame = gimp_frame_new (_("Shape")); gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0); gtk_widget_show (frame); blob_vbox = gtk_vbox_new (FALSE, 2); gtk_container_add (GTK_CONTAINER (frame), blob_vbox); gtk_widget_show (blob_vbox); frame = gtk_aspect_frame_new (NULL, 0.0, 0.5, 1.0, FALSE); gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); gtk_box_pack_start (GTK_BOX (blob_vbox), frame, TRUE, TRUE, 0); gtk_widget_show (frame); editor = gimp_blob_editor_new (ink_options->blob_type, ink_options->blob_aspect, ink_options->blob_angle); gtk_widget_set_size_request (editor, 60, 60); gtk_container_add (GTK_CONTAINER (frame), editor); gtk_widget_show (editor); gimp_config_connect (config, G_OBJECT (editor), NULL); return vbox; }