~ubuntu-branches/ubuntu/lucid/graphviz/lucid-updates

« back to all changes in this revision

Viewing changes to lib/utilities/glTexFont.c

  • Committer: Bazaar Package Importer
  • Author(s): Bryce Harrington
  • Date: 2008-06-19 20:23:23 UTC
  • mfrom: (1.2.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20080619202323-ls23h96ntj9ny94m
Tags: 2.18-1ubuntu1
* Merge from debian unstable, remaining changes:
  - Build depend on liblualib50-dev instead of liblua5.1-0-dev.
  - Drop libttf-dev (libttf-dev is in universe) (LP: #174749).
  - Replace gs-common with ghostscript.
  - Build-depend on python-dev instead of python2.4-dev or python2.5-dev.
  - Mention the correct python version for the python bindings in the
    package description.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    glTexFont Library R6
 
3
 
 
4
    Copyright (c) 1999 Nate Miller
 
5
    
 
6
    Notice: Usage of any code in this file is subject to the rules
 
7
    described in the LICENSE.TXT file included in this directory.
 
8
    Reading, compiling, or otherwise using this code constitutes
 
9
    automatic acceptance of the rules in said text file.
 
10
 
 
11
    File        -- glTexFont.c
 
12
    Date        -- 5/30/99
 
13
    Author      -- Nate 'm|d' Miller
 
14
    Contact     -- vandals1@home.com
 
15
    Web         -- http://members.home.com/vandals1
 
16
*/
 
17
//#define FONT_LIB_DEBUG /* un-comment for debug regions */
 
18
#include "glTexFont.h"
 
19
#include "glTexFontTGA.h"
 
20
#include "glTexFontDefs.h"
 
21
#include "glTexFontInclude.h"
 
22
 
 
23
 
 
24
/* just a global for our default colors */
 
25
float white[] = {1.0, 1.0, 1.0, 1.0};
 
26
float gray[] = {0.5, 0.5, 0.5, 1.0};
 
27
 
 
28
/* the font structure we will use in the library, all values are defaults */
 
29
texFont_t font = 
 
30
{
 
31
    {1.0, 1.0, 1.0, 1.0}, /* white text */
 
32
    {0.5, 0.5, 0.5, 1.0}, /* gray gradient */
 
33
    {0.5, 0.5, 0.5, 1.0}, /* gray shadow */
 
34
    12,                   /* size 12 font */
 
35
    0,                    /* no shadow */
 
36
    0,                    /* no gradient */
 
37
    0,                    /* italic amount */
 
38
    0,                    /* no bold */
 
39
    0,0,0,0,0,            /* text region stuff */
 
40
    0.0,0.0,              /* texture inc stuff */
 
41
    FONT_BLOCK_ROW,       /* characters per row */
 
42
    FONT_BLOCK_COL,       /* characters por col */
 
43
    0,                    /* texture id */
 
44
};
 
45
 
 
46
/*
 
47
    tPoints contains our map for the font image.  After fontMakeMap this array
 
48
    will contain all the information to get the proper key from the font map.
 
49
*/
 
50
vec2_t tPoints[257]; 
 
51
 
 
52
/*
 
53
=============
 
54
fontLoad
 
55
 
 
56
Load the passed image name and use it for the font.  
 
57
=============
 
58
*/
 
59
int fontLoad (char *name)
 
60
{
 
61
    glGenTextures (1, &font.texId);
 
62
 
 
63
        font.blockRow = FONT_BLOCK_ROW;
 
64
        font.blockCol = FONT_BLOCK_COL;
 
65
 
 
66
        fontMakeMap ();
 
67
 
 
68
    return fontLoadTGA (name, font.texId);
 
69
}
 
70
/*
 
71
=============
 
72
fontLoadEx
 
73
 
 
74
Loads the passed image which has 'col' characters per column and 'row' 
 
75
characters per row. 
 
76
=============
 
77
*/
 
78
int fontLoadEx (char *name, int row, int col)
 
79
{
 
80
    /* make sure we have valid dimensions */
 
81
/*      if (row * col != 256)
 
82
                return 0;*/
 
83
 
 
84
    glGenTextures (1, &font.texId);
 
85
 
 
86
        font.blockRow = row;
 
87
        font.blockCol = col;
 
88
 
 
89
        fontMakeMap ();
 
90
 
 
91
    return fontLoadTGA (name, font.texId);
 
92
}
 
93
/*
 
94
=============
 
95
fontDrawChar
 
96
 
 
97
Draws a character that is 'size' pixels in w and h.  
 
98
=============
 
99
*/
 
100
void fontDrawChar (char c, int x, int y, int size, int shadow)
 
101
{
 
102
        if (!font.gradient && !shadow)
 
103
        glColor4fv (font.fgColor);
 
104
    else if (!font.gradient && shadow)
 
105
        glColor4fv (font.bgColor);
 
106
    else if (font.gradient && !shadow)
 
107
        glColor4fv (font.gdColor);
 
108
 
 
109
    glBegin (GL_QUADS);
 
110
                glTexCoord2f (tPoints[(int)c][0], tPoints[(int)c][1]);
 
111
                glVertex3i (x, y,0);
 
112
 
 
113
        glTexCoord2f (tPoints[(int)c][0] + font.tIncX, tPoints[(int)c][1]);
 
114
                glVertex3i (x + size, y,0);
 
115
 
 
116
        if (!shadow)
 
117
            glColor4fv (font.fgColor);
 
118
        else glColor4fv (font.bgColor);
 
119
 
 
120
        glTexCoord2f (tPoints[(int)c][0] + font.tIncX, tPoints[(int)c][1] + font.tIncY);
 
121
                glVertex3i (x + size + font.italic, y + size,0);
 
122
 
 
123
        glTexCoord2f (tPoints[(int)c][0], tPoints[(int)c][1] + font.tIncY);
 
124
                glVertex3i (x + font.italic, y + size,0);
 
125
        glEnd ();
 
126
}
 
127
/*
 
128
=============
 
129
fontScissorNormal
 
130
 
 
131
Normal scissor region for text rendering.  
 
132
=============
 
133
*/
 
134
void fontScissorNormal (int xpos, int ypos, int tabs, int carrage, int size, int len)
 
135
{
 
136
    int sy;
 
137
    int ex;
 
138
    int ey;
 
139
 
 
140
    ex = len * size * tabs;
 
141
 
 
142
    if (carrage)
 
143
        {
 
144
                sy = ypos - (size * carrage);
 
145
                ey = size * (carrage + 1);
 
146
        } else {
 
147
                sy = ypos;
 
148
                ey = size;
 
149
        }
 
150
    glScissor (xpos, sy, ex, ey);
 
151
}
 
152
/*
 
153
=============
 
154
fontScissorTextRegion
 
155
 
 
156
Scissor region used setup for a text region.
 
157
=============
 
158
*/
 
159
void fontScissorTextRegion (void)
 
160
{
 
161
    glScissor (font.regionX, font.regionY, font.regionW, font.regionH);
 
162
}
 
163
/*
 
164
=============
 
165
fontFgColorReset
 
166
 
 
167
Resets the font color.
 
168
=============
 
169
*/
 
170
void fontForeColorReset (void)
 
171
{
 
172
    fontColorCopy (white, font.fgColor);
 
173
}
 
174
/*
 
175
=============
 
176
fontBgColorReset
 
177
 
 
178
Resets the shadow color.
 
179
=============
 
180
*/
 
181
void fontShadowColorReset (void)
 
182
{
 
183
    fontColorCopy (gray, font.bgColor);
 
184
}
 
185
/*
 
186
=============
 
187
fontGdColorReset
 
188
 
 
189
Resets the gradient color.
 
190
=============
 
191
*/
 
192
void fontGradientColorReset (void)
 
193
{
 
194
    fontColorCopy (gray, font.gdColor);
 
195
}
 
196
/*
 
197
=============
 
198
fontReset
 
199
 
 
200
Resets the font.  Only resets variables that could possible change.
 
201
=============
 
202
*/
 
203
void fontReset (void)
 
204
{
 
205
    font.size = 12;
 
206
    font.shadow = 0;
 
207
    font.region = 0;
 
208
    font.gradient = 0;
 
209
    font.italic = 0;
 
210
    font.bold = 0;
 
211
    font.regionX = 0;
 
212
    font.regionY = 0;
 
213
    font.regionW = 0;
 
214
    font.regionH = 0;
 
215
    fontForeColorReset ();
 
216
    fontShadowColorReset ();
 
217
    fontGradientColorReset ();
 
218
}
 
219
/*
 
220
=============
 
221
fontRegion
 
222
 
 
223
Sets up a font region.  Only good for one fontDrawString. 
 
224
=============
 
225
*/
 
226
void fontRegion (int x, int y, int w, int h)
 
227
{
 
228
    font.region = 1;
 
229
    font.regionX = x;
 
230
    font.regionY = y - h;
 
231
    font.regionW = w;
 
232
    font.regionH = h;
 
233
}
 
234
/*
 
235
=============
 
236
fontSize
 
237
 
 
238
Sets the font size.
 
239
=============
 
240
*/
 
241
void fontSize (int size)
 
242
{
 
243
    font.size = size;
 
244
}
 
245
void fontzdepth(float zdepth)
 
246
{
 
247
        font.zdepth=zdepth;
 
248
}
 
249
/*
 
250
=============
 
251
fontShadow
 
252
 
 
253
Draws a shadow if called.
 
254
=============
 
255
*/
 
256
void fontShadow (void)
 
257
{
 
258
    font.shadow = 1;
 
259
}
 
260
/*
 
261
=============
 
262
fontGradient
 
263
 
 
264
Draws gradient text if called.
 
265
=============
 
266
*/
 
267
void fontGradient (void)
 
268
{
 
269
    font.gradient = 1;
 
270
}
 
271
/*
 
272
=============
 
273
fontRenderChar
 
274
 
 
275
Draws a character to the screen
 
276
Bold is just a hack, nothing special
 
277
=============
 
278
*/
 
279
void fontRenderChar (char c, int x, int y, int size)
 
280
{
 
281
    if (font.shadow)
 
282
    {
 
283
        if (!font.bold)
 
284
                fontDrawChar (c, x + 1,  y + 1, size, 1);
 
285
        else fontDrawChar (c, x + 2,  y + 1, size, 1);
 
286
    }
 
287
    
 
288
 
 
289
 
 
290
        fontDrawChar (c, x, y, size, 0);
 
291
 
 
292
        if (font.bold)
 
293
        fontDrawChar (c, x + 1, y, size, 0);
 
294
}
 
295
/*
 
296
=============
 
297
fontSlashParser
 
298
 
 
299
Handles all the fun that comes with a \\, returns amount to advance string.
 
300
After this funtion *buffptr ++ will be the next character to draw or parse.
 
301
=============
 
302
*/
 
303
int fontSlashParser (char *buffPtr, int *x, int *y)
 
304
{
 
305
    int ret = 0;
 
306
 
 
307
    *buffPtr ++;
 
308
 
 
309
    if (!*buffPtr)
 
310
        return ret;
 
311
 
 
312
    switch (*buffPtr)
 
313
    {
 
314
        case 'a':
 
315
        case 'c':
 
316
            *x -= font.size;
 
317
            return fontSetColorFromToken (buffPtr);
 
318
        break;
 
319
        case 'i':
 
320
            *x -= font.size;
 
321
            return fontItalicsMode (buffPtr);
 
322
        break;
 
323
        case 'b':
 
324
            *x -= font.size;
 
325
            return fontBoldMode (buffPtr);
 
326
        break;
 
327
        default:
 
328
            *buffPtr --;
 
329
            fontRenderChar (*buffPtr, *x, *y, font.size);
 
330
            return ret;
 
331
        break;
 
332
    }
 
333
}
 
334
/*
 
335
=============
 
336
fontWalkString
 
337
 
 
338
Does the actual rendering of our string.  
 
339
=============
 
340
*/
 
341
void fontWalkString (char *buffPtr, int xpos, int ypos, int *vPort,float width)
 
342
{
 
343
    int size = font.size;
 
344
        int x = xpos;
 
345
        int y = ypos;
 
346
        int carrage = 0;
 
347
        int tabs = 0;
 
348
    int len = strlen (buffPtr);
 
349
    int xMax;
 
350
        int charCount;
 
351
        int maxcharCount;
 
352
        char* tempC;
 
353
        int charGap;
 
354
        xMax = vPort[0] + vPort[2];
 
355
 
 
356
    carrage = fontGetCharHits (buffPtr, '\n');
 
357
        tabs = fontGetCharHits (buffPtr, '\t');
 
358
 
 
359
        if (!tabs)
 
360
                tabs = 1;
 
361
        else tabs *= FONT_TAB_SPACE;
 
362
 
 
363
/*    if (font.region)
 
364
    {
 
365
        fontScissorTextRegion ();
 
366
        x = font.regionX;
 
367
        y = (font.regionY + font.regionH) - font.size;
 
368
    } else 
 
369
        fontScissorNormal (xpos, ypos, tabs, carrage, font.size, len); */
 
370
 
 
371
#ifdef FONT_LIB_DEBUG
 
372
    glClearColor (1,0,1,1);
 
373
    glClear (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
 
374
#endif
 
375
 
 
376
    /* lets draw! */
 
377
        //width for each char should be calculated , we need the max line length of the paragraph
 
378
 
 
379
        tempC=buffPtr;
 
380
        charCount=0;
 
381
        maxcharCount=0;
 
382
 
 
383
        while (*tempC != '\0')
 
384
        {
 
385
                if ( *tempC == '\n')
 
386
                {
 
387
                        if (charCount > maxcharCount)
 
388
                                        maxcharCount=charCount;
 
389
                        charCount=0;
 
390
 
 
391
                }
 
392
                else
 
393
                {
 
394
                        if ( *tempC == '\t')
 
395
                                charCount=charCount+FONT_TAB_SPACE;
 
396
                        else
 
397
                                charCount++;
 
398
                }
 
399
                tempC++;
 
400
        }
 
401
        if (charCount > maxcharCount)
 
402
                maxcharCount=charCount;
 
403
        charGap=(int)(width / (float)maxcharCount);
 
404
 
 
405
 
 
406
        for ( ; *buffPtr; *buffPtr ++, x += charGap) //size*0.7 is the distance between2 characters
 
407
        {
 
408
        //      if (x > xMax)
 
409
        //              break;
 
410
    /*    if (font.region)
 
411
        {
 
412
            if (x + size > (font.regionX + font.regionW))
 
413
            {
 
414
                y -= size;
 
415
                x = font.regionX;
 
416
            }
 
417
            if (y < font.regionY)
 
418
                break;
 
419
        }*/
 
420
 
 
421
 
 
422
 
 
423
 
 
424
                if(*buffPtr==' ')               //SPACE
 
425
                        x = x - size;
 
426
 
 
427
                switch (*buffPtr)
 
428
                {
 
429
 
 
430
                
 
431
                        case '\n':
 
432
                                y -= size;
 
433
                x = xpos - size;
 
434
                                continue; 
 
435
                        break;
 
436
                        case '\t':
 
437
                                x += (size * FONT_TAB_SPACE);
 
438
                                continue; 
 
439
                        break;
 
440
            case '\\':
 
441
                buffPtr += fontSlashParser (buffPtr, &x, &y);
 
442
                if (*buffPtr == '\n' || *buffPtr == '\t')
 
443
                {
 
444
                    buffPtr -= 1;
 
445
                    continue;
 
446
                }
 
447
            break;
 
448
            default :
 
449
                fontRenderChar (*buffPtr, x, y, size);
 
450
            break;
 
451
                }
 
452
        }
 
453
}
 
454
/*
 
455
=============
 
456
fontDrawString
 
457
 
 
458
Renders a string at xpos, ypos.
 
459
=============
 
460
*/
 
461
void fontDrawString (int xpos, int ypos, char *s,int width,...)
 
462
{
 
463
        va_list msg;
 
464
    char buffer[FONT_MAX_LEN] = {'\0'};
 
465
    int vPort[4];
 
466
        
 
467
        va_start (msg, s);
 
468
#ifdef _WIN32
 
469
        _vsntprintf (buffer, FONT_MAX_LEN - 1, s, msg); 
 
470
#else /* linux */
 
471
        vsnprintf (buffer, FONT_MAX_LEN - 1, s, msg);   
 
472
#endif
 
473
        va_end (msg);
 
474
 
 
475
    /* get current viewport */
 
476
    glGetIntegerv (GL_VIEWPORT, vPort);
 
477
    /* setup various opengl things that we need */
 
478
 
 
479
        fontSetModes (FONT_GET_MODES);
 
480
        //if constant location is desired for fonts turn on these comment outs    
 
481
/*      glMatrixMode (GL_PROJECTION);
 
482
        glPushMatrix ();
 
483
        glLoadIdentity ();
 
484
 
 
485
  
 
486
        glOrtho (0, vPort[2], 0, vPort[3], -1, 1);
 
487
        glMatrixMode (GL_MODELVIEW);
 
488
        glPushMatrix ();
 
489
        glLoadIdentity ();*/
 
490
        glBindTexture (GL_TEXTURE_2D, font.texId);
 
491
 
 
492
    /* draw the string */
 
493
 
 
494
 
 
495
        fontWalkString (buffer, xpos, ypos, vPort,(float)width);
 
496
        
 
497
/*      glMatrixMode (GL_PROJECTION);
 
498
        glPopMatrix ();
 
499
        glMatrixMode (GL_MODELVIEW);
 
500
        glPopMatrix ();*/
 
501
 
 
502
        fontSetModes (FONT_RESTORE_MODES);
 
503
    fontReset ();
 
504
}
 
505
/*
 
506
=============
 
507
fontSetColorFromToken
 
508
 
 
509
Grabs a color token from a buffer and sets color.  
 
510
=============
 
511
*/      
 
512
int fontSetColorFromToken (char *s)
 
513
{
 
514
        int clr[4];
 
515
        int ret = 1;
 
516
 
 
517
        if (*s == 'c')
 
518
        {
 
519
                s += 1;
 
520
                if (sscanf (s, "(%d %d %d)", &clr[0], &clr[1], &clr[2]) != 3)
 
521
                        return -1;
 
522
                fontColor (clr[0] * FONT_ITOF, clr[1] * FONT_ITOF, clr[2] * FONT_ITOF);
 
523
        } else if (*s == 'a')
 
524
        {
 
525
                s += 1;
 
526
                if (sscanf (s, "(%d %d %d %d)", &clr[0], &clr[1], &clr[2], &clr[3]) != 4)
 
527
                        return -1;
 
528
                fontColorA (clr[0] * FONT_ITOF, clr[1] * FONT_ITOF, clr[2] * FONT_ITOF, clr[3] * FONT_ITOF);
 
529
        }
 
530
 
 
531
        while (*s != ')' && ret ++)
 
532
                s += 1;
 
533
 
 
534
    return ret + 1;
 
535
}
 
536
/*
 
537
=============
 
538
fontItalicsMode
 
539
 
 
540
Either turns on or off italics.
 
541
=============
 
542
*/      
 
543
int fontItalicsMode (char *s)
 
544
{
 
545
    s += 1;
 
546
 
 
547
    if (*s == '+')
 
548
        font.italic = FONT_ITALIC;
 
549
    else if (*s == '-')
 
550
        font.italic = 0;
 
551
    else return -1;
 
552
 
 
553
    return 2;
 
554
}
 
555
/*
 
556
=============
 
557
fontBoldMode
 
558
 
 
559
Either turns on or off bold.
 
560
=============
 
561
*/      
 
562
int fontBoldMode (char *s)
 
563
{
 
564
    s += 1;
 
565
 
 
566
    if (*s == '+')
 
567
        font.bold = 1;
 
568
    else if (*s == '-')
 
569
        font.bold = 0;
 
570
    else return -1;
 
571
 
 
572
    return 2;
 
573
}
 
574
/*
 
575
=============
 
576
fontGetCharHits
 
577
 
 
578
Returns number of times a character is found in a buffer.
 
579
=============
 
580
*/
 
581
int fontGetCharHits (char *s, char f)
 
582
{
 
583
        int hits = 0;
 
584
 
 
585
        while (*s)
 
586
        {
 
587
                if (*s == f)
 
588
                        hits ++;
 
589
                *s ++;
 
590
        }
 
591
 
 
592
        return hits;
 
593
}
 
594
/*
 
595
=============
 
596
fontMakeMap
 
597
 
 
598
Makes the font map which allows the correct characters to be drawn.
 
599
=============
 
600
*/
 
601
void fontMakeMap (void)
 
602
{
 
603
#define VCOPY(d,x,y) {d[0] = x; d[1] = y;}
 
604
        int i = 0;
 
605
        float x, y;
 
606
 
 
607
 
 
608
        font.tIncX = (float)pow (font.blockCol, -1);
 
609
        font.tIncY = (float)pow (font.blockRow, -1);
 
610
 
 
611
        
 
612
        for (y = 1 - font.tIncY; y >= 0; y -= font.tIncY)
 
613
                for (x = 0; x <= 1 - font.tIncX; x += font.tIncX, i ++)
 
614
                        VCOPY (tPoints[i], x, y);
 
615
#undef VCOPY
 
616
}
 
617
/*
 
618
=============
 
619
fontSetModes
 
620
 
 
621
Sets or restores OpenGL modes that we need to use.  Here to prevent the drawing
 
622
of text from messing up other stuff.  
 
623
=============
 
624
*/
 
625
void fontSetModes (int state)
 
626
{
 
627
        static int matrixMode;
 
628
        static int polyMode[2];
 
629
        static int lightingOn;
 
630
        static int blendOn;
 
631
        static int depthOn;
 
632
        static int textureOn;
 
633
        static int scissorOn;
 
634
        static int blendSrc;
 
635
        static int blendDst;
 
636
 
 
637
        /* grab the modes that we might need to change */
 
638
        if (state == FONT_GET_MODES)
 
639
        {
 
640
                glGetIntegerv(GL_POLYGON_MODE, polyMode);
 
641
 
 
642
                if (polyMode[0] != GL_FILL)
 
643
                        glPolygonMode (GL_FRONT, GL_FILL);
 
644
                if (polyMode[1] != GL_FILL)
 
645
                        glPolygonMode (GL_BACK, GL_FILL);
 
646
        
 
647
                textureOn = glIsEnabled (GL_TEXTURE_2D);
 
648
                if (!textureOn)
 
649
                        glEnable (GL_TEXTURE_2D);
 
650
 
 
651
                depthOn = glIsEnabled (GL_DEPTH_TEST);
 
652
 
 
653
                if (depthOn)
 
654
                        glDisable (GL_DEPTH_TEST);
 
655
 
 
656
                lightingOn= glIsEnabled (GL_LIGHTING);        
 
657
        
 
658
                if (lightingOn) 
 
659
                        glDisable(GL_LIGHTING);
 
660
 
 
661
                scissorOn= glIsEnabled (GL_SCISSOR_TEST);        
 
662
        
 
663
/*              if (!scissorOn) 
 
664
                        glEnable (GL_SCISSOR_TEST);*/
 
665
 
 
666
                glGetIntegerv(GL_MATRIX_MODE, &matrixMode); 
 
667
        
 
668
                /* i don't know if this is correct */
 
669
                blendOn= glIsEnabled (GL_BLEND);        
 
670
        glGetIntegerv (GL_BLEND_SRC, &blendSrc);
 
671
            glGetIntegerv (GL_BLEND_DST, &blendDst);
 
672
                if (!blendOn)
 
673
                        glEnable (GL_BLEND);
 
674
                glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
675
        } else if (state == FONT_RESTORE_MODES)
 
676
        {
 
677
                /* put everything back where it was before */
 
678
                if (polyMode[0] != GL_FILL)
 
679
                        glPolygonMode (GL_FRONT, polyMode[0]);
 
680
                if (polyMode[1] != GL_FILL)
 
681
                        glPolygonMode (GL_BACK, polyMode[1]);
 
682
        
 
683
                if (lightingOn)
 
684
                        glEnable(GL_LIGHTING);
 
685
        
 
686
                /* i don't know if this is correct */
 
687
                if (!blendOn)
 
688
        {
 
689
                        glDisable (GL_BLEND);
 
690
            glBlendFunc (blendSrc, blendDst);
 
691
        } else glBlendFunc (blendSrc, blendDst);
 
692
 
 
693
                if (depthOn)
 
694
                        glEnable (GL_DEPTH_TEST);
 
695
 
 
696
                if (!textureOn)
 
697
                        glDisable (GL_TEXTURE_2D);
 
698
                
 
699
                if (!scissorOn) 
 
700
                        glDisable (GL_SCISSOR_TEST);
 
701
        
 
702
                glMatrixMode (matrixMode);
 
703
        }
 
704
}