mirror of https://github.com/GNOME/gimp.git
added new function gimp_bezier_stroke_new_ellipse() that provides a simple
2004-08-21 Sven Neumann <sven@gimp.org> * app/vectors/gimpbezierstroke.[ch]: added new function gimp_bezier_stroke_new_ellipse() that provides a simple API to create a bezier stroke that represents an ellipse. * app/vectors/gimpvectors-import.c: added support for the basic SVG shapes "circle" and "ellipse".
This commit is contained in:
parent
5dd10c748d
commit
6f3c1ae503
|
@ -1,3 +1,12 @@
|
|||
2004-08-21 Sven Neumann <sven@gimp.org>
|
||||
|
||||
* app/vectors/gimpbezierstroke.[ch]: added new function
|
||||
gimp_bezier_stroke_new_ellipse() that provides a simple API to
|
||||
create a bezier stroke that represents an ellipse.
|
||||
|
||||
* app/vectors/gimpvectors-import.c: added support for the basic
|
||||
SVG shapes "circle" and "ellipse".
|
||||
|
||||
2004-08-21 Simon Budig <simon@gimp.org>
|
||||
|
||||
* plug-ins/common/gih.c: Fix some GUI issues. Make the relation
|
||||
|
|
|
@ -1583,20 +1583,20 @@ gimp_bezier_stroke_arcto (GimpStroke *bez_stroke,
|
|||
gboolean sweep,
|
||||
const GimpCoords *end)
|
||||
{
|
||||
GimpCoords start;
|
||||
GimpCoords middle; /* between start and end */
|
||||
GimpCoords trans_delta;
|
||||
GimpCoords trans_center;
|
||||
GimpCoords tmp_center;
|
||||
GimpCoords center;
|
||||
GimpCoords ellips[4]; /* control points of untransformed ellipse segment */
|
||||
GimpCoords ctrl[4]; /* control points of next bezier segment */
|
||||
GimpCoords start;
|
||||
GimpCoords middle; /* between start and end */
|
||||
GimpCoords trans_delta;
|
||||
GimpCoords trans_center;
|
||||
GimpCoords tmp_center;
|
||||
GimpCoords center;
|
||||
GimpCoords ellips[4]; /* control points of untransformed ellipse segment */
|
||||
GimpCoords ctrl[4]; /* control points of next bezier segment */
|
||||
|
||||
GimpMatrix3 anglerot;
|
||||
|
||||
gdouble lambda;
|
||||
gdouble phi0, phi1, phi2;
|
||||
gdouble tmpx, tmpy;
|
||||
gdouble lambda;
|
||||
gdouble phi1, phi2;
|
||||
gdouble tmpx, tmpy;
|
||||
|
||||
g_return_if_fail (GIMP_IS_BEZIER_STROKE (bez_stroke));
|
||||
g_return_if_fail (bez_stroke->closed == FALSE);
|
||||
|
@ -1615,13 +1615,14 @@ gimp_bezier_stroke_arcto (GimpStroke *bez_stroke,
|
|||
gimp_matrix3_rotate (&anglerot, -angle_rad);
|
||||
|
||||
gimp_coords_mix (0.5, &start, -0.5, end, &trans_delta);
|
||||
gimp_matrix3_transform_point (&anglerot, trans_delta.x, trans_delta.y,
|
||||
gimp_matrix3_transform_point (&anglerot,
|
||||
trans_delta.x, trans_delta.y,
|
||||
&tmpx, &tmpy);
|
||||
trans_delta.x = tmpx;
|
||||
trans_delta.y = tmpy;
|
||||
|
||||
lambda = (trans_delta.x*trans_delta.x / radius_x / radius_x +
|
||||
trans_delta.y*trans_delta.y / radius_y / radius_y);
|
||||
lambda = (SQR (trans_delta.x) / SQR (radius_x) +
|
||||
SQR (trans_delta.y) / SQR (radius_y));
|
||||
|
||||
if (lambda < 0.00001)
|
||||
{
|
||||
|
@ -1634,7 +1635,7 @@ gimp_bezier_stroke_arcto (GimpStroke *bez_stroke,
|
|||
if (lambda > 1.0)
|
||||
{
|
||||
/* The radii are too small for a matching ellipse. We expand them
|
||||
* so that they fit exacty (center of the ellipse between the
|
||||
* so that they fit exactly (center of the ellipse between the
|
||||
* start- and endpoint
|
||||
*/
|
||||
radius_x *= sqrt (lambda);
|
||||
|
@ -1645,6 +1646,7 @@ gimp_bezier_stroke_arcto (GimpStroke *bez_stroke,
|
|||
else
|
||||
{
|
||||
gdouble factor = sqrt ((1.0 - lambda) / lambda);
|
||||
|
||||
trans_center.x = trans_delta.y * radius_x / radius_y * factor;
|
||||
trans_center.y = - trans_delta.x * radius_y / radius_x * factor;
|
||||
}
|
||||
|
@ -1659,7 +1661,8 @@ gimp_bezier_stroke_arcto (GimpStroke *bez_stroke,
|
|||
gimp_matrix3_rotate (&anglerot, angle_rad);
|
||||
|
||||
tmp_center = trans_center;
|
||||
gimp_matrix3_transform_point (&anglerot, tmp_center.x, tmp_center.y,
|
||||
gimp_matrix3_transform_point (&anglerot,
|
||||
tmp_center.x, tmp_center.y,
|
||||
&tmpx, &tmpy);
|
||||
tmp_center.x = tmpx;
|
||||
tmp_center.y = tmpy;
|
||||
|
@ -1673,14 +1676,17 @@ gimp_bezier_stroke_arcto (GimpStroke *bez_stroke,
|
|||
phi2 = atan2 ((- trans_delta.y - trans_center.y) / radius_y,
|
||||
(- trans_delta.x - trans_center.x) / radius_x);
|
||||
|
||||
if (phi1 < 0) phi1 += 2 * G_PI;
|
||||
if (phi2 < 0) phi2 += 2 * G_PI;
|
||||
if (phi1 < 0)
|
||||
phi1 += 2 * G_PI;
|
||||
if (phi2 < 0)
|
||||
phi2 += 2 * G_PI;
|
||||
|
||||
while (phi1 < phi2)
|
||||
phi1 += 2 * G_PI;
|
||||
|
||||
if (sweep)
|
||||
{
|
||||
while (phi2 < phi1) phi2 += 2 * G_PI;
|
||||
|
||||
phi0 = floor (phi1 / G_PI_2) * G_PI_2;
|
||||
gdouble phi0 = floor (phi1 / G_PI_2) * G_PI_2;
|
||||
|
||||
while (phi0 < phi2)
|
||||
{
|
||||
|
@ -1712,9 +1718,7 @@ gimp_bezier_stroke_arcto (GimpStroke *bez_stroke,
|
|||
}
|
||||
else
|
||||
{
|
||||
while (phi1 < phi2) phi1 += 2 * G_PI;
|
||||
|
||||
phi0 = ceil (phi1 / G_PI_2) * G_PI_2;
|
||||
gdouble phi0 = ceil (phi1 / G_PI_2) * G_PI_2;
|
||||
|
||||
while (phi0 > phi2)
|
||||
{
|
||||
|
@ -1746,6 +1750,34 @@ gimp_bezier_stroke_arcto (GimpStroke *bez_stroke,
|
|||
}
|
||||
}
|
||||
|
||||
GimpStroke *
|
||||
gimp_bezier_stroke_new_ellipse (const GimpCoords *center,
|
||||
gdouble radius_x,
|
||||
gdouble radius_y)
|
||||
{
|
||||
GimpStroke *stroke;
|
||||
GimpCoords a = *center;
|
||||
GimpCoords b = *center;
|
||||
|
||||
if (radius_x > radius_y)
|
||||
{
|
||||
a.x -= radius_x;
|
||||
b.x += radius_x;
|
||||
}
|
||||
else
|
||||
{
|
||||
a.y -= radius_y;
|
||||
b.y += radius_y;
|
||||
}
|
||||
|
||||
stroke = gimp_bezier_stroke_new_moveto (&a);
|
||||
|
||||
gimp_bezier_stroke_arcto (stroke, radius_x, radius_y, 0, TRUE, FALSE, &b);
|
||||
gimp_bezier_stroke_arcto (stroke, radius_x, radius_y, 0, TRUE, FALSE, &a);
|
||||
|
||||
return stroke;
|
||||
}
|
||||
|
||||
|
||||
/* helper function to get the associated anchor of a listitem */
|
||||
|
||||
|
@ -1765,6 +1797,7 @@ gimp_bezier_stroke_get_anchor_listitem (GList *list)
|
|||
return list->next;
|
||||
|
||||
g_return_val_if_fail (/* bezier stroke inconsistent! */ FALSE, NULL);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -66,12 +66,16 @@ void gimp_bezier_stroke_cubicto (GimpStroke *bez_stroke,
|
|||
const GimpCoords *control2,
|
||||
const GimpCoords *end);
|
||||
void gimp_bezier_stroke_arcto (GimpStroke *bez_stroke,
|
||||
const gdouble radius_x,
|
||||
const gdouble radius_y,
|
||||
const gdouble angle_rad,
|
||||
const gboolean large_arc,
|
||||
const gboolean sweep,
|
||||
gdouble radius_x,
|
||||
gdouble radius_y,
|
||||
gdouble angle_rad,
|
||||
gboolean large_arc,
|
||||
gboolean sweep,
|
||||
const GimpCoords *end);
|
||||
GimpStroke * gimp_bezier_stroke_new_ellipse (const GimpCoords *center,
|
||||
gdouble radius_x,
|
||||
gdouble radius_y);
|
||||
|
||||
|
||||
GimpAnchor * gimp_bezier_stroke_extend (GimpStroke *stroke,
|
||||
const GimpCoords *coords,
|
||||
|
|
|
@ -117,37 +117,43 @@ static const GMarkupParser markup_parser =
|
|||
};
|
||||
|
||||
|
||||
static void svg_handler_svg_start (SvgHandler *handler,
|
||||
const gchar **names,
|
||||
const gchar **values,
|
||||
SvgParser *parser);
|
||||
static void svg_handler_svg_end (SvgHandler *handler,
|
||||
SvgParser *parser);
|
||||
static void svg_handler_group_start (SvgHandler *handler,
|
||||
const gchar **names,
|
||||
const gchar **values,
|
||||
SvgParser *parser);
|
||||
static void svg_handler_path_start (SvgHandler *handler,
|
||||
const gchar **names,
|
||||
const gchar **values,
|
||||
SvgParser *parser);
|
||||
static void svg_handler_line_start (SvgHandler *handler,
|
||||
const gchar **names,
|
||||
const gchar **values,
|
||||
SvgParser *parser);
|
||||
static void svg_handler_poly_start (SvgHandler *handler,
|
||||
const gchar **names,
|
||||
const gchar **values,
|
||||
SvgParser *parser);
|
||||
static void svg_handler_svg_start (SvgHandler *handler,
|
||||
const gchar **names,
|
||||
const gchar **values,
|
||||
SvgParser *parser);
|
||||
static void svg_handler_svg_end (SvgHandler *handler,
|
||||
SvgParser *parser);
|
||||
static void svg_handler_group_start (SvgHandler *handler,
|
||||
const gchar **names,
|
||||
const gchar **values,
|
||||
SvgParser *parser);
|
||||
static void svg_handler_path_start (SvgHandler *handler,
|
||||
const gchar **names,
|
||||
const gchar **values,
|
||||
SvgParser *parser);
|
||||
static void svg_handler_ellipse_start (SvgHandler *handler,
|
||||
const gchar **names,
|
||||
const gchar **values,
|
||||
SvgParser *parser);
|
||||
static void svg_handler_line_start (SvgHandler *handler,
|
||||
const gchar **names,
|
||||
const gchar **values,
|
||||
SvgParser *parser);
|
||||
static void svg_handler_poly_start (SvgHandler *handler,
|
||||
const gchar **names,
|
||||
const gchar **values,
|
||||
SvgParser *parser);
|
||||
|
||||
static const SvgHandler svg_handlers[] =
|
||||
{
|
||||
{ "svg", svg_handler_svg_start, svg_handler_svg_end },
|
||||
{ "g", svg_handler_group_start, NULL },
|
||||
{ "path", svg_handler_path_start, NULL },
|
||||
{ "line", svg_handler_line_start, NULL },
|
||||
{ "polyline", svg_handler_poly_start, NULL },
|
||||
{ "polygon", svg_handler_poly_start, NULL }
|
||||
{ "svg", svg_handler_svg_start, svg_handler_svg_end },
|
||||
{ "g", svg_handler_group_start, NULL },
|
||||
{ "path", svg_handler_path_start, NULL },
|
||||
{ "circle", svg_handler_ellipse_start, NULL },
|
||||
{ "ellipse", svg_handler_ellipse_start, NULL },
|
||||
{ "line", svg_handler_line_start, NULL },
|
||||
{ "polyline", svg_handler_poly_start, NULL },
|
||||
{ "polygon", svg_handler_poly_start, NULL }
|
||||
};
|
||||
|
||||
|
||||
|
@ -586,6 +592,63 @@ svg_handler_path_start (SvgHandler *handler,
|
|||
handler->paths = g_list_prepend (handler->paths, path);
|
||||
}
|
||||
|
||||
static void
|
||||
svg_handler_ellipse_start (SvgHandler *handler,
|
||||
const gchar **names,
|
||||
const gchar **values,
|
||||
SvgParser *parser)
|
||||
{
|
||||
SvgPath *path = g_new0 (SvgPath, 1);
|
||||
GimpCoords center = { 0.0, 0.0, 1.0, 0.5, 0.5, 0.5 };
|
||||
gdouble rx = 0.0;
|
||||
gdouble ry = 0.0;
|
||||
|
||||
while (*names)
|
||||
{
|
||||
if (strcmp (*names, "id") == 0 && !path->id)
|
||||
{
|
||||
path->id = g_strdup (*values);
|
||||
}
|
||||
else if (strcmp (*names, "cx") == 0)
|
||||
{
|
||||
center.x = g_ascii_strtod (*values, NULL);
|
||||
}
|
||||
else if (strcmp (*names, "cy") == 0)
|
||||
{
|
||||
center.y = g_ascii_strtod (*values, NULL);
|
||||
}
|
||||
else if (strcmp (*names, "r") == 0)
|
||||
{
|
||||
rx = ry = g_ascii_strtod (*values, NULL);
|
||||
}
|
||||
else if (strcmp (*names, "rx") == 0)
|
||||
{
|
||||
rx = g_ascii_strtod (*values, NULL);
|
||||
}
|
||||
else if (strcmp (*names, "ry") == 0)
|
||||
{
|
||||
ry = g_ascii_strtod (*values, NULL);
|
||||
}
|
||||
else if (strcmp (*names, "transform") == 0 && !handler->transform)
|
||||
{
|
||||
GimpMatrix3 matrix;
|
||||
|
||||
if (parse_svg_transform (*values, &matrix))
|
||||
handler->transform = g_memdup (&matrix, sizeof (GimpMatrix3));
|
||||
}
|
||||
|
||||
names++;
|
||||
values++;
|
||||
}
|
||||
|
||||
if (rx >= 0.0 && ry >= 0.0)
|
||||
path->strokes = g_list_prepend (path->strokes,
|
||||
gimp_bezier_stroke_new_ellipse (¢er,
|
||||
rx, ry));
|
||||
|
||||
handler->paths = g_list_prepend (handler->paths, path);
|
||||
}
|
||||
|
||||
static void
|
||||
svg_handler_line_start (SvgHandler *handler,
|
||||
const gchar **names,
|
||||
|
@ -684,7 +747,7 @@ svg_handler_poly_start (SvgHandler *handler,
|
|||
|
||||
if ((n > 3) && (n % 2 == 0))
|
||||
{
|
||||
points = g_string_sized_new (p - *values + 6);
|
||||
points = g_string_sized_new (p - *values + 8);
|
||||
|
||||
g_string_append_len (points, "M ", 2);
|
||||
g_string_append_len (points, m, l - m);
|
||||
|
@ -868,7 +931,7 @@ parse_svg_viewbox (const gchar *value,
|
|||
return success;
|
||||
}
|
||||
|
||||
gboolean
|
||||
static gboolean
|
||||
parse_svg_transform (const gchar *value,
|
||||
GimpMatrix3 *matrix)
|
||||
{
|
||||
|
@ -880,7 +943,7 @@ parse_svg_transform (const gchar *value,
|
|||
|
||||
gimp_matrix3_identity (matrix);
|
||||
|
||||
for (i= 0; value[i]; i++)
|
||||
for (i = 0; value[i]; i++)
|
||||
{
|
||||
/* skip initial whitespace */
|
||||
while (g_ascii_isspace (value[i]))
|
||||
|
@ -918,10 +981,11 @@ parse_svg_transform (const gchar *value,
|
|||
/* skip whitespace */
|
||||
while (g_ascii_isspace (value[i]))
|
||||
i++;
|
||||
|
||||
c = value[i];
|
||||
if (g_ascii_isdigit (c) || c == '+' || c == '-' || c == '.')
|
||||
{
|
||||
if (n_args == G_N_ELEMENTS(args))
|
||||
if (n_args == G_N_ELEMENTS (args))
|
||||
return FALSE; /* too many args */
|
||||
|
||||
args[n_args] = g_ascii_strtod (value + i, &end_ptr);
|
||||
|
|
Loading…
Reference in New Issue