added gimp_matrix3_affine().

2003-09-12  Sven Neumann  <sven@gimp.org>

	* libgimpmath/gimpmatrix.[ch]: added gimp_matrix3_affine().

	* app/vectors/gimpvectors-import.c: added (yet unused) funtion to
	parse SVG transform attributes.

	* app/vectors/gimpvectors-export.c: fixed a stupid bug.
This commit is contained in:
Sven Neumann
2003-09-12 13:23:01 +00:00
committed by Sven Neumann
parent 9c13b724d4
commit 7dd98d215c
8 changed files with 336 additions and 129 deletions

View File

@ -1,3 +1,12 @@
2003-09-12 Sven Neumann <sven@gimp.org>
* libgimpmath/gimpmatrix.[ch]: added gimp_matrix3_affine().
* app/vectors/gimpvectors-import.c: added (yet unused) funtion to
parse SVG transform attributes.
* app/vectors/gimpvectors-export.c: fixed a stupid bug.
2003-09-12 Michael Natterer <mitch@gimp.org>
* app/core/gimpimage-mask-select.c (gimp_image_mask_select_vectors)

View File

@ -61,7 +61,6 @@ gimp_vectors_export (const GimpImage *image,
GError **error)
{
FILE *file;
gchar *data;
g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
g_return_val_if_fail (vectors == NULL || GIMP_IS_VECTORS (vectors), FALSE);
@ -109,8 +108,6 @@ gimp_vectors_export (const GimpImage *image,
return FALSE;
}
g_free (data);
return TRUE;
}
@ -149,9 +146,7 @@ gimp_vectors_path_data (const GimpVectors *vectors)
control_points = gimp_stroke_control_points_get (stroke, &closed);
if (! first_stroke)
{
g_string_append_printf (str, "\n ");
}
g_string_append_printf (str, "\n ");
first_stroke = FALSE;

View File

@ -84,12 +84,14 @@ static void parser_end_element (GMarkupParseContext *context,
static void parser_start_unknown (VectorsParser *parser);
static void parser_end_unknown (VectorsParser *parser);
static void parse_svg_viewbox (VectorsParser *parser,
const gchar *value);
static void parse_path_data (GimpVectors *vectors,
const gchar *data);
static void parser_add_vectors (VectorsParser *parser,
GimpVectors *vectors);
static gboolean parse_svg_viewbox (const gchar *value,
Rectangle *rect);
static gboolean parse_svg_transform (const gchar *value,
GimpMatrix3 *matrix);
static void parse_path_data (GimpVectors *vectors,
const gchar *data);
static void parser_add_vectors (VectorsParser *parser,
GimpVectors *vectors);
static const GMarkupParser markup_parser =
@ -202,7 +204,12 @@ parser_start_element (GMarkupParseContext *context,
while (*attribute_names)
{
if (strcmp (*attribute_names, "viewBox") == 0)
parse_svg_viewbox (parser, *attribute_values);
{
Rectangle rect;
if (parse_svg_viewbox (*attribute_values, &rect))
parser->viewbox = rect;
}
attribute_names++;
attribute_values++;
@ -318,6 +325,173 @@ parser_add_vectors (VectorsParser *parser,
}
static gboolean
parse_svg_viewbox (const gchar *value,
Rectangle *rect)
{
gchar *tok;
gchar *str = g_strdup (value);
gboolean success = FALSE;
tok = strtok (str, ", \t");
if (tok)
{
rect->x = g_ascii_strtod (tok, NULL);
tok = strtok (NULL, ", \t");
if (tok)
{
rect->y = g_ascii_strtod (tok, NULL);
tok = strtok (NULL, ", \t");
if (tok != NULL)
{
rect->w = g_ascii_strtod (tok, NULL);
tok = strtok (NULL, ", \t");
if (tok)
{
rect->h = g_ascii_strtod (tok, NULL);
success = TRUE;
}
}
}
}
g_free (str);
return success;
}
gboolean
parse_svg_transform (const gchar *value,
GimpMatrix3 *matrix)
{
gint i;
gchar keyword[32];
gdouble args[6];
gint n_args;
gint key_len;
gimp_matrix3_identity (matrix);
for (i= 0; value[i]; i++)
{
/* skip initial whitespace */
while (g_ascii_isspace (value[i]))
i++;
/* parse keyword */
for (key_len = 0; key_len < sizeof (keyword); key_len++)
{
gchar c = value[i];
if (g_ascii_isalpha (c) || c == '-')
keyword[key_len] = value[i++];
else
break;
}
if (key_len >= sizeof (keyword))
return FALSE;
keyword[key_len] = '\0';
/* skip whitespace */
while (g_ascii_isspace (value[i]))
i++;
if (value[i] != '(')
return FALSE;
i++;
for (n_args = 0; ; n_args++)
{
gchar c;
gchar *end_ptr;
/* 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))
return FALSE; /* too many args */
args[n_args] = g_ascii_strtod (value + i, &end_ptr);
i = end_ptr - value;
while (g_ascii_isspace (value[i]))
i++;
/* skip optional comma */
if (value[i] == ',')
i++;
}
else if (c == ')')
break;
else
return FALSE;
}
/* ok, have parsed keyword and args, now modify the transform */
if (!strcmp (keyword, "matrix"))
{
if (n_args != 6)
return FALSE;
gimp_matrix3_affine (matrix,
args[0], args[1],
args[2], args[3],
args[4], args[5]);
}
else if (!strcmp (keyword, "translate"))
{
if (n_args == 1)
args[1] = 0.0;
else if (n_args != 2)
return FALSE;
gimp_matrix3_translate (matrix, args[0], args[1]);
}
else if (!strcmp (keyword, "scale"))
{
if (n_args == 1)
args[1] = args[0];
else if (n_args != 2)
return FALSE;
gimp_matrix3_scale (matrix, args[0], args[1]);
}
else if (!strcmp (keyword, "rotate"))
{
if (n_args != 1)
return FALSE;
gimp_matrix3_rotate (matrix, gimp_deg_to_rad (args[0]));
}
else if (!strcmp (keyword, "skewX"))
{
if (n_args != 1)
return FALSE;
gimp_matrix3_xshear (matrix, tan (gimp_deg_to_rad (args[0])));
}
else if (!strcmp (keyword, "skewY"))
{
if (n_args != 1)
return FALSE;
gimp_matrix3_yshear (matrix, tan (gimp_deg_to_rad (args[0])));
}
else
{
return FALSE; /* unknown keyword */
}
}
return TRUE;
}
/**********************************************************/
/* Below is the code that parses the actual path data. */
/* */
@ -344,50 +518,6 @@ static void parse_path_do_cmd (ParsePathContext *ctx,
gboolean final);
static void
parse_svg_viewbox (VectorsParser *parser,
const gchar *value)
{
gint x, y, w, h;
gchar *tok;
gchar *str = g_strdup (value);
gboolean success = FALSE;
x = y = w = h = 0;
tok = strtok (str, ", \t");
if (tok)
{
x = g_ascii_strtod (tok, NULL);
tok = strtok (NULL, ", \t");
if (tok)
{
y = g_ascii_strtod (tok, NULL);
tok = strtok (NULL, ", \t");
if (tok != NULL)
{
w = g_ascii_strtod (tok, NULL);
tok = strtok (NULL, ", \t");
if (tok)
{
h = g_ascii_strtod (tok, NULL);
success = TRUE;
}
}
}
}
g_free (str);
if (success)
{
parser->viewbox.x = x;
parser->viewbox.y = y;
parser->viewbox.w = w;
parser->viewbox.h = h;
}
}
static void
parse_path_data (GimpVectors *vectors,
const gchar *data)
@ -553,7 +683,6 @@ parse_path_data (GimpVectors *vectors,
}
}
/* supply defaults for missing parameters, assuming relative coordinates
are to be interpreted as x,y */
static void

View File

@ -1,3 +1,8 @@
2003-09-12 Sven Neumann <sven@gimp.org>
* libgimpmath/libgimpmath-sections.txt
* libgimpmath/tmpl/gimpmatrix.sgml: updated for new function.
2003-09-11 Sven Neumann <sven@gimp.org>
* libgimpwidgets/libgimpwidgets-sections.txt

View File

@ -25,13 +25,14 @@ GimpMatrix4
gimp_matrix2_identity
gimp_matrix2_mult
gimp_matrix3_identity
gimp_matrix3_transform_point
gimp_matrix3_mult
gimp_matrix3_translate
gimp_matrix3_scale
gimp_matrix3_rotate
gimp_matrix3_xshear
gimp_matrix3_yshear
gimp_matrix3_affine
gimp_matrix3_transform_point
gimp_matrix3_determinant
gimp_matrix3_invert
gimp_matrix3_is_diagonal

View File

@ -70,18 +70,6 @@ basic matrix manipulations and tests.
@matrix:
<!-- ##### FUNCTION gimp_matrix3_transform_point ##### -->
<para>
</para>
@matrix:
@x:
@y:
@newx:
@newy:
<!-- ##### FUNCTION gimp_matrix3_mult ##### -->
<para>
@ -138,6 +126,32 @@ basic matrix manipulations and tests.
@amount:
<!-- ##### FUNCTION gimp_matrix3_affine ##### -->
<para>
</para>
@matrix:
@a:
@b:
@c:
@d:
@e:
@f:
<!-- ##### FUNCTION gimp_matrix3_transform_point ##### -->
<para>
</para>
@matrix:
@x:
@y:
@newx:
@newy:
<!-- ##### FUNCTION gimp_matrix3_determinant ##### -->
<para>

View File

@ -266,6 +266,52 @@ gimp_matrix3_yshear (GimpMatrix3 *matrix,
matrix->coeff[1][2] += amount * matrix->coeff[0][2];
}
/**
* gimp_matrix3_affine:
* @matrix: The input matrix.
* @a:
* @b:
* @c:
* @d:
* @e:
* @f:
*
* Applies the affine transformation given by six values to @matrix.
* The six values form define an affine transformation matrix as
* illustrated below:
*
* ( a c e )
* ( b d f )
* ( 0 0 1 )
**/
void
gimp_matrix3_affine (GimpMatrix3 *matrix,
gdouble a,
gdouble b,
gdouble c,
gdouble d,
gdouble e,
gdouble f)
{
GimpMatrix3 affine;
affine.coeff[0][0] = a;
affine.coeff[1][0] = b;
affine.coeff[2][0] = 0.0;
affine.coeff[0][1] = c;
affine.coeff[1][1] = d;
affine.coeff[2][1] = 0.0;
affine.coeff[0][2] = e;
affine.coeff[1][2] = f;
affine.coeff[2][2] = 1.0;
gimp_matrix3_mult (&affine, matrix);
}
/**
* gimp_matrix3_determinant:
* @matrix: The input matrix.

View File

@ -48,11 +48,6 @@ void gimp_matrix2_mult (const GimpMatrix2 *matrix1,
GimpMatrix2 *matrix2);
void gimp_matrix3_identity (GimpMatrix3 *matrix);
void gimp_matrix3_transform_point (const GimpMatrix3 *matrix,
gdouble x,
gdouble y,
gdouble *newx,
gdouble *newy);
void gimp_matrix3_mult (const GimpMatrix3 *matrix1,
GimpMatrix3 *matrix2);
void gimp_matrix3_translate (GimpMatrix3 *matrix,
@ -67,6 +62,14 @@ void gimp_matrix3_xshear (GimpMatrix3 *matrix,
gdouble amount);
void gimp_matrix3_yshear (GimpMatrix3 *matrix,
gdouble amount);
void gimp_matrix3_affine (GimpMatrix3 *matrix,
gdouble a,
gdouble b,
gdouble c,
gdouble d,
gdouble e,
gdouble f);
gdouble gimp_matrix3_determinant (const GimpMatrix3 *matrix);
void gimp_matrix3_invert (GimpMatrix3 *matrix);
@ -74,6 +77,11 @@ gboolean gimp_matrix3_is_diagonal (const GimpMatrix3 *matrix);
gboolean gimp_matrix3_is_identity (const GimpMatrix3 *matrix);
gboolean gimp_matrix3_is_simple (const GimpMatrix3 *matrix);
void gimp_matrix3_transform_point (const GimpMatrix3 *matrix,
gdouble x,
gdouble y,
gdouble *newx,
gdouble *newy);
void gimp_matrix4_to_deg (const GimpMatrix4 *matrix,
gdouble *a,