Dave Neary <bolsh@gimp.org>

2003-09-20  Simon Budig  <simon@gimp.org>
            Dave Neary  <bolsh@gimp.org>

	First steps towards Libart stroking. Right now the code
	crashes and thus is disabled by default. If you want to
	test it, change the #define LIBART_STROKE  in
	app/vectors/gimpvectors.c. Then a click on the stroke button
	in the paths dialog invokes the new code.
	The crash is in gimpdrawable-stroke.c - apparently I did not
	yet get the TileManager stuff correctly.

	* app/core/gimpscanconvert.[ch]: Rewritten to be more clear
	and have an easier API. Now can handle open Paths and
	libart-stroke the (open/closed) polygons defined earlier.

	* app/core/core-enums.h: Added Enums for LineJoin-Type and
	EndCap-Type for stroking.

	* app/core/core-enums.c: regenerated.

	* app/core/gimpimage-mask-select.c: Use the new API of
	GimpScanConvert where appropriate.

	* app/vectors/gimpvectors.c: Added #define to enable the libart
	stroking. Disabled by default because of the crash mentioned
	above...

	* app/vectors/gimpbezierstroke.c
	* app/vectors/gimpstroke.c
	* app/vectors/gimpvectors.[ch]: Removed Libart stuff here.
	Libart usage now lives exclusively in GimpScanConvert.

	* app/core/gimpdrawable-stroke.[ch]: New files for the libart
	stroking (right now just vector objects).
	* app/core/Makefile.am: changed accordingly.

	* app/Makefile.am: Needed to tweak linking.  :-/
This commit is contained in:
Simon Budig 2003-09-20 19:58:26 +00:00 committed by Simon Budig
parent 09837f7add
commit ca07f5ddb2
15 changed files with 596 additions and 179 deletions

View File

@ -1,3 +1,41 @@
2003-09-20 Simon Budig <simon@gimp.org>
Dave Neary <bolsh@gimp.org>
First steps towards Libart stroking. Right now the code
crashes and thus is disabled by default. If you want to
test it, change the #define LIBART_STROKE in
app/vectors/gimpvectors.c. Then a click on the stroke button
in the paths dialog invokes the new code.
The crash is in gimpdrawable-stroke.c - apparently I did not
yet get the TileManager stuff correctly.
* app/core/gimpscanconvert.[ch]: Rewritten to be more clear
and have an easier API. Now can handle open Paths and
libart-stroke the (open/closed) polygons defined earlier.
* app/core/core-enums.h: Added Enums for LineJoin-Type and
EndCap-Type for stroking.
* app/core/core-enums.c: regenerated.
* app/core/gimpimage-mask-select.c: Use the new API of
GimpScanConvert where appropriate.
* app/vectors/gimpvectors.c: Added #define to enable the libart
stroking. Disabled by default because of the crash mentioned
above...
* app/vectors/gimpbezierstroke.c
* app/vectors/gimpstroke.c
* app/vectors/gimpvectors.[ch]: Removed Libart stuff here.
Libart usage now lives exclusively in GimpScanConvert.
* app/core/gimpdrawable-stroke.[ch]: New files for the libart
stroking (right now just vector objects).
* app/core/Makefile.am: changed accordingly.
* app/Makefile.am: Needed to tweak linking. :-/
2003-09-20 Henrik Brix Andersen <brix@gimp.org>
* app/config/gimpconfig-dump.c (dump_gimprc): removed reference to

View File

@ -57,7 +57,8 @@ endif
gimp_1_3_LDFLAGS = \
$(mwindows) \
-u $(symprefix)gimp_container_filter \
-u $(symprefix)gimp_xml_parser_new
-u $(symprefix)gimp_xml_parser_new \
-u $(symprefix)gimp_drawable_stroke_vectors
AM_CPPFLAGS = \
-DG_LOG_DOMAIN=\"Gimp\" \

View File

@ -85,6 +85,8 @@ libappcore_a_sources = \
gimpdrawable-offset.h \
gimpdrawable-preview.c \
gimpdrawable-preview.h \
gimpdrawable-stroke.c \
gimpdrawable-stroke.h \
gimpdrawable-transform.c \
gimpdrawable-transform.h \
gimpenvirontable.h \

View File

@ -254,6 +254,46 @@ gimp_grid_type_get_type (void)
}
static const GEnumValue gimp_join_type_enum_values[] =
{
{ GIMP_JOIN_MITER, N_("Miter"), "miter" },
{ GIMP_JOIN_ROUND, N_("Round"), "round" },
{ GIMP_JOIN_BEVEL, N_("Bevel"), "bevel" },
{ 0, NULL, NULL }
};
GType
gimp_join_type_get_type (void)
{
static GType enum_type = 0;
if (!enum_type)
enum_type = g_enum_register_static ("GimpJoinType", gimp_join_type_enum_values);
return enum_type;
}
static const GEnumValue gimp_cap_type_enum_values[] =
{
{ GIMP_CAP_BUTT, N_("Butt"), "butt" },
{ GIMP_CAP_ROUND, N_("Round"), "round" },
{ GIMP_CAP_SQUARE, N_("Square"), "square" },
{ 0, NULL, NULL }
};
GType
gimp_cap_type_get_type (void)
{
static GType enum_type = 0;
if (!enum_type)
enum_type = g_enum_register_static ("GimpCapType", gimp_cap_type_enum_values);
return enum_type;
}
static const GEnumValue gimp_image_base_type_enum_values[] =
{
{ GIMP_RGB, N_("RGB"), "rgb" },

View File

@ -195,6 +195,30 @@ typedef enum /*< pdb-skip >*/
} GimpGridType;
#define GIMP_TYPE_JOIN_TYPE (gimp_join_type_get_type ())
GType gimp_join_type_get_type (void) G_GNUC_CONST;
typedef enum /*< pdb-skip >*/
{
GIMP_JOIN_MITER, /*< desc="Miter" >*/
GIMP_JOIN_ROUND, /*< desc="Round" >*/
GIMP_JOIN_BEVEL /*< desc="Bevel" >*/
} GimpJoinType;
#define GIMP_TYPE_CAP_TYPE (gimp_cap_type_get_type ())
GType gimp_cap_type_get_type (void) G_GNUC_CONST;
typedef enum /*< pdb-skip >*/
{
GIMP_CAP_BUTT, /*< desc="Butt" >*/
GIMP_CAP_ROUND, /*< desc="Round" >*/
GIMP_CAP_SQUARE /*< desc="Square" >*/
} GimpCapType;
#define GIMP_TYPE_IMAGE_BASE_TYPE (gimp_image_base_type_get_type ())
GType gimp_image_base_type_get_type (void) G_GNUC_CONST;

View File

@ -172,7 +172,8 @@ gimp_image_mask_select_polygon (GimpImage *gimage,
scan_convert = gimp_scan_convert_new (gimage->width,
gimage->height,
antialias ? SUPERSAMPLE : 1);
gimp_scan_convert_add_points (scan_convert, n_points, points, FALSE);
gimp_scan_convert_add_polyline (scan_convert, n_points, points, TRUE);
mask = gimp_scan_convert_to_channel (scan_convert, gimage);
@ -253,8 +254,8 @@ gimp_image_mask_select_vectors (GimpImage *gimage,
num_coords++;
}
gimp_scan_convert_add_points (scan_convert, coords->len,
points, TRUE);
gimp_scan_convert_add_polyline (scan_convert, coords->len,
points, TRUE);
g_free (points);
}

View File

@ -0,0 +1,152 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpdrawable-stroke.c
* Copyright (C) 2003 Simon Budig <simon@gimp.org>
*
* 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 <glib-object.h>
#include "libgimpcolor/gimpcolor.h"
#include "core-types.h"
#include "base/pixel-region.h"
#include "base/temp-buf.h"
#include "base/tile-manager.h"
#include "core/gimpitem.h"
#include "core/gimpscanconvert.h"
#include "vectors/gimpstroke.h"
#include "vectors/gimpvectors.h"
#include "paint-funcs/paint-funcs.h"
#include "gimp.h"
#include "gimpdrawable.h"
#include "gimpdrawable-stroke.h"
#include "gimpimage.h"
#include "gimp-intl.h"
/* local function prototypes */
void
gimp_drawable_stroke_vectors (GimpDrawable *drawable,
GimpVectors *vectors,
gdouble opacity,
GimpRGB *color,
GimpLayerModeEffects paint_mode,
gdouble width,
GimpJoinType jointype,
GimpCapType captype,
gboolean antialias)
{
GimpScanConvert *scan_convert;
gint num_coords = 0;
GimpStroke *stroke;
TileManager *base;
TileManager *mask;
gint x1, x2, y1, y2, bytes;
guchar ucolor[4] = { 0, 0, 0, 255 };
PixelRegion maskPR, basePR;
gimp_drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
scan_convert = gimp_scan_convert_new (x2 - x1, y2 - y1, antialias ? 1 : 0);
/* For each Stroke in the vector, interpolate it, and add it to the
* ScanConvert */
for (stroke = gimp_vectors_stroke_get_next (vectors, NULL);
stroke;
stroke = gimp_vectors_stroke_get_next (vectors, stroke))
{
GimpVector2 *points;
gboolean closed;
GArray *coords;
gint i;
/* Get the interpolated version of this stroke, and add it to our
* scanconvert. */
coords = gimp_stroke_interpolate (stroke, 1, &closed);
if (coords && coords->len)
{
points = g_new0 (GimpVector2, coords->len);
for (i = 0; i < coords->len; i++)
{
points[i].x = g_array_index (coords, GimpCoords, i).x;
points[i].y = g_array_index (coords, GimpCoords, i).y;
num_coords++;
}
gimp_scan_convert_add_polyline (scan_convert, coords->len,
points, closed);
g_free (points);
}
}
if (num_coords == 0)
{
gimp_scan_convert_free (scan_convert);
return;
}
gimp_scan_convert_stroke (scan_convert, jointype, captype, width);
mask = tile_manager_new (x2 - x1, y2 - y1, 1);
tile_manager_set_offsets (mask, x1, y1);
pixel_region_init (&maskPR, mask, x1, y1, x2 - x1, y2 - y1, TRUE);
color_region (&maskPR, ucolor);
gimp_scan_convert_render (scan_convert, mask);
gimp_scan_convert_free (scan_convert);
bytes = drawable->bytes;
if (!gimp_drawable_has_alpha (drawable))
bytes++;
base = tile_manager_new (x2 - x1, y2 - y1, bytes);
tile_manager_set_offsets (base, x1, y1);
gimp_rgb_get_uchar (color, &(ucolor[0]), &(ucolor[1]), &(ucolor[2]));
pixel_region_init (&basePR, base, x1, y1, x2 - x1, y2 - y1, TRUE);
color_region (&basePR, ucolor);
apply_mask_to_region (&basePR, &maskPR, OPAQUE_OPACITY);
gimp_image_apply_image (gimp_item_get_image (GIMP_ITEM (drawable)),
drawable, &basePR,
TRUE, _("Render Vectors"), opacity, paint_mode,
base, x1, y1);
tile_manager_unref (mask);
tile_manager_unref (base);
gimp_drawable_update (drawable, x1, y1, x2 - x1, y2 - y1);
}

View File

@ -0,0 +1,36 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpdrawable-stroke.h
* Copyright (C) 2003 Simon Budig <simon@gimp.org>
*
* 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.
*/
#ifndef __GIMP_DRAWABLE_STROKE_H__
#define __GIMP_DRAWABLE_STROKE_H__
void gimp_drawable_stroke_vectors (GimpDrawable *drawable,
GimpVectors *vectors,
gdouble opacity,
GimpRGB *color,
GimpLayerModeEffects paint_mode,
gdouble width,
GimpJoinType jointype,
GimpCapType captype,
gboolean antialias);
#endif /* __GIMP_DRAWABLE_STROKE_H__ */

View File

@ -172,7 +172,8 @@ gimp_image_mask_select_polygon (GimpImage *gimage,
scan_convert = gimp_scan_convert_new (gimage->width,
gimage->height,
antialias ? SUPERSAMPLE : 1);
gimp_scan_convert_add_points (scan_convert, n_points, points, FALSE);
gimp_scan_convert_add_polyline (scan_convert, n_points, points, TRUE);
mask = gimp_scan_convert_to_channel (scan_convert, gimage);
@ -253,8 +254,8 @@ gimp_image_mask_select_vectors (GimpImage *gimage,
num_coords++;
}
gimp_scan_convert_add_points (scan_convert, coords->len,
points, TRUE);
gimp_scan_convert_add_polyline (scan_convert, coords->len,
points, TRUE);
g_free (points);
}

View File

@ -29,6 +29,7 @@
#include "core-types.h"
#include "base/pixel-region.h"
#include "base/tile-manager.h"
#include "gimpchannel.h"
#include "gimpimage.h"
@ -40,23 +41,23 @@ struct _GimpScanConvert
guint width;
guint height;
guint antialias; /* how much to oversample by */
/* currently only used as boolean value */
gboolean antialias; /* do we want antialiasing? */
/* record the first and last points so we can close the current polygon. */
gboolean got_first;
GimpVector2 first;
GimpVector2 prev;
gboolean got_last;
GimpVector2 last;
gboolean have_open;
guint num_nodes;
ArtVpath *vpath;
ArtSVP *svp; /* Sorted vector path
(extension no longer possible) */
};
/* Private functions */
static void gimp_scan_convert_finish (GimpScanConvert *sc);
/* public functions */
GimpScanConvert *
gimp_scan_convert_new (guint width,
guint height,
@ -70,12 +71,16 @@ gimp_scan_convert_new (guint width,
sc = g_new0 (GimpScanConvert, 1);
sc->antialias = antialias;
sc->antialias = (antialias != 0 ? TRUE : FALSE);
sc->width = width;
sc->height = height;
sc->got_first = FALSE;
sc->have_open = FALSE;
sc->num_nodes = 0;
sc->vpath = NULL;
sc->svp = NULL;
return sc;
}
@ -84,11 +89,12 @@ void
gimp_scan_convert_free (GimpScanConvert *sc)
{
art_free (sc->vpath);
art_free (sc->svp);
g_free (sc);
}
/* Add "n_points" from "points" to the polygon currently being
* described by "scan_converter".
* described by "scan_converter". DEPRECATED.
*/
void
gimp_scan_convert_add_points (GimpScanConvert *sc,
@ -96,140 +102,215 @@ gimp_scan_convert_add_points (GimpScanConvert *sc,
GimpVector2 *points,
gboolean new_polygon)
{
GimpVector2 prev;
gint i;
g_return_if_fail (sc != NULL);
g_return_if_fail (points != NULL);
g_return_if_fail (n_points > 0);
g_return_if_fail (sc->svp == NULL);
/* We need up to three extra nodes later to close and finish the path */
sc->vpath = art_renew (sc->vpath, ArtVpath, sc->num_nodes + n_points + 3);
/* We need an extra nodes to end the path */
sc->vpath = art_renew (sc->vpath, ArtVpath, sc->num_nodes + n_points + 2);
/* if we need to start a new polygon check, if we need to close the
* previous.
*/
if (new_polygon)
{
/* close the last polygon if necessary */
if (sc->got_first && sc->got_last &&
(sc->first.x != sc->last.x || sc->first.y != sc->last.y))
{
sc->vpath[sc->num_nodes].code = ART_LINETO;
sc->vpath[sc->num_nodes].x = sc->first.x;
sc->vpath[sc->num_nodes].y = sc->first.y;
sc->num_nodes++;
}
sc->got_first = FALSE;
sc->got_last = FALSE;
}
if (!sc->got_first && n_points > 0)
{
sc->got_first = TRUE;
sc->first = points[0];
sc->vpath[sc->num_nodes].code =
(sc->num_nodes == 0 || new_polygon) ?
ART_MOVETO : ART_LINETO;
sc->vpath[sc->num_nodes].x = points[0].x;
sc->vpath[sc->num_nodes].y = points[0].y;
sc->num_nodes++;
sc->prev = points[0];
}
sc->vpath[sc->num_nodes].code = ((! sc->got_first) || new_polygon) ?
ART_MOVETO : ART_LINETO;
sc->vpath[sc->num_nodes].x = points[0].x;
sc->vpath[sc->num_nodes].y = points[0].y;
sc->num_nodes++;
sc->got_first = TRUE;
prev = points[0];
for (i = 1; i < n_points; i++)
{
if (sc->prev.x != points[i].x || sc->prev.y != points[i].y)
if (prev.x != points[i].x || prev.y != points[i].y)
{
sc->vpath[sc->num_nodes].code = ART_LINETO;
sc->vpath[sc->num_nodes].x = points[i].x;
sc->vpath[sc->num_nodes].y = points[i].y;
sc->num_nodes++;
sc->prev = points[i];
prev = points[i];
}
}
if (n_points > 0)
{
sc->got_last = TRUE;
sc->last = points[n_points - 1];
}
/* for some reason we need to duplicate the last node?? */
sc->vpath[sc->num_nodes] = sc->vpath[sc->num_nodes - 1];
sc->num_nodes++;
sc->vpath[sc->num_nodes].code = ART_END;
}
/* Scan convert the polygon described by the list of points passed to
* scan_convert_add_points, and return a channel with a bits set if
* they fall within the polygon defined. The polygon is filled
* according to the even-odd rule. The polygon is closed by
* joining the final point to the initial point.
/* Add a polygon with "npoints" "points" that may be open or closed.
* It is not recommended to mix gimp_scan_convert_add_polyline with
* gimp_scan_convert_add_points.
*
* Please note that if you should use gimp_scan_convert_stroke() if you
* specify open polygons.
*/
void
gimp_scan_convert_add_polyline (GimpScanConvert *sc,
guint n_points,
GimpVector2 *points,
gboolean closed)
{
GimpVector2 prev;
gint i;
g_return_if_fail (sc != NULL);
g_return_if_fail (points != NULL);
g_return_if_fail (n_points > 0);
g_return_if_fail (sc->svp == NULL);
if (!closed)
sc->have_open = TRUE;
/* We need two extra nodes later to close the path. */
sc->vpath = art_renew (sc->vpath, ArtVpath,
sc->num_nodes + n_points + 2);
for (i = 0; i < n_points; i++)
{
/* compress multiple identical coordinates */
if (i == 0 ||
prev.x != points[i].x ||
prev.y != points[i].y)
{
sc->vpath[sc->num_nodes].code = (i == 0 ? (closed ?
ART_MOVETO :
ART_MOVETO_OPEN) :
ART_LINETO);
sc->vpath[sc->num_nodes].x = points[i].x;
sc->vpath[sc->num_nodes].y = points[i].y;
sc->num_nodes++;
prev = points[i];
}
}
/* for some reason we need to duplicate the last node?? */
sc->vpath[sc->num_nodes] = sc->vpath[sc->num_nodes - 1];
sc->num_nodes++;
sc->vpath[sc->num_nodes].code = ART_END;
/* If someone wants to mix this function with _add_points ()
* try to do something reasonable...
*/
sc->got_first = FALSE;
}
/* Stroke the content of a GimpScanConvert. The next
* gimp_scan_convert_to_channel will result in the outline of the polygon
* defined with the commands above.
*
* You cannot add additional polygons after this command.
*/
void
gimp_scan_convert_stroke (GimpScanConvert *sc,
GimpJoinType join,
GimpCapType cap,
gdouble width)
{
ArtSVP *stroke;
ArtPathStrokeJoinType artjoin;
ArtPathStrokeCapType artcap;
g_return_if_fail (sc->svp == NULL);
switch (join)
{
case GIMP_JOIN_MITER:
artjoin = ART_PATH_STROKE_JOIN_MITER;
break;
case GIMP_JOIN_ROUND:
artjoin = ART_PATH_STROKE_JOIN_ROUND;
break;
case GIMP_JOIN_BEVEL:
artjoin = ART_PATH_STROKE_JOIN_BEVEL;
break;
}
switch (cap)
{
case GIMP_CAP_BUTT:
artcap = ART_PATH_STROKE_CAP_BUTT;
break;
case GIMP_CAP_ROUND:
artcap = ART_PATH_STROKE_CAP_ROUND;
break;
case GIMP_CAP_SQUARE:
artcap = ART_PATH_STROKE_CAP_SQUARE;
break;
}
stroke = art_svp_vpath_stroke (sc->vpath, artjoin, artcap,
width, 10.0, 1.0);
sc->svp = stroke;
}
/* Return a new Channel according to the polygonal shapes defined with
* the commands above.
*
* You cannot add additional polygons after this command.
*/
GimpChannel *
gimp_scan_convert_to_channel (GimpScanConvert *sc,
GimpImage *gimage)
{
GimpChannel *mask;
PixelRegion maskPR;
gint i, j;
gpointer pr;
ArtVpath *pert_vpath;
ArtSVP *svp, *svp2, *svp3;
guchar *dest, *d;
/* do we need to close the polygon? */
if (sc->got_first && sc->got_last &&
(sc->first.x != sc->last.x || sc->first.y != sc->last.y))
{
sc->vpath[sc->num_nodes].code = ART_LINETO;
sc->vpath[sc->num_nodes].x = sc->first.x;
sc->vpath[sc->num_nodes].y = sc->first.y;
sc->num_nodes++;
}
mask = gimp_channel_new_mask (gimage, sc->width, sc->height);
sc->vpath[sc->num_nodes].code = ART_END;
sc->vpath[sc->num_nodes].x = sc->first.x;
sc->vpath[sc->num_nodes].y = sc->first.y;
sc->num_nodes++;
gimp_scan_convert_render (sc, gimp_drawable_data (GIMP_DRAWABLE (mask)));
/*
* Current Libart (2.3.8) recommends a slight random distorsion
* of the path, because art_svp_uncross and art_svp_rewind_uncrossed
* are not yet numerically stable. It is actually possible to construct
* worst case scenarios. The slight perturbation should not have any
* visible effect.
*/
mask->bounds_known = FALSE;
/* Debug output of libart path
for (i=0; i < sc->num_nodes ; i++)
{
g_printerr ("X: %f, Y: %f, Type: %d\n", sc->vpath[i].x, sc->vpath[i].y,
sc->vpath[i].code );
}
*/
return mask;
}
/* This is a more low level version. Expects a tile manager of depth 1.
*
* You cannot add additional polygons after this command.
*/
void
gimp_scan_convert_render (GimpScanConvert *sc,
TileManager *tile_manager)
{
PixelRegion maskPR;
gpointer pr;
gint i, j, x0, y0;
guchar *dest, *d;
pert_vpath = art_vpath_perturb (sc->vpath);
g_return_if_fail (sc != NULL);
g_return_if_fail (tile_manager != NULL);
gimp_scan_convert_finish (sc);
svp = art_svp_from_vpath (pert_vpath);
svp2 = art_svp_uncross (svp);
svp3 = art_svp_rewind_uncrossed (svp2, ART_WIND_RULE_ODDEVEN);
tile_manager_get_offsets (tile_manager, &x0, &y0);
pixel_region_init (&maskPR, gimp_drawable_data (GIMP_DRAWABLE (mask)),
0, 0,
gimp_item_width (GIMP_ITEM (mask)),
gimp_item_height (GIMP_ITEM (mask)),
pixel_region_init (&maskPR, tile_manager,
x0, y0,
tile_manager_width (tile_manager),
tile_manager_height (tile_manager),
TRUE);
g_return_val_if_fail (maskPR.bytes == 1, NULL);
g_return_if_fail (maskPR.bytes == 1);
for (pr = pixel_regions_register (1, &maskPR);
pr != NULL;
pr = pixel_regions_process (pr))
{
art_gray_svp_aa (svp3, maskPR.x, maskPR.y,
art_gray_svp_aa (sc->svp, maskPR.x, maskPR.y,
maskPR.x + maskPR.w, maskPR.y + maskPR.h,
maskPR.data, maskPR.rowstride);
if (!sc->antialias)
if (sc->antialias == FALSE)
{
/*
* Ok, the user didn't want to have antialiasing, so just
@ -249,13 +330,68 @@ gimp_scan_convert_to_channel (GimpScanConvert *sc,
}
}
}
}
art_free (svp3);
art_free (svp2);
art_free (svp);
/* private function to convert the vpath to a svp when not using
* gimp_scan_convert_stroke
*/
static void
gimp_scan_convert_finish (GimpScanConvert *sc)
{
ArtVpath *pert_vpath;
ArtSVP *svp, *svp2;
g_return_if_fail (sc->vpath != NULL);
/* gimp_scan_convert_stroke (sc, GIMP_JOIN_MITER, GIMP_CAP_BUTT, 15.0);
*/
if (sc->svp)
return; /* We already have a valid SVP */
/* Debug output of libart path */
/* {
* gint i;
* for (i=0; i < sc->num_nodes + 1; i++)
* {
* g_printerr ("X: %f, Y: %f, Type: %d\n", sc->vpath[i].x,
* sc->vpath[i].y,
* sc->vpath[i].code );
* }
* }
*/
if (sc->have_open)
{
gint i;
for (i = 0; i < sc->num_nodes; i++)
if (sc->vpath[i].code == ART_MOVETO_OPEN)
{
g_printerr ("Fixing ART_MOVETO_OPEN - result might be incorrect\n");
sc->vpath[i].code = ART_MOVETO;
}
}
/*
* Current Libart (2.3.8) recommends a slight random distorsion
* of the path, because art_svp_uncross and art_svp_rewind_uncrossed
* are not yet numerically stable. It is actually possible to construct
* worst case scenarios. The slight perturbation should not have any
* visible effect.
*/
pert_vpath = art_vpath_perturb (sc->vpath);
svp = art_svp_from_vpath (pert_vpath);
art_free (pert_vpath);
mask->bounds_known = FALSE;
svp2 = art_svp_uncross (svp);
art_free (svp);
svp = art_svp_rewind_uncrossed (svp2, ART_WIND_RULE_ODDEVEN);
art_free (svp2);
return mask;
sc->svp = svp;
}

View File

@ -33,22 +33,51 @@ GimpScanConvert * gimp_scan_convert_new (guint width,
void gimp_scan_convert_free (GimpScanConvert *scan_converter);
/* Add "npoints" from "pointlist" to the polygon currently being
* described by "scan_converter".
* described by "scan_converter". DEPRECATED.
*/
void gimp_scan_convert_add_points (GimpScanConvert *scan_converter,
guint n_points,
GimpVector2 *points,
gboolean new_polygon);
/* Add a polygon with "npoints" "points" that may be open or closed.
* It is not recommended to mix gimp_scan_convert_add_polyline with
* gimp_scan_convert_add_points.
*
* Please note that if you should use gimp_scan_convert_stroke() if you
* specify open polygons.
*/
void gimp_scan_convert_add_polyline (GimpScanConvert *sc,
guint n_points,
GimpVector2 *points,
gboolean closed);
/* Scan convert the polygon described by the list of points passed to
* scan_convert_add_points, and return a channel with a bits set if
* they fall within the polygon defined. The polygon is filled
* according to the even-odd rule. The polygon is closed by
* joining the final point to the initial point.
/* Stroke the content of a GimpScanConvert. The next
* gimp_scan_convert_to_channel will result in the outline of the polygon
* defined with the commands above.
*
* You cannot add additional polygons after this command.
*/
void gimp_scan_convert_stroke (GimpScanConvert *sc,
GimpJoinType join,
GimpCapType cap,
gdouble width);
/* Return a new Channel according to the polygonal shapes defined with
* the commands above.
*
* You cannot add additional polygons after this command.
*/
GimpChannel * gimp_scan_convert_to_channel (GimpScanConvert *scan_converter,
GimpImage *gimage);
/* This is a more low level version. Expects a tile manager of depth 1.
*
* You cannot add additional polygons after this command.
*/
void gimp_scan_convert_render (GimpScanConvert *scan_converter,
TileManager *tile_manager);
#endif /* __GIMP_SCAN_CONVERT_H__ */

View File

@ -21,8 +21,6 @@
#include "config.h"
#include <libart_lgpl/libart.h>
#include <glib-object.h>
#include "libgimpmath/gimpmath.h"
@ -120,8 +118,6 @@ static void gimp_bezier_coords_subdivide2 (const GimpCoords *beziercoords,
static gboolean gimp_bezier_coords_is_straight (const GimpCoords *beziercoords,
const gdouble precision);
static void gimp_bezier_stroke_art_stroke (const GimpStroke *stroke);
/* private variables */
@ -185,7 +181,6 @@ gimp_bezier_stroke_class_init (GimpBezierStrokeClass *klass)
stroke_class->extend = gimp_bezier_stroke_extend;
stroke_class->connect_stroke = gimp_bezier_stroke_connect_stroke;
stroke_class->interpolate = gimp_bezier_stroke_interpolate;
stroke_class->art_stroke = gimp_bezier_stroke_art_stroke;
}
static void
@ -1919,10 +1914,3 @@ gimp_bezier_coords_subdivide2 (const GimpCoords *beziercoords,
}
}
static void
gimp_bezier_stroke_art_stroke (const GimpStroke *stroke)
{
g_printerr ("gimp_bezier_stroke_art_stroke: implement me!\n");
return;
}

View File

@ -21,8 +21,6 @@
#include "config.h"
#include <libart_lgpl/libart.h>
#include <glib-object.h>
#include "vectors-types.h"
@ -150,8 +148,6 @@ static GArray * gimp_stroke_real_get_draw_lines (const GimpStroke *stroke);
static GArray * gimp_stroke_real_control_points_get (const GimpStroke *stroke,
gboolean *ret_closed);
static void gimp_stroke_art_stroke (const GimpStroke *stroke);
/* private variables */
static GimpObjectClass *parent_class = NULL;
@ -246,8 +242,6 @@ gimp_stroke_class_init (GimpStrokeClass *klass)
klass->get_draw_lines = gimp_stroke_real_get_draw_lines;
klass->control_points_get = gimp_stroke_real_control_points_get;
klass->art_stroke = gimp_stroke_art_stroke;
anchor_param_spec = g_param_spec_boxed ("gimp-anchor",
"Gimp Anchor",
"The control points of a Stroke",
@ -1202,13 +1196,3 @@ gimp_stroke_real_control_points_get (const GimpStroke *stroke,
return ret_array;
}
static void
gimp_stroke_art_stroke (const GimpStroke *stroke)
{
g_return_if_fail (GIMP_IS_STROKE (stroke));
GIMP_STROKE_GET_CLASS (stroke)->art_stroke (stroke);
return;
}

View File

@ -21,8 +21,6 @@
#include "config.h"
#include <libart_lgpl/libart.h>
#include <glib-object.h>
#include "vectors-types.h"
@ -33,7 +31,14 @@
#include "core/gimpmarshal.h"
#include "core/gimppaintinfo.h"
#include "paint/gimppaintcore-stroke.h"
#undef LIBART_STROKE
#ifdef LIBART_STROKE
# include "libgimpcolor/gimpcolor.h"
# include "core/gimpdrawable-stroke.h"
#else
# include "paint/gimppaintcore-stroke.h"
#endif
#include "gimpanchor.h"
#include "gimpstroke.h"
@ -540,6 +545,7 @@ gimp_vectors_stroke (GimpItem *item,
GimpVectors *vectors;
GimpPaintCore *core;
gboolean retval;
GimpRGB color;
vectors = GIMP_VECTORS (item);
@ -549,6 +555,14 @@ gimp_vectors_stroke (GimpItem *item,
return FALSE;
}
#ifdef LIBART_STROKE
gimp_rgba_set (&color, 0.0, 0.7, 0.5, 1.0);
gimp_drawable_stroke_vectors (drawable, vectors, 0.5, &color,
GIMP_NORMAL_MODE, 15, GIMP_JOIN_MITER,
GIMP_CAP_SQUARE, TRUE);
retval = TRUE;
#else
core = g_object_new (paint_info->paint_type, NULL);
retval = gimp_paint_core_stroke_vectors (core, drawable,
@ -556,6 +570,7 @@ gimp_vectors_stroke (GimpItem *item,
vectors);
g_object_unref (core);
#endif
return retval;
}
@ -1000,30 +1015,3 @@ gimp_vectors_real_make_bezier (const GimpVectors *vectors)
return NULL;
}
/*
* gimp_vectors_art_stroke: Stroke a GimpVectors object using libart.
* @vectors: The source path
*
* Traverses the stroke list of a GimpVector object, calling art_stroke
* on each stroke as we go. Will eventually take cap type, join type
* and width as arguments.
*/
void
gimp_vectors_art_stroke (const GimpVectors *vectors)
{
GimpStroke *cur_stroke;
/* For each Stroke in the vector, stroke it */
for (cur_stroke = gimp_vectors_stroke_get_next (vectors, NULL);
cur_stroke;
cur_stroke = gimp_vectors_stroke_get_next (vectors, cur_stroke))
{
/* Add this stroke to the art_vpath */
GIMP_STROKE_GET_CLASS(cur_stroke)->art_stroke (cur_stroke);
}
/* That's it - nothing else to see here */
return;
}

View File

@ -170,7 +170,4 @@ gint gimp_vectors_interpolate (const GimpVectors *vectors,
GimpVectors * gimp_vectors_make_bezier (const GimpVectors *vectors);
/* Stroke a vector with libart (needs a better name) */
void gimp_vectors_art_stroke(const GimpVectors * vectors);
#endif /* __GIMP_VECTORS_H__ */