1 /* QuesoGLC
2  * A free implementation of the OpenGL Character Renderer (GLC)
3  * Copyright (c) 2002, 2004-2007, Bertrand Coconnier
4  *
5  *  This library is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU Lesser General Public
7  *  License as published by the Free Software Foundation; either
8  *  version 2.1 of the License, or (at your option) any later version.
9  *
10  *  This library is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *  Lesser General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Lesser General Public
16  *  License along with this library; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19 /* $Id: transform.c 621 2007-03-31 18:05:49Z bcoconni $ */
20 
21 /** \file
22  * defines the so-called "Transformation commands" described in chapter 3.9
23  * of the GLC specs.
24  */
25 
26 /** \defgroup transform Transformation commands
27  *  The GLC transformation commands modify the value of \b GLC_BITMAP_MATRIX.
28  *  Glyph coordinates are defined in the em coordinate system. When the value
29  *  of \b GLC_RENDER_STYLE is \b GLC_BITMAP, GLC uses the 2x2
30  *  \b GLC_BITMAP_MATRIX to transform layouts from the em coordinate system to
31  *  the GL raster coordinate system in which bitmaps are drawn.
32  *
33  *  When the value of the variable \b GLC_RENDER_STYLE is not \b GLC_BITMAP,
34  *  GLC performs no transformations on glyph coordinates. In this case, GLC
35  *  uses em coordinates directly as GL world coordinates when drawing a layout,
36  *  and it is the responsibility of the GLC client to issue GL commands that
37  *  set up the appropriate GL transformations.
38  *
39  *  There is a stack of matrices for \b GLC_BITMAP_MATRIX, the stack depth is
40  *  at least 32 (that is, there is a stack of at least 32 matrices). Matrices
41  *  can be pushed or popped in the stack with glcPushMatrixQSO() and
42  *  glcPopMatrixQSO(). The maximum depth is implementation specific but can be
43  *  retrieved by calling glcGeti() with \b GLC_MAX_MATRIX_STACK_DEPTH_QSO. The
44  *  number of matrices that are currently stored in the stack can be retrieved
45  *  by calling glcGeti() with \b GLC_MATRIX_STACK_DEPTH_QSO.
46  */
47 
48 #include <math.h>
49 #include "internal.h"
50 
51 #define GLC_PI 3.1415926535
52 
53 
54 
55 /** \ingroup transform
56  *  This command assigns the value [1 0 0 1] to the floating point vector
57  *  variable \b GLC_BITMAP_MATRIX.
58  *  \sa glcGetfv() with argument \b GLC_BITMAP_MATRIX
59  *  \sa glcLoadMatrix()
60  *  \sa glcMultMatrix()
61  *  \sa glcRotate()
62  *  \sa glcScale()
63  */
glcLoadIdentity(void)64 void APIENTRY glcLoadIdentity(void)
65 {
66   __GLCcontext *ctx = NULL;
67 
68   GLC_INIT_THREAD();
69 
70   /* Check if the current thread owns a context state */
71   ctx = GLC_GET_CURRENT_CONTEXT();
72   if (!ctx) {
73     __glcRaiseError(GLC_STATE_ERROR);
74     return;
75   }
76 
77   ctx->bitmapMatrix[0] = 1.;
78   ctx->bitmapMatrix[1] = 0.;
79   ctx->bitmapMatrix[2] = 0.;
80   ctx->bitmapMatrix[3] = 1.;
81 }
82 
83 
84 
85 /** \ingroup transform
86  *  This command assigns the value [inMatrix[0] inMatrix[1] inMatrix[2]
87  *  inMatrix[3]] to the floating point vector variable \b GLC_BITMAP_MATRIX.
88  *
89  *  \param inMatrix The value to assign to \b GLC_BITMAP_MATRIX
90  *  \sa glcGetfv() with argument \b GLC_BITMAP_MATRIX
91  *  \sa glcLoadIdentity()
92  *  \sa glcMultMatrix()
93  *  \sa glcRotate()
94  *  \sa glcScale()
95  */
glcLoadMatrix(const GLfloat * inMatrix)96 void APIENTRY glcLoadMatrix(const GLfloat *inMatrix)
97 {
98   __GLCcontext *ctx = NULL;
99 
100   GLC_INIT_THREAD();
101 
102   assert(inMatrix);
103 
104   /* Check if the current thread owns a context state */
105   ctx = GLC_GET_CURRENT_CONTEXT();
106   if (!ctx) {
107     __glcRaiseError(GLC_STATE_ERROR);
108     return;
109   }
110 
111   memcpy(ctx->bitmapMatrix, inMatrix, 4 * sizeof(GLfloat));
112 }
113 
114 
115 
116 /** \ingroup transform
117  *  This command multiply the floating point vector variable
118  *  \b GLC_BITMAP_MATRIX by the incoming matrix \e inMatrix.
119  *
120  *  \param inMatrix A pointer to a 2x2 matrix stored in column-major order
121  *                  as 4 consecutives values.
122  *  \sa glcGetfv() with argument \b GLC_BITMAP_MATRIX
123  *  \sa glcLoadIdentity()
124  *  \sa glcLoadMatrix()
125  *  \sa glcRotate()
126  *  \sa glcScale()
127  */
glcMultMatrix(const GLfloat * inMatrix)128 void APIENTRY glcMultMatrix(const GLfloat *inMatrix)
129 {
130   __GLCcontext *ctx = NULL;
131   GLfloat tempMatrix[4];
132 
133   GLC_INIT_THREAD();
134 
135   assert(inMatrix);
136 
137   /* Check if the current thread owns a context state */
138   ctx = GLC_GET_CURRENT_CONTEXT();
139   if (!ctx) {
140     __glcRaiseError(GLC_STATE_ERROR);
141     return;
142   }
143 
144   memcpy(tempMatrix, ctx->bitmapMatrix, 4 * sizeof(GLfloat));
145 
146   ctx->bitmapMatrix[0] = tempMatrix[0] * inMatrix[0]
147 			 + tempMatrix[2] * inMatrix[1];
148   ctx->bitmapMatrix[1] = tempMatrix[1] * inMatrix[0]
149 			 + tempMatrix[3] * inMatrix[1];
150   ctx->bitmapMatrix[2] = tempMatrix[0] * inMatrix[2]
151 			 + tempMatrix[2] * inMatrix[3];
152   ctx->bitmapMatrix[3] = tempMatrix[1] * inMatrix[2]
153 			 + tempMatrix[3] * inMatrix[3];
154 }
155 
156 
157 
158 /** \ingroup transform
159  *  This command assigns the value [a b c d] to the floating point vector
160  *  variable \b GLC_BITMAP_MATRIX, where \e inAngle is measured in degrees,
161  *  \f$ \theta = inAngle * \pi / 180 \f$ and \n
162  *  \f$ \left [ \begin {array}{ll} a & b \\ c & d \\ \end {array} \right ]
163  *      = \left [ \begin {array}{ll} GLC\_BITMAP\_MATRIX[0] & GLC\_BITMAP\_MATRIX[2]
164  *		  \\ GLC\_BITMAP\_MATRIX[1] & GLC\_BITMAP\_MATRIX[3] \\ \end{array}
165  *	  \right ]
166  *	  \left [ \begin {array}{ll} cos \theta & sin \theta \\
167  *		  -sin \theta & cos\theta \\ \end{array} \right ]
168  *  \f$
169  *  \param inAngle The angle of rotation around the Z axis, in degrees.
170  *  \sa glcGetfv() with argument \b GLC_BITMAP_MATRIX
171  *  \sa glcLoadIdentity()
172  *  \sa glcLoadMatrix()
173  *  \sa glcMultMatrix()
174  *  \sa glcScale()
175  */
glcRotate(GLfloat inAngle)176 void APIENTRY glcRotate(GLfloat inAngle)
177 {
178   GLfloat tempMatrix[4];
179   GLfloat radian = inAngle * GLC_PI / 180.;
180   GLfloat sine = sin(radian);
181   GLfloat cosine = cos(radian);
182 
183   tempMatrix[0] = cosine;
184   tempMatrix[1] = sine;
185   tempMatrix[2] = -sine;
186   tempMatrix[3] = cosine;
187 
188   glcMultMatrix(tempMatrix);
189 }
190 
191 
192 
193 /** \ingroup transform
194  *  This command produces a general scaling along the \b x and \b y
195  *  axes, that is, it assigns the value [a b c d] to the floating point
196  *  vector variable \b GLC_BITMAP_MATRIX, where \n
197  *  \f$ \left [ \begin {array}{ll} a & b \\ c & d \\ \end {array} \right ]
198  *      = \left [ \begin {array}{ll} GLC\_BITMAP\_MATRIX[0] & GLC\_BITMAP\_MATRIX[2]
199  *		  \\ GLC\_BITMAP\_MATRIX[1] & GLC\_BITMAP\_MATRIX[3] \\ \end{array}
200  *	  \right ]
201  *	  \left [ \begin {array}{ll} inX & 0 \\
202  *		  0 & inY \\ \end{array} \right ]
203  *  \f$
204  *  \param inX The scale factor along the \b x axis
205  *  \param inY The scale factor along the \b y axis
206  *  \sa glcGetfv() with argument \b GLC_BITMAP_MATRIX
207  *  \sa glcLoadIdentity()
208  *  \sa glcLoadMatrix()
209  *  \sa glcMultMatrix()
210  *  \sa glcRotate()
211  */
glcScale(GLfloat inX,GLfloat inY)212 void APIENTRY glcScale(GLfloat inX, GLfloat inY)
213 {
214   GLfloat tempMatrix[4];
215 
216   tempMatrix[0] = inX;
217   tempMatrix[1] = 0.;
218   tempMatrix[2] = 0.;
219   tempMatrix[3] = inY;
220 
221   glcMultMatrix(tempMatrix);
222 }
223 
224 
225 
226 /** \ingroup transform
227  *  This command pushes the stack down by one, duplicating the current
228  *  \b GLC_BITMAP_MATRIX in both the top of the stack and the entry below it.
229  *  Pushing a matrix onto a full stack generates the error
230  *  \b GLC_STACK_OVERFLOW_QSO.
231  *  \sa glcPopMatrixQSO()
232  *  \sa glcGeti() with argument \b GLC_MATRIX_STACK_DEPTH_QSO
233  *  \sa glcGeti() with argument \b GLC_MAX_MATRIX_STACK_DEPTH_QSO
234  */
glcPushMatrixQSO(void)235 void APIENTRY glcPushMatrixQSO(void)
236 {
237   __GLCcontext *ctx = NULL;
238 
239   GLC_INIT_THREAD();
240 
241   /* Check if the current thread owns a context state */
242   ctx = GLC_GET_CURRENT_CONTEXT();
243   if (!ctx) {
244     __glcRaiseError(GLC_STATE_ERROR);
245     return;
246   }
247 
248   if (ctx->bitmapMatrixStackDepth >= GLC_MAX_MATRIX_STACK_DEPTH) {
249     __glcRaiseError(GLC_STACK_OVERFLOW_QSO);
250     return;
251   }
252 
253   memcpy(ctx->bitmapMatrix+4, ctx->bitmapMatrix, 4*sizeof(GLfloat));
254   ctx->bitmapMatrix += 4;
255   ctx->bitmapMatrixStackDepth++;
256   return;
257 }
258 
259 
260 
261 /** \ingroup transform
262  *  This command pops the top entry off the stack, replacing the current
263  *  \b GLC_BITMAP_MATRIX with the matrix that was the second entry in the
264  *  stack.
265  *  Popping a matrix off a stack with only one entry generates the error
266  *  \b GLC_STACK_OVERFLOW_QSO.
267  *  \sa glcPushMatrixQSO()
268  *  \sa glcGeti() with argument \b GLC_MATRIX_STACK_DEPTH_QSO
269  *  \sa glcGeti() with argument \b GLC_MAX_MATRIX_STACK_DEPTH_QSO
270  */
glcPopMatrixQSO(void)271 void APIENTRY glcPopMatrixQSO(void)
272 {
273   __GLCcontext *ctx = NULL;
274 
275   GLC_INIT_THREAD();
276 
277   /* Check if the current thread owns a context state */
278   ctx = GLC_GET_CURRENT_CONTEXT();
279   if (!ctx) {
280     __glcRaiseError(GLC_STATE_ERROR);
281     return;
282   }
283 
284   if (ctx->bitmapMatrixStackDepth <= 1) {
285     __glcRaiseError(GLC_STACK_UNDERFLOW_QSO);
286     return;
287   }
288 
289   ctx->bitmapMatrix -= 4;
290   ctx->bitmapMatrixStackDepth--;
291   return;
292 }
293