GitLab repository storage has been migrated to hashed layout. Please contact Infrastructure team if you notice any issues with repositories or hooks.

Commit 6f3c1ae5 authored by Sven Neumann's avatar Sven Neumann Committed by Sven Neumann

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".
parent 5dd10c74
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 (&center,
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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment