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,10 +146,8 @@ 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;
if (GIMP_IS_BEZIER_STROKE (stroke))

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

@ -1,4 +1,4 @@
/* LIBGIMP - The GIMP Library
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* gimpmatrix.c
@ -33,7 +33,7 @@
/**
* gimp_matrix2_identity:
* @matrix: A matrix.
*
*
* Sets the matrix to the identity matrix.
*/
void
@ -49,11 +49,11 @@ gimp_matrix2_identity (GimpMatrix2 *matrix)
* gimp_matrix2_mult:
* @matrix1: The first input matrix.
* @matrix2: The second input matrix which will be overwritten by the result.
*
*
* Multiplies two matrices and puts the result into the second one.
*/
void
gimp_matrix2_mult (const GimpMatrix2 *matrix1,
gimp_matrix2_mult (const GimpMatrix2 *matrix1,
GimpMatrix2 *matrix2)
{
GimpMatrix2 tmp;
@ -73,7 +73,7 @@ gimp_matrix2_mult (const GimpMatrix2 *matrix1,
/**
* gimp_matrix3_identity:
* @matrix: A matrix.
*
*
* Sets the matrix to the identity matrix.
*/
void
@ -93,14 +93,14 @@ gimp_matrix3_identity (GimpMatrix3 *matrix)
* @y: The source Y coordinate.
* @newx: The transformed X coordinate.
* @newy: The transformed Y coordinate.
*
*
* Transforms a point in 2D as specified by the transformation matrix.
*/
void
gimp_matrix3_transform_point (const GimpMatrix3 *matrix,
gdouble x,
gimp_matrix3_transform_point (const GimpMatrix3 *matrix,
gdouble x,
gdouble y,
gdouble *newx,
gdouble *newx,
gdouble *newy)
{
gdouble w;
@ -124,11 +124,11 @@ gimp_matrix3_transform_point (const GimpMatrix3 *matrix,
* gimp_matrix3_mult:
* @matrix1: The first input matrix.
* @matrix2: The second input matrix which will be overwritten by the result.
*
*
* Multiplies two matrices and puts the result into the second one.
*/
void
gimp_matrix3_mult (const GimpMatrix3 *matrix1,
gimp_matrix3_mult (const GimpMatrix3 *matrix1,
GimpMatrix3 *matrix2)
{
gint i, j;
@ -157,12 +157,12 @@ gimp_matrix3_mult (const GimpMatrix3 *matrix1,
* @matrix: The matrix that is to be translated.
* @x: Translation in X direction.
* @y: Translation in Y direction.
*
*
* Translates the matrix by x and y.
*/
void
gimp_matrix3_translate (GimpMatrix3 *matrix,
gdouble x,
gimp_matrix3_translate (GimpMatrix3 *matrix,
gdouble x,
gdouble y)
{
gdouble g, h, i;
@ -184,12 +184,12 @@ gimp_matrix3_translate (GimpMatrix3 *matrix,
* @matrix: The matrix that is to be scaled.
* @x: X scale factor.
* @y: Y scale factor.
*
* Scales the matrix by x and y
*
* Scales the matrix by x and y
*/
void
gimp_matrix3_scale (GimpMatrix3 *matrix,
gdouble x,
gimp_matrix3_scale (GimpMatrix3 *matrix,
gdouble x,
gdouble y)
{
matrix->coeff[0][0] *= x;
@ -205,11 +205,11 @@ gimp_matrix3_scale (GimpMatrix3 *matrix,
* gimp_matrix3_rotate:
* @matrix: The matrix that is to be rotated.
* @theta: The angle of rotation (in radians).
*
*
* Rotates the matrix by theta degrees.
*/
void
gimp_matrix3_rotate (GimpMatrix3 *matrix,
gimp_matrix3_rotate (GimpMatrix3 *matrix,
gdouble theta)
{
gdouble t1, t2;
@ -217,7 +217,7 @@ gimp_matrix3_rotate (GimpMatrix3 *matrix,
cost = cos (theta);
sint = sin (theta);
t1 = matrix->coeff[0][0];
t2 = matrix->coeff[1][0];
matrix->coeff[0][0] = cost * t1 - sint * t2;
@ -238,11 +238,11 @@ gimp_matrix3_rotate (GimpMatrix3 *matrix,
* gimp_matrix3_xshear:
* @matrix: The matrix that is to be sheared.
* @amount: X shear amount.
*
*
* Shears the matrix in the X direction.
*/
void
gimp_matrix3_xshear (GimpMatrix3 *matrix,
gimp_matrix3_xshear (GimpMatrix3 *matrix,
gdouble amount)
{
matrix->coeff[0][0] += amount * matrix->coeff[1][0];
@ -254,11 +254,11 @@ gimp_matrix3_xshear (GimpMatrix3 *matrix,
* gimp_matrix3_yshear:
* @matrix: The matrix that is to be sheared.
* @amount: Y shear amount.
*
*
* Shears the matrix in the Y direction.
*/
void
gimp_matrix3_yshear (GimpMatrix3 *matrix,
gimp_matrix3_yshear (GimpMatrix3 *matrix,
gdouble amount)
{
matrix->coeff[1][0] += amount * matrix->coeff[0][0];
@ -266,12 +266,58 @@ 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.
*
* @matrix: The input matrix.
*
* Calculates the determinant of the given matrix.
*
*
* Returns: The determinant.
*/
gdouble
@ -295,7 +341,7 @@ gimp_matrix3_determinant (const GimpMatrix3 *matrix)
/**
* gimp_matrix3_invert:
* @matrix: The matrix that is to be inverted.
*
*
* Inverts the given matrix.
*/
void
@ -313,7 +359,7 @@ gimp_matrix3_invert (GimpMatrix3 *matrix)
inv.coeff[0][0] = (matrix->coeff[1][1] * matrix->coeff[2][2] -
matrix->coeff[1][2] * matrix->coeff[2][1]) * det;
inv.coeff[1][0] = - (matrix->coeff[1][0] * matrix->coeff[2][2] -
matrix->coeff[1][2] * matrix->coeff[2][0]) * det;
@ -328,13 +374,13 @@ gimp_matrix3_invert (GimpMatrix3 *matrix)
inv.coeff[2][1] = - (matrix->coeff[0][0] * matrix->coeff[2][1] -
matrix->coeff[0][1] * matrix->coeff[2][0]) * det;
inv.coeff[0][2] = (matrix->coeff[0][1] * matrix->coeff[1][2] -
matrix->coeff[0][2] * matrix->coeff[1][1]) * det;
inv.coeff[1][2] = - (matrix->coeff[0][0] * matrix->coeff[1][2] -
matrix->coeff[0][2] * matrix->coeff[1][0]) * det;
inv.coeff[2][2] = (matrix->coeff[0][0] * matrix->coeff[1][1] -
matrix->coeff[0][1] * matrix->coeff[1][0]) * det;
@ -348,9 +394,9 @@ gimp_matrix3_invert (GimpMatrix3 *matrix)
/**
* gimp_matrix3_is_diagonal:
* @matrix: The matrix that is to be tested.
*
*
* Checks if the given matrix is diagonal.
*
*
* Returns: TRUE if the matrix is diagonal.
*/
gboolean
@ -373,9 +419,9 @@ gimp_matrix3_is_diagonal (const GimpMatrix3 *matrix)
/**
* gimp_matrix3_is_identity:
* @matrix: The matrix that is to be tested.
*
*
* Checks if the given matrix is the identity matrix.
*
*
* Returns: TRUE if the matrix is the identity matrix.
*/
gboolean
@ -403,20 +449,20 @@ gimp_matrix3_is_identity (const GimpMatrix3 *matrix)
return TRUE;
}
/* Check if we'll need to interpolate when applying this matrix.
This function returns TRUE if all entries of the upper left
2x2 matrix are either 0 or 1
/* Check if we'll need to interpolate when applying this matrix.
This function returns TRUE if all entries of the upper left
2x2 matrix are either 0 or 1
*/
/**
* gimp_matrix3_is_simple:
* @matrix: The matrix that is to be tested.
*
*
* Checks if we'll need to interpolate when applying this matrix as
* a transformation.
*
* Returns: TRUE if all entries of the upper left 2x2 matrix are either
*
* Returns: TRUE if all entries of the upper left 2x2 matrix are either
* 0 or 1
*/
gboolean

View File

@ -44,29 +44,32 @@ struct _GimpMatrix4
void gimp_matrix2_identity (GimpMatrix2 *matrix);
void gimp_matrix2_mult (const GimpMatrix2 *matrix1,
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,
void gimp_matrix3_mult (const GimpMatrix3 *matrix1,
GimpMatrix3 *matrix2);
void gimp_matrix3_translate (GimpMatrix3 *matrix,
gdouble x,
void gimp_matrix3_translate (GimpMatrix3 *matrix,
gdouble x,
gdouble y);
void gimp_matrix3_scale (GimpMatrix3 *matrix,
gdouble x,
void gimp_matrix3_scale (GimpMatrix3 *matrix,
gdouble x,
gdouble y);
void gimp_matrix3_rotate (GimpMatrix3 *matrix,
void gimp_matrix3_rotate (GimpMatrix3 *matrix,
gdouble theta);
void gimp_matrix3_xshear (GimpMatrix3 *matrix,
void gimp_matrix3_xshear (GimpMatrix3 *matrix,
gdouble amount);
void gimp_matrix3_yshear (GimpMatrix3 *matrix,
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,