/*
 * gfig_read_gimp_style() reads the style settings from the Gimp core,
 * and applies them to the specified style, giving that style the
 * specified name.  This is mainly useful as a way of initializing
 * a style.  The function does not cause a repaint.
 */
void
gfig_read_gimp_style (Style       *style,
                      const gchar *name)
{
  gint dummy;

  if (!name)
    g_message ("Error: name is NULL in gfig_read_gimp_style.");

  if (gfig_context->debug_styles)
    g_printerr ("Reading Gimp settings as style %s\n", name);
  style->name = g_strdup (name);

  gimp_context_get_foreground (&style->foreground);
  gimp_context_get_background (&style->background);

  style->brush_name = gimp_context_get_brush ();
  gimp_brush_get_info (style->brush_name,
                       &style->brush_width, &style->brush_height,
                       &dummy, &dummy);
  gimp_brush_get_spacing (style->brush_name, &style->brush_spacing);

  style->gradient = gimp_context_get_gradient ();
  style->pattern  = gimp_context_get_pattern ();

  style->fill_opacity = 100.;

  gfig_context->bdesc.name   = style->brush_name;
  gfig_context->bdesc.width  = style->brush_width;
  gfig_context->bdesc.height = style->brush_height;
}
Beispiel #2
0
void
gimp_drawable_stroke_boundary (GimpDrawable       *drawable,
                               GimpStrokeOptions  *options,
                               const GimpBoundSeg *bound_segs,
                               gint                n_bound_segs,
                               gint                offset_x,
                               gint                offset_y,
                               gboolean            push_undo)
{
  GimpScanConvert *scan_convert;

  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
  g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)));
  g_return_if_fail (GIMP_IS_STROKE_OPTIONS (options));
  g_return_if_fail (bound_segs == NULL || n_bound_segs != 0);
  g_return_if_fail (gimp_fill_options_get_style (GIMP_FILL_OPTIONS (options)) !=
                    GIMP_FILL_STYLE_PATTERN ||
                    gimp_context_get_pattern (GIMP_CONTEXT (options)) != NULL);

  scan_convert = gimp_scan_convert_new_from_boundary (bound_segs, n_bound_segs,
                                                      offset_x, offset_y);

  if (scan_convert)
    {
      gimp_drawable_stroke_scan_convert (drawable, options,
                                         scan_convert, push_undo);
      gimp_scan_convert_free (scan_convert);
    }
}
Beispiel #3
0
static gboolean
gimp_clone_start (GimpPaintCore     *paint_core,
                  GimpDrawable      *drawable,
                  GimpPaintOptions  *paint_options,
                  const GimpCoords  *coords,
                  GError           **error)
{
  GimpCloneOptions *options = GIMP_CLONE_OPTIONS (paint_options);

  if (! GIMP_PAINT_CORE_CLASS (parent_class)->start (paint_core, drawable,
                                                     paint_options, coords,
                                                     error))
    {
      return FALSE;
    }

  if (options->clone_type == GIMP_PATTERN_CLONE)
    {
      if (! gimp_context_get_pattern (GIMP_CONTEXT (options)))
        {
          g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
			       _("No patterns available for use with this tool."));
          return FALSE;
        }
    }

  return TRUE;
}
Beispiel #4
0
gboolean
gimp_drawable_bucket_fill (GimpDrawable         *drawable,
                           GimpContext          *context,
                           GimpBucketFillMode    fill_mode,
                           gint                  paint_mode,
                           gdouble               opacity,
                           gboolean              do_seed_fill,
                           gboolean              fill_transparent,
                           GimpSelectCriterion   fill_criterion,
                           gdouble               threshold,
                           gboolean              sample_merged,
                           gdouble               x,
                           gdouble               y,
                           GError              **error)
{
  GimpRGB      color;
  GimpPattern *pattern = NULL;

  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_CONTEXT (context), FALSE);
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

  if (fill_mode == GIMP_FG_BUCKET_FILL)
    {
      gimp_context_get_foreground (context, &color);
    }
  else if (fill_mode == GIMP_BG_BUCKET_FILL)
    {
      gimp_context_get_background (context, &color);
    }
  else if (fill_mode == GIMP_PATTERN_BUCKET_FILL)
    {
      pattern = gimp_context_get_pattern (context);

      if (! pattern)
        {
          g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
			       _("No patterns available for this operation."));
          return FALSE;
        }
    }
  else
    {
      g_warning ("%s: invalid fill_mode passed", G_STRFUNC);
      return FALSE;
    }

  gimp_drawable_bucket_fill_full (drawable,
                                  fill_mode,
                                  paint_mode, opacity,
                                  do_seed_fill,
                                  fill_transparent, fill_criterion,
                                  threshold, sample_merged,
                                  x, y,
                                  &color, pattern);

  return TRUE;
}
Beispiel #5
0
static GimpValueArray *
patterns_get_pattern_data_invoker (GimpProcedure         *procedure,
                                   Gimp                  *gimp,
                                   GimpContext           *context,
                                   GimpProgress          *progress,
                                   const GimpValueArray  *args,
                                   GError               **error)
{
  gboolean success = TRUE;
  GimpValueArray *return_vals;
  const gchar *name;
  gchar *actual_name = NULL;
  gint32 width = 0;
  gint32 height = 0;
  gint32 mask_bpp = 0;
  gint32 length = 0;
  guint8 *mask_data = NULL;

  name = g_value_get_string (gimp_value_array_index (args, 0));

  if (success)
    {
      GimpPattern *pattern;

      if (name && strlen (name))
        pattern = gimp_pdb_get_pattern (gimp, name, error);
      else
        pattern = gimp_context_get_pattern (context);

      if (pattern)
        {
          actual_name = g_strdup (gimp_object_get_name (pattern));
          width       = gimp_temp_buf_get_width  (pattern->mask);
          height      = gimp_temp_buf_get_height (pattern->mask);
          mask_bpp    = babl_format_get_bytes_per_pixel (gimp_temp_buf_get_format (pattern->mask));
          length      = gimp_temp_buf_get_data_size (pattern->mask);
          mask_data   = g_memdup (gimp_temp_buf_get_data (pattern->mask), length);
        }
      else
        success = FALSE;
    }

  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    {
      g_value_take_string (gimp_value_array_index (return_vals, 1), actual_name);
      g_value_set_int (gimp_value_array_index (return_vals, 2), width);
      g_value_set_int (gimp_value_array_index (return_vals, 3), height);
      g_value_set_int (gimp_value_array_index (return_vals, 4), mask_bpp);
      g_value_set_int (gimp_value_array_index (return_vals, 5), length);
      gimp_value_take_int8array (gimp_value_array_index (return_vals, 6), mask_data, length);
    }

  return return_vals;
}
Beispiel #6
0
void
edit_actions_setup (GimpActionGroup *group)
{
  GimpContext *context = gimp_get_user_context (group->gimp);
  GimpRGB      color;
  GimpPattern *pattern;
  GtkAction   *action;

  gimp_action_group_add_actions (group, "edit-action",
                                 edit_actions,
                                 G_N_ELEMENTS (edit_actions));

  gimp_action_group_add_enum_actions (group, "edit-action",
                                      edit_fill_actions,
                                      G_N_ELEMENTS (edit_fill_actions),
                                      G_CALLBACK (edit_fill_cmd_callback));

  action = gtk_action_group_get_action (GTK_ACTION_GROUP (group),
                                        "edit-paste-as-new-short");
  gtk_action_set_accel_path (action, "<Actions>/edit/edit-paste-as-new");

  action = gtk_action_group_get_action (GTK_ACTION_GROUP (group),
                                        "edit-fill-pattern");
  g_object_set (action, "context", context, NULL);

  g_signal_connect_object (context, "foreground-changed",
                           G_CALLBACK (edit_actions_foreground_changed),
                           group, 0);
  g_signal_connect_object (context, "background-changed",
                           G_CALLBACK (edit_actions_background_changed),
                           group, 0);
  g_signal_connect_object (context, "pattern-changed",
                           G_CALLBACK (edit_actions_pattern_changed),
                           group, 0);

  gimp_context_get_foreground (context, &color);
  edit_actions_foreground_changed (context, &color, group);

  gimp_context_get_background (context, &color);
  edit_actions_background_changed (context, &color, group);

  pattern = gimp_context_get_pattern (context);
  edit_actions_pattern_changed (context, pattern, group);

#define SET_ALWAYS_SHOW_IMAGE(action,show) \
        gimp_action_group_set_action_always_show_image (group, action, show)

  SET_ALWAYS_SHOW_IMAGE ("edit-fill-fg",      TRUE);
  SET_ALWAYS_SHOW_IMAGE ("edit-fill-bg",      TRUE);
  SET_ALWAYS_SHOW_IMAGE ("edit-fill-pattern", TRUE);

#undef SET_ALWAYS_SHOW_IMAGE
}
Beispiel #7
0
gboolean
gimp_get_fill_params (GimpContext   *context,
                      GimpFillType   fill_type,
                      GimpRGB       *color,
                      GimpPattern  **pattern,
                      GError       **error)

{
  g_return_val_if_fail (GIMP_IS_CONTEXT (context), FALSE);
  g_return_val_if_fail (color != NULL, FALSE);
  g_return_val_if_fail (pattern != NULL, FALSE);
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

  *pattern = NULL;

  switch (fill_type)
    {
    case GIMP_FILL_FOREGROUND:
      gimp_context_get_foreground (context, color);
      break;

    case GIMP_FILL_BACKGROUND:
      gimp_context_get_background (context, color);
      break;

    case GIMP_FILL_WHITE:
      gimp_rgba_set (color, 1.0, 1.0, 1.0, GIMP_OPACITY_OPAQUE);
      break;

    case GIMP_FILL_TRANSPARENT:
      gimp_rgba_set (color, 0.0, 0.0, 0.0, GIMP_OPACITY_TRANSPARENT);
      break;

    case GIMP_FILL_PATTERN:
      *pattern = gimp_context_get_pattern (context);

      if (! *pattern)
        {
          g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
			       _("No patterns available for this operation."));
          return FALSE;
        }
      break;

    default:
      g_warning ("%s: invalid fill_type %d", G_STRFUNC, fill_type);
      return FALSE;
    }

  return TRUE;
}
Beispiel #8
0
static gboolean
gimp_drawable_edit_can_fill_direct (GimpDrawable    *drawable,
                                    GimpFillOptions *options)
{
  GimpImage                *image;
  GimpContext              *context;
  gdouble                   opacity;
  GimpComponentMask         affect;
  GimpLayerMode             mode;
  GimpLayerCompositeMode    composite_mode;
  GimpLayerCompositeRegion  composite_region;

  image            = gimp_item_get_image (GIMP_ITEM (drawable));
  context          = GIMP_CONTEXT (options);
  opacity          = gimp_context_get_opacity (context);
  affect           = gimp_drawable_get_active_mask (drawable);
  mode             = gimp_context_get_paint_mode (context);
  composite_mode   = gimp_layer_mode_get_paint_composite_mode (mode);
  composite_region = gimp_layer_mode_get_included_region (mode, composite_mode);

  if (gimp_channel_is_empty (gimp_image_get_mask (image)) &&
      opacity == GIMP_OPACITY_OPAQUE                      &&
      affect  == GIMP_COMPONENT_MASK_ALL                  &&
      gimp_layer_mode_is_trivial (mode)                   &&
      (! gimp_layer_mode_is_subtractive (mode)            ^
       ! (composite_region & GIMP_LAYER_COMPOSITE_REGION_SOURCE)))
    {
      switch (gimp_fill_options_get_style (options))
        {
        case GIMP_FILL_STYLE_SOLID:
          return TRUE;

        case GIMP_FILL_STYLE_PATTERN:
          {
            GimpPattern *pattern;
            GimpTempBuf *mask;
            const Babl  *format;

            pattern = gimp_context_get_pattern (context);
            mask    = gimp_pattern_get_mask (pattern);
            format  = gimp_temp_buf_get_format (mask);

            return ! babl_format_has_alpha (format);
          }
        }
    }

  return FALSE;
}
Beispiel #9
0
void
gimp_drawable_stroke_scan_convert (GimpDrawable      *drawable,
                                   GimpStrokeOptions *options,
                                   GimpScanConvert   *scan_convert,
                                   gboolean           push_undo)
{
  gdouble  width;
  GimpUnit unit;

  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
  g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)));
  g_return_if_fail (GIMP_IS_STROKE_OPTIONS (options));
  g_return_if_fail (scan_convert != NULL);
  g_return_if_fail (gimp_fill_options_get_style (GIMP_FILL_OPTIONS (options)) !=
                    GIMP_FILL_STYLE_PATTERN ||
                    gimp_context_get_pattern (GIMP_CONTEXT (options)) != NULL);

  if (! gimp_item_mask_intersect (GIMP_ITEM (drawable), NULL, NULL, NULL, NULL))
    return;

  width = gimp_stroke_options_get_width (options);
  unit  = gimp_stroke_options_get_unit (options);

  if (unit != GIMP_UNIT_PIXEL)
    {
      GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable));
      gdouble    xres;
      gdouble    yres;

      gimp_image_get_resolution (image, &xres, &yres);

      gimp_scan_convert_set_pixel_ratio (scan_convert, yres / xres);

      width = gimp_units_to_pixels (width, unit, yres);
    }

  gimp_scan_convert_stroke (scan_convert, width,
                            gimp_stroke_options_get_join_style (options),
                            gimp_stroke_options_get_cap_style (options),
                            gimp_stroke_options_get_miter_limit (options),
                            gimp_stroke_options_get_dash_offset (options),
                            gimp_stroke_options_get_dash_info (options));

  gimp_drawable_fill_scan_convert (drawable, GIMP_FILL_OPTIONS (options),
                                   scan_convert, push_undo);
}
Beispiel #10
0
gboolean
gimp_drawable_stroke_vectors (GimpDrawable       *drawable,
                              GimpStrokeOptions  *options,
                              GimpVectors        *vectors,
                              gboolean            push_undo,
                              GError            **error)
{
  const GimpBezierDesc *bezier;

  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_STROKE_OPTIONS (options), FALSE);
  g_return_val_if_fail (GIMP_IS_VECTORS (vectors), FALSE);
  g_return_val_if_fail (gimp_fill_options_get_style (GIMP_FILL_OPTIONS (options)) !=
                        GIMP_FILL_STYLE_PATTERN ||
                        gimp_context_get_pattern (GIMP_CONTEXT (options)) != NULL,
                        FALSE);
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

  bezier = gimp_vectors_get_bezier (vectors);

  if (bezier && bezier->num_data >= 2)
    {
      GimpScanConvert *scan_convert = gimp_scan_convert_new ();

      gimp_scan_convert_add_bezier (scan_convert, bezier);
      gimp_drawable_stroke_scan_convert (drawable, options,
                                         scan_convert, push_undo);

      gimp_scan_convert_free (scan_convert);

      return TRUE;
    }

  g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
                       _("Not enough points to stroke"));

  return FALSE;
}
Beispiel #11
0
static GimpValueArray *
patterns_get_pattern_invoker (GimpProcedure         *procedure,
                              Gimp                  *gimp,
                              GimpContext           *context,
                              GimpProgress          *progress,
                              const GimpValueArray  *args,
                              GError               **error)
{
  gboolean success = TRUE;
  GimpValueArray *return_vals;
  gchar *name = NULL;
  gint32 width = 0;
  gint32 height = 0;

  GimpPattern *pattern = gimp_context_get_pattern (context);

  if (pattern)
    {
      name   = g_strdup (gimp_object_get_name (pattern));
      width  = gimp_temp_buf_get_width  (pattern->mask);
      height = gimp_temp_buf_get_height (pattern->mask);
    }
  else
    success = FALSE;

  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    {
      g_value_take_string (gimp_value_array_index (return_vals, 1), name);
      g_value_set_int (gimp_value_array_index (return_vals, 2), width);
      g_value_set_int (gimp_value_array_index (return_vals, 3), height);
    }

  return return_vals;
}
static void
gimp_perspective_clone_paint (GimpPaintCore    *paint_core,
                              GimpDrawable     *drawable,
                              GimpPaintOptions *paint_options,
                              const GimpCoords *coords,
                              GimpPaintState    paint_state,
                              guint32           time)
{
  GimpSourceCore       *source_core   = GIMP_SOURCE_CORE (paint_core);
  GimpPerspectiveClone *clone         = GIMP_PERSPECTIVE_CLONE (paint_core);
  GimpContext          *context       = GIMP_CONTEXT (paint_options);
  GimpCloneOptions     *clone_options = GIMP_CLONE_OPTIONS (paint_options);
  GimpSourceOptions    *options       = GIMP_SOURCE_OPTIONS (paint_options);

  switch (paint_state)
    {
    case GIMP_PAINT_STATE_INIT:
      if (source_core->set_source)
        {
          g_object_set (source_core, "src-drawable", drawable, NULL);

          source_core->src_x = coords->x;
          source_core->src_y = coords->y;

          /* get source coordinates in front view perspective */
          gimp_matrix3_transform_point (&clone->transform_inv,
                                        source_core->src_x,
                                        source_core->src_y,
                                        &clone->src_x_fv,
                                        &clone->src_y_fv);

          source_core->first_stroke = TRUE;
        }
      else
        {
          GeglBuffer *orig_buffer = NULL;
          GeglNode   *tile        = NULL;
          GeglNode   *src_node;

          if (options->align_mode == GIMP_SOURCE_ALIGN_NO)
            {
              source_core->orig_src_x = source_core->src_x;
              source_core->orig_src_y = source_core->src_y;

              source_core->first_stroke = TRUE;
            }

          clone->node = gegl_node_new ();

          g_object_set (clone->node,
                        "dont-cache", TRUE,
                        NULL);

          switch (clone_options->clone_type)
            {
            case GIMP_IMAGE_CLONE:
              {
                GimpPickable *src_pickable;
                GimpImage    *src_image;
                GimpImage    *dest_image;

                /*  If the source image is different from the
                 *  destination, then we should copy straight from the
                 *  source image to the canvas.
                 *  Otherwise, we need a call to get_orig_image to make sure
                 *  we get a copy of the unblemished (offset) image
                 */
                src_pickable = GIMP_PICKABLE (source_core->src_drawable);
                src_image    = gimp_pickable_get_image (src_pickable);

                if (options->sample_merged)
                  src_pickable = GIMP_PICKABLE (gimp_image_get_projection (src_image));

                dest_image = gimp_item_get_image (GIMP_ITEM (drawable));

                if ((options->sample_merged &&
                     (src_image != dest_image)) ||
                    (! options->sample_merged &&
                     (source_core->src_drawable != drawable)))
                  {
                    orig_buffer = gimp_pickable_get_buffer (src_pickable);
                  }
                else
                  {
                    if (options->sample_merged)
                      orig_buffer = gimp_paint_core_get_orig_proj (paint_core);
                    else
                      orig_buffer = gimp_paint_core_get_orig_image (paint_core);
                  }
              }
              break;

            case GIMP_PATTERN_CLONE:
              {
                GimpPattern *pattern = gimp_context_get_pattern (context);

                orig_buffer = gimp_pattern_create_buffer (pattern);

                tile = gegl_node_new_child (clone->node,
                                            "operation", "gegl:tile",
                                            NULL);
                clone->crop = gegl_node_new_child (clone->node,
                                                   "operation", "gegl:crop",
                                                   NULL);
              }
              break;
            }

          src_node = gegl_node_new_child (clone->node,
                                          "operation", "gegl:buffer-source",
                                          "buffer",    orig_buffer,
                                          NULL);

          clone->transform_node =
            gegl_node_new_child (clone->node,
                                 "operation", "gegl:transform",
                                 "sampler",    GIMP_INTERPOLATION_LINEAR,
                                 NULL);

          clone->dest_node =
            gegl_node_new_child (clone->node,
                                 "operation", "gegl:write-buffer",
                                 NULL);

          if (tile)
            {
              gegl_node_link_many (src_node,
                                   tile,
                                   clone->crop,
                                   clone->transform_node,
                                   clone->dest_node,
                                   NULL);

              g_object_unref (orig_buffer);
            }
          else
            {
              gegl_node_link_many (src_node,
                                   clone->transform_node,
                                   clone->dest_node,
                                   NULL);
            }
        }
      break;

    case GIMP_PAINT_STATE_MOTION:
      if (source_core->set_source)
        {
          /*  If the control key is down, move the src target and return */

          source_core->src_x = coords->x;
          source_core->src_y = coords->y;

          /* get source coordinates in front view perspective */
          gimp_matrix3_transform_point (&clone->transform_inv,
                                        source_core->src_x,
                                        source_core->src_y,
                                        &clone->src_x_fv,
                                        &clone->src_y_fv);

          source_core->first_stroke = TRUE;
        }
      else
        {
          /*  otherwise, update the target  */

          gint dest_x;
          gint dest_y;

          dest_x = coords->x;
          dest_y = coords->y;

          if (options->align_mode == GIMP_SOURCE_ALIGN_REGISTERED)
            {
              source_core->offset_x = 0;
              source_core->offset_y = 0;
            }
          else if (options->align_mode == GIMP_SOURCE_ALIGN_FIXED)
            {
              source_core->offset_x = source_core->src_x - dest_x;
              source_core->offset_y = source_core->src_y - dest_y;
            }
          else if (source_core->first_stroke)
            {
              source_core->offset_x = source_core->src_x - dest_x;
              source_core->offset_y = source_core->src_y - dest_y;

              /* get destination coordinates in front view perspective */
              gimp_matrix3_transform_point (&clone->transform_inv,
                                            dest_x,
                                            dest_y,
                                            &clone->dest_x_fv,
                                            &clone->dest_y_fv);

              source_core->first_stroke = FALSE;
            }

          gimp_source_core_motion (source_core, drawable, paint_options, coords);
        }
      break;

    case GIMP_PAINT_STATE_FINISH:
      if (clone->node)
        {
          g_object_unref (clone->node);
          clone->node           = NULL;
          clone->crop           = NULL;
          clone->transform_node = NULL;
          clone->dest_node      = NULL;
        }
      break;

    default:
      break;
    }

  g_object_notify (G_OBJECT (clone), "src-x");
  g_object_notify (G_OBJECT (clone), "src-y");
}
Beispiel #13
0
void
gimp_edit_fill (GimpImage       *image,
                GimpDrawable    *drawable,
                GimpFillOptions *options,
                const gchar     *undo_desc)
{
  GeglBuffer  *dest_buffer;
  GimpPattern *pattern = NULL;
  GimpRGB      color;
  const Babl  *format;
  gint         x, y, width, height;

  g_return_if_fail (GIMP_IS_IMAGE (image));
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
  g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)));
  g_return_if_fail (GIMP_IS_FILL_OPTIONS (options));

  if (! gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
    return;  /*  nothing to do, but the fill succeeded  */

  switch (gimp_fill_options_get_style (options))
    {
    case GIMP_FILL_STYLE_SOLID:
      gimp_context_get_foreground (GIMP_CONTEXT (options), &color);
      break;

    case GIMP_FILL_STYLE_PATTERN:
      pattern = gimp_context_get_pattern (GIMP_CONTEXT (options));
      break;
    }

  if (pattern &&
      babl_format_has_alpha (gimp_temp_buf_get_format (pattern->mask)) &&
      ! gimp_drawable_has_alpha (drawable))
    {
      format = gimp_drawable_get_format_with_alpha (drawable);
    }
  else
    {
      format = gimp_drawable_get_format (drawable);
    }

  dest_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, width, height),
                                 format);

  if (pattern)
    {
      GeglBuffer *src_buffer = gimp_pattern_create_buffer (pattern);

      gegl_buffer_set_pattern (dest_buffer, NULL, src_buffer, 0, 0);
      g_object_unref (src_buffer);
    }
  else
    {
      GeglColor *gegl_color = gimp_gegl_color_new (&color);

      gegl_buffer_set_color (dest_buffer, NULL, gegl_color);
      g_object_unref (gegl_color);
    }

  if (! undo_desc)
    undo_desc = gimp_fill_options_get_undo_desc (options);

  gimp_drawable_apply_buffer (drawable, dest_buffer,
                              GEGL_RECTANGLE (0, 0, width, height),
                              TRUE, undo_desc,
                              gimp_context_get_opacity (GIMP_CONTEXT (options)),
                              gimp_context_get_paint_mode (GIMP_CONTEXT (options)),
                              NULL, x, y);

  g_object_unref (dest_buffer);

  gimp_drawable_update (drawable, x, y, width, height);
}
Beispiel #14
0
static void
gimp_drawable_stroke_scan_convert (GimpDrawable      *drawable,
                                   GimpStrokeOptions *options,
                                   GimpScanConvert   *scan_convert)
{
  GimpContext *context = GIMP_CONTEXT (options);
  GimpImage   *image;
  gdouble      width;
  TileManager *base;
  TileManager *mask;
  gint         x, y, w, h;
  gint         bytes;
  gint         off_x, off_y;
  guchar       bg[1] = { 0, };
  PixelRegion  maskPR, basePR;

  image = gimp_item_get_image (GIMP_ITEM (drawable));

  /*  must call gimp_channel_is_empty() instead of relying on
   *  gimp_drawable_mask_intersect() because the selection pretends to
   *  be empty while it is being stroked, to prevent masking itself.
   */
  if (gimp_channel_is_empty (gimp_image_get_mask (image)))
    {
      x = 0;
      y = 0;
      w = gimp_item_width (GIMP_ITEM (drawable));
      h = gimp_item_height (GIMP_ITEM (drawable));
    }
  else if (! gimp_drawable_mask_intersect (drawable, &x, &y, &w, &h))
    {
      return;
    }

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

  width = options->width;

  if (options->unit != GIMP_UNIT_PIXEL)
    {
      gimp_scan_convert_set_pixel_ratio (scan_convert,
                                         image->yresolution /
                                         image->xresolution);

      width *= (image->yresolution /
                _gimp_unit_get_factor (image->gimp, options->unit));
    }

  gimp_scan_convert_stroke (scan_convert, width,
                            options->join_style,
                            options->cap_style,
                            options->miter_limit,
                            options->dash_offset,
                            options->dash_info);

  /* fill a 1-bpp Tilemanager with black, this will describe the shape
   * of the stroke.
   */
  mask = tile_manager_new (w, h, 1);
  pixel_region_init (&maskPR, mask, 0, 0, w, h, TRUE);
  color_region (&maskPR, bg);

  /* render the stroke into it */
  gimp_scan_convert_render (scan_convert, mask,
                            x + off_x, y + off_y,
                            options->antialias);

  bytes = gimp_drawable_bytes_with_alpha (drawable);

  base = tile_manager_new (w, h, bytes);
  pixel_region_init (&basePR, base, 0, 0, w, h, TRUE);
  pixel_region_init (&maskPR, mask, 0, 0, w, h, FALSE);

  switch (options->style)
    {
    case GIMP_STROKE_STYLE_SOLID:
      {
        guchar tmp_col[MAX_CHANNELS] = { 0, };
        guchar col[MAX_CHANNELS]     = { 0, };

        gimp_rgb_get_uchar (&context->foreground,
                            &tmp_col[RED_PIX],
                            &tmp_col[GREEN_PIX],
                            &tmp_col[BLUE_PIX]);

        gimp_image_transform_color (image, gimp_drawable_type (drawable), col,
                                    GIMP_RGB, tmp_col);
        col[bytes - 1] = OPAQUE_OPACITY;

        color_region_mask (&basePR, &maskPR, col);
      }
      break;

    case GIMP_STROKE_STYLE_PATTERN:
      {
        GimpPattern *pattern;
        TempBuf     *pat_buf;
        gboolean     new_buf;

        pattern = gimp_context_get_pattern (context);
        pat_buf = gimp_image_transform_temp_buf (image,
                                                 gimp_drawable_type (drawable),
                                                 pattern->mask, &new_buf);

        pattern_region (&basePR, &maskPR, pat_buf, x, y);

        if (new_buf)
          temp_buf_free (pat_buf);
      }
      break;
    }

  /* Apply to drawable */
  pixel_region_init (&basePR, base, 0, 0, w, h, FALSE);
  gimp_drawable_apply_region (drawable, &basePR,
                              TRUE, _("Render Stroke"),
                              gimp_context_get_opacity (context),
                              gimp_context_get_paint_mode (context),
                              NULL, x, y);

  tile_manager_unref (mask);
  tile_manager_unref (base);

  gimp_drawable_update (drawable, x, y, w, h);
}
GtkWidget *
gimp_toolbox_indicator_area_create (GimpToolbox *toolbox)
{
  GimpContext *context;
  GtkWidget   *indicator_table;
  GtkWidget   *brush_view;
  GtkWidget   *pattern_view;
  GtkWidget   *gradient_view;

  g_return_val_if_fail (GIMP_IS_TOOLBOX (toolbox), NULL);

  context = GIMP_DOCK (toolbox)->context;

  indicator_table = gtk_table_new (2, 2, FALSE);
  gtk_table_set_row_spacings (GTK_TABLE (indicator_table), CELL_SPACING);
  gtk_table_set_col_spacings (GTK_TABLE (indicator_table), CELL_SPACING);

  /*  brush view  */

  brush_view =
    gimp_view_new_full_by_types (context,
                                 GIMP_TYPE_VIEW, GIMP_TYPE_BRUSH,
                                 CELL_SIZE, CELL_SIZE, 1,
                                 FALSE, TRUE, TRUE);
  gimp_view_set_viewable (GIMP_VIEW (brush_view),
                          GIMP_VIEWABLE (gimp_context_get_brush (context)));
  gtk_table_attach_defaults (GTK_TABLE (indicator_table), brush_view,
                             0, 1, 0, 1);
  gtk_widget_show (brush_view);

  gimp_help_set_help_data (brush_view,
                           _("The active brush.\n"
                             "Click to open the Brush Dialog."), NULL);

  g_signal_connect_object (context, "brush-changed",
                           G_CALLBACK (gimp_view_set_viewable),
                           brush_view,
                           G_CONNECT_SWAPPED);

  g_signal_connect (brush_view, "clicked",
                    G_CALLBACK (brush_preview_clicked),
                    toolbox);

  gimp_dnd_viewable_dest_add (brush_view,
                              GIMP_TYPE_BRUSH,
                              brush_preview_drop_brush,
                              context);

  /*  pattern view  */

  pattern_view =
    gimp_view_new_full_by_types (context,
                                 GIMP_TYPE_VIEW, GIMP_TYPE_PATTERN,
                                 CELL_SIZE, CELL_SIZE, 1,
                                 FALSE, TRUE, TRUE);
  gimp_view_set_viewable (GIMP_VIEW (pattern_view),
                          GIMP_VIEWABLE (gimp_context_get_pattern (context)));

  gtk_table_attach_defaults (GTK_TABLE (indicator_table), pattern_view,
                             1, 2, 0, 1);
  gtk_widget_show (pattern_view);

  gimp_help_set_help_data (pattern_view,
                           _("The active pattern.\n"
                             "Click to open the Pattern Dialog."), NULL);

  g_signal_connect_object (context, "pattern-changed",
                           G_CALLBACK (gimp_view_set_viewable),
                           pattern_view,
                           G_CONNECT_SWAPPED);

  g_signal_connect (pattern_view, "clicked",
                    G_CALLBACK (pattern_preview_clicked),
                    toolbox);

  gimp_dnd_viewable_dest_add (pattern_view,
                              GIMP_TYPE_PATTERN,
                              pattern_preview_drop_pattern,
                              context);

  /*  gradient view  */

  gradient_view =
    gimp_view_new_full_by_types (context,
                                 GIMP_TYPE_VIEW, GIMP_TYPE_GRADIENT,
                                 GRAD_CELL_WIDTH, GRAD_CELL_HEIGHT, 1,
                                 FALSE, TRUE, TRUE);
  gimp_view_set_viewable (GIMP_VIEW (gradient_view),
                          GIMP_VIEWABLE (gimp_context_get_gradient (context)));

  gtk_table_attach_defaults (GTK_TABLE (indicator_table), gradient_view,
                             0, 2, 1, 2);
  gtk_widget_show (gradient_view);

  gimp_help_set_help_data (gradient_view,
                           _("The active gradient.\n"
                             "Click to open the Gradient Dialog."), NULL);

  g_signal_connect_object (context, "gradient-changed",
                           G_CALLBACK (gimp_view_set_viewable),
                           gradient_view,
                           G_CONNECT_SWAPPED);

  g_signal_connect (gradient_view, "clicked",
                    G_CALLBACK (gradient_preview_clicked),
                    toolbox);

  gimp_dnd_viewable_dest_add (gradient_view,
                              GIMP_TYPE_GRADIENT,
                              gradient_preview_drop_gradient,
                              context);

  gtk_widget_show (indicator_table);

  return indicator_table;
}
Beispiel #16
0
static void
gimp_clone_motion (GimpSourceCore   *source_core,
                   GimpDrawable     *drawable,
                   GimpPaintOptions *paint_options,
                   const GimpCoords *coords,
                   gdouble           opacity,
                   GimpPickable     *src_pickable,
                   PixelRegion      *srcPR,
                   gint              src_offset_x,
                   gint              src_offset_y,
                   TempBuf          *paint_area,
                   gint              paint_area_offset_x,
                   gint              paint_area_offset_y,
                   gint              paint_area_width,
                   gint              paint_area_height)
{
  GimpPaintCore      *paint_core     = GIMP_PAINT_CORE (source_core);
  GimpCloneOptions   *options        = GIMP_CLONE_OPTIONS (paint_options);
  GimpSourceOptions  *source_options = GIMP_SOURCE_OPTIONS (paint_options);
  GimpContext        *context        = GIMP_CONTEXT (paint_options);
  GimpImage          *image          = gimp_item_get_image (GIMP_ITEM (drawable));
  GimpImage          *src_image      = NULL;
  GimpDynamicsOutput *force_output;
  GimpImageType       src_type       = 0;
  GimpImageType       dest_type;
  gpointer            pr = NULL;
  gint                y;
  PixelRegion         destPR;
  GimpPattern        *pattern = NULL;
  gdouble             fade_point;
  gdouble             force;

  switch (options->clone_type)
    {
    case GIMP_IMAGE_CLONE:
      src_image = gimp_pickable_get_image (src_pickable);

      src_type = gimp_pickable_get_image_type (src_pickable);

      if (gimp_pickable_get_bytes (src_pickable) < srcPR->bytes)
        src_type = GIMP_IMAGE_TYPE_WITH_ALPHA (src_type);

      pixel_region_init_temp_buf (&destPR, paint_area,
                                  paint_area_offset_x, paint_area_offset_y,
                                  paint_area_width, paint_area_height);

      pr = pixel_regions_register (2, srcPR, &destPR);
      break;

    case GIMP_PATTERN_CLONE:
      pattern = gimp_context_get_pattern (context);

      pixel_region_init_temp_buf (&destPR, paint_area,
                                  0, 0,
                                  paint_area->width, paint_area->height);

      pr = pixel_regions_register (1, &destPR);
      break;
    }

  dest_type = gimp_drawable_type (drawable);

  for (; pr != NULL; pr = pixel_regions_process (pr))
    {
      guchar *s = srcPR->data;
      guchar *d = destPR.data;

      for (y = 0; y < destPR.h; y++)
        {
          switch (options->clone_type)
            {
            case GIMP_IMAGE_CLONE:
              gimp_clone_line_image (image, dest_type,
                                     src_image, src_type,
                                     s, d,
                                     srcPR->bytes, destPR.bytes, destPR.w);
              s += srcPR->rowstride;
              break;

            case GIMP_PATTERN_CLONE:
              gimp_clone_line_pattern (image, dest_type,
                                       pattern, d,
                                       paint_area->x     + src_offset_x,
                                       paint_area->y + y + src_offset_y,
                                       destPR.bytes, destPR.w);
              break;
            }

          d += destPR.rowstride;
        }
    }

  force_output = gimp_dynamics_get_output (GIMP_BRUSH_CORE (paint_core)->dynamics,
                                           GIMP_DYNAMICS_OUTPUT_FORCE);

  fade_point = gimp_paint_options_get_fade (paint_options, image,
                                            paint_core->pixel_dist);

  force = gimp_dynamics_output_get_linear_value (force_output,
                                                 coords,
                                                 paint_options,
                                                 fade_point);

  gimp_brush_core_paste_canvas (GIMP_BRUSH_CORE (paint_core), drawable,
                                coords,
                                MIN (opacity, GIMP_OPACITY_OPAQUE),
                                gimp_context_get_opacity (context),
                                gimp_context_get_paint_mode (context),
                                gimp_paint_options_get_brush_mode (paint_options),
                                force,

                                /* In fixed mode, paint incremental so the
                                 * individual brushes are properly applied
                                 * on top of each other.
                                 * Otherwise the stuff we paint is seamless
                                 * and we don't need intermediate masking.
                                 */
                                source_options->align_mode ==
                                GIMP_SOURCE_ALIGN_FIXED ?
                                GIMP_PAINT_INCREMENTAL : GIMP_PAINT_CONSTANT);
}
Beispiel #17
0
static void
gimp_clone_motion (GimpSourceCore   *source_core,
                   GimpDrawable     *drawable,
                   GimpPaintOptions *paint_options,
                   const GimpCoords *coords,
                   gdouble           opacity,
                   GimpPickable     *src_pickable,
                   GeglBuffer       *src_buffer,
                   GeglRectangle    *src_rect,
                   gint              src_offset_x,
                   gint              src_offset_y,
                   GeglBuffer       *paint_buffer,
                   gint              paint_buffer_x,
                   gint              paint_buffer_y,
                   gint              paint_area_offset_x,
                   gint              paint_area_offset_y,
                   gint              paint_area_width,
                   gint              paint_area_height)
{
  GimpPaintCore     *paint_core     = GIMP_PAINT_CORE (source_core);
  GimpCloneOptions  *options        = GIMP_CLONE_OPTIONS (paint_options);
  GimpSourceOptions *source_options = GIMP_SOURCE_OPTIONS (paint_options);
  GimpContext       *context        = GIMP_CONTEXT (paint_options);
  GimpImage         *image          = gimp_item_get_image (GIMP_ITEM (drawable));
  gdouble            fade_point;
  gdouble            force;

  if (gimp_source_core_use_source (source_core, source_options))
    {
      gegl_buffer_copy (src_buffer,
                        GEGL_RECTANGLE (src_rect->x,
                                        src_rect->y,
                                        paint_area_width,
                                        paint_area_height),
                        paint_buffer,
                        GEGL_RECTANGLE (paint_area_offset_x,
                                        paint_area_offset_y,
                                        0, 0));
    }
  else if (options->clone_type == GIMP_PATTERN_CLONE)
    {
      GimpPattern *pattern    = gimp_context_get_pattern (context);
      GeglBuffer  *src_buffer = gimp_pattern_create_buffer (pattern);

      gegl_buffer_set_pattern (paint_buffer,
                               GEGL_RECTANGLE (paint_area_offset_x,
                                               paint_area_offset_y,
                                               paint_area_width,
                                               paint_area_height),
                               src_buffer,
                               - paint_buffer_x - src_offset_x,
                               - paint_buffer_y - src_offset_y);

      g_object_unref (src_buffer);
    }
  else
    {
      g_return_if_reached ();
    }

  fade_point = gimp_paint_options_get_fade (paint_options, image,
                                            paint_core->pixel_dist);

  force = gimp_dynamics_get_linear_value (GIMP_BRUSH_CORE (paint_core)->dynamics,
                                          GIMP_DYNAMICS_OUTPUT_FORCE,
                                          coords,
                                          paint_options,
                                          fade_point);

  gimp_brush_core_paste_canvas (GIMP_BRUSH_CORE (paint_core), drawable,
                                coords,
                                MIN (opacity, GIMP_OPACITY_OPAQUE),
                                gimp_context_get_opacity (context),
                                gimp_context_get_paint_mode (context),
                                gimp_paint_options_get_brush_mode (paint_options),
                                force,

                                /* In fixed mode, paint incremental so the
                                 * individual brushes are properly applied
                                 * on top of each other.
                                 * Otherwise the stuff we paint is seamless
                                 * and we don't need intermediate masking.
                                 */
                                source_options->align_mode ==
                                GIMP_SOURCE_ALIGN_FIXED ?
                                GIMP_PAINT_INCREMENTAL : GIMP_PAINT_CONSTANT);
}