Commit 868bdfff authored by Tor Lillqvist's avatar Tor Lillqvist

Overhaul of pixmap brushes and pipes: No separate pixmap pipe

brush tool any longer. The paintbrush, airbrush and pencil
tools, which already knew how to handle the single-pixmap
brushes now also handle the pipes as well.

* app/pixmapbrush.{h,c}
* app/gimpbrushpixmap.{h,c}: Removed these files.

* app/Makefile.am
* app/makefile.{cygwin,msc}: Remove from here, too.

* app/gimpbrushpipe.{h,c}: Total overhaul.

* app/paint_core.h
* app/apptypes.h: Some more types moved to apptypes.h

* app/context_manager.c
* app/tool_options.c
* app/tools.c
* app/toolsF.h: Remove PIXMAPBRUSH tool.

* app/gimpbrush.h: New method: select_brush. Used to change the
brush in paint_core, for pipe brushes.

* app/gimpbrush.c: Add gimp_brush_select_brush, which is dummy for
the normal brushes (returns the same brush).

* app/paint_core.c: Call the brush's select_brush method to get a
potential new brush before calling the paint_func.

* app/gimpbrushlist.c: Various changes related to the pixmap and
pipe overhaul.

* app/airbrush.c
* app/pencil.c: Reorder code a bit in the tool motion function to
avoid executing unnecessary code in the case of a pixmap brush.

Other changes in the same commit:

* app/install.c: Make quote_spaces extern.

* app/appenv.h: Declare it.

* libgimp/gimpui.def: Add missing entry points.

* libgimp/makefile.{cygwin,msc}: Add missing objects to gimpui.
parent 3cf62e52
......@@ -187,8 +187,6 @@ gimp_SOURCES = \
gimpbrushgenerated.h \
gimpbrushpipe.c \
gimpbrushpipe.h \
gimpbrushpixmap.c \
gimpbrushpixmap.h \
gimpbrushlist.c \
gimpbrushlist.h \
gimpbrushlistF.h \
......@@ -330,8 +328,6 @@ gimp_SOURCES = \
pixel_region.c \
pixel_region.h \
pixel_regionP.h \
pixmapbrush.c \
pixmapbrush.h \
pixmaps.h \
pixmaps2.h \
plug_in.c \
......
......@@ -18,7 +18,7 @@
#include <stdlib.h>
#include "appenv.h"
#include "gimpbrushlist.h"
#include "gimpbrushpixmap.h"
#include "gimpbrushpipe.h"
#include "drawable.h"
#include "errors.h"
#include "gdisplay.h"
......@@ -26,8 +26,6 @@
#include "paint_core.h"
#include "paint_options.h"
#include "palette.h"
/* for color_area_with_pixmap */
#include "pixmapbrush.h"
#include "airbrush.h"
#include "selection.h"
#include "tool_options_ui.h"
......@@ -293,23 +291,19 @@ airbrush_motion (PaintCore *paint_core,
if (! (gimage = drawable_gimage (drawable)))
return;
gimage_get_foreground (gimage, drawable, col);
if (! (area = paint_core_get_paint_area (paint_core, drawable)))
return;
/* color the pixels */
col[area->bytes - 1] = OPAQUE_OPACITY;
if (GIMP_IS_BRUSH_PIXMAP (paint_core->brush))
{
color_area_with_pixmap (gimage, drawable, area, paint_core->brush);
color_area_with_pixmap (paint_core, gimage, drawable, area);
mode = INCREMENTAL;
}
else
{
/* color the pixels */
gimage_get_foreground (gimage, drawable, col);
col[area->bytes - 1] = OPAQUE_OPACITY;
color_pixels (temp_buf_data (area), col,
area->width * area->height, area->bytes);
}
......
......@@ -92,4 +92,8 @@ extern int we_are_exiting; /* this is used in session_get_window_info() */
extern GimpSet* image_context;
extern MessageHandlerType message_handler;
#ifdef NATIVE_WIN32
char *quote_spaces (char *string);
#endif
#endif /* APPENV_H */
......@@ -135,19 +135,25 @@ typedef enum
NEAREST_NEIGHBOR_INTERPOLATION
} InterpolationType;
typedef struct _GimpChannel GimpChannel;
typedef struct _GimpChannelClass GimpChannelClass;
typedef struct _GimpChannel GimpChannel;
typedef struct _GimpChannelClass GimpChannelClass;
typedef GimpChannel Channel; /* convenience */
typedef struct _GimpLayer GimpLayer;
typedef struct _GimpLayerClass GimpLayerClass;
typedef struct _GimpLayer GimpLayer;
typedef struct _GimpLayerClass GimpLayerClass;
typedef struct _GimpLayerMask GimpLayerMask;
typedef struct _GimpLayerMaskClass GimpLayerMaskClass;
typedef GimpLayer Layer; /* convenience */
typedef GimpLayerMask LayerMask; /* convenience */
typedef struct _paint_core PaintCore;
typedef struct _GimpBrush GimpBrush;
typedef struct _GimpBrush *GimpBrushP;
typedef struct _GimpBrushClass GimpBrushClass;
typedef struct _layer_undo LayerUndo;
typedef struct _layer_mask_undo LayerMaskUndo;
......
......@@ -20,7 +20,7 @@
#include "appenv.h"
#include "actionarea.h"
#include "brush_scale.h"
#include "gimpbrushpixmap.h"
#include "gimpbrushpipe.h"
#include "gimpbrushlist.h"
#include "gimpcontext.h"
#include "gimplist.h"
......@@ -736,7 +736,7 @@ brush_popup_timeout (gpointer data)
if (GIMP_IS_BRUSH_PIXMAP (brush))
{
GimpBrushPixmap *pixmapbrush = GIMP_BRUSH_PIXMAP(brush);
src = (gchar *) temp_buf_data (pixmapbrush->pixmap_mask);
src = (gchar *) temp_buf_data (gimp_brush_pixmap_pixmap (pixmapbrush));
for (y = 0; y < brush->mask->height; y++)
{
gtk_preview_draw_row (GTK_PREVIEW (bsp->brush_preview), (guchar *)src,
......@@ -817,8 +817,9 @@ display_brush (BrushSelectP bsp,
int ystart;
int i, j;
brush_buf = GIMP_IS_BRUSH_PIXMAP (brush) ? GIMP_BRUSH_PIXMAP(brush)->pixmap_mask
: brush->mask;
brush_buf = GIMP_IS_BRUSH_PIXMAP (brush) ?
gimp_brush_pixmap_pixmap (GIMP_BRUSH_PIXMAP(brush))
: brush->mask;
if (brush_buf->width > bsp->cell_width || brush_buf->height > bsp->cell_height)
{
......
......@@ -92,7 +92,6 @@ context_manager_init (void)
case INK:
case DODGEBURN:
case SMUDGE:
case PIXMAPBRUSH:
tool_info[i].tool_context =
gimp_context_new (tool_info[i].private_tip, NULL, context);
break;
......
......@@ -33,6 +33,8 @@ enum{
LAST_SIGNAL
};
static GimpBrush *gimp_brush_select_brush (PaintCore *paint_core);
static guint gimp_brush_signals[LAST_SIGNAL];
static GimpObjectClass* parent_class;
......@@ -64,6 +66,8 @@ gimp_brush_class_init (GimpBrushClass *klass)
object_class->destroy = gimp_brush_destroy;
klass->select_brush = gimp_brush_select_brush;
gimp_brush_signals[DIRTY] =
gimp_signal_new ("dirty", GTK_RUN_FIRST, type, 0, gimp_sigtype_void);
......@@ -116,6 +120,12 @@ gimp_brush_new (char *filename)
return brush;
}
static GimpBrush *
gimp_brush_select_brush (PaintCore *paint_core)
{
return paint_core->brush;
}
TempBuf *
gimp_brush_get_mask (GimpBrush *brush)
{
......
......@@ -33,6 +33,8 @@ enum{
LAST_SIGNAL
};
static GimpBrush *gimp_brush_select_brush (PaintCore *paint_core);
static guint gimp_brush_signals[LAST_SIGNAL];
static GimpObjectClass* parent_class;
......@@ -64,6 +66,8 @@ gimp_brush_class_init (GimpBrushClass *klass)
object_class->destroy = gimp_brush_destroy;
klass->select_brush = gimp_brush_select_brush;
gimp_brush_signals[DIRTY] =
gimp_signal_new ("dirty", GTK_RUN_FIRST, type, 0, gimp_sigtype_void);
......@@ -116,6 +120,12 @@ gimp_brush_new (char *filename)
return brush;
}
static GimpBrush *
gimp_brush_select_brush (PaintCore *paint_core)
{
return paint_core->brush;
}
TempBuf *
gimp_brush_get_mask (GimpBrush *brush)
{
......
......@@ -20,12 +20,13 @@
#define __GIMPBRUSH_H__
#include <stdio.h>
#include "apptypes.h"
#include "gimpobjectP.h"
#include "paint_core.h"
#include "temp_buf.h"
#include "vector2d.h"
typedef struct _GimpBrush GimpBrush, * GimpBrushP;
struct _GimpBrush
{
GimpObject gobject;
......@@ -40,10 +41,10 @@ struct _GimpBrush
struct _GimpBrushClass
{
GimpObjectClass parent_class;
GimpBrush *(* select_brush) (PaintCore *);
};
typedef struct _GimpBrushClass GimpBrushClass;
#define BRUSH_CLASS(klass) \
#define GIMP_BRUSH_CLASS(klass) \
GTK_CHECK_CLASS_CAST (klass, gimp_brush_get_type(), GimpBrushClass)
#define GIMP_TYPE_BRUSH (gimp_brush_get_type ())
......
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
* Copyright (C) 1999 Adrian Likins and Tor Lillqvist
*
* 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
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "appenv.h"
#include "brush_header.h"
#include "pattern_header.h"
#include "patterns.h"
#include "gimpbrush.h"
#include "gimpbrushpixmap.h"
#include "gimpbrushlist.h"
#include "gimpbrushpipe.h"
#include "gimpbrushpipeP.h"
#include "paint_core.h"
#include "gimprc.h"
#include "gimpbrushpipe.h"
#include "libgimp/gimpintl.h"
static GimpBrushClass* gimp_brush_class;
static GtkObjectClass* gimp_object_class;
static GimpBrush *gimp_brush_pixmap_select_brush (PaintCore *paint_core);
static void paint_line_pixmap_mask(GImage *dest,
GimpDrawable *drawable,
GimpBrushPixmap *brush,
guchar *d,
int x,
int y,
int bytes,
int width);
static void
gimp_brush_pipe_generate(GimpBrushPipe *brush);
gimp_brush_pixmap_destroy (GtkObject *object)
{
GimpBrushPixmap *pixmap;
g_return_if_fail (GIMP_IS_BRUSH_PIXMAP (object));
pixmap = GIMP_BRUSH_PIXMAP (object);
temp_buf_free (pixmap->pixmap_mask);
(* GTK_OBJECT_CLASS (gimp_object_class)->destroy) (object);
}
static void
gimp_brush_pixmap_class_init (GimpBrushPixmapClass *klass)
{
GtkObjectClass *object_class;
GimpBrushClass *brush_class;
object_class = GTK_OBJECT_CLASS (klass);
brush_class = GIMP_BRUSH_CLASS (klass);
gimp_brush_class = gtk_type_class (gimp_brush_get_type ());
object_class->destroy = gimp_brush_pixmap_destroy;
brush_class->select_brush = gimp_brush_pixmap_select_brush;
}
void
gimp_brush_pixmap_init (GimpBrushPixmap *brush)
{
brush->pixmap_mask = NULL;
brush->pipe = NULL;
}
GtkType
gimp_brush_pixmap_get_type (void)
{
static GtkType type=0;
if(!type){
GtkTypeInfo info={
"GimpBrushPixmap",
sizeof (GimpBrushPixmap),
sizeof (GimpBrushPixmapClass),
(GtkClassInitFunc) gimp_brush_pixmap_class_init,
(GtkObjectInitFunc) gimp_brush_pixmap_init,
/* reserved_1 */ NULL,
/* reserved_2 */ NULL,
(GtkClassInitFunc) NULL};
type = gtk_type_unique (GIMP_TYPE_BRUSH, &info);
}
return type;
}
static GimpObjectClass* parent_class;
static GimpBrush *
gimp_brush_pixmap_select_brush (PaintCore *paint_core)
{
GimpBrushPixmap *pixmap;
g_return_val_if_fail (GIMP_IS_BRUSH_PIXMAP (paint_core->brush), NULL);
pixmap = GIMP_BRUSH_PIXMAP (paint_core->brush);
if (pixmap->pipe->nbrushes == 1)
return GIMP_BRUSH (pixmap->pipe->current);
/* Just select the next one for now. This is the place where we
* will select the correct brush based on various parameters
* in paint_core.
*/
pixmap->pipe->index[0] = (pixmap->pipe->index[0] + 1) % pixmap->pipe->nbrushes;
pixmap->pipe->current = pixmap->pipe->brushes[pixmap->pipe->index[0]];
return GIMP_BRUSH (pixmap->pipe->current);
}
static void
gimp_brush_pipe_destroy(GtkObject *object)
{
GTK_OBJECT_CLASS(parent_class)->destroy (object);
GimpBrushPipe *pipe;
int i;
g_return_if_fail (object != NULL);
g_return_if_fail (GIMP_IS_BRUSH_PIPE (object));
pipe = GIMP_BRUSH_PIPE (object);
g_free (pipe->rank);
for (i = 1; i < pipe->nbrushes; i++)
gimp_object_destroy (pipe->brushes[i]);
g_free (pipe->brushes);
g_free (pipe->select);
g_free (pipe->index);
if (GTK_OBJECT_CLASS (gimp_object_class)->destroy)
(* GTK_OBJECT_CLASS (gimp_object_class)->destroy) (object);
}
static void
......@@ -35,116 +154,294 @@ gimp_brush_pipe_class_init (GimpBrushPipeClass *klass)
{
GtkObjectClass *object_class;
object_class = GTK_OBJECT_CLASS(klass);
parent_class = gtk_type_class (GIMP_TYPE_BRUSH_PIXMAP);
object_class->destroy = gimp_brush_pipe_destroy;
object_class = GTK_OBJECT_CLASS (klass);
gimp_object_class = gtk_type_class (GIMP_TYPE_OBJECT);
object_class->destroy = gimp_brush_pipe_destroy;
}
void
gimp_brush_pipe_init(GimpBrushPipe *brush)
gimp_brush_pipe_init (GimpBrushPipe *pipe)
{
brush->name = NULL;
brush->filename = NULL;
brush->brush_list = gimp_brush_list_new();
pipe->dimension = 0;
pipe->rank = NULL;
pipe->nbrushes = 0;
pipe->select = NULL;
pipe->index = NULL;
}
GtkType gimp_brush_pipe_get_type(void)
GtkType
gimp_brush_pipe_get_type (void)
{
static GtkType type=0;
if(!type){
if (!type){
GtkTypeInfo info={
"GimpBrushPipe",
sizeof(GimpBrushPipe),
sizeof(GimpBrushPipeClass),
(GtkClassInitFunc)gimp_brush_pipe_class_init,
(GtkObjectInitFunc)gimp_brush_pipe_init,
/* reserved_1 */ NULL,
/* reserver_2 */ NULL,
sizeof (GimpBrushPipe),
sizeof (GimpBrushPipeClass),
(GtkClassInitFunc) gimp_brush_pipe_class_init,
(GtkObjectInitFunc) gimp_brush_pipe_init,
/* reserved_1 */ NULL,
/* reserved_2 */ NULL,
(GtkClassInitFunc) NULL};
type=gtk_type_unique(GIMP_TYPE_BRUSH_PIXMAP, &info);
type = gtk_type_unique (GIMP_TYPE_BRUSH_PIXMAP, &info);
}
return type;
}
GimpBrushPipe *
gimp_brush_pipe_load (char *file_name)
gimp_brush_pipe_load (char *filename)
{
GimpBrushPipe *pipe;
GimpBrushPixmap *brush;
GimpBrushList *list;
GPatternP pattern;
FILE *fp;
gchar buf2[1024];
guchar buf[1024];
guchar *name;
int num_of_brushes;
int brush_count=0;
pipe = GIMP_BRUSH_PIPE(gimp_type_new(gimp_brush_pipe_get_type()));
GIMP_BRUSH_PIPE(pipe)->filename = g_strdup(file_name);
guchar *params;
pattern = (GPatternP) g_malloc (sizeof (GPattern));
pattern->filename = g_strdup (file_name);
pattern->name = NULL;
pattern->mask = NULL;
if ((fp = fopen (filename, "rb")) == NULL)
return NULL;
brush = GIMP_BRUSH_PIXMAP (pipe);
/* The file format starts with a painfully simple text header
* and we use a painfully simple way to read it
*/
if (fgets (buf, 1024, fp) == NULL)
{
fclose (fp);
return NULL;
}
buf[strlen (buf) - 1] = 0;
list = gimp_brush_list_new();
if ((fp = fopen(file_name, "rb")) == NULL)
return NULL;
/* the file format starts with a painfully simple text header
and we use a painfully simple way to read it */
if(fgets (buf2, 1024, fp) == NULL)
return NULL;
buf2[strlen(buf2) - 1] = '\0';
pipe->name = g_strdup(buf2);
pipe = GIMP_BRUSH_PIPE (gimp_type_new (GIMP_TYPE_BRUSH_PIPE));
name = g_strdup (buf);
/* get the number of brushes */
if(fgets (buf2, 1024, fp) == NULL)
return NULL;
num_of_brushes = strtol(buf2,NULL,10);
if (fgets (buf, 1024, fp) == NULL)
{
fclose (fp);
gimp_object_destroy (pipe);
return NULL;
}
num_of_brushes = strtol(buf, &params, 10);
if (num_of_brushes < 1)
{
g_message (_("pixmap brush pipe should have at least one brush"));
fclose (fp);
gimp_object_destroy (pipe);
return NULL;
}
/* Here we should parse the params to get the dimension, ranks,
* placement options, etc. But just use defaults for now.
*/
pipe->dimension = 1;
pipe->rank = g_new (int, 1);
pipe->rank[0] = num_of_brushes;
pipe->select = g_new (PipeSelectModes, 1);
pipe->select[0] = PIPE_SELECT_INCREMENTAL;
pipe->index = g_new (int, 1);
pipe->index[0] = 0;
while(brush_count < num_of_brushes)
{
pattern = (GPatternP) g_malloc (sizeof (GPattern));
pattern->filename = NULL;
pattern->name = NULL;
pattern->mask = NULL;
if (brush_count > 0)
brush = GIMP_BRUSH_PIXMAP(gimp_type_new(gimp_brush_pixmap_get_type()));
GIMP_BRUSH(brush)->filename = g_strdup(file_name);
pipe->brushes =
(GimpBrushPixmap **) g_new0 (GimpBrushPixmap *, num_of_brushes);
/* First pixmap brush in the list is the pipe itself */
pipe->brushes[0] = GIMP_BRUSH_PIXMAP (pipe);
/* load the brush */
if(!gimp_brush_load_brush(GIMP_BRUSH(brush),fp,file_name))
/* Current pixmap brush is the first one. */
pipe->current = pipe->brushes[0];
while (pipe->nbrushes < num_of_brushes)
{
if (pipe->nbrushes > 0)
{
g_message (_("failed to load a brush mask in the pipe"));
return NULL;
pipe->brushes[pipe->nbrushes] =
GIMP_BRUSH_PIXMAP (gimp_type_new (GIMP_TYPE_BRUSH_PIXMAP));
GIMP_BRUSH (pipe->brushes[pipe->nbrushes])->name = NULL;
}
pipe->brushes[pipe->nbrushes]->pipe = pipe;
/* load the pattern data*/
if(!load_pattern_pattern(pattern, fp, file_name))
/* load the brush */
if (!gimp_brush_load_brush (GIMP_BRUSH (pipe->brushes[pipe->nbrushes]),
fp, filename)
|| !load_pattern_pattern (pattern, fp, filename))
{
g_message (_("failed to load a section of pixmap mask in the pipe"));
g_message (_("failed to load one of the pixmap brushes in the pipe"));
fclose (fp);
g_free (pattern);
gimp_object_destroy (pipe);
return NULL;
}
brush->pixmap_mask = pattern->mask;
gimp_brush_list_add(list,GIMP_BRUSH(brush));
brush_count++;
if (pipe->nbrushes == 0)
{
/* Replace name with the whole pipe's name */
GIMP_BRUSH (pipe)->name = name;
}
pipe->brushes[pipe->nbrushes]->pixmap_mask = pattern->mask;
pipe->nbrushes++;
}
/* Clean up */
fclose (fp);
if (!GIMP_IS_BRUSH_PIPE(pipe))
g_print ("Is not BRUSH_PIPE???\n");
g_free(pattern);
return pipe;
}
GimpBrushPipe *
gimp_brush_pixmap_load (char *filename)
{
GimpBrushPipe *pipe;
GPatternP pattern;
FILE *fp;
if ((fp = fopen (filename, "rb")) == NULL)
return NULL;
pipe = GIMP_BRUSH_PIPE (gimp_type_new (GIMP_TYPE_BRUSH_PIPE));
pipe->brush_list = list;
/* A (single) pixmap brush is a pixmap pipe brush with just one pixmap */
pipe->dimension = 1;
pipe->rank = g_new (int, 1);
pipe->rank[0] = 1;
pipe->select = g_new (PipeSelectModes, 1);
pipe->select[0] = PIPE_SELECT_INCREMENTAL;
pipe->index = g_new (int, 1);
pipe->index[0] = 0;
pattern = (GPatternP) g_malloc (sizeof (GPattern));
pattern->filename = NULL;
pattern->name = NULL;
pattern->mask = NULL;
pipe->brushes = (GimpBrushPixmap **) g_new (GimpBrushPixmap *, 1);
pipe->brushes[0] = GIMP_BRUSH_PIXMAP (pipe);
pipe->current = pipe->brushes[0];
pipe->brushes[0]->pipe = pipe;
/* load the brush */
if (!gimp_brush_load_brush (GIMP_BRUSH (pipe->brushes[0]),
fp, filename)
|| !load_pattern_pattern (pattern, fp, filename))
{
g_message (_("failed to load pixmap brush"));
fclose (fp);
g_free (pattern);
gimp_object_destroy (pipe);
return NULL;
}
pipe->brushes[0]->pixmap_mask = pattern->mask;
pipe->nbrushes = 1;
/* Clean up */
fclose (fp);
g_free(pattern);
return pipe;
}
TempBuf *
gimp_brush_pixmap_pixmap (GimpBrushPixmap *brush)
{
g_return_val_if_fail (brush != NULL, NULL);
g_return_val_if_fail (GIMP_IS_BRUSH_PIXMAP (brush), NULL);
return brush->pixmap_mask;
}
void
color_area_with_pixmap (PaintCore *paint_core,
GImage *dest,
GimpDrawable *drawable,
TempBuf *area)
{
PixelRegion destPR;
void *pr;
guchar *d;
int ulx, uly, offsetx, offsety, y;
GimpBrushPixmap *pixmap;
g_return_if_fail (GIMP_IS_BRUSH_PIXMAP (paint_core->brush));
pixmap = GIMP_BRUSH_PIXMAP (paint_core->brush);
destPR.bytes = area->bytes;
destPR.x = 0; destPR.y = 0;
destPR.w = area->width;
destPR.h = area->height;
destPR.rowstride = destPR.bytes * area->width;
destPR.data = temp_buf_data (area);
pr = pixel_regions_register (1, &destPR);
/* Calculate upper left corner of brush as in
* paint_core_get_paint_area. Ugly to have to do this here, too.
*/
ulx = (int) paint_core->curx - (paint_core->brush->mask->width >> 1);
uly = (int) paint_core->cury - (paint_core->brush->mask->height >> 1);
offsetx = area->x - ulx;
offsety = area->y - uly;
for (; pr != NULL; pr = pixel_regions_process (pr))
{
d = destPR.data;
for (y = 0; y < destPR.h; y++)
{
paint_line_pixmap_mask (dest, drawable, pixmap,
d, offsetx, y + offsety,
destPR.bytes, destPR.w);
d += destPR.rowstride;
}
}
}
static void
paint_line_pixmap_mask (GImage *dest,
GimpDrawable *drawable,
GimpBrushPixmap *brush,