mirror of https://github.com/GNOME/gimp.git
app/vectors/gimpvectors.[ch] app/vectors/gimpstroke.[ch] Implement
2008-05-12 Simon Budig <simon@gimp.org> * app/vectors/gimpvectors.[ch] * app/vectors/gimpstroke.[ch] * app/vectors/gimpbezierstroke.c: Implement functionality to get a bezier description a la moveto/curveto/closepath. * app/vectors/vectors-types.h: implement an evil hack to avoid the inclusion of cairo.h in most C files... * app/vectors/Makefile.am: link against cairo * app/widgets/gimpviewrenderervectors.c: use the new functionality for preview rendering. svn path=/trunk/; revision=25645
This commit is contained in:
parent
7f2d708819
commit
80039486aa
15
ChangeLog
15
ChangeLog
|
@ -1,3 +1,18 @@
|
|||
2008-05-12 Simon Budig <simon@gimp.org>
|
||||
|
||||
* app/vectors/gimpvectors.[ch]
|
||||
* app/vectors/gimpstroke.[ch]
|
||||
* app/vectors/gimpbezierstroke.c: Implement functionality to
|
||||
get a bezier description a la moveto/curveto/closepath.
|
||||
|
||||
* app/vectors/vectors-types.h: implement an evil hack to avoid
|
||||
the inclusion of cairo.h in most C files...
|
||||
|
||||
* app/vectors/Makefile.am: link against cairo
|
||||
|
||||
* app/widgets/gimpviewrenderervectors.c: use the new functionality
|
||||
for preview rendering.
|
||||
|
||||
2008-05-11 Sven Neumann <sven@gimp.org>
|
||||
|
||||
* app/core/Makefile.am
|
||||
|
|
|
@ -9,7 +9,7 @@ INCLUDES = \
|
|||
-I$(top_builddir)/app \
|
||||
-I$(top_srcdir)/app \
|
||||
$(GDK_PIXBUF_CFLAGS) \
|
||||
$(LIBART_CFLAGS) \
|
||||
$(CAIRO_CFLAGS) \
|
||||
$(GLIB_CFLAGS) \
|
||||
-I$(includedir)
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "config.h"
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <cairo/cairo.h>
|
||||
|
||||
#include "libgimpmath/gimpmath.h"
|
||||
|
||||
|
@ -130,6 +131,8 @@ static GArray *
|
|||
gimp_bezier_stroke_interpolate (const GimpStroke *stroke,
|
||||
const gdouble precision,
|
||||
gboolean *closed);
|
||||
static GimpBezierDesc *
|
||||
gimp_bezier_stroke_make_bezier (const GimpStroke *stroke);
|
||||
|
||||
static void gimp_bezier_stroke_finalize (GObject *object);
|
||||
|
||||
|
@ -185,6 +188,7 @@ 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->make_bezier = gimp_bezier_stroke_make_bezier;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1438,6 +1442,94 @@ gimp_bezier_stroke_anchor_convert (GimpStroke *stroke,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static GimpBezierDesc *
|
||||
gimp_bezier_stroke_make_bezier (const GimpStroke *stroke)
|
||||
{
|
||||
GArray *points, *cmd_array;
|
||||
GimpBezierDesc *bezdesc;
|
||||
cairo_path_data_t pathdata;
|
||||
gint num_cmds, i;
|
||||
|
||||
points = gimp_stroke_control_points_get (stroke, NULL);
|
||||
|
||||
g_return_val_if_fail (points && points->len % 3 == 0, NULL);
|
||||
if (points->len < 3)
|
||||
return NULL;
|
||||
|
||||
/* Moveto + (n-1) * curveto + (if closed) curveto + closepath */
|
||||
num_cmds = 2 + (points->len / 3 - 1) * 4;
|
||||
if (stroke->closed)
|
||||
num_cmds += 1 + 4;
|
||||
|
||||
cmd_array = g_array_sized_new (FALSE, FALSE,
|
||||
sizeof (cairo_path_data_t),
|
||||
num_cmds);
|
||||
|
||||
pathdata.header.type = CAIRO_PATH_MOVE_TO;
|
||||
pathdata.header.length = 2;
|
||||
g_array_append_val (cmd_array, pathdata);
|
||||
pathdata.point.x = g_array_index (points, GimpAnchor, 1).position.x;
|
||||
pathdata.point.y = g_array_index (points, GimpAnchor, 1).position.y;
|
||||
g_array_append_val (cmd_array, pathdata);
|
||||
|
||||
for (i = 2; i+2 < points->len; i += 3)
|
||||
{
|
||||
pathdata.header.type = CAIRO_PATH_CURVE_TO;
|
||||
pathdata.header.length = 4;
|
||||
g_array_append_val (cmd_array, pathdata);
|
||||
|
||||
pathdata.point.x = g_array_index (points, GimpAnchor, i).position.x;
|
||||
pathdata.point.y = g_array_index (points, GimpAnchor, i).position.y;
|
||||
g_array_append_val (cmd_array, pathdata);
|
||||
|
||||
pathdata.point.x = g_array_index (points, GimpAnchor, i+1).position.x;
|
||||
pathdata.point.y = g_array_index (points, GimpAnchor, i+1).position.y;
|
||||
g_array_append_val (cmd_array, pathdata);
|
||||
|
||||
pathdata.point.x = g_array_index (points, GimpAnchor, i+2).position.x;
|
||||
pathdata.point.y = g_array_index (points, GimpAnchor, i+2).position.y;
|
||||
g_array_append_val (cmd_array, pathdata);
|
||||
}
|
||||
|
||||
if (stroke->closed)
|
||||
{
|
||||
pathdata.header.type = CAIRO_PATH_CURVE_TO;
|
||||
pathdata.header.length = 4;
|
||||
g_array_append_val (cmd_array, pathdata);
|
||||
|
||||
pathdata.point.x = g_array_index (points, GimpAnchor, i).position.x;
|
||||
pathdata.point.y = g_array_index (points, GimpAnchor, i).position.y;
|
||||
g_array_append_val (cmd_array, pathdata);
|
||||
|
||||
pathdata.point.x = g_array_index (points, GimpAnchor, 0).position.x;
|
||||
pathdata.point.y = g_array_index (points, GimpAnchor, 0).position.y;
|
||||
g_array_append_val (cmd_array, pathdata);
|
||||
|
||||
pathdata.point.x = g_array_index (points, GimpAnchor, 1).position.x;
|
||||
pathdata.point.y = g_array_index (points, GimpAnchor, 1).position.y;
|
||||
g_array_append_val (cmd_array, pathdata);
|
||||
|
||||
pathdata.header.type = CAIRO_PATH_CLOSE_PATH;
|
||||
pathdata.header.length = 1;
|
||||
g_array_append_val (cmd_array, pathdata);
|
||||
}
|
||||
|
||||
if (cmd_array->len != num_cmds)
|
||||
g_printerr ("miscalculated path cmd length! (%d vs. %d)\n",
|
||||
cmd_array->len, num_cmds);
|
||||
|
||||
bezdesc = g_new (GimpBezierDesc, 1);
|
||||
bezdesc->status = CAIRO_STATUS_SUCCESS;
|
||||
bezdesc->data = (cairo_path_data_t *) cmd_array->data;
|
||||
bezdesc->num_data = cmd_array->len;
|
||||
g_array_free (points, TRUE);
|
||||
g_array_free (cmd_array, FALSE);
|
||||
|
||||
return bezdesc;
|
||||
}
|
||||
|
||||
|
||||
static GArray *
|
||||
gimp_bezier_stroke_interpolate (const GimpStroke *stroke,
|
||||
gdouble precision,
|
||||
|
|
|
@ -129,7 +129,7 @@ static GArray * gimp_stroke_real_interpolate (const GimpStroke *stroke,
|
|||
gdouble precision,
|
||||
gboolean *closed);
|
||||
static GimpStroke * gimp_stroke_real_duplicate (const GimpStroke *stroke);
|
||||
static GimpStroke * gimp_stroke_real_make_bezier (const GimpStroke *stroke);
|
||||
static GimpBezierDesc * gimp_stroke_real_make_bezier (const GimpStroke *stroke);
|
||||
|
||||
static void gimp_stroke_real_translate (GimpStroke *stroke,
|
||||
gdouble offset_x,
|
||||
|
@ -1006,7 +1006,7 @@ gimp_stroke_real_duplicate (const GimpStroke *stroke)
|
|||
}
|
||||
|
||||
|
||||
GimpStroke *
|
||||
GimpBezierDesc *
|
||||
gimp_stroke_make_bezier (const GimpStroke *stroke)
|
||||
{
|
||||
g_return_val_if_fail (GIMP_IS_STROKE (stroke), NULL);
|
||||
|
@ -1014,7 +1014,7 @@ gimp_stroke_make_bezier (const GimpStroke *stroke)
|
|||
return GIMP_STROKE_GET_CLASS (stroke)->make_bezier (stroke);
|
||||
}
|
||||
|
||||
static GimpStroke *
|
||||
static GimpBezierDesc *
|
||||
gimp_stroke_real_make_bezier (const GimpStroke *stroke)
|
||||
{
|
||||
g_printerr ("gimp_stroke_make_bezier: default implementation\n");
|
||||
|
|
|
@ -149,7 +149,7 @@ struct _GimpStrokeClass
|
|||
|
||||
GimpStroke * (* duplicate) (const GimpStroke *stroke);
|
||||
|
||||
GimpStroke * (* make_bezier) (const GimpStroke *stroke);
|
||||
GimpBezierDesc * (* make_bezier) (const GimpStroke *stroke);
|
||||
|
||||
void (* translate) (GimpStroke *stroke,
|
||||
gdouble offset_x,
|
||||
|
@ -177,8 +177,6 @@ struct _GimpStrokeClass
|
|||
GArray * (* get_draw_lines) (const GimpStroke *stroke);
|
||||
GArray * (* control_points_get) (const GimpStroke *stroke,
|
||||
gboolean *ret_closed);
|
||||
|
||||
void (* art_stroke) (const GimpStroke *stroke);
|
||||
};
|
||||
|
||||
|
||||
|
@ -312,7 +310,7 @@ GArray * gimp_stroke_interpolate (const GimpStroke *stroke,
|
|||
GimpStroke * gimp_stroke_duplicate (const GimpStroke *stroke);
|
||||
|
||||
/* creates a bezier approximation. */
|
||||
GimpStroke * gimp_stroke_make_bezier (const GimpStroke *stroke);
|
||||
GimpBezierDesc * gimp_stroke_make_bezier (const GimpStroke *stroke);
|
||||
|
||||
void gimp_stroke_translate (GimpStroke *stroke,
|
||||
gdouble offset_x,
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "config.h"
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <cairo/cairo.h>
|
||||
|
||||
#include "libgimpcolor/gimpcolor.h"
|
||||
#include "libgimpmath/gimpmath.h"
|
||||
|
@ -135,7 +136,7 @@ static gint gimp_vectors_real_interpolate (const GimpVectors *vectors,
|
|||
gdouble precision,
|
||||
gint max_points,
|
||||
GimpCoords *ret_coords);
|
||||
static GimpVectors * gimp_vectors_real_make_bezier (const GimpVectors *vectors);
|
||||
static GimpBezierDesc * gimp_vectors_real_make_bezier (const GimpVectors *vectors);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (GimpVectors, gimp_vectors, GIMP_TYPE_ITEM)
|
||||
|
@ -1013,7 +1014,7 @@ gimp_vectors_real_interpolate (const GimpVectors *vectors,
|
|||
}
|
||||
|
||||
|
||||
GimpVectors *
|
||||
GimpBezierDesc *
|
||||
gimp_vectors_make_bezier (const GimpVectors *vectors)
|
||||
{
|
||||
g_return_val_if_fail (GIMP_IS_VECTORS (vectors), NULL);
|
||||
|
@ -1021,11 +1022,38 @@ gimp_vectors_make_bezier (const GimpVectors *vectors)
|
|||
return GIMP_VECTORS_GET_CLASS (vectors)->make_bezier (vectors);
|
||||
}
|
||||
|
||||
static GimpVectors *
|
||||
static GimpBezierDesc *
|
||||
gimp_vectors_real_make_bezier (const GimpVectors *vectors)
|
||||
{
|
||||
g_printerr ("gimp_vectors_make_bezier: default implementation\n");
|
||||
GimpStroke *cur_stroke;
|
||||
GArray *cmd_array;
|
||||
GimpBezierDesc *bezdesc;
|
||||
GimpBezierDesc *ret_bezdesc = NULL;
|
||||
|
||||
return NULL;
|
||||
cmd_array = g_array_new (FALSE, FALSE, sizeof (cairo_path_data_t));
|
||||
|
||||
for (cur_stroke = gimp_vectors_stroke_get_next (vectors, NULL);
|
||||
cur_stroke;
|
||||
cur_stroke = gimp_vectors_stroke_get_next (vectors, cur_stroke))
|
||||
{
|
||||
bezdesc = gimp_stroke_make_bezier (cur_stroke);
|
||||
if (bezdesc)
|
||||
{
|
||||
cmd_array = g_array_append_vals (cmd_array, bezdesc->data,
|
||||
bezdesc->num_data);
|
||||
g_free (bezdesc->data);
|
||||
g_free (bezdesc);
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd_array->len > 0)
|
||||
{
|
||||
ret_bezdesc = g_new (GimpBezierDesc, 1);
|
||||
ret_bezdesc->num_data = cmd_array->len;
|
||||
ret_bezdesc->data = (cairo_path_data_t *) cmd_array->data;
|
||||
g_array_free (cmd_array, FALSE);
|
||||
}
|
||||
|
||||
return ret_bezdesc;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
|
||||
#include "core/gimpitem.h"
|
||||
|
||||
|
||||
#define GIMP_TYPE_VECTORS (gimp_vectors_get_type ())
|
||||
#define GIMP_VECTORS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_VECTORS, GimpVectors))
|
||||
#define GIMP_VECTORS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_VECTORS, GimpVectorsClass))
|
||||
|
@ -79,7 +78,7 @@ struct _GimpVectorsClass
|
|||
gdouble precision,
|
||||
gint max_points,
|
||||
GimpCoords *ret_coords);
|
||||
GimpVectors * (* make_bezier) (const GimpVectors *vectors);
|
||||
GimpBezierDesc * (* make_bezier) (const GimpVectors *vectors);
|
||||
};
|
||||
|
||||
|
||||
|
@ -173,8 +172,8 @@ gint gimp_vectors_interpolate (const GimpVectors *vectors,
|
|||
|
||||
/* usually overloaded */
|
||||
|
||||
/* creates a bezier approximation. */
|
||||
/* creates a bezier representation. */
|
||||
|
||||
GimpVectors * gimp_vectors_make_bezier (const GimpVectors *vectors);
|
||||
GimpBezierDesc * gimp_vectors_make_bezier (const GimpVectors *vectors);
|
||||
|
||||
#endif /* __GIMP_VECTORS_H__ */
|
||||
|
|
|
@ -35,5 +35,10 @@ typedef struct _GimpVectorsPropUndo GimpVectorsPropUndo;
|
|||
typedef struct _GimpStroke GimpStroke;
|
||||
typedef struct _GimpBezierStroke GimpBezierStroke;
|
||||
|
||||
#ifdef CAIRO_VERSION
|
||||
typedef cairo_path_t GimpBezierDesc;
|
||||
#else
|
||||
typedef void * GimpBezierDesc;
|
||||
#endif
|
||||
|
||||
#endif /* __VECTORS_TYPES_H__ */
|
||||
|
|
|
@ -69,61 +69,40 @@ gimp_view_renderer_vectors_draw (GimpViewRenderer *renderer,
|
|||
cairo_t *cr,
|
||||
const GdkRectangle *area)
|
||||
{
|
||||
GimpVectors *vectors = GIMP_VECTORS (renderer->viewable);
|
||||
GimpStroke *stroke;
|
||||
gdouble xscale;
|
||||
gdouble yscale;
|
||||
gint x, y;
|
||||
GimpVectors *vectors = GIMP_VECTORS (renderer->viewable);
|
||||
GimpBezierDesc *bezdesc;
|
||||
gdouble xscale;
|
||||
gdouble yscale;
|
||||
gint x, y;
|
||||
|
||||
gdk_cairo_set_source_color (cr, &widget->style->white);
|
||||
|
||||
x = area->x + (area->width - renderer->width) / 2;
|
||||
y = area->y + (area->height - renderer->height) / 2;
|
||||
|
||||
cairo_rectangle (cr, x, y, renderer->width, renderer->height);
|
||||
cairo_translate (cr, x, y);
|
||||
cairo_rectangle (cr, 0, 0, renderer->width, renderer->height);
|
||||
cairo_clip_preserve (cr);
|
||||
cairo_fill (cr);
|
||||
|
||||
cairo_set_line_width (cr, 1.0);
|
||||
xscale = (gdouble) renderer->width / (gdouble) gimp_item_width (GIMP_ITEM (vectors));
|
||||
yscale = (gdouble) renderer->height / (gdouble) gimp_item_height (GIMP_ITEM (vectors));
|
||||
cairo_scale (cr, xscale, yscale);
|
||||
|
||||
/* determine line width */
|
||||
xscale = yscale = 0.5;
|
||||
cairo_device_to_user_distance (cr, &xscale, &yscale);
|
||||
|
||||
cairo_set_line_width (cr, MAX (xscale, yscale));
|
||||
gdk_cairo_set_source_color (cr, &widget->style->black);
|
||||
|
||||
xscale = (gdouble) gimp_item_width (GIMP_ITEM (vectors)) / (gdouble) renderer->width;
|
||||
yscale = (gdouble) gimp_item_height (GIMP_ITEM (vectors)) / (gdouble) renderer->height;
|
||||
bezdesc = gimp_vectors_make_bezier (vectors);
|
||||
|
||||
for (stroke = gimp_vectors_stroke_get_next (vectors, NULL);
|
||||
stroke != NULL;
|
||||
stroke = gimp_vectors_stroke_get_next (vectors, stroke))
|
||||
if (bezdesc)
|
||||
{
|
||||
GArray *coordinates;
|
||||
|
||||
coordinates = gimp_stroke_interpolate (stroke,
|
||||
MIN (xscale, yscale) / 2,
|
||||
NULL);
|
||||
if (! coordinates)
|
||||
continue;
|
||||
|
||||
if (coordinates->len > 0)
|
||||
{
|
||||
GimpCoords *coords = &(g_array_index (coordinates, GimpCoords, 0));
|
||||
gdouble cx = x + ROUND (coords->x / xscale);
|
||||
gdouble cy = y + ROUND (coords->y / yscale);
|
||||
gint i;
|
||||
|
||||
cairo_move_to (cr, cx, cy);
|
||||
|
||||
for (i = 1; i < coordinates->len; i++)
|
||||
{
|
||||
coords = &(g_array_index (coordinates, GimpCoords, i));
|
||||
|
||||
cx = x + ROUND (coords->x / xscale) + 0.5;
|
||||
cy = y + ROUND (coords->y / yscale) + 0.5;
|
||||
|
||||
cairo_line_to (cr, cx, cy);
|
||||
}
|
||||
|
||||
cairo_stroke (cr);
|
||||
}
|
||||
|
||||
g_array_free (coordinates, TRUE);
|
||||
cairo_append_path (cr, (cairo_path_t *) bezdesc);
|
||||
cairo_stroke (cr);
|
||||
g_free (bezdesc->data);
|
||||
g_free (bezdesc);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue