1 /* QuesoGLC
2  * A free implementation of the OpenGL Character Renderer (GLC)
3  * Copyright (c) 2002, 2004-2008, 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: context.c 841 2008-10-19 10:36:00Z bcoconni $ */
20 
21 /** \file
22  * defines the so-called "Context commands" described in chapter 3.5 of the GLC
23  * specs.
24  */
25 
26 /** \defgroup context Context State Commands
27  *  Commands to get or modify informations of the context state of the current
28  *  thread.
29  *
30  * GLC refers to the current context state whenever it executes a command.
31  * Most of its state is directly available to the user : in order to control
32  * the result of the GLC commands, the user may want to get or modify the
33  * state of the current context. This is precisely the purpose of the context
34  * state commands.
35  *
36  * \note Some GLC commands create, use or delete display lists and/or textures.
37  * The IDs of those display lists and textures are stored in the current GLC
38  * context but the display lists and the textures themselves are managed by
39  * the current \b GL context. In order not to impact the performance of
40  * error-free programs, QuesoGLC does not check if the current GL context is
41  * the same as the context where the display lists and the textures are
42  * actually stored. If the current GL context has changed meanwhile, the result
43  * of commands that refer to the corresponding display lists or textures is
44  * undefined.
45  */
46 
47 #include <string.h>
48 
49 #include "internal.h"
50 
51 
52 
53 /** \ingroup context
54  *  This command assigns the value \e inFunc to the callback function variable
55  *  identified by \e inOpCode which must be chosen in the following table.
56  *  <center>
57  *  <table>
58  *  <caption>Callback function variables</caption>
59  *    <tr>
60  *      <td>Name</td>
61  *      <td>Enumerant</td>
62  *      <td>Initial value</td>
63  *      <td>Type signature</td>
64  *    </tr>
65  *    <tr>
66  *      <td><b>GLC_OP_glcUnmappedCode</b></td>
67  *      <td>0x0020</td>
68  *      <td><b>GLC_NONE</b></td>
69  *      <td><b>GLboolean (*)(GLint)</b></td>
70  *    </tr>
71  *  </table>
72  *  </center>
73  *
74  *  The callback function can access to client data in a thread-safe manner
75  *  with glcGetPointer().
76  *  \param inOpcode Type of the callback function
77  *  \param inFunc Callback function
78  *  \sa glcGetCallbackFunc()
79  *  \sa glcGetPointer()
80  *  \sa glcDataPointer()
81  *  \sa glcRenderChar()
82  */
glcCallbackFunc(GLCenum inOpcode,GLCfunc inFunc)83 void APIENTRY glcCallbackFunc(GLCenum inOpcode, GLCfunc inFunc)
84 {
85   __GLCcontext *ctx = NULL;
86 
87   GLC_INIT_THREAD();
88 
89   /* Check parameters */
90   if (inOpcode != GLC_OP_glcUnmappedCode) {
91     __glcRaiseError(GLC_PARAMETER_ERROR);
92     return;
93   }
94 
95   /* Check if the thread has a current context */
96   ctx = GLC_GET_CURRENT_CONTEXT();
97   if (!ctx) {
98     __glcRaiseError(GLC_STATE_ERROR);
99     return;
100   }
101 
102   ctx->stringState.callback = inFunc;
103 }
104 
105 
106 
107 /** \ingroup context
108  *  This command assigns the value \e inPointer to the variable
109  *  \b GLC_DATA_POINTER. It is used for an access to client data from the
110  *  callback function assigned to the variable \b GLC_OP_glcUnmappedCode
111  *
112  *  \e glcDataPointer provides a way to store, in the GLC context, a pointer to
113  *  any data. A GLC callback function can subsequently use the command
114  *  glcGetPointer() to obtain access to those data in a thread-safe manner.
115  *  \param inPointer The pointer to assign to \b GLC_DATA_POINTER
116  *  \sa glcGetPointer()
117  *  \sa glcCallbackFunc()
118  */
glcDataPointer(GLvoid * inPointer)119 void APIENTRY glcDataPointer(GLvoid *inPointer)
120 {
121   __GLCcontext *ctx = NULL;
122 
123   GLC_INIT_THREAD();
124 
125   /* Check if the thread has a current context */
126   ctx = GLC_GET_CURRENT_CONTEXT();
127   if (!ctx) {
128     __glcRaiseError(GLC_STATE_ERROR);
129     return;
130   }
131 
132   ctx->stringState.dataPointer = inPointer;
133 }
134 
135 
136 
137 /** \ingroup context
138  *  This command causes GLC to issue a sequence of GL commands to delete all
139  *  of the GL objects it owns.
140  *
141  *  GLC uses the command \c glDeleteLists to delete all of the GL objects named
142  *  in \b GLC_LIST_OBJECT_LIST and uses the command \c glDeleteTextures to
143  *  delete all of the GL objects named in \b GLC_TEXTURE_OBJECT_LIST. When an
144  *  execution of glcDeleteGLObjects finishes, both of these lists are empty.
145  *  \note \c glcDeleteGLObjects deletes only the objects that the current
146  *  GLC context owns, not all objects in all contexts.
147  *  \note Generally speaking, it is always a good idea to call
148  *  \c glcDeleteGLObjects before calling glcDeleteContext(). It is also a good
149  *  idea to call \c glcDeleteGLObjects before changing the GL context that is
150  *  associated with the current GLC context.
151  *  \sa glcGetListi()
152  */
glcDeleteGLObjects(void)153 void APIENTRY glcDeleteGLObjects(void)
154 {
155   __GLCcontext *ctx = NULL;
156   FT_ListNode node = NULL;
157 
158   GLC_INIT_THREAD();
159 
160   /* Check if the thread has a current context */
161   ctx = GLC_GET_CURRENT_CONTEXT();
162   if (!ctx) {
163     __glcRaiseError(GLC_STATE_ERROR);
164     return;
165   }
166 
167   /* The GL objects are managed by the __GLCfaceDescriptor object. Hence we
168    * parse the __GLCfaceDescriptor stored in each __GLCfont.
169    */
170   for(node = ctx->fontList.head; node; node = node->next)
171     __glcFaceDescDestroyGLObjects(((__GLCfont*)(node->data))->faceDesc, ctx);
172 
173   /* Delete the texture used for immediate mode */
174   if (ctx->texture.id) {
175     glDeleteTextures(1, &ctx->texture.id);
176     ctx->texture.id = 0;
177     ctx->texture.width = 0;
178     ctx->texture.heigth = 0;
179   }
180 
181   /* Delete the pixel buffer object */
182   if (GLEW_ARB_pixel_buffer_object && ctx->texture.bufferObjectID) {
183     glDeleteBuffersARB(1, &ctx->texture.bufferObjectID);
184     ctx->texture.bufferObjectID = 0;
185   }
186 
187   /* Delete the vertex buffer object */
188   if (GLEW_ARB_vertex_buffer_object && ctx->atlas.bufferObjectID) {
189     glDeleteBuffersARB(1, &ctx->atlas.bufferObjectID);
190     ctx->atlas.bufferObjectID = 0;
191   }
192 }
193 
194 
195 
196 /* This internal function is used by both glcEnable/glcDisable since they
197  * actually do the same job : put a value into a member of the
198  * __GLCcontext struct. The only difference is the value that it puts.
199  */
__glcChangeState(GLCenum inAttrib,GLboolean value)200 static void __glcChangeState(GLCenum inAttrib, GLboolean value)
201 {
202   __GLCcontext *ctx = NULL;
203 
204   /* Check the parameters. */
205   assert((value == GL_TRUE) || (value == GL_FALSE));
206 
207   switch(inAttrib) {
208   case GLC_AUTO_FONT:
209   case GLC_GL_OBJECTS:
210   case GLC_MIPMAP:
211   case GLC_HINTING_QSO: /* QuesoGLC Extension */
212   case GLC_EXTRUDE_QSO: /* QuesoGLC Extension */
213   case GLC_KERNING_QSO: /* QuesoGLC Extension */
214     break;
215   default:
216     __glcRaiseError(GLC_PARAMETER_ERROR);
217     return;
218   }
219 
220   /* Check if the thread has a current context */
221   ctx = GLC_GET_CURRENT_CONTEXT();
222   if (!ctx) {
223     __glcRaiseError(GLC_STATE_ERROR);
224     return;
225   }
226 
227   /* Assigns the value to the member identified by inAttrib */
228   switch(inAttrib) {
229   case GLC_AUTO_FONT:
230     ctx->enableState.autoFont = value;
231     break;
232   case GLC_GL_OBJECTS:
233     ctx->enableState.glObjects = value;
234     break;
235   case GLC_MIPMAP:
236     ctx->enableState.mipmap = value;
237     if (ctx->atlas.id) {
238       GLuint boundTexture = 0;
239       glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)&boundTexture);
240       glBindTexture(GL_TEXTURE_2D, ctx->atlas.id);
241       if (ctx->enableState.mipmap)
242         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
243 			GL_LINEAR_MIPMAP_LINEAR);
244       else
245         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
246 			GL_LINEAR);
247       glBindTexture(GL_TEXTURE_2D, boundTexture);
248     }
249     break;
250   case GLC_HINTING_QSO:
251     ctx->enableState.hinting = value;
252     break;
253   case GLC_EXTRUDE_QSO:
254     ctx->enableState.extrude = value;
255     break;
256   case GLC_KERNING_QSO:
257     ctx->enableState.kerning = value;
258     break;
259   }
260 }
261 
262 
263 
264 /** \ingroup context
265  *  This command assigns the value \b GL_FALSE to the boolean variable
266  *  identified by \e inAttrib.
267  *  <center>
268  *  <table>
269  *  <caption>Boolean variables</caption>
270  *    <tr>
271  *      <td>Name</td> <td>Enumerant</td> <td>Initial value</td>
272  *    </tr>
273  *    <tr>
274  *      <td><b>GLC_AUTO_FONT</b></td> <td>0x0010</td> <td><b>GL_TRUE</b></td>
275  *    </tr>
276  *    <tr>
277  *      <td><b>GLC_GL_OBJECTS</b></td> <td>0x0011</td> <td><b>GL_TRUE</b></td>
278  *    </tr>
279  *    <tr>
280  *      <td><b>GLC_MIPMAP</b></td> <td>0x0012</td> <td><b>GL_TRUE</b></td>
281  *    </tr>
282  *    <tr>
283  *      <td><b>GLC_HINTING_QSO</b></td>
284  *      <td>0x8005</td>
285  *      <td><b>GL_FALSE</b></td>
286  *    </tr>
287  *    <tr>
288  *      <td><b>GLC_EXTRUDE_QSO</b></td>
289  *      <td>0x8006</td>
290  *      <td><b>GL_FALSE</b></td>
291  *    </tr>
292  *    <tr>
293  *      <td><b>GLC_KERNING_QSO</b></td>
294  *      <td>0x8007</td>
295  *      <td><b>GL_FALSE</b></td>
296  *    </tr>
297  *  </table>
298  *  </center>
299  *  \param inAttrib A symbolic constant indicating a GLC capability.
300  *  \sa glcIsEnabled()
301  *  \sa glcEnable()
302  */
glcDisable(GLCenum inAttrib)303 void APIENTRY glcDisable(GLCenum inAttrib)
304 {
305   GLC_INIT_THREAD();
306 
307   __glcChangeState(inAttrib, GL_FALSE);
308 }
309 
310 
311 
312 /** \ingroup context
313  *  This command assigns the value \b GL_TRUE to the boolean variable
314  *  identified by \e inAttrib which must be chosen in the table above.
315  *
316  *  - \b GLC_AUTO_FONT : if enabled, GLC tries to automatically find a font
317  *    among the masters to map the character code to be rendered (see also
318  *    glcRenderChar()).
319  *  - \b GLC_GL_OBJECTS : if enabled, GLC stores characters rendering commands
320  *    in GL display lists and textures (if any) in GL texture objects.
321  *  - \b GLC_MIPMAP : if enabled, texture objects used by GLC are mipmapped
322  *  - \b GLC_HINTING_QSO : if enabled, GLC uses the hinting procedures that are
323  *    available for most scalable fonts. It gives better results for characters
324  *    that are rendered at small sizes. This attribute is ignored when
325  *    \b GLC_GL_OBJECTS is enabled. Hinting may generate visual artifacts such
326  *    as "shaking outlines" if the character is animated. This attribute should
327  *    be disabled in such cases.
328  *  - \b GLC_EXTRUDE_QSO : if enabled and \b GLC_RENDER_STYLE is
329  *    \b GLC_TRIANGLE then GLC renders extruded characters with a thickness
330  *    equal to 1.0. A call to glScale3*(1., 1., \e thickness ) can be added
331  *    before the rendering commands in order to obtain the desired thickness.
332  *  - \b GLC_KERNING_QSO : if enabled, GLC uses kerning information when
333  *    rendering or measuring a string. Not all fonts have kerning informations.
334  *
335  *  \param inAttrib A symbolic constant indicating a GLC attribute.
336  *  \sa glcDisable()
337  *  \sa glcIsEnabled()
338  */
glcEnable(GLCenum inAttrib)339 void APIENTRY glcEnable(GLCenum inAttrib)
340 {
341   GLC_INIT_THREAD();
342 
343   __glcChangeState(inAttrib, GL_TRUE);
344 }
345 
346 
347 
348 /** \ingroup context
349  *  This command returns the value of the callback function variable identified
350  *  by \e inOpcode. Currently, \e inOpcode can only have the value
351  *  \b GLC_OP_glcUnmappedCode. Its initial value and the type signature are
352  *  defined in the table shown in glcCallbackFunc()'s definition.
353  *  \param inOpcode The callback function to be retrieved
354  *  \return The value of the callback function variable
355  *  \sa glcCallbackFunc()
356  */
glcGetCallbackFunc(GLCenum inOpcode)357 GLCfunc APIENTRY glcGetCallbackFunc(GLCenum inOpcode)
358 {
359   __GLCcontext *ctx = NULL;
360 
361   GLC_INIT_THREAD();
362 
363   /* Check the parameters */
364   if (inOpcode != GLC_OP_glcUnmappedCode) {
365     __glcRaiseError(GLC_PARAMETER_ERROR);
366     return GLC_NONE;
367   }
368 
369   /* Check if the thread has a current context */
370   ctx = GLC_GET_CURRENT_CONTEXT();
371   if (!ctx) {
372     __glcRaiseError(GLC_STATE_ERROR);
373     return GLC_NONE;
374   }
375 
376   return ctx->stringState.callback;
377 }
378 
379 
380 
381 /** \ingroup context
382  *  This command returns the string at offset \e inIndex from the first element
383  *  in the string list identified by \e inAttrib which must be chosen in the
384  *  table below :
385  *
386  *  <center>
387  *  <table>
388  *  <caption>String lists</caption>
389  *    <tr>
390  *      <td>Name</td>
391  *      <td>Enumerant</td>
392  *      <td>Initial value</td>
393  *      <td>Element count variable</td>
394  *    </tr>
395  *    <tr>
396  *      <td><b>GLC_CATALOG_LIST</b></td>
397  *      <td>0x0080</td>
398  *      <td>\<empty list\></td>
399  *      <td><b>GLC_CATALOG_COUNT</b></td>
400  *    </tr>
401  *  </table>
402  *  </center>
403  *
404  *  The command raises a \b GLC_PARAMETER_ERROR if \e inIndex is less than zero
405  *  or is greater than or equal to the value of the list's element count
406  *  variable.
407  *  \param inAttrib The string list attribute
408  *  \param inIndex The index from which to retrieve an element.
409  *  \return The string list element
410  *  \sa glcGetListi()
411  */
glcGetListc(GLCenum inAttrib,GLint inIndex)412 const GLCchar* APIENTRY glcGetListc(GLCenum inAttrib, GLint inIndex)
413 {
414   __GLCcontext *ctx = NULL;
415   GLCchar8* catalog = NULL;
416   GLCchar* buffer = NULL;
417   size_t length = 0;
418 
419   GLC_INIT_THREAD();
420 
421   /* Check the parameters */
422   if (inAttrib != GLC_CATALOG_LIST) {
423     __glcRaiseError(GLC_PARAMETER_ERROR);
424     return GLC_NONE;
425   }
426 
427   /* NOTE : at this stage we can not verify if inIndex is greater than or equal
428    * to the last element index. In order to perform such a verification we
429    * would need to have the current context state but GLC specs tells that we
430    * should first check the parameters _then_ the current context (section 2.2
431    * of specs). We are done !
432    */
433   if (inIndex < 0) {
434     __glcRaiseError(GLC_PARAMETER_ERROR);
435     return GLC_NONE;
436   }
437 
438   /* Check if the thread has a current context */
439   ctx = GLC_GET_CURRENT_CONTEXT();
440   if (!ctx) {
441     __glcRaiseError(GLC_STATE_ERROR);
442     return GLC_NONE;
443   }
444 
445   catalog = __glcContextGetCatalogPath(ctx, inIndex);
446   if (!catalog)
447     return GLC_NONE;
448 
449   /* Three remarks have to be made concerning the following code :
450    * 1. We do not return a pointer that points to the actual location of the
451    *    string in order to prevent the user to modify it. Instead QuesoGLC
452    *    returns a pointer that points to a copy of the requested data.
453    * 2. File names are not translated from one string format (UCS1, UCS2, ...)
454    *    to another because it is not relevant. We make the assumption that
455    *    the user gave us the file names in the current coding of his/her OS and
456    *    that this coding will not change during the program execution even when
457    *    glcStringType() is called.
458    * 3. There are few chances that this code is executed in a critical loop
459    *    then there is no need to care about optimization.
460    */
461 
462   /* Grmmff, is the use of strlen() adequate here ?
463    * What if 'catalog' is encoded in UCS2 format or any other weird format ?
464    */
465   length = strlen((const char*) catalog) + 1;
466 
467   buffer = __glcContextQueryBuffer(ctx, length * sizeof(char));
468   if (!buffer)
469     return GLC_NONE; /* GLC_RESOURCE_ERROR has been raised */
470   strncpy((char*)buffer, (const char*)catalog, length);
471   return buffer;
472 }
473 
474 
475 
476 /** \ingroup context
477  *  This command returns the integer at offset \e inIndex from the first
478  *  element in the integer list identified by \e inAttrib.
479  *
480  *  You can choose from the following integer lists, listed below with their
481  *  element count variables :
482  *  <center>
483  *  <table>
484  *  <caption>Integer lists</caption>
485  *    <tr>
486  *      <td>Name</td>
487  *      <td>Enumerant</td>
488  *      <td>Initial value</td>
489  *      <td>Element count variable</td>
490  *    </tr>
491  *    <tr>
492  *      <td><b>GLC_CURRENT_FONT_LIST</b></td>
493  *      <td>0x0090</td>
494  *      <td>\<empty list\></td>
495  *      <td><b>GLC_CURRENT_FONT_COUNT</b></td>
496  *    </tr>
497  *    <tr>
498  *      <td><b>GLC_FONT_LIST</b></td>
499  *      <td>0x0091</td>
500  *      <td>\<empty list\></td>
501  *      <td><b>GLC_FONT_COUNT</b></td>
502  *    </tr>
503  *    <tr>
504  *      <td><b>GLC_LIST_OBJECT_LIST</b></td>
505  *      <td>0x0092</td>
506  *      <td>\<empty list\></td>
507  *      <td><b>GLC_LIST_OBJECT_COUNT</b></td>
508  *    </tr>
509  *    <tr>
510  *      <td><b>GLC_TEXTURE_OBJECT_LIST</b></td>
511  *      <td>0x0093</td>
512  *      <td>\<empty list\></td>
513  *      <td><b>GLC_TEXTURE_OBJECT_COUNT</b></td>
514  *    </tr>
515  *    <tr>
516  *      <td><b>GLC_BUFFER_OBJECT_LIST_QSO</b></td>
517  *      <td>0x800F</td>
518  *      <td>\<empty list\></td>
519  *      <td><b>GLC_BUFFER_OBJECT_COUNT_QSO</b></td>
520  *    </tr>
521  *  </table>
522  *  </center>
523  *
524  *  The command raises a \b GLC_PARAMETER_ERROR if \e inIndex is less than zero
525  *  or is greater than or equal to the value of the list's element count
526  *  variable.
527  *  \param inAttrib The integer list attribute
528  *  \param inIndex The index from which to retrieve the element.
529  *  \return The element from the integer list.
530  *  \sa glcGetListc()
531  */
glcGetListi(GLCenum inAttrib,GLint inIndex)532 GLint APIENTRY glcGetListi(GLCenum inAttrib, GLint inIndex)
533 {
534   __GLCcontext *ctx = NULL;
535   FT_ListNode node = NULL;
536 
537   GLC_INIT_THREAD();
538 
539   /* Check parameters */
540   switch(inAttrib) {
541   case GLC_CURRENT_FONT_LIST:
542   case GLC_FONT_LIST:
543   case GLC_LIST_OBJECT_LIST:
544   case GLC_TEXTURE_OBJECT_LIST:
545     break;
546   case GLC_BUFFER_OBJECT_LIST_QSO: /* QuesoGLC extension */
547     /* This parameter is available only if the corresponding GL extensions are
548      * supported by the GL driver.
549      */
550     if (GLEW_ARB_vertex_buffer_object || GLEW_ARB_pixel_buffer_object)
551       break;
552     else {
553       __glcRaiseError(GLC_PARAMETER_ERROR);
554       return 0;
555     }
556   default:
557     __glcRaiseError(GLC_PARAMETER_ERROR);
558     return 0;
559   }
560 
561   /* NOTE : at this stage we can not verify if inIndex is greater than or equal
562    * to the last element index. In order to perform such a verification we
563    * would need to have the current context states but GLC specs says that we
564    * should first check the parameters _then_ the current context (section 2.2
565    * of specs). We are done !
566    */
567   if (inIndex < 0) {
568     __glcRaiseError(GLC_PARAMETER_ERROR);
569     return 0;
570   }
571 
572   /* Check if the thread has a current context */
573   ctx = GLC_GET_CURRENT_CONTEXT();
574   if (!ctx) {
575     __glcRaiseError(GLC_STATE_ERROR);
576     return 0;
577   }
578 
579   /* Perform the final part of verifications (the one which needs
580    * the current context's states) then return the requested value.
581    */
582   switch(inAttrib) {
583   case GLC_CURRENT_FONT_LIST:
584     for (node = ctx->currentFontList.head; inIndex && node;
585          node = node->next, inIndex--);
586 
587     if (node)
588       return ((__GLCfont*)node->data)->id;
589     else
590       break;
591   case GLC_FONT_LIST:
592     for (node = ctx->fontList.head; inIndex && node;
593          node = node->next, inIndex--);
594 
595     if (node)
596       return ((__GLCfont*)node->data)->id;
597     else
598       break;
599   case GLC_LIST_OBJECT_LIST:
600     /* In order to get the display list name, we have to perform a search
601      * through the list of display lists of every face descriptor.
602      */
603     for (node = ctx->fontList.head; node; node = node->next) {
604       __GLCfaceDescriptor* faceDesc =
605 		(__GLCfaceDescriptor*)(((__GLCfont*)(node->data))->faceDesc);
606       FT_ListNode glyphNode = NULL;
607 
608       for (glyphNode = faceDesc->glyphList.head; glyphNode;
609 	   glyphNode = glyphNode->next) {
610 	__GLCglyph* glyph = (__GLCglyph*)glyphNode;
611 	int count = __glcGlyphGetDisplayListCount(glyph);
612 
613 	if (inIndex < count)
614 	  return __glcGlyphGetDisplayList(glyph, inIndex);
615 	else
616 	  inIndex -= count;
617       }
618     }
619     break;
620   case GLC_TEXTURE_OBJECT_LIST:
621     switch(inIndex) {
622       /* QuesoGLC uses at most 2 textures : one for immediate mode rendering and
623        * another one for the texture atlas. That's all. They are virtually
624        * stored in the following order : texture for immediate mode first, then
625        * texture atlas.
626        */
627       case 0:
628 	if (ctx->texture.id)
629 	  return ctx->texture.id;
630 	/* If the texture for immediate mode does not exist, then the first
631 	 * texture is the texture atlas.
632 	 * NOTE: if the texture atlas is created first and the texture for
633 	 * immediate mode is created after then this algorithm leads to a
634 	 * modification of the order which is not satisfying...
635 	 */
636 	if (ctx->atlas.id)
637 	  return ctx->atlas.id;
638 	break;
639       case 1:
640 	if ((ctx->texture.id) && (ctx->atlas.id))
641 	  return ctx->atlas.id;
642 	break;
643       default:
644 	break;
645     }
646     break;
647   case GLC_BUFFER_OBJECT_LIST_QSO: /* QuesoGLC extension */
648     switch(inIndex) {
649       /* QuesoGLC uses at most 2 buffer objects : one PBO for immediate mode
650        * rendering and one VBO for the texture atlas. That's all. They are
651        * virtually stored in the following order : PBO for immediate mode first,
652        * then VBO for texture atlas.
653        */
654       case 0:
655 	if (ctx->texture.bufferObjectID)
656 	  return ctx->texture.bufferObjectID;
657 	/* If the PBO for immediate mode does not exist, then the first buffer
658 	 * object is the VBO for the texture atlas.
659 	 * NOTE: if the texture atlas is created first and the PBO for
660 	 * immediate mode is created after then this algorithm leads to a
661 	 * modification of the order in which buffer objects are reported which
662 	 * is not satisfying...
663 	 */
664 	if (ctx->atlas.bufferObjectID)
665 	  return ctx->atlas.bufferObjectID;
666 	break;
667       case 1:
668 	if ((ctx->texture.bufferObjectID) && (ctx->atlas.bufferObjectID))
669 	  return ctx->atlas.bufferObjectID;
670 	break;
671       default:
672 	break;
673     }
674 
675     if (ctx->texture.bufferObjectID)
676       inIndex--;
677     if (ctx->atlas.bufferObjectID)
678       inIndex--;
679 
680     for (node = ctx->fontList.head; node; node = node->next) {
681       __GLCfaceDescriptor* faceDesc =
682 		(__GLCfaceDescriptor*)(((__GLCfont*)(node->data))->faceDesc);
683       FT_ListNode glyphNode = NULL;
684 
685       for (glyphNode = faceDesc->glyphList.head; glyphNode;
686 	   glyphNode = glyphNode->next) {
687 	__GLCglyph* glyph = (__GLCglyph*)glyphNode;
688 	int count = __glcGlyphGetBufferObjectCount(glyph);
689 
690 	if (inIndex < count)
691 	  return __glcGlyphGetBufferObject(glyph, inIndex);
692 	else
693 	  inIndex -= count;
694       }
695     }
696     break;
697   }
698 
699   __glcRaiseError(GLC_PARAMETER_ERROR);
700   return 0;
701 }
702 
703 
704 
705 /** \ingroup context
706  *  This command returns the value of the pointer variable identified by
707  *  \e inAttrib.
708  *  <center>
709  *  <table>
710  *  <caption>Pointer variables</caption>
711  *    <tr>
712  *      <td>Name</td> <td>Enumerant</td> <td>Initial value</td>
713  *    </tr>
714  *    <tr>
715  *      <td><b>GLC_DATA_POINTER</b></td>
716  *      <td>0x00A0</td>
717  *      <td><b>GLC_NONE</b></td>
718  *    </tr>
719  *  </table>
720  *  </center>
721  *  \param inAttrib The pointer category
722  *  \return The pointer
723  *  \sa glcDataPointer()
724  */
glcGetPointer(GLCenum inAttrib)725 GLvoid* APIENTRY glcGetPointer(GLCenum inAttrib)
726 {
727   __GLCcontext *ctx = NULL;
728 
729   GLC_INIT_THREAD();
730 
731   /* Check the parameter */
732   if (inAttrib != GLC_DATA_POINTER) {
733     __glcRaiseError(GLC_PARAMETER_ERROR);
734     return GLC_NONE;
735   }
736 
737   /* Check if the thread has a current context */
738   ctx = GLC_GET_CURRENT_CONTEXT();
739   if (!ctx) {
740     __glcRaiseError(GLC_STATE_ERROR);
741     return GLC_NONE;
742   }
743 
744   return ctx->stringState.dataPointer;
745 }
746 
747 
748 
749 /** \ingroup context
750  *  This command returns the value of the string constant identified by
751  *  \e inAttrib. String constants must be chosen in the table below :
752  *  <center>
753  *  <table>
754  *  <caption>String constants</caption>
755  *    <tr>
756  *      <td>Name</td> <td>Enumerant</td>
757  *    </tr>
758  *    <tr>
759  *      <td><b>GLC_EXTENSIONS</b></td> <td>0x00B0</td>
760  *    </tr>
761  *    <tr>
762  *      <td><b>GLC_RELEASE</b></td> <td>0x00B1</td>
763  *    </tr>
764  *    <tr>
765  *      <td><b>GLC_VENDOR</b></td> <td>0x00B2</td>
766  *    </tr>
767  *  </table>
768  *  </center>
769  *  \param inAttrib The attribute that identifies the string constant
770  *  \return The string constant.
771  *  \sa glcGetf()
772  *  \sa glcGeti()
773  *  \sa glcGetfv()
774  *  \sa glcGetPointer()
775  */
glcGetc(GLCenum inAttrib)776 const GLCchar* APIENTRY glcGetc(GLCenum inAttrib)
777 {
778   static const char* __glcExtensions1 = "GLC_QSO_attrib_stack";
779   static const char* __glcExtensions2 = " GLC_QSO_buffer_object";
780   static const char* __glcExtensions3 = " GLC_QSO_extrude GLC_QSO_hinting"
781     " GLC_QSO_kerning GLC_QSO_matrix_stack GLC_QSO_utf8 GLC_SGI_full_name";
782   static const GLCchar8* __glcVendor = (const GLCchar8*) "The QuesoGLC Project";
783 #ifdef HAVE_CONFIG_H
784   static const GLCchar8* __glcRelease = (const GLCchar8*) PACKAGE_VERSION;
785 #else
786   static const GLCchar8* __glcRelease = (const GLCchar8*) QUESOGLC_VERSION;
787 #endif
788 
789   __GLCcontext *ctx = NULL;
790 
791   GLC_INIT_THREAD();
792 
793   /* Check the parameters */
794   switch(inAttrib) {
795   case GLC_EXTENSIONS:
796   case GLC_RELEASE:
797   case GLC_VENDOR:
798     break;
799   default:
800     __glcRaiseError(GLC_PARAMETER_ERROR);
801     return GLC_NONE;
802   }
803 
804   /* Check if the thread has a current context */
805   ctx = GLC_GET_CURRENT_CONTEXT();
806   if (!ctx) {
807     __glcRaiseError(GLC_STATE_ERROR);
808     return GLC_NONE;
809   }
810 
811   /* Translate the string to the relevant Unicode format */
812   switch(inAttrib) {
813   case GLC_EXTENSIONS:
814     {
815       GLCchar8 __glcExtensions[256];
816 
817       assert((strlen(__glcExtensions1) + strlen(__glcExtensions2)
818 	      + strlen(__glcExtensions3)) <= 256);
819 
820       /* Build the extensions string depending on the available GL extensions */
821       strcpy((char*)__glcExtensions, __glcExtensions1);
822       if (GLEW_ARB_vertex_buffer_object || GLEW_ARB_pixel_buffer_object)
823 	strcat((char*)__glcExtensions, __glcExtensions2);
824       strcat((char*)__glcExtensions, __glcExtensions3);
825 
826       return __glcConvertFromUtf8ToBuffer(ctx, __glcExtensions,
827 					  ctx->stringState.stringType);
828     }
829   case GLC_RELEASE:
830     return __glcConvertFromUtf8ToBuffer(ctx, __glcRelease,
831 					ctx->stringState.stringType);
832   case GLC_VENDOR:
833     return __glcConvertFromUtf8ToBuffer(ctx, __glcVendor,
834 					ctx->stringState.stringType);
835   default:
836     return GLC_NONE;
837   }
838 }
839 
840 
841 
842 /** \ingroup context
843  *  This command returns the value of the floating point variable identified
844  *  by \e inAttrib.
845  *  <center>
846  *  <table>
847  *    <caption>Float point variables</caption>
848  *    <tr>
849  *      <td>Name</td> <td>Enumerant</td> <td>Initial value</td>
850  *    </tr>
851  *    <tr>
852  *      <td><b>GLC_RESOLUTION</b></td> <td>0x00C0</td> <td>0.0</td>
853  *    </tr>
854  *  </table>
855  *  </center>
856  *  \param inAttrib The parameter value to be returned.
857  *  \return The current value of the floating point variable.
858  *  \sa glcGetc()
859  *  \sa glcGeti()
860  *  \sa glcGetfv()
861  *  \sa glcGetPointer()
862  */
glcGetf(GLCenum inAttrib)863 GLfloat APIENTRY glcGetf(GLCenum inAttrib)
864 {
865   __GLCcontext *ctx = NULL;
866 
867   GLC_INIT_THREAD();
868 
869   /* Check the parameter */
870   if (inAttrib != GLC_RESOLUTION) {
871     __glcRaiseError(GLC_PARAMETER_ERROR);
872     return 0.f;
873   }
874 
875   /* Check if the thread has a current context */
876   ctx = GLC_GET_CURRENT_CONTEXT();
877   if (!ctx) {
878     __glcRaiseError(GLC_STATE_ERROR);
879     return 0.f;
880   }
881 
882   return ctx->renderState.resolution;
883 }
884 
885 
886 
887 /** \ingroup context
888  *  This command stores into \e outVec the value of the floating point vector
889  *  identified by \e inAttrib. If the command does not raise an error, it
890  *  returns \e outVec, otherwise it returns a \b NULL value.
891  *  <center>
892  *  <table>
893  *  <caption>Floating point vector variables</caption>
894  *  <tr>
895  *    <td>Name</td> <td>Enumerant</td> <td>Initial value</td>
896  *  </tr>
897  *  <tr>
898  *    <td><b>GLC_BITMAP_MATRIX</b></td> <td>0x00D0</td> <td>[ 1. 0. 0. 1.]</td>
899  *  </tr>
900  *  </table>
901  *  </center>
902  *
903  *  The command raises \b GLC_PARAMETER_ERROR if \e outVec is NULL.
904  *  \param inAttrib The parameter value to be returned
905  *  \param outVec Specifies where to store the return value
906  *  \return The current value of the floating point vector variable
907  *  \sa glcGetf()
908  *  \sa glcGeti()
909  *  \sa glcGetc()
910  *  \sa glcGetPointer()
911  */
glcGetfv(GLCenum inAttrib,GLfloat * outVec)912 GLfloat* APIENTRY glcGetfv(GLCenum inAttrib, GLfloat* outVec)
913 {
914   __GLCcontext *ctx = NULL;
915 
916   GLC_INIT_THREAD();
917 
918   assert(outVec);
919 
920   /* Check the parameters */
921   if (inAttrib != GLC_BITMAP_MATRIX) {
922     __glcRaiseError(GLC_PARAMETER_ERROR);
923     return NULL;
924   }
925 
926   /* Check if the thread has a current context */
927   ctx = GLC_GET_CURRENT_CONTEXT();
928   if (!ctx) {
929     __glcRaiseError(GLC_STATE_ERROR);
930     return NULL;
931   }
932 
933   memcpy(outVec, ctx->bitmapMatrix, 4 * sizeof(GLfloat));
934 
935   return outVec;
936 }
937 
938 
939 
940 /** \ingroup context
941  *  This command returns the value of the integer variable or constant
942  *  identified by \e inAttrib.
943  *  <center>
944  *  <table>
945  *  <caption>Integer variables and constants</caption>
946  *  <tr>
947  *    <td>Name</td> <td>Enumerant</td> <td>Initial value</td>
948  *  </tr>
949  *  <tr>
950  *    <td><b>GLC_CATALOG_COUNT</b></td>
951  *    <td>0x00E0</td>
952  *    <td>\<implementation specific\></td>
953  *  </tr>
954  *  <tr>
955  *    <td><b>GLC_CURRENT_FONT_COUNT</b></td> <td>0x00E1</td> <td>0</td>
956  *  </tr>
957  *  <tr>
958  *    <td><b>GLC_FONT_COUNT</b></td> <td>0x00E2</td> <td>0</td>
959  *  </tr>
960  *  <tr>
961  *    <td><b>GLC_LIST_OBJECT_COUNT</b></td> <td>0x00E3</td> <td>0</td>
962  *  </tr>
963  *  <tr>
964  *    <td><b>GLC_MASTER_COUNT</b></td>
965  *    <td>0x00E4</td>
966  *    <td>\<implementation specific\></td>
967  *  </tr>
968  *  <tr>
969  *    <td><b>GLC_MEASURED_CHAR_COUNT</b></td> <td>0x00E5</td> <td>0</td>
970  *  </tr>
971  *  <tr>
972  *    <td><b>GLC_RENDER_STYLE</b></td>
973  *    <td>0x00E6</td>
974  *    <td><b>GLC_BITMAP</b></td>
975  *  </tr>
976  *  <tr>
977  *    <td><b>GLC_REPLACEMENT_CODE</b></td> <td>0x00E7</td> <td>0</td>
978  *  </tr>
979  *  <tr>
980  *    <td><b>GLC_STRING_TYPE</b></td> <td>0x00E8</td> <td><b>GLC_UCS1</b></td>
981  *  </tr>
982  *  <tr>
983  *    <td><b>GLC_TEXTURE_OBJECT_COUNT</b></td> <td>0x00E9</td> <td>0</td>
984  *  </tr>
985  *  <tr>
986  *    <td><b>GLC_VERSION_MAJOR</b></td>
987  *    <td>0x00EA</td>
988  *    <td>\<implementation specific\></td>
989  *  </tr>
990  *  <tr>
991  *    <td><b>GLC_VERSION_MINOR</b></td>
992  *    <td>0x00EB</td>
993  *    <td>\<implementation specific\></td>
994  *  </tr>
995  *  <tr>
996  *    <td><b>GLC_MATRIX_STACK_DEPTH_QSO</b></td> <td>0x8008</td> <td>0</td>
997  *  </tr>
998  *  <tr>
999  *    <td><b>GLC_MAX_MATRIX_STACK_DEPTH_QSO</b></td>
1000  *    <td>0x8009</td>
1001  *    <td>\<implementation specific\></td>
1002  *  </tr>
1003  *  <tr>
1004  *    <td><b>GLC_ATTRIB_STACK_DEPTH_QSO</b></td> <td>0x800C</td> <td>0</td>
1005  *  </tr>
1006  *  <tr>
1007  *    <td><b>GLC_MAX_ATTRIB_STACK_DEPTH_QSO</b></td>
1008  *    <td>0x800D</td>
1009  *    <td>\<implementation specific\></td>
1010  *  </tr>
1011  *  <tr>
1012  *    <td><b>GLC_BUFFER_OBJECT_COUNT_QSO</b></td> <td>0x800E</td> <td>0</td>
1013  *  </tr>
1014  *  </table>
1015  *  </center>
1016  *  \param inAttrib Attribute for which an integer variable is requested.
1017  *  \return The value or values of the integer variable.
1018  *  \sa glcGetc()
1019  *  \sa glcGetf()
1020  *  \sa glcGetfv()
1021  *  \sa glcGetPointer()
1022  */
glcGeti(GLCenum inAttrib)1023 GLint APIENTRY glcGeti(GLCenum inAttrib)
1024 {
1025   __GLCcontext *ctx = NULL;
1026   FT_ListNode node = NULL;
1027   GLint count = 0;
1028 
1029   GLC_INIT_THREAD();
1030 
1031   /* Check the parameters */
1032   switch(inAttrib) {
1033   case GLC_CATALOG_COUNT:
1034   case GLC_CURRENT_FONT_COUNT:
1035   case GLC_FONT_COUNT:
1036   case GLC_LIST_OBJECT_COUNT:
1037   case GLC_MASTER_COUNT:
1038   case GLC_MEASURED_CHAR_COUNT:
1039   case GLC_RENDER_STYLE:
1040   case GLC_REPLACEMENT_CODE:
1041   case GLC_STRING_TYPE:
1042   case GLC_TEXTURE_OBJECT_COUNT:
1043   case GLC_VERSION_MAJOR:
1044   case GLC_VERSION_MINOR:
1045   case GLC_MATRIX_STACK_DEPTH_QSO:     /* QuesoGLC extension */
1046   case GLC_MAX_MATRIX_STACK_DEPTH_QSO: /* QuesoGLC extension */
1047   case GLC_ATTRIB_STACK_DEPTH_QSO:     /* QuesoGLC extension */
1048   case GLC_MAX_ATTRIB_STACK_DEPTH_QSO: /* QuesoGLC extension */
1049     break;
1050   case GLC_BUFFER_OBJECT_COUNT_QSO:    /* QuesoGLC extension */
1051     /* This parameter is available only if the corresponding GL extensions are
1052      * supported by the GL driver.
1053      */
1054     if (GLEW_ARB_vertex_buffer_object || GLEW_ARB_pixel_buffer_object)
1055       break;
1056     else {
1057       __glcRaiseError(GLC_PARAMETER_ERROR);
1058       return 0;
1059     }
1060   default:
1061     __glcRaiseError(GLC_PARAMETER_ERROR);
1062     return 0;
1063   }
1064 
1065   /* Check if the thread has a current context */
1066   ctx = GLC_GET_CURRENT_CONTEXT();
1067   if (!ctx) {
1068     __glcRaiseError(GLC_STATE_ERROR);
1069     return 0;
1070   }
1071 
1072   /* Returns the requested value */
1073   switch(inAttrib) {
1074   case GLC_CATALOG_COUNT:
1075     return GLC_ARRAY_LENGTH(ctx->catalogList);
1076   case GLC_CURRENT_FONT_COUNT:
1077     for (node = ctx->currentFontList.head, count = 0; node;
1078 	 node = node->next, count++);
1079     return count;
1080   case GLC_FONT_COUNT:
1081     for (count = 0, node = ctx->fontList.head; node;
1082 	 node = node->next, count++);
1083     return count;
1084   case GLC_LIST_OBJECT_COUNT:
1085     for (node = ctx->fontList.head; node; node = node->next) {
1086       __GLCfaceDescriptor* faceDesc =
1087 		(__GLCfaceDescriptor*)(((__GLCfont*)(node->data))->faceDesc);
1088       FT_ListNode glyphNode = NULL;
1089 
1090       for (glyphNode = faceDesc->glyphList.head; glyphNode;
1091 	   glyphNode = glyphNode->next) {
1092 	__GLCglyph* glyph = (__GLCglyph*)glyphNode;
1093 
1094 	count += __glcGlyphGetDisplayListCount(glyph);
1095       }
1096     }
1097     return count;
1098   case GLC_MASTER_COUNT:
1099     return GLC_ARRAY_LENGTH(ctx->masterHashTable);
1100   case GLC_MEASURED_CHAR_COUNT:
1101     return GLC_ARRAY_LENGTH(ctx->measurementBuffer);
1102   case GLC_RENDER_STYLE:
1103     return ctx->renderState.renderStyle;
1104   case GLC_REPLACEMENT_CODE:
1105     /* Return the replacement character converted to the current string type */
1106     return __glcConvertUcs4ToGLint(ctx, ctx->stringState.replacementCode);
1107   case GLC_STRING_TYPE:
1108     return ctx->stringState.stringType;
1109   case GLC_TEXTURE_OBJECT_COUNT:
1110     count += (ctx->texture.id ? 1 : 0);
1111     count += (ctx->atlas.id ? 1 : 0);
1112     return count;
1113   case GLC_VERSION_MAJOR:
1114     return __glcCommonArea.versionMajor;
1115   case GLC_VERSION_MINOR:
1116     return __glcCommonArea.versionMinor;
1117   case GLC_MATRIX_STACK_DEPTH_QSO:     /* QuesoGLC extension */
1118     return ctx->bitmapMatrixStackDepth;
1119   case GLC_MAX_MATRIX_STACK_DEPTH_QSO: /* QuesoGLC extension */
1120     return GLC_MAX_MATRIX_STACK_DEPTH;
1121   case GLC_ATTRIB_STACK_DEPTH_QSO:     /* QuesoGLC extension */
1122     return ctx->attribStackDepth;
1123   case GLC_MAX_ATTRIB_STACK_DEPTH_QSO: /* QuesoGLC extension */
1124     return GLC_MAX_ATTRIB_STACK_DEPTH;
1125   case GLC_BUFFER_OBJECT_COUNT_QSO:    /* QuesoGLC extension */
1126     count += (ctx->texture.bufferObjectID ? 1 : 0);
1127     count += (ctx->atlas.bufferObjectID ? 1 : 0);
1128     for (node = ctx->fontList.head; node; node = node->next) {
1129       __GLCfaceDescriptor* faceDesc =
1130 		(__GLCfaceDescriptor*)(((__GLCfont*)(node->data))->faceDesc);
1131       FT_ListNode glyphNode = NULL;
1132 
1133       for (glyphNode = faceDesc->glyphList.head; glyphNode;
1134 	   glyphNode = glyphNode->next) {
1135 	__GLCglyph* glyph = (__GLCglyph*)glyphNode;
1136 
1137 	count += __glcGlyphGetBufferObjectCount(glyph);
1138       }
1139     }
1140     return count;
1141   }
1142 
1143   return 0;
1144 }
1145 
1146 
1147 
1148 /** \ingroup context
1149  *  This command returns \b GL_TRUE if the value of the boolean variable
1150  *  identified by inAttrib is \b GL_TRUE <em>(quoted from the specs ^_^)</em>
1151  *
1152  *  Attributes that can be enabled or disabled are listed on the glcDisable()
1153  *  description.
1154  *  \param inAttrib The attribute to be tested
1155  *  \return The state of the attribute \e inAttrib.
1156  *  \sa glcEnable()
1157  *  \sa glcDisable()
1158  */
glcIsEnabled(GLCenum inAttrib)1159 GLboolean APIENTRY glcIsEnabled(GLCenum inAttrib)
1160 {
1161   __GLCcontext *ctx = NULL;
1162 
1163   GLC_INIT_THREAD();
1164 
1165   /* Check the parameters */
1166   switch(inAttrib) {
1167   case GLC_AUTO_FONT:
1168   case GLC_GL_OBJECTS:
1169   case GLC_MIPMAP:
1170   case GLC_HINTING_QSO: /* QuesoGLC Extension */
1171   case GLC_EXTRUDE_QSO: /* QuesoGLC Extension */
1172   case GLC_KERNING_QSO: /* QuesoGLC Extension */
1173     break;
1174   default:
1175     __glcRaiseError(GLC_PARAMETER_ERROR);
1176     return GL_FALSE;
1177   }
1178 
1179   /* Check if the thread has a current context */
1180   ctx = GLC_GET_CURRENT_CONTEXT();
1181   if (!ctx) {
1182     __glcRaiseError(GLC_STATE_ERROR);
1183     return GL_FALSE;
1184   }
1185 
1186   /* Returns the requested value */
1187   switch(inAttrib) {
1188   case GLC_AUTO_FONT:
1189     return ctx->enableState.autoFont;
1190   case GLC_GL_OBJECTS:
1191     return ctx->enableState.glObjects;
1192   case GLC_MIPMAP:
1193     return ctx->enableState.mipmap;
1194   case GLC_HINTING_QSO:
1195     return ctx->enableState.hinting;
1196   case GLC_EXTRUDE_QSO:
1197     return ctx->enableState.extrude;
1198   case GLC_KERNING_QSO:
1199     return ctx->enableState.kerning;
1200   }
1201 
1202   return GL_FALSE;
1203 }
1204 
1205 
1206 
1207 /** \ingroup context
1208  *  This command assigns the value \e inStringType to the variable
1209  *  \b GLC_STRING_TYPE. The string types are listed in the table
1210  *  below :
1211  *  <center>
1212  *  <table>
1213  *  <caption>String types</caption>
1214  *  <tr>
1215  *    <td>Name</td> <td>Enumerant</td> <td>Type of characters</td>
1216  *  </tr>
1217  *  <tr>
1218  *    <td><b>GLC_UCS1</b></td> <td>0x0110</td> <td>GLubyte</td>
1219  *  </tr>
1220  *  <tr>
1221  *    <td><b>GLC_UCS2</b></td> <td>0x0111</td> <td>GLushort</td>
1222  *  </tr>
1223  *  <tr>
1224  *    <td><b>GLC_UCS4</b></td> <td>0x0112</td> <td>GLuint</td>
1225  *  </tr>
1226  *  <tr>
1227  *    <td><b>GLC_UTF8_QSO</b></td>
1228  *    <td>0x8004</td>
1229  *    <td>\<character dependent\></td>
1230  *  </tr>
1231  *  </table>
1232  *  </center>
1233  *
1234  *  Every character string used in the GLC API is represented as a
1235  *  zero-terminated array, unless otherwise specified. The value of the
1236  *  variable \b GLC_STRING_TYPE determines the interpretation of the array. The
1237  *  values \b GLC_UCS1, \b GLC_UCS2, \b GLC_UCS4 and \b GLC_UTF8_QSO indicate
1238  *  how each element of the string should be interpreted. Currently QuesoGLC
1239  *  supports UCS1, UCS2, UCS4 and UTF-8 formats as defined in the Unicode 4.0.1
1240  *  and ISO/IEC 10646:2003 standards. The initial value of \b GLC_STRING_TYPE
1241  *  is \b GLC_UCS1.
1242  *
1243  *  \note Currently, the string formats UCS2 and UCS4 are interpreted according
1244  *  to the underlying platform endianess. If the strings are provided in a
1245  *  different endianess than the platform's, the client must translate the
1246  *  strings in the correct endianess.
1247  *
1248  *  The value of a character code in a returned string may exceed the range
1249  *  of the character encoding selected by \b GLC_STRING_TYPE. In this case,
1250  *  the returned character is converted to a character sequence
1251  *  <em>\\\<hexcode\></em>, where \\ is the character REVERSE SOLIDUS (U+5C),
1252  *  \< is the character LESS-THAN SIGN (U+3C), \> is the character
1253  *  GREATER-THAN SIGN (U+3E), and \e hexcode is the original character code
1254  *  represented as a sequence of hexadecimal digits. The sequence has no
1255  *  leading zeros, and alphabetic digits are in upper case.
1256  *  \param inStringType Value to assign to \b GLC_STRING_TYPE
1257  *  \sa glcGeti() with argument \b GLC_STRING_TYPE
1258  */
glcStringType(GLCenum inStringType)1259 void APIENTRY glcStringType(GLCenum inStringType)
1260 {
1261   __GLCcontext *ctx = NULL;
1262 
1263   GLC_INIT_THREAD();
1264 
1265   /* Check the parameters */
1266   switch(inStringType) {
1267   case GLC_UCS1:
1268   case GLC_UCS2:
1269   case GLC_UCS4:
1270   case GLC_UTF8_QSO: /* QuesoGLC Extension */
1271     break;
1272   default:
1273     __glcRaiseError(GLC_PARAMETER_ERROR);
1274     return;
1275   }
1276 
1277   /* Check if the thread has a current context */
1278   ctx = GLC_GET_CURRENT_CONTEXT();
1279   if (!ctx) {
1280     __glcRaiseError(GLC_STATE_ERROR);
1281     return;
1282   }
1283 
1284   ctx->stringState.stringType = inStringType;
1285   return;
1286 }
1287 
1288 
1289 
1290 /** \ingroup context
1291  *  This command provides a means to save groups of state variables. It takes a
1292  *  OR of symbolic constants indicating which groups of state variables to push
1293  *  onto the attribute stack. Each constant refers to a group of state
1294  *  variables.
1295  *  <center>
1296  *  <table>
1297  *  <caption>Group attributes</caption>
1298  *  <tr>
1299  *    <td>Group attribute</td> <td>Name</td> <td>Enumerant</td>
1300  *  </tr>
1301  *  <tr>
1302  *    <td>enable</td> <td><b>GLC_ENABLE_BIT_QSO</b></td> <td>0x0001</td>
1303  *  </tr>
1304  *  <tr>
1305  *    <td>render</td> <td><b>GLC_RENDER_BIT_QSO</b></td> <td>0x0002</td>
1306  *  </tr>
1307  *  <tr>
1308  *    <td>string</td> <td><b>GLC_STRING_BIT_QSO</b></td> <td>0x0004</td>
1309  *  </tr>
1310  *  <tr>
1311  *    <td> </td> <td><b>GLC_GL_ATTRIB_BIT_QSO</b></td> <td>0x0008</td>
1312  *  </tr>
1313  *  <tr>
1314  *    <td> </td> <td><b>GLC_ALL_ATTRIBS_BIT_QSO</b></td> <td>0xFFFF</td>
1315  *  </tr>
1316  *  </table>
1317  *  </center>
1318  *
1319  *  The classification of each variable into a group is indicated in the
1320  *  following table of state variables.
1321  *  <center>
1322  *  <table>
1323  *  <caption>State variables</caption>
1324  *  <tr>
1325  *    <td>Name</td> <td>Type</td> <td>Get command</td> <td>Group attribute</td>
1326  *  </tr>
1327  *  <tr>
1328  *    <td><b>GLC_AUTO_FONT</b></td>
1329  *    <td>GLboolean</td>
1330  *    <td>glcIsEnabled()</td>
1331  *    <td>enable</td>
1332  *  </tr>
1333  *  <tr>
1334  *    <td><b>GLC_GL_OBJECTS</b></td>
1335  *    <td>GLboolean</td>
1336  *    <td>glcIsEnabled()</td>
1337  *    <td>enable</td>
1338  *  </tr>
1339  *  <tr>
1340  *    <td><b>GLC_MIPMAP</b></td>
1341  *    <td>GLboolean</td>
1342  *    <td>glcIsEnabled()</td>
1343  *    <td>enable</td>
1344  *  </tr>
1345  *  <tr>
1346  *    <td><b>GLC_HINTING_QSO</b></td>
1347  *    <td>GLboolean</td>
1348  *    <td>glcIsEnabled()</td>
1349  *    <td>enable</td>
1350  *  </tr>
1351  *  <tr>
1352  *    <td><b>GLC_EXTRUDE_QSO</b></td>
1353  *    <td>GLboolean</td>
1354  *    <td>glcIsEnabled()</td>
1355  *    <td>enable</td>
1356  *  </tr>
1357   *  <tr>
1358  *    <td><b>GLC_KERNING_QSO</b></td>
1359  *    <td>GLboolean</td>
1360  *    <td>glcIsEnabled()</td>
1361  *    <td>enable</td>
1362  *  </tr>
1363  *  <tr>
1364  *    <td><b>GLC_RENDER_STYLE</b></td>
1365  *    <td>GLint</td>
1366  *    <td>glcGeti()</td>
1367  *    <td>render</td>
1368  *  </tr>
1369  *  <tr>
1370  *    <td><b>GLC_RESOLUTION</b></td>
1371  *    <td>GLfloat</td>
1372  *    <td>glcGetf()</td>
1373  *    <td>render</td>
1374  *  </tr>
1375  *  <tr>
1376  *    <td><b>GLC_STRING_TYPE</b></td>
1377  *    <td>GLint</td>
1378  *    <td>glcGeti()</td>
1379  *    <td>string</td>
1380  *  </tr>
1381  *  <tr>
1382  *    <td><b>GLC_REPLACEMENT_CODE</b></td>
1383  *    <td>GLint</td>
1384  *    <td>glcGeti()</td>
1385  *    <td>string</td>
1386  *  </tr>
1387  *  <tr>
1388  *    <td><b>GLC_OP_glcUnmappedCode</b></td>
1389  *    <td>GLCfunc</td>
1390  *    <td>glcGetCallbackFunc()</td>
1391  *    <td>string</td>
1392  *  </tr>
1393  *  <tr>
1394  *    <td><b>GLC_DATA_POINTER</b></td>
1395  *    <td>GLvoid*</td>
1396  *    <td>glcGetPointer()</td>
1397  *    <td>string</td>
1398  *  </tr>
1399  *  </table>
1400  *  </center>
1401  *
1402  *  The error \b GLC_STACK_OVERFLOW_QSO is generated if glcPushAttribQSO() is
1403  *  executed while the attribute stack depth is equal to
1404  *  \b GLC_MAX_ATTRIB_STACK_DEPTH_QSO.
1405  *  \b GLC_STACK_OVERFLOW_QSO.
1406  *  \param inMask The list of state variables to be saved
1407  *  \sa glcPopAttribQSO()
1408  *  \sa glcGeti() with argument \b GLC_ATTRIB_STACK_DEPTH_QSO
1409  *  \sa glcGeti() with argument \b GLC_MAX_ATTRIB_STACK_DEPTH_QSO
1410  */
glcPushAttribQSO(GLbitfield inMask)1411 void APIENTRY glcPushAttribQSO(GLbitfield inMask)
1412 {
1413   __GLCcontext *ctx = NULL;
1414   __GLCattribStackLevel *level = NULL;
1415 
1416   GLC_INIT_THREAD();
1417 
1418   /* Check if the current thread owns a context state */
1419   ctx = GLC_GET_CURRENT_CONTEXT();
1420   if (!ctx) {
1421     __glcRaiseError(GLC_STATE_ERROR);
1422     return;
1423   }
1424 
1425   if (ctx->attribStackDepth >= GLC_MAX_ATTRIB_STACK_DEPTH) {
1426     __glcRaiseError(GLC_STACK_OVERFLOW_QSO);
1427     return;
1428   }
1429 
1430   level = &ctx->attribStack[ctx->attribStackDepth++];
1431   level->attribBits = 0;
1432 
1433   if (inMask & GLC_ENABLE_BIT_QSO) {
1434     memcpy(&level->enableState, &ctx->enableState, sizeof(__GLCenableState));
1435     level->attribBits |= GLC_ENABLE_BIT_QSO;
1436   }
1437 
1438   if (inMask & GLC_RENDER_BIT_QSO) {
1439     memcpy(&level->renderState, &ctx->renderState, sizeof(__GLCrenderState));
1440     level->attribBits |= GLC_RENDER_BIT_QSO;
1441   }
1442 
1443   if (inMask & GLC_STRING_BIT_QSO) {
1444     memcpy(&level->stringState, &ctx->stringState, sizeof(__GLCstringState));
1445     level->attribBits |= GLC_STRING_BIT_QSO;
1446   }
1447 
1448   if (inMask & GLC_GL_ATTRIB_BIT_QSO) {
1449     __glcSaveGLState(&level->glState, ctx, GL_TRUE);
1450     level->attribBits |= GLC_GL_ATTRIB_BIT_QSO;
1451   }
1452 
1453   return;
1454 }
1455 
1456 
1457 
1458 /** \ingroup context
1459  *  This command resets the values of those state variables that were saved with
1460  *  the last corresponding glcPushAttribQSO(). Those not saved remain unchanged.
1461  *  The error \b GLC_STACK_UNDERFLOW_QSO is generated if glcPopAttrib() is
1462  *  executed while the attribute stack is empty.
1463  *  \sa glcPushAttribQSO()
1464  *  \sa glcGeti() with argument \b GLC_ATTRIB_STACK_DEPTH_QSO
1465  *  \sa glcGeti() with argument \b GLC_MAX_ATTRIB_STACK_DEPTH_QSO
1466  */
glcPopAttribQSO(void)1467 void APIENTRY glcPopAttribQSO(void)
1468 {
1469   __GLCcontext *ctx = NULL;
1470   __GLCattribStackLevel *level = NULL;
1471   GLbitfield mask;
1472 
1473   GLC_INIT_THREAD();
1474 
1475   /* Check if the current thread owns a context state */
1476   ctx = GLC_GET_CURRENT_CONTEXT();
1477   if (!ctx) {
1478     __glcRaiseError(GLC_STATE_ERROR);
1479     return;
1480   }
1481 
1482   if (ctx->attribStackDepth <= 0) {
1483     __glcRaiseError(GLC_STACK_UNDERFLOW_QSO);
1484     return;
1485   }
1486 
1487   level = &ctx->attribStack[--ctx->attribStackDepth];
1488   mask = level->attribBits;
1489 
1490   if (mask & GLC_ENABLE_BIT_QSO)
1491     memcpy(&ctx->enableState, &level->enableState, sizeof(__GLCenableState));
1492 
1493   if (mask & GLC_RENDER_BIT_QSO)
1494     memcpy(&ctx->renderState, &level->renderState, sizeof(__GLCrenderState));
1495 
1496   if (mask & GLC_STRING_BIT_QSO)
1497     memcpy(&ctx->stringState, &level->stringState, sizeof(__GLCstringState));
1498 
1499   if (mask & GLC_GL_ATTRIB_BIT_QSO)
1500     __glcRestoreGLState(&level->glState, ctx, GL_TRUE);
1501 
1502   return;
1503 }
1504