/* Libvisual - The audio visualisation framework. * * Copyright (C) 2004, 2005, 2006 Dennis Smit * * Authors: Dennis Smit * * $Id: lv_rectangle.c,v 1.10 2006/02/13 20:54:08 synap Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include "lv_math.h" #include "lv_rectangle.h" /** * @defgroup VisRectangle VisRectangle * @{ */ /** * Creates a new VisRectangle. * * @param x X Position of the upper left corner. * @param y Y Position of the upper left corner. * @param width The width of the rectangle. * @param height The height of the rectangle. * * @return A newly allocated VisRectangle. */ VisRectangle *visual_rectangle_new (int x, int y, int width, int height) { VisRectangle *rect; /* Do the VisObject initialization */ visual_object_initialize (VISUAL_OBJECT (rect), TRUE, NULL); visual_rectangle_set (rect, x, y, width, height); return rect; } /** * Sets the values for a VisRectangle. * * @param rect Pointer to the VisRectangle in which the values are set. * @param x X Position of the upper left corner. * @param y Y Position of the upper left corner. * @param width The width of the rectangle. * @param height The height of the rectangle. * * @return VISUAL_OK on succes, -VISUAL_ERROR_RECTANGLE_NULL on failure. */ int visual_rectangle_set (VisRectangle *rect, int x, int y, int width, int height) { visual_log_return_val_if_fail (rect != NULL, -VISUAL_ERROR_RECTANGLE_NULL); rect->x = x; rect->y = y; rect->width = width; rect->height = height; return VISUAL_OK; } /** * Checks if a certain point is within the defined VisRectangle. * * @param rect Pointer to the VisRectangle to which the position is checked. * @param x X Position of the point to be checked. * @param y Y Position of the point to be checked. * * @return TRUE if within rectangle, FALSE if not, -VISUAL_ERROR_RECTANGLE_NULL on failure. */ int visual_rectangle_position_within (VisRectangle *rect, int x, int y) { visual_log_return_val_if_fail (rect != NULL, -VISUAL_ERROR_RECTANGLE_NULL); if ((x >= rect->x) && (x <= rect->x + rect->width) && (y >= rect->y) && (y <= rect->y + rect->height)) { return TRUE; } return FALSE; } /** * Checks whether the src VisRectangle partially falls within the dest VisRectangle. * * @param dest Pointer to the destination VisRectangle in which the src should partially fall within. * @param src Pointer to the source VisRectangle that should partially fall within the destination. * * @return TRUE if the src partially falls within the dest, FALSE if not, -VISUAL_ERROR_RECTANGLE_NULL on failure. */ int visual_rectangle_within_partially (VisRectangle *dest, VisRectangle *src) { visual_log_return_val_if_fail (dest != NULL, -VISUAL_ERROR_RECTANGLE_NULL); visual_log_return_val_if_fail (src != NULL, -VISUAL_ERROR_RECTANGLE_NULL); if ((src->x + src->width) < dest->x) return FALSE; if ((src->y + src->height) < dest->y) return FALSE; if (src->x > (dest->x + dest->width)) return FALSE; if (src->y > (dest->y + dest->height)) return FALSE; return TRUE; } /** * Checks whether the src VisRectangle falls within the dest VisRectangle. * * @param dest Pointer to the destination VisRectangle in which the src should fall within. * @param src Pointer to the source VisRectangle that should fall within the destination. * * @return TRUE if the src partially falls within the dest, FALSE if not, -VISUAL_ERROR_RECTANGLE_NULL on failure. */ int visual_rectangle_within (VisRectangle *dest, VisRectangle *src) { visual_log_return_val_if_fail (dest != NULL, -VISUAL_ERROR_RECTANGLE_NULL); visual_log_return_val_if_fail (src != NULL, -VISUAL_ERROR_RECTANGLE_NULL); if (src->x < dest->x) return FALSE; if (src->y < dest->y) return FALSE; if ((src->x + src->width) > (dest->x + dest->width)) return FALSE; if ((src->y + src->height) > (dest->y + dest->height)) return FALSE; return TRUE; } /** * Copies the colors from one VisRectangle to another. * * @param dest Pointer to the destination VisRectangle. * @param src Pointer to the source VisRectangle in which dest is copied. * * @return VISUAL_OK on succes, -VISUAL_ERROR_RECTANGLE_NULL on failure. */ int visual_rectangle_copy (VisRectangle *dest, VisRectangle *src) { visual_log_return_val_if_fail (dest != NULL, -VISUAL_ERROR_RECTANGLE_NULL); visual_log_return_val_if_fail (src != NULL, -VISUAL_ERROR_RECTANGLE_NULL); dest->x = src->x; dest->y = src->y; dest->width = src->width; dest->height = src->height; return VISUAL_OK; } /** * Clips two VisRectangles into one, This is done by using the within parameter as the * boundary for the src parameter, so src is adopten so that is falls within the within parameter. * The final result is stored in dest. It's legal to give the same VisRectangle for the dest * and src VisRectangle. * * @param dest Pointer to the destination VisRectangle. * @param within Pointer to the boundary VisRectangle. * @param src Pointer to the source VisRectangle which is boundary adopted to the within parameter. * * @return VISUAL_OK on succes, -VISUAL_ERROR_RECTANGLE_NULL or -VISUAL_ERROR_RECTANGLE_OUT_OF_BOUNDS * on failure. */ int visual_rectangle_clip (VisRectangle *dest, VisRectangle *within, VisRectangle *src) { visual_log_return_val_if_fail (dest != NULL, -VISUAL_ERROR_RECTANGLE_NULL); visual_log_return_val_if_fail (within != NULL, -VISUAL_ERROR_RECTANGLE_NULL); visual_log_return_val_if_fail (src != NULL, -VISUAL_ERROR_RECTANGLE_NULL); /* If not partially within, don't even try to clip */ if (visual_rectangle_within_partially (within, src) == FALSE) { visual_rectangle_set (dest, 0, 0, 0, 0); return -VISUAL_ERROR_RECTANGLE_OUT_OF_BOUNDS; } visual_rectangle_copy (dest, src); /* Left, Upper boundries */ if (src->x < within->x) { dest->width = src->width - (within->x - src->x); dest->x = within->x; } if (src->y < within->y) { dest->height = src->height - (within->y - src->y); dest->y = within->y; } /* Right, Lower boundries */ if (dest->x + dest->width > within->width) dest->width = within->width - dest->x; if (dest->y + dest->height > within->height) dest->height = within->height - dest->y; return VISUAL_OK; } /** * Normalizes the VisRectangle, this means that both the x and y position are set to 0. * * @param rect Pointer to the VisRectangle that is to be normalized. * * @return VISUAL_OK on succes, -VISUAL_ERROR_RECTANGLE_NULL on failure. */ int visual_rectangle_normalise (VisRectangle *rect) { visual_log_return_val_if_fail (rect != NULL, -VISUAL_ERROR_RECTANGLE_NULL); rect->x = 0; rect->y = 0; return VISUAL_OK; } /** * Normalizes the VisRectangle to another VisRectangle, this means that the x and y position * of the destination VisRectangle is set to that of the source VisRectangle. * * @param dest Pointer to the VisRectangle that is to be normalized. * @param src Pointer to the VisRectangle that is used as the source for normalization. * * @return VISUAL_OK on succes, -VISUAL_ERROR_RECTANGLE_NULL on failure. */ int visual_rectangle_normalise_to (VisRectangle *dest, VisRectangle *src) { visual_log_return_val_if_fail (dest != NULL, -VISUAL_ERROR_RECTANGLE_NULL); visual_log_return_val_if_fail (src != NULL, -VISUAL_ERROR_RECTANGLE_NULL); dest->x = src->x; dest->y = src->y; return VISUAL_OK; } /** * Checks if a VisRectangle occupies an area. If either the width or height is equal * or lower than 0, this returns TRUE. * * @param rect Pointer to the VisRectangle that is checked for emptyness. * * @return VISUAL_OK on succes, TRUE if it's empty, FALSE if not or * -VISUAL_ERROR_RECTANGLE_NULL on failure. */ int visual_rectangle_is_empty (VisRectangle *rect) { visual_log_return_val_if_fail (rect != NULL, -VISUAL_ERROR_RECTANGLE_NULL); if (rect->width <= 0 || rect->height <= 0) return TRUE; return FALSE; } /** * Denormalises a set of floating point x y coordinates that are ranging from 0.0 to 1.0 to absolute * locations using the VisRectangle as reference. The floating point coordinates are clamped * to 0.0 and 1.0. Don't use this function to do many transforms, instead use * visual_rectangle_denormalise_many_values. * * @see visual_rectangle_denormalise_many_values * * @param rect Pointer to the VisRectangle used as the reference. * @param fx Floating point X location ranging from 0.0 to 1.0. * @param fy Floating point Y location ranging from 0.0 to 1.0. * @param x Pointer to an integer in which the absolute X location is stored. * @param y Pointer to an integer in which the absolute Y location is stored. * * @return VISUAL_OK on succes, -VISUAL_ERROR_RECTANGLE_NULL on failure. */ int visual_rectangle_denormalise_values (VisRectangle *rect, float fx, float fy, int32_t *x, int32_t *y) { visual_log_return_val_if_fail (rect != NULL, -VISUAL_ERROR_RECTANGLE_NULL); if (fx < 0) fx = 0; if (fx > 1) fx = 1; if (fy < 0) fy = 0; if (fy > 1) fy = 1; *x = rect->width * fx; *y = rect->height * fy; return VISUAL_OK; } /** * Denormalises a list of floating point x y coordinates tht are ranging from 0.0 to 1.0 to absolute * locations using the VisRectangle as reference. WARNING: Unlike visual_rectangle_denormalise_values, the * floating point locations are NOT clamped. This is done because of performance reasons. * * @param rect Pointer to the VisRectangle used as the reference. * @param fxlist Pointer to a floating point X location ranging from 0.0 to 1.0 array. * @param fylist Pointer to a floating point Y location ranging from 0.0 to 1.0 array. * @param xlist Pointer to an array of integers in which the absolute X location are stored. * @param ylist Pointer to an array of integers in which the absolute Y location are stored. * @param size The size of the arrays for all X Y locations. * * @return VISUAL_OK on succes, -VISUAL_ERROR_RECTANGLE_NULL on failure. */ int visual_rectangle_denormalise_many_values (VisRectangle *rect, float *fxlist, float *fylist, int32_t *xlist, int32_t *ylist, int size) { int i; visual_log_return_val_if_fail (rect != NULL, -VISUAL_ERROR_RECTANGLE_NULL); visual_math_vectorized_floats_to_int32s_multiply (xlist, fxlist, size, rect->width); visual_math_vectorized_floats_to_int32s_multiply (ylist, fylist, size, rect->height); return VISUAL_OK; } /** * Denormalises a set of floating point x y coordinates that are ranging from -1.0 to 1.0 to absolute * locations using the VisRectangle as reference. The floating point coordinates are clamped * to -1.0 and 1.0. Don't use this function to do many transforms, instead use * visual_rectangle_denormalise_many_values_neg. * * @see visual_rectangle_denormalise_many_values_neg * * @param rect Pointer to the VisRectangle used as the reference. * @param fx Floating point X location ranging from -1.0 to 1.0. * @param fy Floating point Y location ranging from -1.0 to 1.0. * @param x Pointer to an integer in which the absolute X location is stored. * @param y Pointer to an integer in which the absolute Y location is stored. * * @return VISUAL_OK on succes, -VISUAL_ERROR_RECTANGLE_NULL on failure. */ int visual_rectangle_denormalise_values_neg (VisRectangle *rect, float fx, float fy, int32_t *x, int32_t *y) { visual_log_return_val_if_fail (rect != NULL, -VISUAL_ERROR_RECTANGLE_NULL); if (fx < -1) fx = -1; if (fx > 1) fx = 1; if (fy < -1) fy = -1; if (fy > 1) fy = 1; fx = (fx + 1) * 0.5; fy = (fy + 1) * 0.5; *x = rect->width * fx; *y = rect->height * fy; return VISUAL_OK; } /** * Denormalises a list of floating point x y coordinates tht are ranging from -1.0 to 1.0 to absolute * locations using the VisRectangle as reference. WARNING: Unlike visual_rectangle_denormalise_values_neg, the * floating point locations are NOT clamped. This is done because of performance reasons. * * @param rect Pointer to the VisRectangle used as the reference. * @param fxlist Pointer to a floating point X location ranging from -1.0 to 1.0 array. * @param fylist Pointer to a floating point Y location ranging from -1.0 to 1.0 array. * @param xlist Pointer to an array of integers in which the absolute X location are stored. * @param ylist Pointer to an array of integers in which the absolute Y location are stored. * @param size The size of the arrays for all X Y locations. * * @return VISUAL_OK on succes, -VISUAL_ERROR_RECTANGLE_NULL on failure. */ int visual_rectangle_denormalise_many_values_neg (VisRectangle *rect, float *fxlist, float *fylist, int32_t *xlist, int32_t *ylist, int size) { visual_math_vectorized_floats_to_int32s_multiply_denormalise (xlist, fxlist, size, rect->width); visual_math_vectorized_floats_to_int32s_multiply_denormalise (ylist, fylist, size, rect->height); return VISUAL_OK; } /** * @} */