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