pencil.c 5.87 KB
Newer Older
Elliot Lee's avatar
Elliot Lee committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/* The GIMP -- an image manipulation program
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
16
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Elliot Lee's avatar
Elliot Lee committed
17 18 19
 */
#include <stdlib.h>
#include "appenv.h"
20
#include "gimpbrushlist.h"
Elliot Lee's avatar
Elliot Lee committed
21 22 23 24 25 26 27 28 29 30 31 32
#include "drawable.h"
#include "errors.h"
#include "gdisplay.h"
#include "paint_funcs.h"
#include "paint_core.h"
#include "palette.h"
#include "paintbrush.h"
#include "pencil.h"
#include "selection.h"
#include "tools.h"

/*  forward function declarations  */
33
static void         pencil_motion       (PaintCore *, GimpDrawable *);
Elliot Lee's avatar
Elliot Lee committed
34 35 36 37 38
static Argument *   pencil_invoker  (Argument *);

static void *  pencil_options = NULL;

void *
39
pencil_paint_func (paint_core, drawable, state)
Elliot Lee's avatar
Elliot Lee committed
40
     PaintCore *paint_core;
41
     GimpDrawable *drawable;
Elliot Lee's avatar
Elliot Lee committed
42 43 44 45 46 47 48 49
     int state;
{
  switch (state)
    {
    case INIT_PAINT :
      break;

    case MOTION_PAINT :
50
      pencil_motion (paint_core, drawable);
Elliot Lee's avatar
Elliot Lee committed
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
      break;

    case FINISH_PAINT :
      break;

    default :
      break;
    }

  return NULL;
}


Tool *
tools_new_pencil ()
{
  Tool * tool;
  PaintCore * private;

  if (!pencil_options)
    pencil_options = tools_register_no_options (PENCIL, "Pencil Options");

  tool = paint_core_new (PENCIL);

  private = (PaintCore *) tool->private;
  private->paint_func = pencil_paint_func;

  return tool;
}


void
tools_free_pencil (tool)
     Tool * tool;
{
  paint_core_free (tool);
}


90
static void
91
pencil_motion (paint_core, drawable)
Elliot Lee's avatar
Elliot Lee committed
92
     PaintCore *paint_core;
93
     GimpDrawable *drawable;
Elliot Lee's avatar
Elliot Lee committed
94 95 96 97 98
{
  GImage *gimage;
  TempBuf * area;
  unsigned char col[MAX_CHANNELS];

99
  if (! (gimage = drawable_gimage (drawable)))
Elliot Lee's avatar
Elliot Lee committed
100 101
    return;

102
  gimage_get_foreground (gimage, drawable, col);
Elliot Lee's avatar
Elliot Lee committed
103 104

  /*  Get a region which can be used to paint to  */
105
  if (! (area = paint_core_get_paint_area (paint_core, drawable)))
Elliot Lee's avatar
Elliot Lee committed
106 107 108
    return;

  /*  set the alpha channel  */
Manish Singh's avatar
Manish Singh committed
109
  col[area->bytes - 1] = OPAQUE_OPACITY;
Elliot Lee's avatar
Elliot Lee committed
110 111 112 113 114 115

  /*  color the pixels  */
  color_pixels (temp_buf_data (area), col,
		area->width * area->height, area->bytes);

  /*  paste the newly painted canvas to the gimage which is being worked on  */
Manish Singh's avatar
Manish Singh committed
116
  paint_core_paste_canvas (paint_core, drawable, OPAQUE_OPACITY,
117 118
			   (int) (gimp_brush_get_opacity () * 255),
			   gimp_brush_get_paint_mode (), HARD, CONSTANT);
Elliot Lee's avatar
Elliot Lee committed
119 120 121 122
}


static void *
123
pencil_non_gui_paint_func (PaintCore *paint_core, GimpDrawable *drawable, int state)
Elliot Lee's avatar
Elliot Lee committed
124
{
125
  pencil_motion (paint_core, drawable);
Elliot Lee's avatar
Elliot Lee committed
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159

  return NULL;
}


/*  The pencil procedure definition  */
ProcArg pencil_args[] =
{
  { PDB_DRAWABLE,
    "drawable",
    "the drawable"
  },
  { PDB_INT32,
    "num_strokes",
    "number of stroke control points (count each coordinate as 2 points)"
  },
  { PDB_FLOATARRAY,
    "strokes",
    "array of stroke coordinates: {s1.x, s1.y, s2.x, s2.y, ..., sn.x, sn.y}"
  }
};


ProcRecord pencil_proc =
{
  "gimp_pencil",
  "Paint in the current brush without sub-pixel sampling",
  "This tool is the standard pencil.  It draws linearly interpolated lines through the specified stroke coordinates.  It operates on the specified drawable in the foreground color with the active brush.  The brush mask is treated as though it contains only black and white values.  Any value below half is treated as black; any above half, as white.",
  "Spencer Kimball & Peter Mattis",
  "Spencer Kimball & Peter Mattis",
  "1995-1996",
  PDB_INTERNAL,

  /*  Input arguments  */
160
  3,
Elliot Lee's avatar
Elliot Lee committed
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
  pencil_args,

  /*  Output arguments  */
  0,
  NULL,

  /*  Exec method  */
  { { pencil_invoker } },
};

static Argument *
pencil_invoker (args)
     Argument *args;
{
  int success = TRUE;
  GImage *gimage;
177
  GimpDrawable *drawable;
Elliot Lee's avatar
Elliot Lee committed
178 179 180 181 182
  int num_strokes;
  double *stroke_array;
  int int_value;
  int i;

183
  drawable = NULL;
Elliot Lee's avatar
Elliot Lee committed
184 185 186 187 188
  num_strokes = 0;

  /*  the drawable  */
  if (success)
    {
189
      int_value = args[0].value.pdb_int;
190
      drawable = drawable_get_ID (int_value);
191 192 193 194
      if (drawable == NULL)                                        
        success = FALSE;
      else
        gimage = drawable_gimage (drawable);
Elliot Lee's avatar
Elliot Lee committed
195 196 197 198
    }
  /*  num strokes  */
  if (success)
    {
199
      int_value = args[1].value.pdb_int;
Elliot Lee's avatar
Elliot Lee committed
200 201 202 203 204 205 206 207
      if (int_value > 0)
	num_strokes = int_value / 2;
      else
	success = FALSE;
    }

  /*  point array  */
  if (success)
208
    stroke_array = (double *) args[2].value.pdb_pointer;
Elliot Lee's avatar
Elliot Lee committed
209 210 211

  if (success)
    /*  init the paint core  */
212
    success = paint_core_init (&non_gui_paint_core, drawable,
Elliot Lee's avatar
Elliot Lee committed
213 214 215 216 217 218 219 220 221 222 223
			       stroke_array[0], stroke_array[1]);

  if (success)
    {
      /*  set the paint core's paint func  */
      non_gui_paint_core.paint_func = pencil_non_gui_paint_func;

      non_gui_paint_core.startx = non_gui_paint_core.lastx = stroke_array[0];
      non_gui_paint_core.starty = non_gui_paint_core.lasty = stroke_array[1];

      if (num_strokes == 1)
224
	pencil_non_gui_paint_func (&non_gui_paint_core, drawable, 0);
Elliot Lee's avatar
Elliot Lee committed
225 226 227 228 229 230

      for (i = 1; i < num_strokes; i++)
	{
	  non_gui_paint_core.curx = stroke_array[i * 2 + 0];
	  non_gui_paint_core.cury = stroke_array[i * 2 + 1];

231
	  paint_core_interpolate (&non_gui_paint_core, drawable);
Elliot Lee's avatar
Elliot Lee committed
232 233 234 235 236 237

	  non_gui_paint_core.lastx = non_gui_paint_core.curx;
	  non_gui_paint_core.lasty = non_gui_paint_core.cury;
	}

      /*  finish the painting  */
238
      paint_core_finish (&non_gui_paint_core, drawable, -1);
Elliot Lee's avatar
Elliot Lee committed
239 240 241 242 243 244 245

      /*  cleanup  */
      paint_core_cleanup ();
    }

  return procedural_db_return_args (&pencil_proc, success);
}