Example #1
0
gboolean
gimp_paint_core_stroke (GimpPaintCore     *core,
                        GimpDrawable      *drawable,
                        GimpPaintOptions  *paint_options,
                        GimpCoords        *strokes,
                        gint               n_strokes,
                        gboolean           push_undo,
                        GError           **error)
{
  g_return_val_if_fail (GIMP_IS_PAINT_CORE (core), FALSE);
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
  g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), FALSE);
  g_return_val_if_fail (GIMP_IS_PAINT_OPTIONS (paint_options), FALSE);
  g_return_val_if_fail (strokes != NULL, FALSE);
  g_return_val_if_fail (n_strokes > 0, FALSE);
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

  if (gimp_paint_core_start (core, drawable, paint_options, &strokes[0],
                             error))
    {
      gint i;

      core->last_coords = strokes[0];

      gimp_paint_core_paint (core, drawable, paint_options,
                             GIMP_PAINT_STATE_INIT, 0);

      gimp_paint_core_paint (core, drawable, paint_options,
                             GIMP_PAINT_STATE_MOTION, 0);

      for (i = 1; i < n_strokes; i++)
        {
          gimp_paint_core_interpolate (core, drawable, paint_options,
                                       &strokes[i], 0);
        }

      gimp_paint_core_paint (core, drawable, paint_options,
                             GIMP_PAINT_STATE_FINISH, 0);

      gimp_paint_core_finish (core, drawable, push_undo);

      gimp_paint_core_cleanup (core);

      return TRUE;
    }

  return FALSE;
}
Example #2
0
static void
gimp_paint_tool_button_release (GimpTool              *tool,
                                const GimpCoords      *coords,
                                guint32                time,
                                GdkModifierType        state,
                                GimpButtonReleaseType  release_type,
                                GimpDisplay           *display)
{
  GimpPaintTool    *paint_tool    = GIMP_PAINT_TOOL (tool);
  GimpPaintOptions *paint_options = GIMP_PAINT_TOOL_GET_OPTIONS (tool);
  GimpPaintCore    *core          = paint_tool->core;
  GimpDisplayShell *shell         = gimp_display_get_shell (display);
  GimpImage        *image         = gimp_display_get_image (display);
  GimpDrawable     *drawable      = gimp_image_get_active_drawable (image);

  if (gimp_color_tool_is_enabled (GIMP_COLOR_TOOL (tool)))
    {
      GIMP_TOOL_CLASS (parent_class)->button_release (tool, coords, time,
                                                      state, release_type,
                                                      display);
      return;
    }

  gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));

  /*  Let the specific painting function finish up  */
  gimp_paint_core_paint (core, drawable, paint_options,
                         GIMP_PAINT_STATE_FINISH, time);

  /*  resume the current selection  */
  gimp_display_shell_selection_resume (shell);

  /*  chain up to halt the tool */
  GIMP_TOOL_CLASS (parent_class)->button_release (tool, coords, time, state,
                                                  release_type, display);

  if (release_type == GIMP_BUTTON_RELEASE_CANCEL)
    gimp_paint_core_cancel (core, drawable);
  else
    gimp_paint_core_finish (core, drawable, TRUE);

  gimp_image_flush (image);

  gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
}
Example #3
0
gboolean
gimp_paint_core_stroke_boundary (GimpPaintCore      *core,
                                 GimpDrawable       *drawable,
                                 GimpPaintOptions   *paint_options,
                                 gboolean            emulate_dynamics,
                                 const GimpBoundSeg *bound_segs,
                                 gint                n_bound_segs,
                                 gint                offset_x,
                                 gint                offset_y,
                                 gboolean            push_undo,
                                 GError            **error)
{
  GimpBoundSeg *stroke_segs;
  gint          n_stroke_segs;
  gint          off_x;
  gint          off_y;
  GimpCoords   *coords;
  gboolean      initialized = FALSE;
  gint          n_coords;
  gint          seg;
  gint          s;

  g_return_val_if_fail (GIMP_IS_PAINT_CORE (core), FALSE);
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
  g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), FALSE);
  g_return_val_if_fail (GIMP_IS_PAINT_OPTIONS (paint_options), FALSE);
  g_return_val_if_fail (bound_segs != NULL && n_bound_segs > 0, FALSE);
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

  stroke_segs = gimp_boundary_sort (bound_segs, n_bound_segs,
                                    &n_stroke_segs);

  if (n_stroke_segs == 0)
    return TRUE;

  gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);

  off_x -= offset_x;
  off_y -= offset_y;

  coords = g_new0 (GimpCoords, n_bound_segs + 4);

  seg      = 0;
  n_coords = 0;

  /* we offset all coordinates by 0.5 to align the brush with the path */

  coords[n_coords]   = default_coords;
  coords[n_coords].x = (gdouble) (stroke_segs[0].x1 - off_x + 0.5);
  coords[n_coords].y = (gdouble) (stroke_segs[0].y1 - off_y + 0.5);

  n_coords++;

  for (s = 0; s < n_stroke_segs; s++)
    {
      while (stroke_segs[seg].x1 != -1 ||
             stroke_segs[seg].x2 != -1 ||
             stroke_segs[seg].y1 != -1 ||
             stroke_segs[seg].y2 != -1)
        {
          coords[n_coords]   = default_coords;
          coords[n_coords].x = (gdouble) (stroke_segs[seg].x1 - off_x + 0.5);
          coords[n_coords].y = (gdouble) (stroke_segs[seg].y1 - off_y + 0.5);

          n_coords++;
          seg++;
        }

      /* Close the stroke points up */
      coords[n_coords] = coords[0];

      n_coords++;

      if (emulate_dynamics)
        gimp_paint_core_stroke_emulate_dynamics (coords, n_coords);

      if (initialized ||
          gimp_paint_core_start (core, drawable, paint_options, &coords[0],
                                 error))
        {
          gint i;

          initialized = TRUE;

          core->cur_coords  = coords[0];
          core->last_coords = coords[0];

          gimp_paint_core_paint (core, drawable, paint_options,
                                 GIMP_PAINT_STATE_INIT, 0);

          gimp_paint_core_paint (core, drawable, paint_options,
                                 GIMP_PAINT_STATE_MOTION, 0);

          for (i = 1; i < n_coords; i++)
            {
              gimp_paint_core_interpolate (core, drawable, paint_options,
                                           &coords[i], 0);
            }

          gimp_paint_core_paint (core, drawable, paint_options,
                                 GIMP_PAINT_STATE_FINISH, 0);
        }
      else
        {
          break;
        }

      n_coords = 0;
      seg++;

      coords[n_coords]   = default_coords;
      coords[n_coords].x = (gdouble) (stroke_segs[seg].x1 - off_x + 0.5);
      coords[n_coords].y = (gdouble) (stroke_segs[seg].y1 - off_y + 0.5);

      n_coords++;
    }

  if (initialized)
    {
      gimp_paint_core_finish (core, drawable, push_undo);

      gimp_paint_core_cleanup (core);
    }

  g_free (coords);
  g_free (stroke_segs);

  return initialized;
}
Example #4
0
gboolean
gimp_paint_core_stroke_vectors (GimpPaintCore     *core,
                                GimpDrawable      *drawable,
                                GimpPaintOptions  *paint_options,
                                gboolean           emulate_dynamics,
                                GimpVectors       *vectors,
                                gboolean           push_undo,
                                GError           **error)
{
  GList    *stroke;
  gboolean  initialized = FALSE;
  gboolean  due_to_lack_of_points = FALSE;
  gint      off_x, off_y;
  gint      vectors_off_x, vectors_off_y;

  g_return_val_if_fail (GIMP_IS_PAINT_CORE (core), FALSE);
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
  g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), FALSE);
  g_return_val_if_fail (GIMP_IS_PAINT_OPTIONS (paint_options), FALSE);
  g_return_val_if_fail (GIMP_IS_VECTORS (vectors), FALSE);
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

  gimp_item_get_offset (GIMP_ITEM (vectors),  &vectors_off_x, &vectors_off_y);
  gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);

  off_x -= vectors_off_x;
  off_y -= vectors_off_y;

  for (stroke = vectors->strokes; stroke; stroke = stroke->next)
    {
      GArray   *coords;
      gboolean  closed;

      coords = gimp_stroke_interpolate (GIMP_STROKE (stroke->data),
                                        1.0, &closed);

      if (coords && coords->len)
        {
          gint i;

          for (i = 0; i < coords->len; i++)
            {
              g_array_index (coords, GimpCoords, i).x -= off_x;
              g_array_index (coords, GimpCoords, i).y -= off_y;
            }

          if (emulate_dynamics)
            gimp_paint_core_stroke_emulate_dynamics ((GimpCoords *) coords->data,
                                                     coords->len);

          if (initialized ||
              gimp_paint_core_start (core, drawable, paint_options,
                                     &g_array_index (coords, GimpCoords, 0),
                                     error))
            {
              initialized = TRUE;

              core->cur_coords  = g_array_index (coords, GimpCoords, 0);
              core->last_coords = g_array_index (coords, GimpCoords, 0);

              gimp_paint_core_paint (core, drawable, paint_options,
                                     GIMP_PAINT_STATE_INIT, 0);

              gimp_paint_core_paint (core, drawable, paint_options,
                                     GIMP_PAINT_STATE_MOTION, 0);

              for (i = 1; i < coords->len; i++)
                {
                  gimp_paint_core_interpolate (core, drawable, paint_options,
                                               &g_array_index (coords, GimpCoords, i),
                                               0);
                }

              gimp_paint_core_paint (core, drawable, paint_options,
                                     GIMP_PAINT_STATE_FINISH, 0);
            }
          else
            {
              if (coords)
                g_array_free (coords, TRUE);

              break;
            }
        }
      else
        {
          due_to_lack_of_points = TRUE;
        }

      if (coords)
        g_array_free (coords, TRUE);
    }

  if (initialized)
    {
      gimp_paint_core_finish (core, drawable, push_undo);

      gimp_paint_core_cleanup (core);
    }

  if (! initialized && due_to_lack_of_points && *error == NULL)
    {
      g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
                           _("Not enough points to stroke"));
    }

  return initialized;
}