Esempio n. 1
0
static GimpCanvasItem *
gimp_brush_tool_get_outline (GimpPaintTool *paint_tool,
                             GimpDisplay   *display,
                             gdouble        x,
                             gdouble        y)
{
  GimpBrushTool  *brush_tool = GIMP_BRUSH_TOOL (paint_tool);
  GimpCanvasItem *item;

  item = gimp_brush_tool_create_outline (brush_tool, display, x, y);

  if (! item)
    {
      GimpBrushCore *brush_core = GIMP_BRUSH_CORE (paint_tool->core);

      if (brush_core->main_brush && brush_core->dynamics)
        {
          /*  if an outline was expected, but got scaled away by
           *  transform/dynamics, draw a circle in the "normal" size.
           */
          GimpPaintOptions *options;

          options = GIMP_PAINT_TOOL_GET_OPTIONS (brush_tool);

          gimp_paint_tool_set_draw_circle (paint_tool,
                                           TRUE, options->brush_size);
        }
    }

  return item;
}
Esempio n. 2
0
static void
gimp_paint_tool_motion (GimpTool         *tool,
                        const GimpCoords *coords,
                        guint32           time,
                        GdkModifierType   state,
                        GimpDisplay      *display)
{
  GimpPaintTool    *paint_tool    = GIMP_PAINT_TOOL (tool);
  GimpPaintOptions *paint_options = GIMP_PAINT_TOOL_GET_OPTIONS (tool);
  GimpPaintCore    *core          = paint_tool->core;
  GimpImage        *image         = gimp_display_get_image (display);
  GimpDrawable     *drawable      = gimp_image_get_active_drawable (image);
  GimpCoords        curr_coords;
  gint              off_x, off_y;

  GIMP_TOOL_CLASS (parent_class)->motion (tool, coords, time, state, display);

  if (gimp_color_tool_is_enabled (GIMP_COLOR_TOOL (tool)))
    return;

  curr_coords = *coords;

  gimp_paint_core_smooth_coords (core, paint_options, &curr_coords);

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

  curr_coords.x -= off_x;
  curr_coords.y -= off_y;

  /*  don't paint while the Shift key is pressed for line drawing  */
  if (paint_tool->draw_line)
    {
      gimp_paint_core_set_current_coords (core, &curr_coords);
      return;
    }

  gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));

  gimp_paint_core_interpolate (core, drawable, paint_options,
                               &curr_coords, time);

  gimp_projection_flush_now (gimp_image_get_projection (image));
  gimp_display_flush_now (display);

  gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
}
Esempio n. 3
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));
}
Esempio n. 4
0
static void
gimp_brush_tool_set_brush (GimpBrushCore *brush_core,
                           GimpBrush     *brush,
                           GimpBrushTool *brush_tool)
{
  gimp_draw_tool_pause (GIMP_DRAW_TOOL (brush_tool));

  if (GIMP_BRUSH_CORE_GET_CLASS (brush_core)->handles_transforming_brush)
    {
      GimpPaintCore *paint_core = GIMP_PAINT_CORE (brush_core);

      gimp_brush_core_eval_transform_dynamics (brush_core,
                                               NULL,
                                               GIMP_PAINT_TOOL_GET_OPTIONS (brush_tool),
                                               &paint_core->cur_coords);
    }

  gimp_draw_tool_resume (GIMP_DRAW_TOOL (brush_tool));
}
Esempio n. 5
0
static void
gimp_brush_tool_oper_update (GimpTool         *tool,
                             const GimpCoords *coords,
                             GdkModifierType   state,
                             gboolean          proximity,
                             GimpDisplay      *display)
{
  GimpPaintOptions *paint_options = GIMP_PAINT_TOOL_GET_OPTIONS (tool);
  GimpDrawable     *drawable;

  gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));

  GIMP_TOOL_CLASS (parent_class)->oper_update (tool, coords, state,
                                               proximity, display);

  drawable = gimp_image_get_active_drawable (gimp_display_get_image (display));

  if (! gimp_color_tool_is_enabled (GIMP_COLOR_TOOL (tool)) &&
      drawable && proximity)
    {
      GimpContext   *context    = GIMP_CONTEXT (paint_options);
      GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (tool);
      GimpBrushCore *brush_core = GIMP_BRUSH_CORE (paint_tool->core);

      gimp_brush_core_set_brush (brush_core,
                                 gimp_context_get_brush (context));

      gimp_brush_core_set_dynamics (brush_core,
                                    gimp_context_get_dynamics (context));

      if (GIMP_BRUSH_CORE_GET_CLASS (brush_core)->handles_transforming_brush)
        {
          gimp_brush_core_eval_transform_dynamics (brush_core,
                                                   drawable,
                                                   paint_options,
                                                   coords);
        }
    }

  gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
}
Esempio n. 6
0
static void
gimp_paint_tool_constructed (GObject *object)
{
  GimpTool          *tool       = GIMP_TOOL (object);
  GimpPaintTool     *paint_tool = GIMP_PAINT_TOOL (object);
  GimpPaintOptions  *options    = GIMP_PAINT_TOOL_GET_OPTIONS (tool);
  GimpDisplayConfig *display_config;
  GimpPaintInfo     *paint_info;

  G_OBJECT_CLASS (parent_class)->constructed (object);

  g_assert (GIMP_IS_TOOL_INFO (tool->tool_info));
  g_assert (GIMP_IS_PAINT_INFO (tool->tool_info->paint_info));

  display_config = GIMP_DISPLAY_CONFIG (tool->tool_info->gimp->config);

  paint_info = tool->tool_info->paint_info;

  g_assert (g_type_is_a (paint_info->paint_type, GIMP_TYPE_PAINT_CORE));

  paint_tool->core = g_object_new (paint_info->paint_type,
                                   "undo-desc", paint_info->blurb,
                                   NULL);

  g_signal_connect_object (options, "notify::hard",
                           G_CALLBACK (gimp_paint_tool_hard_notify),
                           tool, 0);

  gimp_paint_tool_hard_notify (options, NULL, tool);

  paint_tool->show_cursor = display_config->show_paint_tool_cursor;
  paint_tool->draw_brush  = display_config->show_brush_outline;

  g_signal_connect_object (display_config, "notify::show-paint-tool-cursor",
                           G_CALLBACK (gimp_paint_tool_cursor_notify),
                           paint_tool, 0);
  g_signal_connect_object (display_config, "notify::show-brush-outline",
                           G_CALLBACK (gimp_paint_tool_cursor_notify),
                           paint_tool, 0);
}
Esempio n. 7
0
static void
gimp_paint_tool_oper_update (GimpTool         *tool,
                             const GimpCoords *coords,
                             GdkModifierType   state,
                             gboolean          proximity,
                             GimpDisplay      *display)
{
  GimpPaintTool    *paint_tool    = GIMP_PAINT_TOOL (tool);
  GimpDrawTool     *draw_tool     = GIMP_DRAW_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)->oper_update (tool, coords, state,
                                                   proximity, display);
      return;
    }

  gimp_draw_tool_pause (draw_tool);

  if (gimp_draw_tool_is_active (draw_tool) &&
      draw_tool->display != display)
    gimp_draw_tool_stop (draw_tool);

  gimp_tool_pop_status (tool, display);

  if (tool->display            &&
      tool->display != display &&
      gimp_display_get_image (tool->display) == image)
    {
      /*  if this is a different display, but the same image, HACK around
       *  in tool internals AFTER stopping the current draw_tool, so
       *  straight line drawing works across different views of the
       *  same image.
       */

      tool->display = display;
    }

  if (drawable && proximity)
    {
      gboolean constrain_mask = gimp_get_constrain_behavior_mask ();
      gint     off_x, off_y;

      core->cur_coords = *coords;

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

      core->cur_coords.x -= off_x;
      core->cur_coords.y -= off_y;

      if (display == tool->display && (state & GIMP_PAINT_TOOL_LINE_MASK))
        {
          /*  If shift is down and this is not the first paint stroke,
           *  draw a line.
           */

          gchar   *status_help;
          gdouble  dx, dy, dist;

          gimp_paint_core_round_line (core, paint_options,
                                      (state & constrain_mask) != 0);

          dx = core->cur_coords.x - core->last_coords.x;
          dy = core->cur_coords.y - core->last_coords.y;

          status_help = gimp_suggest_modifiers (paint_tool->status_line,
                                                constrain_mask & ~state,
                                                NULL,
                                                _("%s for constrained angles"),
                                                NULL);

          /*  show distance in statusbar  */
          if (shell->unit == GIMP_UNIT_PIXEL)
            {
              dist = sqrt (SQR (dx) + SQR (dy));

              gimp_tool_push_status (tool, display, "%.1f %s.  %s",
                                     dist, _("pixels"), status_help);
            }
          else
            {
              gdouble xres;
              gdouble yres;
              gchar   format_str[64];

              gimp_image_get_resolution (image, &xres, &yres);

              g_snprintf (format_str, sizeof (format_str), "%%.%df %s.  %%s",
                          gimp_unit_get_digits (shell->unit),
                          gimp_unit_get_symbol (shell->unit));

              dist = (gimp_unit_get_factor (shell->unit) *
                      sqrt (SQR (dx / xres) +
                            SQR (dy / yres)));

              gimp_tool_push_status (tool, display, format_str,
                                     dist, status_help);
            }

          g_free (status_help);

          paint_tool->draw_line = TRUE;
        }
      else
        {
          gchar           *status;
          GdkModifierType  modifiers = 0;

          /* HACK: A paint tool may set status_ctrl to NULL to indicate that
           * it ignores the Ctrl modifier (temporarily or permanently), so
           * it should not be suggested.  This is different from how
           * gimp_suggest_modifiers() would interpret this parameter.
           */
          if (paint_tool->status_ctrl != NULL)
            modifiers |= constrain_mask;

          /* suggest drawing lines only after the first point is set
           */
          if (display == tool->display)
            modifiers |= GIMP_PAINT_TOOL_LINE_MASK;

          status = gimp_suggest_modifiers (paint_tool->status,
                                           modifiers & ~state,
                                           _("%s for a straight line"),
                                           paint_tool->status_ctrl,
                                           NULL);
          gimp_tool_push_status (tool, display, "%s", status);
          g_free (status);

          paint_tool->draw_line = FALSE;
        }

      if (! gimp_draw_tool_is_active (draw_tool))
        gimp_draw_tool_start (draw_tool, display);
    }
  else if (gimp_draw_tool_is_active (draw_tool))
    {
      gimp_draw_tool_stop (draw_tool);
    }

  GIMP_TOOL_CLASS (parent_class)->oper_update (tool, coords, state, proximity,
                                               display);

  gimp_draw_tool_resume (draw_tool);
}
Esempio n. 8
0
static void
gimp_paint_tool_button_press (GimpTool            *tool,
                              const GimpCoords    *coords,
                              guint32              time,
                              GdkModifierType      state,
                              GimpButtonPressType  press_type,
                              GimpDisplay         *display)
{
  GimpDrawTool     *draw_tool     = GIMP_DRAW_TOOL (tool);
  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);
  GimpCoords        curr_coords;
  gint              off_x, off_y;
  GError           *error = NULL;

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

  if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)))
    {
      gimp_tool_message_literal (tool, display,
                                 _("Cannot paint on layer groups."));
      return;
    }

  if (gimp_item_is_content_locked (GIMP_ITEM (drawable)))
    {
      gimp_tool_message_literal (tool, display,
                                 _("The active layer's pixels are locked."));
      return;
    }

  if (! gimp_item_is_visible (GIMP_ITEM (drawable)))
    {
      gimp_tool_message_literal (tool, display,
                                 _("The active layer is not visible."));
      return;
    }

  curr_coords = *coords;

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

  curr_coords.x -= off_x;
  curr_coords.y -= off_y;

  if (gimp_draw_tool_is_active (draw_tool))
    gimp_draw_tool_stop (draw_tool);

  if (tool->display            &&
      tool->display != display &&
      gimp_display_get_image (tool->display) == image)
    {
      /*  if this is a different display, but the same image, HACK around
       *  in tool internals AFTER stopping the current draw_tool, so
       *  straight line drawing works across different views of the
       *  same image.
       */

      tool->display = display;
    }

  if (! gimp_paint_core_start (core, drawable, paint_options, &curr_coords,
                               &error))
    {
      gimp_tool_message_literal (tool, display, error->message);
      g_clear_error (&error);
      return;
    }

  if ((display != tool->display) || ! paint_tool->draw_line)
    {
      /* if this is a new display, resest the "last stroke's endpoint"
       * because there is none
       */
      if (display != tool->display)
        core->start_coords = core->cur_coords;

      core->last_coords = core->cur_coords;

      core->distance    = 0.0;
      core->pixel_dist  = 0.0;
    }
  else if (paint_tool->draw_line)
    {
      gboolean constrain = (state & gimp_get_constrain_behavior_mask ()) != 0;

      /*  If shift is down and this is not the first paint
       *  stroke, then draw a line from the last coords to the pointer
       */
      gimp_paint_core_round_line (core, paint_options, constrain);
    }

  /*  chain up to activate the tool  */
  GIMP_TOOL_CLASS (parent_class)->button_press (tool, coords, time, state,
                                                press_type, display);

  /*  pause the current selection  */
  gimp_display_shell_selection_pause (shell);

  /*  Let the specific painting function initialize itself  */
  gimp_paint_core_paint (core, drawable, paint_options,
                         GIMP_PAINT_STATE_INIT, time);

  /*  Paint to the image  */
  if (paint_tool->draw_line)
    {
      gimp_paint_core_interpolate (core, drawable, paint_options,
                                   &core->cur_coords, time);
    }
  else
    {
      gimp_paint_core_paint (core, drawable, paint_options,
                             GIMP_PAINT_STATE_MOTION, time);
    }

  gimp_projection_flush_now (gimp_image_get_projection (image));
  gimp_display_flush_now (display);

  gimp_draw_tool_start (draw_tool, display);
}
Esempio n. 9
0
GimpCanvasItem *
gimp_brush_tool_create_outline (GimpBrushTool *brush_tool,
                                GimpDisplay   *display,
                                gdouble        x,
                                gdouble        y)
{
  GimpBrushCore        *brush_core;
  GimpPaintOptions     *options;
  GimpDisplayShell     *shell;
  const GimpBezierDesc *boundary = NULL;
  gint                  width    = 0;
  gint                  height   = 0;

  g_return_val_if_fail (GIMP_IS_BRUSH_TOOL (brush_tool), NULL);
  g_return_val_if_fail (GIMP_IS_DISPLAY (display), NULL);

  if (! GIMP_PAINT_TOOL (brush_tool)->draw_brush)
    return NULL;

  brush_core = GIMP_BRUSH_CORE (GIMP_PAINT_TOOL (brush_tool)->core);
  options    = GIMP_PAINT_TOOL_GET_OPTIONS (brush_tool);
  shell      = gimp_display_get_shell (display);

  if (! brush_core->main_brush || ! brush_core->dynamics)
    return NULL;

  if (brush_core->scale > 0.0)
    boundary = gimp_brush_transform_boundary (brush_core->main_brush,
                                              brush_core->scale,
                                              brush_core->aspect_ratio,
                                              brush_core->angle,
                                              brush_core->hardness,
                                              &width,
                                              &height);

  /*  don't draw the boundary if it becomes too small  */
  if (boundary                   &&
      SCALEX (shell, width)  > 4 &&
      SCALEY (shell, height) > 4)
    {
      x -= width  / 2.0;
      y -= height / 2.0;

      if (gimp_paint_options_get_brush_mode (options) == GIMP_BRUSH_HARD)
        {
#define EPSILON 0.000001
          /*  Add EPSILON before rounding since e.g.
           *  (5.0 - 0.5) may end up at (4.499999999....)
           *  due to floating point fnords
           */
          x = RINT (x + EPSILON);
          y = RINT (y + EPSILON);
#undef EPSILON
        }

      return gimp_canvas_path_new (shell, boundary, x, y, FALSE,
                                   GIMP_PATH_STYLE_OUTLINE);
    }

  return NULL;
}