home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / clone.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-17  |  19.9 KB  |  744 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include <stdlib.h>
  22. #include <string.h>
  23.  
  24. #include <gtk/gtk.h>
  25.  
  26. #include "apptypes.h"
  27.  
  28. #include "appenv.h"
  29. #include "drawable.h"
  30. #include "gdisplay.h"
  31. #include "gimage_mask.h"
  32. #include "gimpui.h"
  33. #include "paint_funcs.h"
  34. #include "paint_core.h"
  35. #include "paint_options.h"
  36. #include "clone.h"
  37. #include "selection.h"
  38. #include "tools.h"
  39. #include "cursorutil.h"
  40.  
  41. #include "libgimp/gimpintl.h"
  42.  
  43. #define TARGET_HEIGHT  15
  44. #define TARGET_WIDTH   15
  45.  
  46. /* default types */
  47. #define CLONE_DEFAULT_TYPE     IMAGE_CLONE
  48. #define CLONE_DEFAULT_ALIGNED  ALIGN_NO
  49.  
  50. /*  the clone structures  */
  51.  
  52. typedef enum
  53. {
  54.   ALIGN_NO,
  55.   ALIGN_YES,
  56.   ALIGN_REGISTERED
  57. } AlignType;
  58.  
  59. typedef struct _CloneOptions CloneOptions;
  60.  
  61. struct _CloneOptions
  62. {
  63.   PaintOptions  paint_options;
  64.  
  65.   CloneType     type;
  66.   CloneType     type_d;
  67.   GtkWidget    *type_w[2];  /* 2 radio buttons */
  68.  
  69.   AlignType     aligned;
  70.   AlignType     aligned_d;
  71.   GtkWidget    *aligned_w[3];  /* 3 radio buttons */
  72. };
  73.  
  74.  
  75. /*  the clone tool options  */
  76. static CloneOptions *clone_options = NULL;
  77.  
  78. /*  local variables  */
  79. static int           src_x = 0;                /*                         */
  80. static int           src_y = 0;                /*  position of clone src  */
  81. static int           dest_x = 0;               /*                         */
  82. static int           dest_y = 0;               /*  position of clone src  */
  83. static int           offset_x = 0;             /*                         */
  84. static int           offset_y = 0;             /*  offset for cloning     */
  85. static int           first = TRUE;
  86. static int           trans_tx, trans_ty;       /*  transformed target     */
  87. static GDisplay     *the_src_gdisp = NULL;     /*  ID of source gdisplay  */
  88. static GimpDrawable *src_drawable_ = NULL;     /*  source drawable        */
  89.  
  90. static GimpDrawable *non_gui_src_drawable;
  91. static int           non_gui_offset_x;
  92. static int           non_gui_offset_y;
  93. static CloneType     non_gui_type;
  94.  
  95. /*  forward function declarations  */
  96.  
  97. static void   clone_draw         (Tool *);
  98. static void   clone_motion       (PaintCore *, GimpDrawable *, GimpDrawable *,
  99.                   PaintPressureOptions *, CloneType, int, int);
  100. static void   clone_line_image   (GImage *, GImage *, GimpDrawable *,
  101.                   GimpDrawable *, unsigned char *,
  102.                   unsigned char *, int, int, int, int);
  103. static void   clone_line_pattern (GImage *, GimpDrawable *, GPattern *,
  104.                   unsigned char *, int, int, int, int);
  105.  
  106.  
  107. /*  functions  */
  108.  
  109. static void
  110. clone_options_reset (void)
  111. {
  112.   CloneOptions *options = clone_options;
  113.  
  114.   paint_options_reset ((PaintOptions *) options);
  115.  
  116.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->type_w[options->type_d]), TRUE);
  117.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->aligned_w[options->aligned_d]), TRUE);
  118. }
  119.  
  120. static CloneOptions *
  121. clone_options_new (void)
  122. {
  123.   CloneOptions *options;
  124.   GtkWidget *vbox;
  125.   GtkWidget *frame;
  126.  
  127.   /*  the new clone tool options structure  */
  128.   options = g_new (CloneOptions, 1);
  129.   paint_options_init ((PaintOptions *) options,
  130.               CLONE,
  131.               clone_options_reset);
  132.   options->type    = options->type_d    = CLONE_DEFAULT_TYPE;
  133.   options->aligned = options->aligned_d = CLONE_DEFAULT_ALIGNED;
  134.  
  135.   /*  the main vbox  */
  136.   vbox = ((ToolOptions *) options)->main_vbox;
  137.  
  138.   frame = gimp_radio_group_new2 (TRUE, _("Source"),
  139.                  gimp_radio_button_update,
  140.                  &options->type, (gpointer) options->type,
  141.  
  142.                  _("Image Source"), (gpointer) IMAGE_CLONE,
  143.                  &options->type_w[0],
  144.                  _("Pattern Source"), (gpointer) PATTERN_CLONE,
  145.                  &options->type_w[1],
  146.  
  147.                  NULL);
  148.  
  149.   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  150.   gtk_widget_show (frame);
  151.  
  152.   frame = gimp_radio_group_new2 (TRUE, _("Alignment"),
  153.                  gimp_radio_button_update,
  154.                  &options->aligned, (gpointer) options->aligned,
  155.  
  156.                  _("Non Aligned"), (gpointer) ALIGN_NO,
  157.                  &options->aligned_w[0],
  158.                  _("Aligned"), (gpointer) ALIGN_YES,
  159.                  &options->aligned_w[1],
  160.                  _("Registered"), (gpointer) ALIGN_REGISTERED,
  161.                  &options->aligned_w[2],
  162.  
  163.                  NULL);
  164.  
  165.   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  166.   gtk_widget_show (frame);
  167.   
  168.   return options;
  169. }
  170.  
  171. static void
  172. clone_src_drawable_destroyed_cb (GimpDrawable  *drawable,
  173.                  GimpDrawable **src_drawable)
  174. {
  175.   if (drawable == *src_drawable)
  176.     {
  177.       *src_drawable = NULL;
  178.       the_src_gdisp = NULL;
  179.     }
  180. }
  181.  
  182. static void
  183. clone_set_src_drawable (GimpDrawable *drawable)
  184. {
  185.   if (src_drawable_ == drawable)
  186.     return;
  187.   if (src_drawable_)
  188.     gtk_signal_disconnect_by_data (GTK_OBJECT (src_drawable_), &src_drawable_);
  189.   src_drawable_ = drawable;
  190.   if (drawable)
  191.     {
  192.       gtk_signal_connect (GTK_OBJECT (drawable), "destroy",
  193.               GTK_SIGNAL_FUNC (clone_src_drawable_destroyed_cb),
  194.               &src_drawable_);
  195.     }
  196. }
  197.  
  198. void *
  199. clone_paint_func (PaintCore    *paint_core,
  200.           GimpDrawable *drawable,
  201.           gint          state)
  202. {
  203.   GDisplay * gdisp;
  204.   GDisplay * src_gdisp;
  205.   int x1, y1, x2, y2;
  206.   static int orig_src_x, orig_src_y;
  207.  
  208.   gdisp = (GDisplay *) active_tool->gdisp_ptr;
  209.  
  210.   switch (state)
  211.     {
  212.     case PRETRACE_PAINT:
  213.       draw_core_pause (paint_core->core, active_tool);
  214.       break;
  215.     case MOTION_PAINT:
  216.       x1 = paint_core->curx;
  217.       y1 = paint_core->cury;
  218.       x2 = paint_core->lastx;
  219.       y2 = paint_core->lasty;
  220.  
  221.       /*  If the control key is down, move the src target and return */
  222.       if (paint_core->state & GDK_CONTROL_MASK)
  223.     {
  224.       src_x = x1;
  225.       src_y = y1;
  226.       first = TRUE;
  227.     }
  228.       /*  otherwise, update the target  */
  229.       else
  230.     {
  231.       dest_x = x1;
  232.       dest_y = y1;
  233.  
  234.           if (clone_options->aligned == ALIGN_REGISTERED)
  235.             {
  236.           offset_x = 0;
  237.           offset_y = 0;
  238.             }
  239.           else if (first)
  240.         {
  241.           offset_x = src_x - dest_x;
  242.           offset_y = src_y - dest_y;
  243.           first = FALSE;
  244.         }
  245.  
  246.       src_x = dest_x + offset_x;
  247.       src_y = dest_y + offset_y;
  248.  
  249.       clone_motion (paint_core, drawable, src_drawable_, 
  250.             clone_options->paint_options.pressure_options, 
  251.             clone_options->type, offset_x, offset_y);
  252.     }
  253.  
  254.       break;
  255.  
  256.     case INIT_PAINT:
  257.       if (paint_core->state & GDK_CONTROL_MASK)
  258.     {
  259.       the_src_gdisp = gdisp;
  260.       clone_set_src_drawable(drawable);
  261.       src_x = paint_core->curx;
  262.       src_y = paint_core->cury;
  263.       first = TRUE;
  264.     }
  265.       else if (clone_options->aligned == ALIGN_NO)
  266.     {
  267.       first = TRUE;
  268.       orig_src_x = src_x;
  269.       orig_src_y = src_y;
  270.     }
  271.       if (clone_options->type == PATTERN_CLONE)
  272.     if (! gimp_context_get_pattern (NULL))
  273.       g_message (_("No patterns available for this operation."));
  274.       break;
  275.  
  276.     case FINISH_PAINT:
  277.       draw_core_stop (paint_core->core, active_tool);
  278.       if (clone_options->aligned == ALIGN_NO && !first)
  279.     {
  280.       src_x = orig_src_x;
  281.       src_y = orig_src_y;
  282.     } 
  283.       return NULL;
  284.       break;
  285.  
  286.     default:
  287.       break;
  288.     }
  289.  
  290.   /*  Calculate the coordinates of the target  */
  291.   src_gdisp = the_src_gdisp;
  292.   if (!src_gdisp)
  293.     {
  294.       the_src_gdisp = gdisp;
  295.       src_gdisp = the_src_gdisp;
  296.     }
  297.  
  298.   if (state == INIT_PAINT)
  299.     /*  Initialize the tool drawing core  */
  300.     draw_core_start (paint_core->core,
  301.              src_gdisp->canvas->window,
  302.              active_tool);
  303.   else if (state == POSTTRACE_PAINT)
  304.     {
  305.       /*  Find the target cursor's location onscreen  */
  306.       gdisplay_transform_coords (src_gdisp, src_x, src_y,
  307.                  &trans_tx, &trans_ty, 1);
  308.       draw_core_resume (paint_core->core, active_tool);      
  309.     }
  310.   return NULL;
  311. }
  312.  
  313. void
  314. clone_cursor_update (Tool           *tool,
  315.              GdkEventMotion *mevent,
  316.              gpointer        gdisp_ptr)
  317. {
  318.   GDisplay *gdisp;
  319.   Layer *layer;
  320.   GdkCursorType ctype = GDK_TOP_LEFT_ARROW;
  321.   int x, y;
  322.  
  323.   gdisp = (GDisplay *) gdisp_ptr;
  324.  
  325.   gdisplay_untransform_coords (gdisp, (double) mevent->x, (double) mevent->y,
  326.                    &x, &y, TRUE, FALSE);
  327.  
  328.   if ((layer = gimage_get_active_layer (gdisp->gimage))) 
  329.     {
  330.       int off_x, off_y;
  331.       drawable_offsets (GIMP_DRAWABLE (layer), &off_x, &off_y);
  332.  
  333.       if (x >= off_x && y >= off_y &&
  334.       x < (off_x + drawable_width (GIMP_DRAWABLE (layer))) &&
  335.       y < (off_y + drawable_height (GIMP_DRAWABLE (layer))))
  336.     {
  337.       /*  One more test--is there a selected region?
  338.        *  if so, is cursor inside?
  339.        */
  340.       if (gimage_mask_is_empty (gdisp->gimage))
  341.         ctype = GIMP_MOUSE_CURSOR;
  342.       else if (gimage_mask_value (gdisp->gimage, x, y))
  343.         ctype = GIMP_MOUSE_CURSOR;
  344.     }
  345.     }
  346.   
  347.   if (clone_options->type == IMAGE_CLONE)
  348.     {
  349.       if (mevent->state & GDK_CONTROL_MASK)
  350.     ctype = GIMP_CROSSHAIR_SMALL_CURSOR;
  351.       else if (!src_drawable_)
  352.     ctype = GIMP_BAD_CURSOR;
  353.     }
  354.  
  355.   gdisplay_install_tool_cursor (gdisp, ctype,
  356.                 ctype == GIMP_CROSSHAIR_SMALL_CURSOR ?
  357.                 TOOL_TYPE_NONE : CLONE,
  358.                 CURSOR_MODIFIER_NONE,
  359.                 FALSE);
  360. }
  361.  
  362. Tool *
  363. tools_new_clone (void)
  364. {
  365.   Tool * tool;
  366.   PaintCore * private;
  367.  
  368.   /*  The tool options  */
  369.   if (! clone_options)
  370.     {
  371.       clone_options = clone_options_new ();
  372.       tools_register (CLONE, (ToolOptions *) clone_options);
  373.  
  374.       /*  press all default buttons  */
  375.       clone_options_reset ();
  376.     }
  377.  
  378.   tool = paint_core_new (CLONE);
  379.   /* the clone tool provides its own cursor_update_function 
  380.      until I figure out somethinh nicer -- Sven  */
  381.   tool->cursor_update_func = clone_cursor_update;
  382.  
  383.   private = (PaintCore *) tool->private;
  384.   private->paint_func = clone_paint_func;
  385.   private->core->draw_func = clone_draw;
  386.   private->flags |= TOOL_TRACES_ON_WINDOW;
  387.  
  388.   return tool;
  389. }
  390.  
  391. void
  392. tools_free_clone (Tool *tool)
  393. {
  394.   paint_core_free (tool);
  395. }
  396.  
  397. static void
  398. clone_draw (Tool *tool)
  399. {
  400.   PaintCore * paint_core;
  401.  
  402.   paint_core = (PaintCore *) tool->private;
  403.  
  404.   if (paint_core->core->gc != NULL && clone_options->type == IMAGE_CLONE)
  405.     {
  406.       gdk_draw_line (paint_core->core->win, paint_core->core->gc,
  407.              trans_tx - (TARGET_WIDTH >> 1), trans_ty,
  408.              trans_tx + (TARGET_WIDTH >> 1), trans_ty);
  409.       gdk_draw_line (paint_core->core->win, paint_core->core->gc,
  410.              trans_tx, trans_ty - (TARGET_HEIGHT >> 1),
  411.              trans_tx, trans_ty + (TARGET_HEIGHT >> 1));
  412.     }
  413. }
  414.  
  415. static void
  416. clone_motion (PaintCore            *paint_core,
  417.           GimpDrawable         *drawable,
  418.           GimpDrawable         *src_drawable,
  419.           PaintPressureOptions *pressure_options,
  420.           CloneType             type,
  421.           int                   offset_x,
  422.           int                   offset_y)
  423. {
  424.   GImage *gimage;
  425.   GImage *src_gimage = NULL;
  426.   unsigned char * s;
  427.   unsigned char * d;
  428.   TempBuf * orig;
  429.   TempBuf * area;
  430.   void * pr;
  431.   int y;
  432.   int x1, y1, x2, y2;
  433.   int has_alpha = -1;
  434.   PixelRegion srcPR, destPR;
  435.   GPattern *pattern;
  436.   gint opacity;
  437.   gdouble scale;
  438.  
  439.   pr      = NULL;
  440.   pattern = NULL;
  441.  
  442.   /*  Make sure we still have a source if we are doing image cloning */
  443.   if (type == IMAGE_CLONE)
  444.     {
  445.       if (!src_drawable)
  446.     return;
  447.       if (! (src_gimage = drawable_gimage (src_drawable)))
  448.     return;
  449.       /*  Determine whether the source image has an alpha channel  */
  450.       has_alpha = drawable_has_alpha (src_drawable);
  451.     }
  452.  
  453.   /*  We always need a destination image */
  454.   if (! (gimage = drawable_gimage (drawable)))
  455.     return;
  456.  
  457.   if (pressure_options->size)
  458.     scale = paint_core->curpressure;
  459.   else
  460.     scale = 1.0;
  461.  
  462.   /*  Get a region which can be used to paint to  */
  463.   if (! (area = paint_core_get_paint_area (paint_core, drawable, scale)))
  464.     return;
  465.  
  466.   switch (type)
  467.     {
  468.     case IMAGE_CLONE:
  469.       /*  Set the paint area to transparent  */
  470.       memset (temp_buf_data (area), 0, area->width * area->height * area->bytes);
  471.  
  472.       /*  If the source gimage is different from the destination,
  473.        *  then we should copy straight from the destination image
  474.        *  to the canvas.
  475.        *  Otherwise, we need a call to get_orig_image to make sure
  476.        *  we get a copy of the unblemished (offset) image
  477.        */
  478.       if (src_drawable != drawable)
  479.     {
  480.       x1 = CLAMP (area->x + offset_x, 0, drawable_width (src_drawable));
  481.       y1 = CLAMP (area->y + offset_y, 0, drawable_height (src_drawable));
  482.       x2 = CLAMP (area->x + offset_x + area->width,
  483.               0, drawable_width (src_drawable));
  484.       y2 = CLAMP (area->y + offset_y + area->height,
  485.               0, drawable_height (src_drawable));
  486.  
  487.       if (!(x2 - x1) || !(y2 - y1))
  488.         return;
  489.  
  490.       pixel_region_init (&srcPR, drawable_data (src_drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
  491.     }
  492.       else
  493.     {
  494.       x1 = CLAMP (area->x + offset_x, 0, drawable_width (drawable));
  495.       y1 = CLAMP (area->y + offset_y, 0, drawable_height (drawable));
  496.       x2 = CLAMP (area->x + offset_x + area->width,
  497.               0, drawable_width (drawable));
  498.       y2 = CLAMP (area->y + offset_y + area->height,
  499.               0, drawable_height (drawable));
  500.  
  501.       if (!(x2 - x1) || !(y2 - y1))
  502.         return;
  503.  
  504.       /*  get the original image  */
  505.       orig = paint_core_get_orig_image (paint_core, drawable, x1, y1, x2, y2);
  506.  
  507.       srcPR.bytes = orig->bytes;
  508.       srcPR.x = 0; srcPR.y = 0;
  509.       srcPR.w = x2 - x1;
  510.       srcPR.h = y2 - y1;
  511.       srcPR.rowstride = srcPR.bytes * orig->width;
  512.       srcPR.data = temp_buf_data (orig);
  513.     }
  514.  
  515.       offset_x = x1 - (area->x + offset_x);
  516.       offset_y = y1 - (area->y + offset_y);
  517.  
  518.       /*  configure the destination  */
  519.       destPR.bytes = area->bytes;
  520.       destPR.x = 0; destPR.y = 0;
  521.       destPR.w = srcPR.w;
  522.       destPR.h = srcPR.h;
  523.       destPR.rowstride = destPR.bytes * area->width;
  524.       destPR.data = temp_buf_data (area) + offset_y * destPR.rowstride +
  525.     offset_x * destPR.bytes;
  526.  
  527.       pr = pixel_regions_register (2, &srcPR, &destPR);
  528.       break;
  529.  
  530.     case PATTERN_CLONE:
  531.       pattern = gimp_context_get_pattern (NULL);
  532.  
  533.       if (!pattern)
  534.     return;
  535.  
  536.       destPR.bytes = area->bytes;
  537.       destPR.x = 0; destPR.y = 0;
  538.       destPR.w = area->width;
  539.       destPR.h = area->height;
  540.       destPR.rowstride = destPR.bytes * area->width;
  541.       destPR.data = temp_buf_data (area);
  542.  
  543.       pr = pixel_regions_register (1, &destPR);
  544.       break;
  545.     }
  546.  
  547.   for (; pr != NULL; pr = pixel_regions_process (pr))
  548.     {
  549.       s = srcPR.data;
  550.       d = destPR.data;
  551.       for (y = 0; y < destPR.h; y++)
  552.     {
  553.       switch (type)
  554.         {
  555.         case IMAGE_CLONE:
  556.           clone_line_image (gimage, src_gimage, drawable, src_drawable, s, d,
  557.                 has_alpha, srcPR.bytes, destPR.bytes, destPR.w);
  558.           s += srcPR.rowstride;
  559.           break;
  560.         case PATTERN_CLONE:
  561.           clone_line_pattern (gimage, drawable, pattern, d,
  562.                   area->x + offset_x, area->y + y + offset_y,
  563.                   destPR.bytes, destPR.w);
  564.           break;
  565.         }
  566.  
  567.       d += destPR.rowstride;
  568.     }
  569.     }
  570.  
  571.   opacity = 255.0 * gimp_context_get_opacity (NULL);
  572.   if (pressure_options->opacity)
  573.     opacity = opacity * 2.0 * paint_core->curpressure;
  574.  
  575.   /*  paste the newly painted canvas to the gimage which is being worked on  */
  576.   paint_core_paste_canvas (paint_core, drawable, 
  577.                MIN (opacity, 255),
  578.                (int) (gimp_context_get_opacity (NULL) * 255),
  579.                gimp_context_get_paint_mode (NULL),
  580.                pressure_options->pressure ? PRESSURE : SOFT, 
  581.                scale, CONSTANT);
  582. }
  583.  
  584.  
  585. static void
  586. clone_line_image (GImage        *dest,
  587.           GImage        *src,
  588.           GimpDrawable  *d_drawable,
  589.           GimpDrawable  *s_drawable,
  590.           unsigned char *s,
  591.           unsigned char *d,
  592.           int            has_alpha,
  593.           int            src_bytes,
  594.           int            dest_bytes,
  595.           int            width)
  596. {
  597.   unsigned char rgb[3];
  598.   int src_alpha, dest_alpha;
  599.  
  600.   src_alpha = src_bytes - 1;
  601.   dest_alpha = dest_bytes - 1;
  602.  
  603.   while (width--)
  604.     {
  605.       gimage_get_color (src, drawable_type (s_drawable), rgb, s);
  606.       gimage_transform_color (dest, d_drawable, rgb, d, RGB);
  607.  
  608.       if (has_alpha)
  609.     d[dest_alpha] = s[src_alpha];
  610.       else
  611.     d[dest_alpha] = OPAQUE_OPACITY;
  612.  
  613.       s += src_bytes;
  614.       d += dest_bytes;
  615.     }
  616. }
  617.  
  618. static void
  619. clone_line_pattern (GImage        *dest,
  620.             GimpDrawable  *drawable,
  621.             GPattern      *pattern,
  622.             unsigned char *d,
  623.             int            x,
  624.             int            y,
  625.             int            bytes,
  626.             int            width)
  627. {
  628.   unsigned char *pat, *p;
  629.   int color, alpha;
  630.   int i;
  631.  
  632.   /*  Make sure x, y are positive  */
  633.   while (x < 0)
  634.     x += pattern->mask->width;
  635.   while (y < 0)
  636.     y += pattern->mask->height;
  637.  
  638.   /*  Get a pointer to the appropriate scanline of the pattern buffer  */
  639.   pat = temp_buf_data (pattern->mask) +
  640.     (y % pattern->mask->height) * pattern->mask->width * pattern->mask->bytes;
  641.   color = (pattern->mask->bytes == 3) ? RGB : GRAY;
  642.  
  643.   alpha = bytes - 1;
  644.  
  645.   for (i = 0; i < width; i++)
  646.     {
  647.       p = pat + ((i + x) % pattern->mask->width) * pattern->mask->bytes;
  648.  
  649.       gimage_transform_color (dest, drawable, p, d, color);
  650.  
  651.       d[alpha] = OPAQUE_OPACITY;
  652.  
  653.       d += bytes;
  654.     }
  655. }
  656.  
  657. static void *
  658. clone_non_gui_paint_func (PaintCore *paint_core,
  659.               GimpDrawable *drawable,
  660.               int        state)
  661. {
  662.   clone_motion (paint_core, drawable, non_gui_src_drawable, &non_gui_pressure_options,
  663.         non_gui_type, non_gui_offset_x, non_gui_offset_y);
  664.  
  665.   return NULL;
  666. }
  667.  
  668. gboolean
  669. clone_non_gui_default (GimpDrawable *drawable,
  670.                int           num_strokes,
  671.                double       *stroke_array)
  672. {
  673.   GimpDrawable *src_drawable = NULL;
  674.   CloneType     clone_type = CLONE_DEFAULT_TYPE;
  675.   double        local_src_x = 0.0;
  676.   double        local_src_y = 0.0;
  677.   CloneOptions *options = clone_options;
  678.   
  679.   if(options)
  680.     {
  681.       clone_type = options->type;
  682.       src_drawable = src_drawable_;
  683.       local_src_x = src_x;
  684.       local_src_y = src_y;
  685.     }
  686.   
  687.   return clone_non_gui(drawable,
  688.                src_drawable,
  689.                clone_type,
  690.                local_src_x,local_src_y,
  691.                num_strokes,stroke_array);
  692. }
  693.  
  694. gboolean
  695. clone_non_gui (GimpDrawable *drawable,
  696.                GimpDrawable *src_drawable,
  697.            CloneType     clone_type,
  698.            double        src_x,
  699.            double        src_y,
  700.            int           num_strokes,
  701.            double       *stroke_array)
  702. {
  703.   int i;
  704.  
  705.   if (paint_core_init (&non_gui_paint_core, drawable,
  706.                stroke_array[0], stroke_array[1]))
  707.     {
  708.       /* Set the paint core's paint func */
  709.       non_gui_paint_core.paint_func = clone_non_gui_paint_func;
  710.       
  711.       non_gui_type = clone_type;
  712.  
  713.       non_gui_src_drawable = src_drawable;
  714.  
  715.       non_gui_paint_core.startx = non_gui_paint_core.lastx = stroke_array[0];
  716.       non_gui_paint_core.starty = non_gui_paint_core.lasty = stroke_array[1];
  717.  
  718.       non_gui_offset_x = (int) (src_x - non_gui_paint_core.startx);
  719.       non_gui_offset_y = (int) (src_y - non_gui_paint_core.starty);
  720.  
  721.       clone_non_gui_paint_func (&non_gui_paint_core, drawable, 0);
  722.  
  723.       for (i = 1; i < num_strokes; i++)
  724.     {
  725.       non_gui_paint_core.curx = stroke_array[i * 2 + 0];
  726.       non_gui_paint_core.cury = stroke_array[i * 2 + 1];
  727.  
  728.       paint_core_interpolate (&non_gui_paint_core, drawable);
  729.  
  730.       non_gui_paint_core.lastx = non_gui_paint_core.curx;
  731.       non_gui_paint_core.lasty = non_gui_paint_core.cury;
  732.     }
  733.  
  734.       /* Finish the painting */
  735.       paint_core_finish (&non_gui_paint_core, drawable, -1);
  736.  
  737.       /* Cleanup */
  738.       paint_core_cleanup ();
  739.       return TRUE;
  740.     }
  741.   else
  742.     return FALSE;
  743. }
  744.