version 2.8
gmisc.h
Go to the documentation of this file.
1 /*
2  * This file is subject to the terms of the GFX License. If a copy of
3  * the license was not distributed with this file, you can obtain one at:
4  *
5  * http://ugfx.org/license.html
6  */
7 
8 /**
9  * @file src/gmisc/gmisc.h
10  * @brief GMISC - Miscellaneous Routines header file.
11  *
12  * @addtogroup GMISC
13  *
14  * @brief Module which contains different features such as array conversions
15  *
16  * @{
17  */
18 
19 #ifndef _GMISC_H
20 #define _GMISC_H
21 
22 #include "../../gfx.h"
23 
24 /*===========================================================================*/
25 /* Type definitions */
26 /*===========================================================================*/
27 
28 // Forward definition
29 typedef struct point point;
30 
31 /**
32  * @brief Sample data formats
33  * @note These are defined regardless of whether you use the GMISC module
34  * or not as they are used in lots of places.
35  */
36 typedef enum ArrayDataFormat_e {
37  ARRAY_DATA_UNKNOWN = 0,
38  ARRAY_DATA_4BITUNSIGNED = 4, ARRAY_DATA_4BITSIGNED = 5,
39  ARRAY_DATA_8BITUNSIGNED = 8, ARRAY_DATA_8BITSIGNED = 9,
40  ARRAY_DATA_10BITUNSIGNED = 10, ARRAY_DATA_10BITSIGNED = 11,
41  ARRAY_DATA_12BITUNSIGNED = 12, ARRAY_DATA_12BITSIGNED = 13,
42  ARRAY_DATA_14BITUNSIGNED = 14, ARRAY_DATA_14BITSIGNED = 15,
43  ARRAY_DATA_16BITUNSIGNED = 16, ARRAY_DATA_16BITSIGNED = 17,
45 
46 /**
47  * @brief Is the sample data format a "signed" data format?
48  */
49 #define gfxSampleFormatIsSigned(fmt) ((fmt) & 1)
50 
51 /**
52  * @brief How many bits are in the sample data format
53  */
54 #define gfxSampleFormatBits(fmt) ((fmt) & ~1)
55 
56 /**
57  * @brief The type for a fixed point type.
58  * @details The top 16 bits are the integer component, the bottom 16 bits are the real component.
59  */
60 typedef int32_t fixed;
61 
62 /**
63  * @brief Macros to convert to and from a fixed point.
64  * @{
65  */
66 #define FIXED(x) ((fixed)(x)<<16) /* @< integer to fixed */
67 #define NONFIXED(x) ((x)>>16) /* @< fixed to integer */
68 #define FIXED0_5 32768 /* @< 0.5 as a fixed (used for rounding) */
69 #define FP2FIXED(x) ((fixed)((x)*65536.0)) /* @< floating point to fixed */
70 #define FIXED2FP(x) ((double)(x)/65536.0) /* @< fixed to floating point */
71 #define FIXEDMUL(a,b) ((fixed)((((long long)(a))*(b))>>16)) /* @< fixed,fixed multiplication */
72 #define FIXEDMULINT(a,b) ((a)*(b)) /* @< integer,fixed multiplication */
73 /** @} */
74 
75 /**
76  * @brief The famous number pi
77  */
78 #ifndef GFX_PI
79  #define GFX_PI 3.1415926535897932384626433832795028841971693993751
80 #endif
81 
82 /**
83  * @brief pi as a fixed point
84  */
85 #define FIXED_PI FP2FIXED(GFX_PI)
86 
87 /*===========================================================================*/
88 /* External declarations. */
89 /*===========================================================================*/
90 
91 #if GFX_USE_GMISC || defined(__DOXYGEN__)
92 
93 #ifdef __cplusplus
94 extern "C" {
95 #endif
96 
97 #if GMISC_NEED_ARRAYOPS || defined(__DOXYGEN__)
98  /**
99  * @brief Convert from one array format to another array format.
100  * @pre Requires GFX_USE_GMISC and GMISC_NEED_ARRAYOPS
101  *
102  * @param[in] srcfmt The format of the source array
103  * @param[in] src The source array
104  * @param[in] dstfmt The format of the destination array
105  * @param[in] dst The dstination array
106  * @param[in] cnt The number of array elements to convert
107  *
108  * @note Assumes the destination buffer is large enough for the resultant data.
109  * @note This routine is optimised to perform as fast as possible.
110  * @note No type checking is performed on the source format. It is assumed to
111  * have only valid values eg. ARRAY_DATA_4BITSIGNED will have values
112  * 0000 -> 0111 for positive numbers and 1111 -> 1000 for negative numbers
113  * Bits 5 -> 8 in the storage byte are treated in an undefined manner.
114  * @note If srcfmt or dstfmt is an unknown format, this routine does nothing
115  * with no warning that something is wrong
116  *
117  * @api
118  */
119  void gmiscArrayConvert(ArrayDataFormat srcfmt, void *src, ArrayDataFormat dstfmt, void *dst, size_t cnt);
120 
121  #if 0
122  void gmiscArrayTranslate(ArrayDataFormat fmt, void *src, void *dst, size_t cnt, int trans);
123 
124  void gmiscArrayMultiply(ArrayDataFormat fmt, void *src, void *dst, size_t cnt, int mult);
125 
126  void gmiscArrayDivide(ArrayDataFormat fmt, void *src, void *dst, size_t cnt, int mdiv);
127 
128  void gmiscArrayMultDiv(ArrayDataFormat fmt, void *src, void *dst, size_t cnt, int mult, int div);
129 
130  void gmiscArrayAdd(ArrayDataFormat fmt, void *src1, void *src2, void *dst, size_t cnt);
131 
132  void gmiscArrayAddNoOverflow(ArrayDataFormat fmt, void *src1, void *src2, void *dst, size_t cnt);
133  #endif
134 #endif
135 
136 #if GMISC_NEED_FASTTRIG || defined(__DOXYGEN__)
137  #include <math.h>
138 
139  extern const double sintabledouble[];
140 
141  /**
142  * @brief Fast Table Based Trig functions
143  * @return A double in the range -1.0 .. 0.0 .. 1.0
144  * @pre Requires GFX_USE_GMISC and GMISC_NEED_FASTTRIG
145  *
146  * @param[in] degrees The angle in degrees (not radians)
147  *
148  * @note These functions use degrees rather than radians to describe the angle.
149  *
150  * @api
151  * @{
152  */
153  double fsin(int degrees);
154  double fcos(int degrees);
155  /** @}
156  *
157  * @brief Fast Table Based Trig functions
158  * @return A double in the range -1.0 .. 0.0 .. 1.0
159  * @pre Requires GFX_USE_GMISC and GMISC_NEED_FASTTRIG
160  *
161  * @param[in] degrees The angle in degrees 0 .. 359
162  *
163  * @note These functions use degrees rather than radians to describe the angle.
164  * @note These functions are super fast but require the parameter to be in range.
165  * Use the lowercase functions if the parameter may not be in range or if a
166  * required trig function is not supported in this form.
167  *
168  * @api
169  * @{
170  */
171  #define FSIN(degrees) sintabledouble[degrees];
172  /** @} */
173 #endif
174 
175 #if GMISC_NEED_FIXEDTRIG || defined(__DOXYGEN__)
176  extern const fixed sintablefixed[];
177 
178  /**
179  * @brief Fast Table Based Trig functions
180  * @return A fixed point in the range -1.0 .. 0.0 .. 1.0
181  * @pre Requires GFX_USE_GMISC and GMISC_NEED_FIXEDTRIG
182  *
183  * @param[in] degrees The angle in degrees (not radians)
184  *
185  * @note These functions use degrees rather than radians to describe the angle.
186  *
187  * @api
188  * @{
189  */
190  fixed ffsin(int degrees);
191  fixed ffcos(int degrees);
192  /** @}
193  *
194  * @brief Fast Table Based Trig functions
195  * @return A fixed point in the range -1.0 .. 0.0 .. 1.0
196  * @pre Requires GFX_USE_GMISC and GMISC_NEED_FIXEDTRIG
197  *
198  * @param[in] degrees The angle in degrees 0 .. 359
199  *
200  * @note These functions use degrees rather than radians to describe the angle.
201  * @note These functions are super fast but require the parameter to be in range.
202  * Use the lowercase functions if the parameter may not be in range or if a
203  * required trig function is not supported in this form.
204  *
205  * @api
206  * @{
207  */
208  #define FFSIN(degrees) sintablefixed[degrees];
209  /** @} */
210 #endif
211 
212 #if GMISC_NEED_INVSQRT || defined(__DOXYGEN__)
213  /**
214  * @brief Fast inverse square root function (x^-1/2)
215  * @return The approximate inverse square root
216  * @pre Requires GFX_USE_GMISC and GMISC_NEED_INVSQRT
217  *
218  * @param[in] n The number to find the inverse square root of
219  *
220  * @note This function generates an approximate result. Higher accuracy (at the expense
221  * of speed) can be obtained by modifying the source code (the necessary line
222  * is already there - just commented out).
223  * @note This function relies on the internal machine format of a float and a long.
224  * If your machine architecture is very unusual this function may not work.
225  *
226  * @api
227  */
228  float invsqrt(float n);
229 #endif
230 
231 #if GMISC_NEED_MATRIXFLOAT2D || defined(__DOXYGEN__)
232 
233  /**
234  * @brief A matrix for doing 2D graphics using floats
235  * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFLOAT2D
236  */
237  typedef struct MatrixFloat2D {
238  float a00, a01, a02;
239  float a10, a11, a12;
240  float a20, a21, a22;
241  } MatrixFloat2D;
242 
243  /**
244  * @brief Apply the matrix to a set of points
245  * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFLOAT2D
246  *
247  * @param[in] dst The destination array of points
248  * @param[in] src The source array of points
249  * @param[in] m The matrix to apply
250  * @param[in] cnt How many points are in the array
251  *
252  * @note In-place matrix application is allowed ie. dst = src
253  *
254  * @api
255  */
256  void gmiscMatrixFloat2DApplyToPoints(point *dst, const point *src, const MatrixFloat2D *m, int cnt);
257 
258  /**
259  * @brief Set the 2D matrix to the identity matrix
260  * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFLOAT2D
261  *
262  * @param[in] m The matrix to set to identity
263  *
264  * @api
265  */
267 
268  /**
269  * @brief Multiple two 2D matrixes together
270  * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFLOAT2D
271  *
272  * @param[in] dst The destination matrix
273  * @param[in] src1 The first source matrix
274  * @param[in] src2 The second source matrix
275  *
276  * @note In-place matrix application is NOT allowed ie. dst != src1, dst != src2
277  *
278  * @api
279  */
280  void gmiscMatrixFloat2DMultiply(MatrixFloat2D *dst, const MatrixFloat2D *src1, const MatrixFloat2D *src2);
281 
282  /**
283  * @brief Add an x,y translation to a matrix
284  * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFLOAT2D
285  *
286  * @param[in] dst The destination matrix
287  * @param[in] src The source matrix. Can be NULL
288  * @param[in] tx, ty The x and y translation to apply
289  *
290  * @note In-place matrix operation is NOT allowed ie. dst != src
291  * @note If no source matrix is provided, it is equivalent to applying the operation
292  * to an identity matrix. It also is a much simpler operation requiring no multiplication.
293  *
294  * @api
295  */
296  void gmiscMatrixFloat2DApplyTranslation(MatrixFloat2D *dst, const MatrixFloat2D *src, float tx, float ty);
297 
298  /**
299  * @brief Add x,y scaling to a matrix
300  * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFLOAT2D
301  *
302  * @param[in] dst The destination matrix
303  * @param[in] src The source matrix. Can be NULL
304  * @param[in] sx, sy The scaling to apply in the x and y direction. Negative numbers give reflection.
305  *
306  * @note In-place matrix operation is NOT allowed ie. dst != src
307  * @note If no source matrix is provided, it is equivalent to applying the operation
308  * to an identity matrix. It also is a much simpler operation requiring no multiplication.
309  *
310  * @api
311  */
312  void gmiscMatrixFloat2DApplyScale(MatrixFloat2D *dst, const MatrixFloat2D *src, float sx, float sy);
313 
314  /**
315  * @brief Add x,y shear to a matrix
316  * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFLOAT2D
317  *
318  * @param[in] dst The destination matrix
319  * @param[in] src The source matrix. Can be NULL
320  * @param[in] sx, sy The shear to apply in the x and y direction.
321  *
322  * @note In-place matrix operation is NOT allowed ie. dst != src
323  * @note If no source matrix is provided, it is equivalent to applying the operation
324  * to an identity matrix. It also is a much simpler operation requiring no multiplication.
325  *
326  * @api
327  */
328  void gmiscMatrixFloat2DApplyShear(MatrixFloat2D *dst, const MatrixFloat2D *src, float sx, float sy);
329 
330  /**
331  * @brief Add rotation to a matrix
332  * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFLOAT2D
333  *
334  * @param[in] dst The destination matrix
335  * @param[in] src The source matrix. Can be NULL
336  * @param[in] angle The angle to apply in degrees (not radians).
337  *
338  * @note In-place matrix operation is NOT allowed ie. dst != src
339  * @note If no source matrix is provided, it is equivalent to applying the operation
340  * to an identity matrix. It also is a much simpler operation.
341  * @note If GMISC_NEED_FASTTRIG is defined then the fast table sin and cos lookup's will be used
342  * rather than the C library versions.
343  *
344  * @api
345  */
346  void gmiscMatrixFloat2DApplyRotation(MatrixFloat2D *dst, const MatrixFloat2D *src, int angle);
347 #endif
348 
349 #if GMISC_NEED_MATRIXFIXED2D || defined(__DOXYGEN__)
350 
351  /**
352  * @brief A matrix for doing 2D graphics using fixed point maths
353  * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFIXED2D
354  */
355  typedef struct MatrixFixed2D {
356  fixed a00, a01, a02;
357  fixed a10, a11, a12;
358  fixed a20, a21, a22;
359  } MatrixFixed2D;
360 
361  /**
362  * @brief Apply the matrix to a set of points
363  * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFIXED2D
364  *
365  * @param[in] dst The destination array of points
366  * @param[in] src The source array of points
367  * @param[in] m The matrix to apply
368  * @param[in] cnt How many points are in the array
369  *
370  * @note In-place matrix application is allowed ie. dst = src
371  *
372  * @api
373  */
374  void gmiscMatrixFixed2DApplyToPoints(point *dst, const point *src, const MatrixFixed2D *m, int cnt);
375 
376  /**
377  * @brief Set the 2D matrix to the identity matrix
378  * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFIXED2D
379  *
380  * @param[in] m The matrix to set to identity
381  *
382  * @api
383  */
385 
386  /**
387  * @brief Multiple two 2D matrixes together
388  * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFIXED2D
389  *
390  * @param[in] dst The destination matrix
391  * @param[in] src1 The first source matrix
392  * @param[in] src2 The second source matrix
393  *
394  * @note In-place matrix application is NOT allowed ie. dst != src1, dst != src2
395  *
396  * @api
397  */
398  void gmiscMatrixFixed2DMultiply(MatrixFixed2D *dst, const MatrixFixed2D *src1, const MatrixFixed2D *src2);
399 
400  /**
401  * @brief Add an x,y translation to a matrix
402  * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFIXED2D
403  *
404  * @param[in] dst The destination matrix
405  * @param[in] src The source matrix. Can be NULL
406  * @param[in] tx, ty The x and y translation to apply
407  *
408  * @note In-place matrix operation is NOT allowed ie. dst != src
409  * @note If no source matrix is provided, it is equivalent to applying the operation
410  * to an identity matrix. It also is a much simpler operation requiring no multiplication.
411  *
412  * @api
413  */
415 
416  /**
417  * @brief Add x,y scaling to a matrix
418  * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFIXED2D
419  *
420  * @param[in] dst The destination matrix
421  * @param[in] src The source matrix. Can be NULL
422  * @param[in] sx, sy The scaling to apply in the x and y direction. Negative numbers give reflection.
423  *
424  * @note In-place matrix operation is NOT allowed ie. dst != src
425  * @note If no source matrix is provided, it is equivalent to applying the operation
426  * to an identity matrix. It also is a much simpler operation requiring no multiplication.
427  *
428  * @api
429  */
430  void gmiscMatrixFixed2DApplyScale(MatrixFixed2D *dst, const MatrixFixed2D *src, fixed sx, fixed sy);
431 
432  /**
433  * @brief Add x,y shear to a matrix
434  * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFIXED2D
435  *
436  * @param[in] dst The destination matrix
437  * @param[in] src The source matrix. Can be NULL
438  * @param[in] sx, sy The shear to apply in the x and y direction.
439  *
440  * @note In-place matrix operation is NOT allowed ie. dst != src
441  * @note If no source matrix is provided, it is equivalent to applying the operation
442  * to an identity matrix. It also is a much simpler operation requiring no multiplication.
443  *
444  * @api
445  */
446  void gmiscMatrixFixed2DApplyShear(MatrixFixed2D *dst, const MatrixFixed2D *src, fixed sx, fixed sy);
447 
448  #if GMISC_NEED_FIXEDTRIG || defined(__DOXYGEN__)
449  /**
450  * @brief Add rotation to a matrix
451  * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFIXED2D and GMISC_NEED_FIXEDTRIG
452  *
453  * @param[in] dst The destination matrix
454  * @param[in] src The source matrix. Can be NULL
455  * @param[in] angle The angle to apply in degrees (not radians).
456  *
457  * @note In-place matrix operation is NOT allowed ie. dst != src
458  * @note If no source matrix is provided, it is equivalent to applying the operation
459  * to an identity matrix. It also is a much simpler operation requiring no multiplication.
460  *
461  * @api
462  */
463  void gmiscMatrixFixed2DApplyRotation(MatrixFixed2D *dst, const MatrixFixed2D *src, int angle);
464  #endif
465 #endif
466 
467 
468 #if GMISC_NEED_HITTEST_POLY || defined(__DOXYGEN__)
469  /**
470  * @brief Check whether a point is inside or on the edge of a polygon
471  * @pre Requires GFX_USE_GMISC and GMISC_NEED_HITTEST_POLY
472  *
473  * @note This function works both with convex and concave polygons
474  *
475  * @param[in] pntarray The array of points that form the polygon
476  * @param[in] cnt The number of points in the point array @p pntarray
477  * @param[in] p The point to test
478  *
479  * @return @p TRUE if the point @p p is inside or on the edge of the polygon @p pntarray, @p FALSE otherwise.
480  *
481  * @api
482  */
483  bool_t gmiscHittestPoly(const point *pntarray, unsigned cnt, const point *p);
484 #endif // GMISC_NEED_HITTEST_POLY
485 
486 #ifdef __cplusplus
487 }
488 #endif
489 
490 #endif /* GFX_USE_MISC */
491 
492 #endif /* _GMISC_H */
493 /** @} */
494 
void gmiscMatrixFloat2DMultiply(MatrixFloat2D *dst, const MatrixFloat2D *src1, const MatrixFloat2D *src2)
Multiple two 2D matrixes together.
void gmiscMatrixFixed2DApplyTranslation(MatrixFixed2D *dst, const MatrixFixed2D *src, fixed tx, fixed ty)
Add an x,y translation to a matrix.
void gmiscMatrixFixed2DApplyRotation(MatrixFixed2D *dst, const MatrixFixed2D *src, int angle)
Add rotation to a matrix.
int32_t fixed
The type for a fixed point type.
Definition: gmisc.h:60
float invsqrt(float n)
Fast inverse square root function (x^-1/2)
void gmiscMatrixFixed2DMultiply(MatrixFixed2D *dst, const MatrixFixed2D *src1, const MatrixFixed2D *src2)
Multiple two 2D matrixes together.
void gmiscMatrixFloat2DApplyRotation(MatrixFloat2D *dst, const MatrixFloat2D *src, int angle)
Add rotation to a matrix.
void gmiscMatrixFixed2DApplyToPoints(point *dst, const point *src, const MatrixFixed2D *m, int cnt)
Apply the matrix to a set of points.
void gmiscMatrixFixed2DApplyShear(MatrixFixed2D *dst, const MatrixFixed2D *src, fixed sx, fixed sy)
Add x,y shear to a matrix.
ArrayDataFormat_e
Sample data formats.
Definition: gmisc.h:36
struct MatrixFixed2D MatrixFixed2D
A matrix for doing 2D graphics using fixed point maths.
void gmiscArrayConvert(ArrayDataFormat srcfmt, void *src, ArrayDataFormat dstfmt, void *dst, size_t cnt)
Convert from one array format to another array format.
void gmiscMatrixFixed2DSetIdentity(MatrixFixed2D *m)
Set the 2D matrix to the identity matrix.
struct MatrixFloat2D MatrixFloat2D
A matrix for doing 2D graphics using floats.
Type for a 2D point on the screen.
Definition: gdisp.h:51
void gmiscMatrixFloat2DSetIdentity(MatrixFloat2D *m)
Set the 2D matrix to the identity matrix.
void gmiscMatrixFixed2DApplyScale(MatrixFixed2D *dst, const MatrixFixed2D *src, fixed sx, fixed sy)
Add x,y scaling to a matrix.
void gmiscMatrixFloat2DApplyShear(MatrixFloat2D *dst, const MatrixFloat2D *src, float sx, float sy)
Add x,y shear to a matrix.
fixed ffsin(int degrees)
Fast Table Based Trig functions.
void gmiscMatrixFloat2DApplyScale(MatrixFloat2D *dst, const MatrixFloat2D *src, float sx, float sy)
Add x,y scaling to a matrix.
A matrix for doing 2D graphics using floats.
Definition: gmisc.h:237
enum ArrayDataFormat_e ArrayDataFormat
Sample data formats.
A matrix for doing 2D graphics using fixed point maths.
Definition: gmisc.h:355
void gmiscMatrixFloat2DApplyToPoints(point *dst, const point *src, const MatrixFloat2D *m, int cnt)
Apply the matrix to a set of points.
void gmiscMatrixFloat2DApplyTranslation(MatrixFloat2D *dst, const MatrixFloat2D *src, float tx, float ty)
Add an x,y translation to a matrix.
double fsin(int degrees)
Fast Table Based Trig functions.
bool_t gmiscHittestPoly(const point *pntarray, unsigned cnt, const point *p)
Check whether a point is inside or on the edge of a polygon.