1 /**************************************************************************\
2  * Copyright (c) Kongsberg Oil & Gas Technologies AS
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * Redistributions of source code must retain the above copyright notice,
10  * this list of conditions and the following disclaimer.
11  *
12  * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  *
16  * Neither the name of the copyright holder nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 \**************************************************************************/
32 
33 /*!
34   \class SoGlyph SoGlyph.h Inventor/misc/SoGlyph.h
35   \brief The SoGlyph class is used to generate and reuse font glyph bitmaps and outlines.
36 
37   <b>This class is now obsolete, and will be removed from a later
38   version of Coin.</b>
39 
40   SoGlyph is the public interface all text nodes (both built-in and
41   extensions) should use to generate bitmaps and outlines for font
42   glyphs. It maintains an internal cache of previously requested
43   glyphs to avoid needless calls into the font library.
44 
45   Primer: a \e glyph is the graphical representation of a given
46   character of a given font at a given size and orientation. It can be
47   either a \e bitmap (pixel aligned with the viewport) or an \e
48   outline (polygonal representation) that can be transformed or
49   extruded like any other 3D geometry. Bitmaps are used by SoText2,
50   while the other text nodes uses outlines.
51 
52   \COIN_CLASS_EXTENSION
53 
54   \since Coin 2.0
55 
56   \sa SoText2, SoText3, SoAsciiText
57 */
58 
59 // SoGlyph uses the Coin-internal font lib wrapper functions
60 // (cc_flw_*()) to provide bitmaps and outlines.
61 //
62 // FIXME: font support for outline glyphs. 200303?? preng.
63 
64 #include <Inventor/misc/SoGlyph.h>
65 #include "coindefs.h"
66 
67 #include <cstdlib>
68 #include <cstring>
69 
70 #include <Inventor/errors/SoDebugError.h>
71 #include <Inventor/C/tidbits.h>
72 #include <Inventor/SbName.h>
73 #include <Inventor/SbString.h>
74 #include <Inventor/SbVec2f.h>
75 #include <Inventor/SbVec2s.h>
76 #include <Inventor/lists/SbList.h>
77 #include <Inventor/elements/SoFontNameElement.h>
78 #include <Inventor/elements/SoFontSizeElement.h>
79 
80 #include "tidbitsp.h"
81 #include "threads/threadsutilp.h"
82 #include "fonts/common.h"
83 #include "fonts/fontlib_wrapper.h"
84 #include "fonts/defaultfonts.h"
85 
86 class SoGlyphP {
87 public:
SoGlyphP(SoGlyph * master)88   SoGlyphP(SoGlyph * master) : master(master) { }
89   SoGlyph * master;
90 
91 
92   const SbVec2f * coords;
93   SbBox2f bbox;
94   const int * faceidx;
95   const int * edgeidx;
96   int refcount;
97   float ymin, ymax;
98 
99   int fontidx;
100   int glyphidx;
101   float angle;
102   SbVec2s size;
103   unsigned int character;
104   SbBool fonttypeis3d;
105   SbBool coordsinstalled;
106 
107   int bitmapwidth;
108   int bitmapheight;
109   cc_font_bitmap * bitmap;
110 
111   struct {
112     unsigned int didcalcbbox : 1;
113   } flags;
114 
115   void setup3DFontData();
116 
117   static SoGlyph * createSystemGlyph(const char character, const SbName & font);
createSystemGlyph(const unsigned int COIN_UNUSED_ARG (character),SoState * COIN_UNUSED_ARG (state))118   static SoGlyph * createSystemGlyph(const unsigned int COIN_UNUSED_ARG(character), SoState * COIN_UNUSED_ARG(state)) {return NULL;};  static SoGlyph * createSystemGlyph(const char character, int fontid);
119 };
120 
121 #define PRIVATE(p) ((p)->pimpl)
122 #define PUBLIC(p) ((p)->master)
123 
124 
125 /*!
126   Constructor.
127 */
SoGlyph(void)128 SoGlyph::SoGlyph(void)
129 {
130   PRIVATE(this) = new SoGlyphP(this);
131   PRIVATE(this)->refcount = 0;
132   PRIVATE(this)->flags.didcalcbbox = 0;
133   PRIVATE(this)->coords = NULL;
134   PRIVATE(this)->faceidx = NULL;
135   PRIVATE(this)->edgeidx = NULL;
136   PRIVATE(this)->ymin = 0.0f;
137   PRIVATE(this)->ymax = 0.0f;
138 
139   /* Setting fonttype==3D as default since the 2D text node (SoText2)
140      is no longer depending on the SoGlyph node (20030908 handegar) */
141   PRIVATE(this)->fonttypeis3d = TRUE;
142 
143   PRIVATE(this)->fontidx = 0;
144   PRIVATE(this)->coordsinstalled = FALSE;
145 
146   PRIVATE(this)->bitmapwidth = 0;
147   PRIVATE(this)->bitmapheight = 0;
148   PRIVATE(this)->bitmap = NULL;
149 }
150 
151 /*!
152   Destructor.
153 */
~SoGlyph()154 SoGlyph::~SoGlyph()
155 {
156   delete PRIVATE(this);
157 }
158 
159 /*!
160   Should be called when a node no longer will use a glyph. Will
161   free memory used by this glyph when it is no longer used by any node.
162 */
163 void
unref(void) const164 SoGlyph::unref(void) const
165 {
166   SoGlyph::unrefGlyph((SoGlyph*)this);
167 }
168 
169 /*!
170   Used to indicate how the glyph should be treated. This is needed if
171   correct bounding box shall be calculated etc. As default, glyphs are
172   treated as a part of a 2D font.
173 */
174 
175 void
setFontType(Fonttype type) const176 SoGlyph::setFontType(Fonttype type) const
177 {
178   if (type == SoGlyph::FONT3D) {
179     PRIVATE(this)->fonttypeis3d = TRUE;
180   }
181   else {
182     PRIVATE(this)->fonttypeis3d = FALSE;
183   }
184 }
185 
186 
187 /*!
188   Returns coordinates for this glyph.
189 */
190 const SbVec2f *
getCoords(void) const191 SoGlyph::getCoords(void) const
192 {
193   if (!PRIVATE(this)->coordsinstalled) {
194     PRIVATE(this)->setup3DFontData();
195     PRIVATE(this)->coordsinstalled = TRUE;
196   }
197   return PRIVATE(this)->coords;
198 }
199 
200 /*!
201   Returns face indices for this glyph.
202 */
203 const int *
getFaceIndices(void) const204 SoGlyph::getFaceIndices(void) const
205 {
206   if (!PRIVATE(this)->coordsinstalled) {
207     PRIVATE(this)->setup3DFontData();
208     PRIVATE(this)->coordsinstalled = TRUE;
209   }
210 
211   return PRIVATE(this)->faceidx;
212 }
213 
214 /*!
215   Returns edge indices for this glyph.
216 */
217 const int *
getEdgeIndices(void) const218 SoGlyph::getEdgeIndices(void) const
219 {
220   if (!PRIVATE(this)->coordsinstalled) {
221     PRIVATE(this)->setup3DFontData();
222     PRIVATE(this)->coordsinstalled = TRUE;
223   }
224 
225   return PRIVATE(this)->edgeidx;
226 }
227 
228 /*!
229   Returns a pointer to the next clockwise edge. Returns NULL if
230   none could be found.
231 */
232 const int *
getNextCWEdge(const int edgeidx) const233 SoGlyph::getNextCWEdge(const int edgeidx) const
234 {
235   int idx = edgeidx * 2;
236   // test for common case
237   if (edgeidx > 0) {
238     if (PRIVATE(this)->edgeidx[idx] == PRIVATE(this)->edgeidx[idx-1])
239       return &PRIVATE(this)->edgeidx[idx-2];
240   }
241   // do a linear search
242   int findidx = PRIVATE(this)->edgeidx[idx];
243   const int * ptr = PRIVATE(this)->edgeidx;
244   while (*ptr >= 0) {
245     if (ptr[1] == findidx) return ptr;
246     ptr += 2;
247   }
248   return NULL;
249 }
250 
251 /*!
252   Returns a pointer to the next counter clockwise edge.
253   NULL if none could be found.
254 */
255 const int *
getNextCCWEdge(const int edgeidx) const256 SoGlyph::getNextCCWEdge(const int edgeidx) const
257 {
258   int idx = edgeidx * 2;
259   // test for common case
260   if (PRIVATE(this)->edgeidx[idx+1] == PRIVATE(this)->edgeidx[idx+2])
261     return &PRIVATE(this)->edgeidx[idx+2];
262   // do a linear search
263   int findidx = PRIVATE(this)->edgeidx[idx+1];
264   const int * ptr = PRIVATE(this)->edgeidx;
265   while (*ptr >= 0) {
266     if (*ptr == findidx) return ptr;
267     ptr += 2;
268   }
269   return NULL;
270 }
271 
272 /*!
273   Convenience method which returns the exact width of the glyph.
274 */
275 float
getWidth(void) const276 SoGlyph::getWidth(void) const
277 {
278 
279   if (!PRIVATE(this)->fonttypeis3d)
280     return (float) PRIVATE(this)->bitmapwidth;
281 
282   const SbBox2f & box = this->getBoundingBox();
283   return box.getMax()[0] - box.getMin()[0];
284 }
285 
286 /*!
287   Returns the bounding box of this glyph. This value is cached for performance.
288 */
289 const SbBox2f &
getBoundingBox(void) const290 SoGlyph::getBoundingBox(void) const
291 {
292   // this method needs to be const, so cast away constness
293   SoGlyph * thisp = (SoGlyph*) this;
294   if (!PRIVATE(this)->flags.didcalcbbox) {
295 
296     if (!PRIVATE(this)->coordsinstalled) {
297       PRIVATE(this)->setup3DFontData();
298       PRIVATE(this)->coordsinstalled = TRUE;
299     }
300 
301     PRIVATE(thisp)->bbox.makeEmpty();
302     const int *ptr = PRIVATE(this)->edgeidx;
303     int idx = *ptr++;
304 
305     while (idx >= 0) {
306       PRIVATE(thisp)->bbox.extendBy(PRIVATE(this)->coords[idx]);
307       idx = *ptr++;
308     }
309 
310     // FIXME: the 'get_advance' call has been separated into one
311     // 'get_vector_advance' and one 'get_bitmap_advance' call. As we
312     // cannot separate whether we are dealing with bitmaps or vector
313     // glyphs in this class, we choose 'get_vector_advance' as
314     // default. (20030926 handegar)
315     float advancex, advancey;
316     cc_flw_get_vector_advance(PRIVATE(this)->fontidx, PRIVATE(this)->glyphidx, &advancex, &advancey);
317     SbVec2f max = PRIVATE(this)->bbox.getMax();
318 
319     PRIVATE(this)->bbox.extendBy(SbVec2f(advancex, advancey));
320 
321     PRIVATE(thisp)->flags.didcalcbbox = 1;
322   }
323 
324 
325   return PRIVATE(this)->bbox;
326 }
327 
328 /*!
329   Sets the coordinates for this glyph.
330 */
331 void
setCoords(const SbVec2f * coords,int numcoords)332 SoGlyph::setCoords(const SbVec2f *coords, int numcoords)
333 {
334   // It used to be valid to call this function with a negative value
335   // (which signified that data should not be copied). All invoking
336   // code just passed in -1, so we have simplified this function
337   // (SoGlyph is being obsoleted anyway).
338   //
339   // Note that since we are just copying the data pointer, we assume
340   // that all 3D glyphs use permanent storage for their publicly
341   // exposed data.
342   assert(numcoords == -1);
343 
344   PRIVATE(this)->coords = coords;
345 }
346 
347 /*!
348   Sets the face indices for this glyph.
349 */
350 void
setFaceIndices(const int * indices,int numindices)351 SoGlyph::setFaceIndices(const int *indices, int numindices)
352 {
353   // It used to be valid to call this function with a negative value
354   // (which signified that data should not be copied). All invoking
355   // code just passed in -1, so we have simplified this function
356   // (SoGlyph is being obsoleted anyway).
357   //
358   // Note that since we are just copying the data pointer, we assume
359   // that all 3D glyphs use permanent storage for their publicly
360   // exposed data.
361   assert(numindices == -1);
362 
363   PRIVATE(this)->faceidx = indices;
364 }
365 
366 /*!
367   Sets the edge indices for this glyph.
368 */
369 void
setEdgeIndices(const int * indices,int numindices)370 SoGlyph::setEdgeIndices(const int *indices, int numindices)
371 {
372   // It used to be valid to call this function with a negative value
373   // (which signified that data should not be copied). All invoking
374   // code just passed in -1, so we have simplified this function
375   // (SoGlyph is being obsoleted anyway).
376   //
377   // Note that since we are just copying the data pointer, we assume
378   // that all 3D glyphs use permanent storage for their publicly
379   // exposed data.
380   assert(numindices == -1);
381 
382   PRIVATE(this)->edgeidx = indices;
383 }
384 
385 
386 
387 //
388 // static methods to handle glyph reusage.
389 //
390 // FIXME: use SbHash to look up glyphs a bit faster. pederb, 20000323
391 //
392 
393 class coin_glyph_info {
394 public:
coin_glyph_info()395   coin_glyph_info() {
396     this->character = 0;
397     this->size = 0.0;
398     this->glyph = NULL;
399     this->angle = 0.0;
400   }
coin_glyph_info(const unsigned int characterarg,const float sizearg,const SbName & fontarg,SoGlyph * glypharg,const float anglearg)401   coin_glyph_info(const unsigned int characterarg, const float sizearg, const SbName &fontarg, SoGlyph *glypharg, const float anglearg)
402   {
403     this->character = characterarg;
404     this->size = sizearg;
405     this->font = fontarg;
406     this->angle = anglearg;
407     this->glyph = glypharg;
408   }
409 
410   // Note: bitmap glyphs have valid size, polygonal glyphs have size=-1.0
matches(const unsigned int characterarg,const float sizearg,const SbName fontarg,const float anglearg)411   SbBool matches(const unsigned int characterarg, const float sizearg,
412                  const SbName fontarg, const float anglearg) {
413     return (this->character == characterarg) && (this->size == sizearg) && (this->font == fontarg) && (this->angle == anglearg);
414   }
415 
416   // AIX native compiler xlC needs equality and inequality operators
417   // to compile templates where these operators are referenced (even
418   // if they are actually never used).
419 
operator ==(const coin_glyph_info & gi)420   SbBool operator==(const coin_glyph_info & gi) {
421     return this->matches(gi.character, gi.size, gi.font, gi.angle) && this->glyph == gi.glyph;
422   }
operator !=(const coin_glyph_info & gi)423   SbBool operator!=(const coin_glyph_info & gi) {
424     return !(*this == gi);
425   }
426 
427   unsigned int character;
428   float size;
429   SbName font;
430   SoGlyph * glyph;
431   float angle;
432 };
433 
434 static SbList <coin_glyph_info> * activeGlyphs = NULL;
435 static void * SoGlyph_mutex = NULL;
436 
437 static void
SoGlyph_cleanup(void)438 SoGlyph_cleanup(void)
439 {
440   delete activeGlyphs;
441   activeGlyphs = NULL;
442   CC_MUTEX_DESTRUCT(SoGlyph_mutex);
443 }
444 
445 /*!
446   Returns a character of the specified font, suitable for polygonal
447   rendering.
448 */
449 const SoGlyph *
getGlyph(const char character,const SbName & font)450 SoGlyph::getGlyph(const char character, const SbName & font)
451 {
452 
453   // FIXME: the API and implementation of this class isn't consistent
454   // with regard to the paraneters and variabls that are glyph codes
455   // -- some places they are "char", other places "int", some places
456   // signed, other places unsigned. Should audit and fix as much as
457   // possible without breaking API and ABI compatibility. *sigh*
458   // 20030611 mortene.
459 
460   // Similar code in start of getGlyph(..., state) - keep in sync.
461   if (SoGlyph_mutex == NULL) {
462     CC_MUTEX_CONSTRUCT(SoGlyph_mutex);
463   }
464 
465   // FIXME: it would probably be a good idea to have a small LRU-type
466   // glyph cache to avoid freeing glyphs too early. If for instance
467   // the user creates a single SoText3 node which is used several
468   // times in a graph with different fonts, glyphs will be freed and
469   // recreated all the time. pederb, 20000324
470 
471   CC_MUTEX_LOCK(SoGlyph_mutex);
472 
473   if (activeGlyphs == NULL) {
474     activeGlyphs = new SbList <coin_glyph_info>;
475     coin_atexit((coin_atexit_f *)SoGlyph_cleanup, CC_ATEXIT_NORMAL);
476   }
477 
478   int i, n = activeGlyphs->getLength();
479   for (i = 0; i < n; i++) {
480     // Search for fontsize -1 to avoid getting a bitmap glyph.
481     if ((*activeGlyphs)[i].matches(character, -1.0, font, 0.0)) break;
482   }
483   if (i < n) {
484     SoGlyph *glyph = (*activeGlyphs)[i].glyph;
485     PRIVATE(glyph)->refcount++;
486     CC_MUTEX_UNLOCK(SoGlyph_mutex);
487     return glyph;
488   }
489 
490   SoGlyph * glyph = SoGlyphP::createSystemGlyph(character, font);
491 
492   // FIXME: don't think this is necessary, we should _always_ get a
493   // glyph. If none exist in the font, we should eventually fall back
494   // on making a square in the code we're calling into. Move the code
495   // below to handle this deeper down into the call-stack. 20030527 mortene.
496   if (glyph == NULL) { // no system font could be loaded
497     glyph = new SoGlyph;
498     if (character <= 32 || character >= 127) {
499       // treat all these characters as spaces
500       static int spaceidx[] = { -1 };
501       glyph->setCoords(NULL);
502       glyph->setFaceIndices(spaceidx);
503       glyph->setEdgeIndices(spaceidx);
504       PRIVATE(glyph)->bbox.setBounds(SbVec2f(0.0f, 0.0f), SbVec2f(0.2f, 0.0f));
505       PRIVATE(glyph)->flags.didcalcbbox = 1;
506     }
507     else {
508       const int idx = character-33;
509       glyph->setCoords((const SbVec2f*)coin_default3dfont_get_coords()[idx]);
510       glyph->setFaceIndices(coin_default3dfont_get_faceidx()[idx]);
511       glyph->setEdgeIndices(coin_default3dfont_get_edgeidx()[idx]);
512     }
513   }
514   // Use impossible font size to avoid mixing polygonal & bitmap glyphs.
515   coin_glyph_info info(character, -1.0, font, glyph, 0.0);
516   PRIVATE(glyph)->refcount++;
517   activeGlyphs->append(info);
518   CC_MUTEX_UNLOCK(SoGlyph_mutex);
519   return glyph;
520 
521 }
522 
523 // private method that removed glyph from active list when deleted
524 void
unrefGlyph(SoGlyph * glyph)525 SoGlyph::unrefGlyph(SoGlyph *glyph)
526 {
527   CC_MUTEX_LOCK(SoGlyph_mutex);
528   assert(activeGlyphs);
529   assert(PRIVATE(glyph)->refcount > 0);
530   PRIVATE(glyph)->refcount--;
531   if (PRIVATE(glyph)->refcount == 0) {
532     int i, n = activeGlyphs->getLength();
533     for (i = 0; i < n; i++) {
534       if ((*activeGlyphs)[i].glyph == glyph) break;
535     }
536     assert(i < n);
537     activeGlyphs->removeFast(i);
538     cc_flw_unref_font(PRIVATE(glyph)->fontidx);
539     delete glyph;
540   }
541   CC_MUTEX_UNLOCK(SoGlyph_mutex);
542 }
543 
544 /*!
545   Returns a character of the specified font, suitable for bitmap
546   rendering.  The size parameter overrides state's SoFontSizeElement
547   (if != SbVec2s(0,0))
548 */
549 const SoGlyph *
getGlyph(SoState * state,const unsigned int character,const SbVec2s & size,const float angle)550 SoGlyph::getGlyph(SoState * state,
551                   const unsigned int character,
552                   const SbVec2s & size,
553                   const float angle)
554 {
555   assert(state);
556 
557   SbName state_name = SoFontNameElement::get(state);
558   float state_size = SoFontSizeElement::get(state);
559 
560   if (state_name == SbName::empty()) {
561     state_name = SbName("defaultFont");
562     state_size = 10.0;
563   }
564 
565   SbVec2s fontsize((short)state_size, (short)state_size);
566   if (size != SbVec2s(0,0)) { fontsize = size; }
567 
568   // Similar code in start of getGlyph(..., fontname) - keep in sync.
569   if (SoGlyph_mutex == NULL) {
570     CC_MUTEX_CONSTRUCT(SoGlyph_mutex);
571   }
572 
573   CC_MUTEX_LOCK(SoGlyph_mutex);
574 
575   if (activeGlyphs == NULL) {
576     activeGlyphs = new SbList <coin_glyph_info>;
577     coin_atexit((coin_atexit_f *)SoGlyph_cleanup, CC_ATEXIT_NORMAL);
578   }
579 
580   int i, n = activeGlyphs->getLength();
581   for (i = 0; i < n; i++) {
582     if ((*activeGlyphs)[i].matches(character, fontsize[0], state_name, angle)) {
583       SoGlyph *glyph = (*activeGlyphs)[i].glyph;
584       PRIVATE(glyph)->refcount++;
585       CC_MUTEX_UNLOCK(SoGlyph_mutex);
586       return glyph;
587     }
588   }
589 
590   // FIXME: use font style in addition to font name. preng 2003-03-03
591   SbString fontname = state_name.getString();
592 
593   const int font = cc_flw_get_font_id(fontname.getString(), fontsize[1], angle, 0.5f);
594   // Should _always_ be able to get hold of a font.
595   assert(font >= 0);
596   cc_flw_ref_font(font);
597 
598   const int glyphidx = cc_flw_get_glyph(font, character);
599 
600   // Should _always_ be able to get hold of a glyph -- if no glyph is
601   // available for a specific character, a default empty rectangle
602   // should be used.  -mortene.
603   assert(glyphidx >= 0);
604 
605   SoGlyph * g = new SoGlyph();
606   PRIVATE(g)->fontidx = font;
607   PRIVATE(g)->glyphidx = glyphidx;
608   PRIVATE(g)->size = fontsize;
609   PRIVATE(g)->angle = angle;
610   PRIVATE(g)->character = character;
611   coin_glyph_info info(character, state_size, state_name, g, angle);
612   PRIVATE(g)->refcount++;
613   activeGlyphs->append(info);
614 
615   CC_MUTEX_UNLOCK(SoGlyph_mutex);
616   return g;
617 }
618 
619 // Pixel advance for this glyph.
620 SbVec2s
getAdvance(void) const621 SoGlyph::getAdvance(void) const
622 {
623   assert(PRIVATE(this)->fontidx >= 0 && PRIVATE(this)->glyphidx >= 0);
624 
625   int x, y;
626   // FIXME: the 'get_advance' call has been separated into one
627   // 'get_vector_advance' and one 'get_bitmap_advance' call. As we
628   // cannot separate whether we are dealing with bitmaps or vector
629   // glyphs in this class, we choose 'get_bitmap_advance' as
630   // default. (20030926 handegar)
631   cc_flw_get_bitmap_advance(PRIVATE(this)->fontidx, PRIVATE(this)->glyphidx, &x, &y);
632   return SbVec2s((short)x, (short)y);
633 }
634 
635 // Pixel kerning when rightglyph is placed to the right of this.
636 SbVec2s
getKerning(const SoGlyph & rightglyph) const637 SoGlyph::getKerning(const SoGlyph & rightglyph) const
638 {
639   assert(PRIVATE(this)->fontidx >= 0 && PRIVATE(this)->glyphidx >= 0);
640   assert(PRIVATE(&rightglyph)->fontidx >= 0 && PRIVATE(&rightglyph)->glyphidx >= 0);
641 
642   int x, y;
643   // FIXME: Same issues as with 'getAdvance()'. See fixme. (20030926 handegar)
644   cc_flw_get_bitmap_kerning(PRIVATE(this)->fontidx,
645                             PRIVATE(this)->glyphidx, PRIVATE(&rightglyph)->glyphidx,
646                             &x, &y);
647   return SbVec2s((short)x, (short)y);
648 }
649 
650 /*!
651   Bitmap for glyph. \a size and \a pos are return parameters.
652   Antialiased bitmap graphics not yet supported.
653 
654   Note that this function may return \c NULL if the glyph has no
655   visible pixels (as for e.g. the space character).
656 
657   The returned buffer should \e not be deallocated by the caller.
658 */
659 unsigned char *
getBitmap(SbVec2s & size,SbVec2s & pos,const SbBool COIN_UNUSED_ARG (antialiased)) const660 SoGlyph::getBitmap(SbVec2s & size, SbVec2s & pos, const SbBool COIN_UNUSED_ARG(antialiased)) const
661 {
662   if (PRIVATE(this)->bitmap == NULL) {
663     PRIVATE(this)->bitmap = cc_flw_get_bitmap(PRIVATE(this)->fontidx, PRIVATE(this)->glyphidx);
664   }
665   struct cc_font_bitmap * bm = PRIVATE(this)->bitmap;
666   assert(bm);
667 
668   PRIVATE(this)->bitmapwidth = bm->width;
669   PRIVATE(this)->bitmapheight = bm->rows;
670 
671   size[0] = bm->pitch * 8;
672   size[1] = bm->rows;
673   pos[0] = bm->bearingX;
674   pos[1] = bm->bearingY;
675 
676   return bm->buffer;
677 }
678 
679 
680 void
setup3DFontData(void)681 SoGlyphP::setup3DFontData(void)
682 {
683   PUBLIC(this)->setFontType(SoGlyph::FONT3D);
684 
685   if (character <= 32 || character >= 127) {
686     // treat all these characters as spaces
687     static int spaceidx[] = { -1 };
688     PUBLIC(this)->setCoords(NULL);
689     PUBLIC(this)->setFaceIndices(spaceidx);
690     PUBLIC(this)->setEdgeIndices(spaceidx);
691     this->bbox.setBounds(SbVec2f(0.0f, 0.0f), SbVec2f(0.2f, 0.0f));
692     this->flags.didcalcbbox = 1;
693   }
694   else {
695     cc_font_vector_glyph * vector_glyph = cc_flw_get_vector_glyph(this->fontidx, this->character);
696 
697     if (vector_glyph == NULL) {
698       // Default hardcoded 3d font. Size = 1.0
699       const int idx = this->character-33;
700       PUBLIC(this)->setCoords((const SbVec2f *)coin_default3dfont_get_coords()[idx]);
701       PUBLIC(this)->setFaceIndices(coin_default3dfont_get_faceidx()[idx]);
702       PUBLIC(this)->setEdgeIndices(coin_default3dfont_get_edgeidx()[idx]);
703     }
704     else {
705       // Install truetype font
706 
707       PUBLIC(this)->setCoords((const SbVec2f *)cc_flw_get_vector_glyph_coords(vector_glyph));
708       PUBLIC(this)->setFaceIndices(cc_flw_get_vector_glyph_faceidx(vector_glyph));
709       PUBLIC(this)->setEdgeIndices(cc_flw_get_vector_glyph_edgeidx(vector_glyph));
710     }
711   }
712 }
713 
714 
715 // should handle platform-specific font loading
716 SoGlyph *
createSystemGlyph(const char COIN_UNUSED_ARG (character),int COIN_UNUSED_ARG (fontid))717 SoGlyphP::createSystemGlyph(const char COIN_UNUSED_ARG(character), int COIN_UNUSED_ARG(fontid))
718 {
719   return NULL;
720 }
721 
722 SoGlyph *
createSystemGlyph(const char COIN_UNUSED_ARG (character),const SbName & COIN_UNUSED_ARG (font))723 SoGlyphP::createSystemGlyph(const char COIN_UNUSED_ARG(character), const SbName & COIN_UNUSED_ARG(font))
724 {
725   return NULL;
726 }
727 
728 #undef PRIVATE
729 #undef PUBLIC
730