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