Blame src/gd_matrix.c

Packit Service df60bb
#ifdef HAVE_CONFIG_H
Packit Service df60bb
#include "config.h"
Packit Service df60bb
#endif /* HAVE_CONFIG_H */
Packit Service df60bb
Packit Service df60bb
#include "gd.h"
Packit Service df60bb
#include <math.h>
Packit Service df60bb
Packit Service df60bb
#ifndef M_PI
Packit Service df60bb
# define M_PI 3.14159265358979323846
Packit Service df60bb
#endif
Packit Service df60bb
Packit Service df60bb
/**
Packit Service df60bb
 * Title: Matrix
Packit Service df60bb
 * Group: Affine Matrix
Packit Service df60bb
 */
Packit Service df60bb
Packit Service df60bb
/**
Packit Service df60bb
 * Function: gdAffineApplyToPointF
Packit Service df60bb
 *  Applies an affine transformation to a point (floating point
Packit Service df60bb
 *  gdPointF)
Packit Service df60bb
 *
Packit Service df60bb
 *
Packit Service df60bb
 * Parameters:
Packit Service df60bb
 * 	dst - Where to store the resulting point
Packit Service df60bb
 *  affine - Source Point
Packit Service df60bb
 *  flip_horz - affine matrix
Packit Service df60bb
 *
Packit Service df60bb
 * Returns:
Packit Service df60bb
 *  GD_TRUE if the affine is rectilinear or GD_FALSE
Packit Service df60bb
 */
Packit Service df60bb
BGD_DECLARE(int) gdAffineApplyToPointF (gdPointFPtr dst, const gdPointFPtr src,
Packit Service df60bb
		  const double affine[6])
Packit Service df60bb
{
Packit Service df60bb
	double x = src->x;
Packit Service df60bb
	double y = src->y;
Packit Service df60bb
	dst->x = x * affine[0] + y * affine[2] + affine[4];
Packit Service df60bb
	dst->y = x * affine[1] + y * affine[3] + affine[5];
Packit Service df60bb
	return GD_TRUE;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
/**
Packit Service df60bb
 * Function: gdAffineInvert
Packit Service df60bb
 *  Find the inverse of an affine transformation.
Packit Service df60bb
 *
Packit Service df60bb
 * All non-degenerate affine transforms are invertible. Applying the
Packit Service df60bb
 * inverted matrix will restore the original values. Multiplying <src>
Packit Service df60bb
 * by <dst> (commutative) will return the identity affine (rounding
Packit Service df60bb
 * error possible).
Packit Service df60bb
 *
Packit Service df60bb
 * Parameters:
Packit Service df60bb
 * 	dst - Where to store the resulting affine transform
Packit Service df60bb
 *  src_affine - Original affine matrix
Packit Service df60bb
 *  flip_horz - Whether or not to flip horizontally
Packit Service df60bb
 *  flip_vert - Whether or not to flip vertically
Packit Service df60bb
 *
Packit Service df60bb
 * See also:
Packit Service df60bb
 *  <gdAffineIdentity>
Packit Service df60bb
 *
Packit Service df60bb
 * Returns:
Packit Service df60bb
 *  GD_TRUE if the affine is rectilinear or GD_FALSE
Packit Service df60bb
 */
Packit Service df60bb
BGD_DECLARE(int) gdAffineInvert (double dst[6], const double src[6])
Packit Service df60bb
{
Packit Service df60bb
	double r_det = (src[0] * src[3] - src[1] * src[2]);
Packit Service df60bb
Packit Service df60bb
	if (r_det <= 0.0) {
Packit Service df60bb
		return GD_FALSE;
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	r_det = 1.0 / r_det;
Packit Service df60bb
	dst[0] = src[3] * r_det;
Packit Service df60bb
	dst[1] = -src[1] * r_det;
Packit Service df60bb
	dst[2] = -src[2] * r_det;
Packit Service df60bb
	dst[3] = src[0] * r_det;
Packit Service df60bb
	dst[4] = -src[4] * dst[0] - src[5] * dst[2];
Packit Service df60bb
	dst[5] = -src[4] * dst[1] - src[5] * dst[3];
Packit Service df60bb
	return GD_TRUE;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
/**
Packit Service df60bb
 * Function: gdAffineFlip
Packit Service df60bb
 *  Flip an affine transformation horizontally or vertically.
Packit Service df60bb
 *
Packit Service df60bb
 * Flips the affine transform, giving GD_FALSE for <flip_horz> and
Packit Service df60bb
 * <flip_vert> will clone the affine matrix. GD_TRUE for both will
Packit Service df60bb
 * copy a 180° rotation.
Packit Service df60bb
 *
Packit Service df60bb
 * Parameters:
Packit Service df60bb
 * 	dst - Where to store the resulting affine transform
Packit Service df60bb
 *  src_affine - Original affine matrix
Packit Service df60bb
 *  flip_h - Whether or not to flip horizontally
Packit Service df60bb
 *  flip_v - Whether or not to flip vertically
Packit Service df60bb
 *
Packit Service df60bb
 * Returns:
Packit Service df60bb
 *  GD_TRUE on success or GD_FALSE
Packit Service df60bb
 */
Packit Service df60bb
BGD_DECLARE(int) gdAffineFlip (double dst[6], const double src[6], const int flip_h, const int flip_v)
Packit Service df60bb
{
Packit Service df60bb
	dst[0] = flip_h ? - src[0] : src[0];
Packit Service df60bb
	dst[1] = flip_h ? - src[1] : src[1];
Packit Service df60bb
	dst[2] = flip_v ? - src[2] : src[2];
Packit Service df60bb
	dst[3] = flip_v ? - src[3] : src[3];
Packit Service df60bb
	dst[4] = flip_h ? - src[4] : src[4];
Packit Service df60bb
	dst[5] = flip_v ? - src[5] : src[5];
Packit Service df60bb
	return GD_TRUE;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
/**
Packit Service df60bb
 * Function: gdAffineConcat
Packit Service df60bb
 * Concat (Multiply) two affine transformation matrices.
Packit Service df60bb
 *
Packit Service df60bb
 * Concats two affine transforms together, i.e. the result
Packit Service df60bb
 * will be the equivalent of doing first the transformation m1 and then
Packit Service df60bb
 * m2. All parameters can be the same matrix (safe to call using
Packit Service df60bb
 * the same array for all three arguments).
Packit Service df60bb
 *
Packit Service df60bb
 * Parameters:
Packit Service df60bb
 * 	dst - Where to store the resulting affine transform
Packit Service df60bb
 *  m1 - First affine matrix
Packit Service df60bb
 *  m2 - Second affine matrix
Packit Service df60bb
 *
Packit Service df60bb
 * Returns:
Packit Service df60bb
 *  GD_TRUE on success or GD_FALSE
Packit Service df60bb
 */
Packit Service df60bb
BGD_DECLARE(int) gdAffineConcat (double dst[6], const double m1[6], const double m2[6])
Packit Service df60bb
{
Packit Service df60bb
	double dst0, dst1, dst2, dst3, dst4, dst5;
Packit Service df60bb
Packit Service df60bb
	dst0 = m1[0] * m2[0] + m1[1] * m2[2];
Packit Service df60bb
	dst1 = m1[0] * m2[1] + m1[1] * m2[3];
Packit Service df60bb
	dst2 = m1[2] * m2[0] + m1[3] * m2[2];
Packit Service df60bb
	dst3 = m1[2] * m2[1] + m1[3] * m2[3];
Packit Service df60bb
	dst4 = m1[4] * m2[0] + m1[5] * m2[2] + m2[4];
Packit Service df60bb
	dst5 = m1[4] * m2[1] + m1[5] * m2[3] + m2[5];
Packit Service df60bb
	dst[0] = dst0;
Packit Service df60bb
	dst[1] = dst1;
Packit Service df60bb
	dst[2] = dst2;
Packit Service df60bb
	dst[3] = dst3;
Packit Service df60bb
	dst[4] = dst4;
Packit Service df60bb
	dst[5] = dst5;
Packit Service df60bb
	return GD_TRUE;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
/**
Packit Service df60bb
 * Function: gdAffineIdentity
Packit Service df60bb
 * Set up the identity matrix.
Packit Service df60bb
 *
Packit Service df60bb
 * Parameters:
Packit Service df60bb
 * 	dst - Where to store the resulting affine transform
Packit Service df60bb
 *
Packit Service df60bb
 * Returns:
Packit Service df60bb
 *  GD_TRUE on success or GD_FALSE
Packit Service df60bb
 */
Packit Service df60bb
BGD_DECLARE(int) gdAffineIdentity (double dst[6])
Packit Service df60bb
{
Packit Service df60bb
	dst[0] = 1;
Packit Service df60bb
	dst[1] = 0;
Packit Service df60bb
	dst[2] = 0;
Packit Service df60bb
	dst[3] = 1;
Packit Service df60bb
	dst[4] = 0;
Packit Service df60bb
	dst[5] = 0;
Packit Service df60bb
	return GD_TRUE;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
/**
Packit Service df60bb
 * Function: gdAffineScale
Packit Service df60bb
 * Set up a scaling matrix.
Packit Service df60bb
 *
Packit Service df60bb
 * Parameters:
Packit Service df60bb
 * 	scale_x - X scale factor
Packit Service df60bb
 * 	scale_y - Y scale factor
Packit Service df60bb
 *
Packit Service df60bb
 * Returns:
Packit Service df60bb
 *  GD_TRUE on success or GD_FALSE
Packit Service df60bb
 */
Packit Service df60bb
BGD_DECLARE(int) gdAffineScale (double dst[6], const double scale_x, const double scale_y)
Packit Service df60bb
{
Packit Service df60bb
	dst[0] = scale_x;
Packit Service df60bb
	dst[1] = 0;
Packit Service df60bb
	dst[2] = 0;
Packit Service df60bb
	dst[3] = scale_y;
Packit Service df60bb
	dst[4] = 0;
Packit Service df60bb
	dst[5] = 0;
Packit Service df60bb
	return GD_TRUE;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
/**
Packit Service df60bb
 * Function: gdAffineRotate
Packit Service df60bb
 * Set up a rotation affine transform.
Packit Service df60bb
 *
Packit Service df60bb
 * Like the other angle in libGD, in which increasing y moves
Packit Service df60bb
 * downward, this is a counterclockwise rotation.
Packit Service df60bb
 *
Packit Service df60bb
 * Parameters:
Packit Service df60bb
 * 	dst - Where to store the resulting affine transform
Packit Service df60bb
 * 	angle - Rotation angle in degrees
Packit Service df60bb
 *
Packit Service df60bb
 * Returns:
Packit Service df60bb
 *  GD_TRUE on success or GD_FALSE
Packit Service df60bb
 */
Packit Service df60bb
BGD_DECLARE(int) gdAffineRotate (double dst[6], const double angle)
Packit Service df60bb
{
Packit Service df60bb
	const double sin_t = sin (angle * M_PI / 180.0);
Packit Service df60bb
	const double cos_t = cos (angle * M_PI / 180.0);
Packit Service df60bb
Packit Service df60bb
	dst[0] = cos_t;
Packit Service df60bb
	dst[1] = sin_t;
Packit Service df60bb
	dst[2] = -sin_t;
Packit Service df60bb
	dst[3] = cos_t;
Packit Service df60bb
	dst[4] = 0;
Packit Service df60bb
	dst[5] = 0;
Packit Service df60bb
	return GD_TRUE;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
/**
Packit Service df60bb
 * Function: gdAffineShearHorizontal
Packit Service df60bb
 * Set up a horizontal shearing matrix || becomes \\.
Packit Service df60bb
 *
Packit Service df60bb
 * Parameters:
Packit Service df60bb
 * 	dst - Where to store the resulting affine transform
Packit Service df60bb
 * 	angle - Shear angle in degrees
Packit Service df60bb
 *
Packit Service df60bb
 * Returns:
Packit Service df60bb
 *  GD_TRUE on success or GD_FALSE
Packit Service df60bb
 */
Packit Service df60bb
BGD_DECLARE(int) gdAffineShearHorizontal(double dst[6], const double angle)
Packit Service df60bb
{
Packit Service df60bb
	dst[0] = 1;
Packit Service df60bb
	dst[1] = 0;
Packit Service df60bb
	dst[2] = tan(angle * M_PI / 180.0);
Packit Service df60bb
	dst[3] = 1;
Packit Service df60bb
	dst[4] = 0;
Packit Service df60bb
	dst[5] = 0;
Packit Service df60bb
  	return GD_TRUE;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
/**
Packit Service df60bb
 * Function: gdAffineShearVertical
Packit Service df60bb
 * Set up a vertical shearing matrix, columns are untouched.
Packit Service df60bb
 *
Packit Service df60bb
 * Parameters:
Packit Service df60bb
 * 	dst - Where to store the resulting affine transform
Packit Service df60bb
 * 	angle - Shear angle in degrees
Packit Service df60bb
 *
Packit Service df60bb
 * Returns:
Packit Service df60bb
 *  GD_TRUE on success or GD_FALSE
Packit Service df60bb
 */
Packit Service df60bb
BGD_DECLARE(int) gdAffineShearVertical(double dst[6], const double angle)
Packit Service df60bb
{
Packit Service df60bb
	dst[0] = 1;
Packit Service df60bb
	dst[1] = tan(angle * M_PI / 180.0);
Packit Service df60bb
	dst[2] = 0;
Packit Service df60bb
	dst[3] = 1;
Packit Service df60bb
	dst[4] = 0;
Packit Service df60bb
	dst[5] = 0;
Packit Service df60bb
  	return GD_TRUE;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
/**
Packit Service df60bb
 * Function: gdAffineTranslate
Packit Service df60bb
 * Set up a translation matrix.
Packit Service df60bb
 *
Packit Service df60bb
 * Parameters:
Packit Service df60bb
 * 	dst - Where to store the resulting affine transform
Packit Service df60bb
 * 	offset_x - Horizontal translation amount
Packit Service df60bb
 * 	offset_y - Vertical translation amount
Packit Service df60bb
 *
Packit Service df60bb
 * Returns:
Packit Service df60bb
 *  GD_TRUE on success or GD_FALSE
Packit Service df60bb
 */
Packit Service df60bb
BGD_DECLARE(int) gdAffineTranslate (double dst[6], const double offset_x, const double offset_y)
Packit Service df60bb
{
Packit Service df60bb
	dst[0] = 1;
Packit Service df60bb
	dst[1] = 0;
Packit Service df60bb
	dst[2] = 0;
Packit Service df60bb
	dst[3] = 1;
Packit Service df60bb
	dst[4] = offset_x;
Packit Service df60bb
	dst[5] = offset_y;
Packit Service df60bb
    return GD_TRUE;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
/**
Packit Service df60bb
 * gdAffineexpansion: Find the affine's expansion factor.
Packit Service df60bb
 * @src: The affine transformation.
Packit Service df60bb
 *
Packit Service df60bb
 * Finds the expansion factor, i.e. the square root of the factor
Packit Service df60bb
 * by which the affine transform affects area. In an affine transform
Packit Service df60bb
 * composed of scaling, rotation, shearing, and translation, returns
Packit Service df60bb
 * the amount of scaling.
Packit Service df60bb
 *
Packit Service df60bb
 *  GD_TRUE on success or GD_FALSE
Packit Service df60bb
 **/
Packit Service df60bb
BGD_DECLARE(double) gdAffineExpansion (const double src[6])
Packit Service df60bb
{
Packit Service df60bb
  return sqrt (fabs (src[0] * src[3] - src[1] * src[2]));
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
/**
Packit Service df60bb
 * Function: gdAffineRectilinear
Packit Service df60bb
 * Determines whether the affine transformation is axis aligned. A
Packit Service df60bb
 * tolerance has been implemented using GD_EPSILON.
Packit Service df60bb
 *
Packit Service df60bb
 * Parameters:
Packit Service df60bb
 * 	m - The affine transformation
Packit Service df60bb
 *
Packit Service df60bb
 * Returns:
Packit Service df60bb
 *  GD_TRUE if the affine is rectilinear or GD_FALSE
Packit Service df60bb
 */
Packit Service df60bb
BGD_DECLARE(int) gdAffineRectilinear (const double m[6])
Packit Service df60bb
{
Packit Service df60bb
  return ((fabs (m[1]) < GD_EPSILON && fabs (m[2]) < GD_EPSILON) ||
Packit Service df60bb
	  (fabs (m[0]) < GD_EPSILON && fabs (m[3]) < GD_EPSILON));
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
/**
Packit Service df60bb
 * Function: gdAffineEqual
Packit Service df60bb
 * Determines whether two affine transformations are equal. A tolerance
Packit Service df60bb
 * has been implemented using GD_EPSILON.
Packit Service df60bb
 *
Packit Service df60bb
 * Parameters:
Packit Service df60bb
 * 	m1 - The first affine transformation
Packit Service df60bb
 * 	m2 - The first affine transformation
Packit Service df60bb
 *
Packit Service df60bb
 * Returns:
Packit Service df60bb
 * 	GD_TRUE on success or GD_FALSE
Packit Service df60bb
 */
Packit Service df60bb
BGD_DECLARE(int) gdAffineEqual (const double m1[6], const double m2[6])
Packit Service df60bb
{
Packit Service df60bb
  return (fabs (m1[0] - m2[0]) < GD_EPSILON &&
Packit Service df60bb
	  fabs (m1[1] - m2[1]) < GD_EPSILON &&
Packit Service df60bb
	  fabs (m1[2] - m2[2]) < GD_EPSILON &&
Packit Service df60bb
	  fabs (m1[3] - m2[3]) < GD_EPSILON &&
Packit Service df60bb
	  fabs (m1[4] - m2[4]) < GD_EPSILON &&
Packit Service df60bb
	  fabs (m1[5] - m2[5]) < GD_EPSILON);
Packit Service df60bb
}
Packit Service df60bb