@@ -328,114 +328,85 @@ namespace Ogre
328328 mTexture ->load ();
329329 }
330330 // ---------------------------------------------------------------------
331- void Font::loadResource (Resource* res )
331+ DataStreamPtr Font::_getTTFData ( )
332332 {
333- // Locate ttf file, load it pre-buffered into memory by wrapping the
334- // original DataStream in a MemoryDataStream
335- DataStreamPtr dataStreamPtr =
336- ResourceGroupManager::getSingleton ().openResource (
337- mSource , mGroup , this );
338- MemoryDataStream ttfchunk (dataStreamPtr);
333+ // Locate ttf file, load it pre-buffered into memory by wrapping
334+ // the original DataStream in a MemoryDataStream
335+ return ResourceGroupManager::getSingleton ().openResource (mSource , mGroup , this );
336+ }
339337
340- // If codepoints not supplied, assume ASCII
341- if (mCodePointRangeList .empty ())
342- {
343- mCodePointRangeList .push_back (CodePointRange (32 , 126 ));
344- }
338+ void * Font::_prepareFont (void * context, uint32& glyphCount, int32& max_height, int32& max_width)
339+ {
345340 float vpScale = OverlayManager::getSingleton ().getPixelRatio ();
341+ MemoryDataStream ttfchunk (_getTTFData (), false );
346342#ifdef HAVE_FREETYPE
347- // ManualResourceLoader implementation - load the texture
348- FT_Library ftLibrary;
349- // Init freetype
350- if ( FT_Init_FreeType ( &ftLibrary ) )
351- OGRE_EXCEPT ( Exception::ERR_INTERNAL_ERROR, " Could not init FreeType library!" ,
352- " Font::Font" );
353-
343+ FT_Library ftLibrary = static_cast <FT_Library>(context);
354344 FT_Face face;
355345
356346 // Load font
357- if ( FT_New_Memory_Face ( ftLibrary, ttfchunk.getPtr (), (FT_Long)ttfchunk.size () , 0 , &face ) )
358- OGRE_EXCEPT ( Exception::ERR_INTERNAL_ERROR,
359- " Could not open font face!" , " Font::createTextureFromFont" );
360-
347+ if (FT_New_Memory_Face (ftLibrary, ttfchunk.getPtr (), (FT_Long)ttfchunk.size (), 0 , &face))
348+ OGRE_EXCEPT (Exception::ERR_INTERNAL_ERROR, " Could not open font face" );
361349
362350 // Convert our point size to freetype 26.6 fixed point format
363351 FT_F26Dot6 ftSize = (FT_F26Dot6)(mTtfSize * (1 << 6 ));
364352 if (FT_Set_Char_Size (face, ftSize, 0 , mTtfResolution * vpScale, mTtfResolution * vpScale))
365- OGRE_EXCEPT (Exception::ERR_INTERNAL_ERROR, " Could not set char size!" );
366-
367- // FILE *fo_def = stdout;
368-
369- FT_Pos max_height = 0 , max_width = 0 ;
353+ OGRE_EXCEPT (Exception::ERR_INTERNAL_ERROR, " Could not set char size" );
370354
371355 // Calculate maximum width, height and bearing
372- size_t glyphCount = 0 ;
373356 for (const CodePointRange& range : mCodePointRangeList )
374357 {
375- for (CodePoint cp = range.first ; cp <= range.second ; ++cp, ++glyphCount)
358+ glyphCount += range.second - range.first + 1 ;
359+ for (CodePoint cp = range.first ; cp <= range.second ; ++cp)
376360 {
377361 FT_Load_Char ( face, cp, FT_LOAD_RENDER );
378362
379- max_height = std::max<FT_Pos >(2 * face->glyph ->bitmap .rows - (face->glyph ->metrics .horiBearingY >> 6 ), max_height);
363+ max_height = std::max<int32 >(2 * face->glyph ->bitmap .rows - (face->glyph ->metrics .horiBearingY >> 6 ), max_height);
380364 mTtfMaxBearingY = std::max (int (face->glyph ->metrics .horiBearingY >> 6 ), mTtfMaxBearingY );
381- max_width = std::max<FT_Pos >(face->glyph ->bitmap .width , max_width);
365+ max_width = std::max<int32 >(face->glyph ->bitmap .width , max_width);
382366 }
383-
384367 }
368+
369+ return face;
385370#else
386- stbtt_fontinfo font;
387- stbtt_InitFont (&font, ttfchunk.getPtr (), 0 );
388- // 64 gives the same texture resolution as freetype.
389- float scale = stbtt_ScaleForPixelHeight (&font, vpScale * mTtfSize * mTtfResolution / 64 );
371+ stbtt_fontinfo* font = static_cast <stbtt_fontinfo*>(context);
372+ stbtt_InitFont (font, ttfchunk.getPtr (), 0 );
390373
391- int max_width = 0 , max_height = 0 ;
392- // Calculate maximum width, height and bearing
393- size_t glyphCount = 0 ;
374+ // 64 gives the same texture resolution as freetype.
375+ float scale = stbtt_ScaleForPixelHeight (font, vpScale * mTtfSize * mTtfResolution / 64 );
394376 for (const CodePointRange& range : mCodePointRangeList )
395377 {
396- for (CodePoint cp = range.first ; cp <= range.second ; ++cp, ++glyphCount)
378+ glyphCount += range.second - range.first + 1 ;
379+ for (CodePoint cp = range.first ; cp <= range.second ; ++cp)
397380 {
398- int idx = stbtt_FindGlyphIndex (& font, cp);
381+ int idx = stbtt_FindGlyphIndex (font, cp);
399382 if (!idx) // It is actually in the font?
400383 continue ;
401384 TRect<int > r;
402- stbtt_GetGlyphBitmapBox (& font, idx, scale, scale, &r.left , &r.top , &r.right , &r.bottom );
385+ stbtt_GetGlyphBitmapBox (font, idx, scale, scale, &r.left , &r.top , &r.right , &r.bottom );
403386 max_height = std::max (r.height (), max_height);
404387 mTtfMaxBearingY = std::max (-r.top , mTtfMaxBearingY );
405388 max_width = std::max (r.width (), max_width);
406389 }
407390 }
408391
409392 max_height *= 1.125 ;
393+ return font;
410394#endif
411- uint char_spacer = 1 ;
412-
413- // Now work out how big our texture needs to be
414- size_t rawSize = (max_width + char_spacer) * (max_height + char_spacer) * glyphCount;
415-
416- uint32 tex_side = static_cast <uint32>(Math::Sqrt ((Real)rawSize));
417- // Now round up to nearest power of two
418- uint32 roundUpSize = Bitwise::firstPO2From (tex_side);
419-
420- // Would we benefit from using a non-square texture (2X width)
421- uint32 finalWidth, finalHeight;
422- if (roundUpSize * roundUpSize * 0.5 >= rawSize)
423- {
424- finalHeight = static_cast <uint32>(roundUpSize * 0.5 );
425- }
426- else
427- {
428- finalHeight = roundUpSize;
429- }
430- finalWidth = roundUpSize;
395+ }
431396
432- Real textureAspect = (Real)finalWidth / (Real)finalHeight;
397+ void Font::_loadGlyphs (void * _face, int32 max_height, Image& img, uint32& l, uint32& m)
398+ {
399+ uint char_spacer = 1 ;
400+ float finalWidth = img.getWidth ();
401+ float finalHeight = img.getHeight ();
402+ float textureAspect = finalWidth / finalHeight;
433403
434- Image img (PF_BYTE_LA, finalWidth, finalHeight);
435- // Reset content (transparent)
436- img.setTo (ColourValue::ZERO);
404+ #ifdef HAVE_FREETYPE
405+ FT_Face face = static_cast <FT_Face>(_face);
406+ #else
407+ stbtt_fontinfo* font = static_cast <stbtt_fontinfo*>(_face);
408+ #endif
437409
438- uint32 l = 0 , m = 0 ;
439410 for (const CodePointRange& range : mCodePointRangeList )
440411 {
441412 for (CodePoint cp = range.first ; cp <= range.second ; ++cp )
@@ -464,7 +435,7 @@ namespace Ogre
464435 FT_Pos y_bearing = mTtfMaxBearingY - (face->glyph ->metrics .horiBearingY >> 6 );
465436 FT_Pos x_bearing = face->glyph ->metrics .horiBearingX >> 6 ;
466437#else
467- int idx = stbtt_FindGlyphIndex (& font, cp);
438+ int idx = stbtt_FindGlyphIndex (font, cp);
468439 if (!idx)
469440 {
470441 LogManager::getSingleton ().logWarning (
@@ -473,20 +444,20 @@ namespace Ogre
473444 }
474445
475446 if (cp == ' ' ) // should figure out how advance works for stbtt..
476- idx = stbtt_FindGlyphIndex (& font, ' 0' );
447+ idx = stbtt_FindGlyphIndex (font, ' 0' );
477448
478449 TRect<int > r;
479- stbtt_GetGlyphBitmapBox (& font, idx, scale, scale, &r.left , &r.top , &r.right , &r.bottom );
450+ stbtt_GetGlyphBitmapBox (font, idx, scale, scale, &r.left , &r.top , &r.right , &r.bottom );
480451
481452 uint width = r.width ();
482453
483454 int y_bearing = mTtfMaxBearingY + r.top ;
484455 int xoff = 0 , yoff = 0 ;
485- buffer = stbtt_GetCodepointBitmap (& font, scale, scale, cp, &buffer_pitch, &buffer_h, &xoff, &yoff);
456+ buffer = stbtt_GetCodepointBitmap (font, scale, scale, cp, &buffer_pitch, &buffer_h, &xoff, &yoff);
486457
487458 int advance = xoff + width, x_bearing = xoff;
488459 // should be multiplied with scale, but still does not seem to do the right thing
489- // stbtt_GetGlyphHMetrics(& font, cp, &advance, &x_bearing);
460+ // stbtt_GetGlyphHMetrics(font, cp, &advance, &x_bearing);
490461#endif
491462 // If at end of row
492463 if ( finalWidth - 1 < l + width )
@@ -532,11 +503,76 @@ namespace Ogre
532503#ifndef HAVE_FREETYPE
533504 if (buffer != NULL )
534505 {
535- STBTT_free (buffer, font. userdata );
506+ STBTT_free (buffer, font-> userdata );
536507 }
537508#endif
538509 }
539510 }
511+ }
512+
513+ void Font::loadResource (Resource* res)
514+ {
515+ // If codepoints not supplied, assume ASCII
516+ if (mCodePointRangeList .empty ())
517+ {
518+ mCodePointRangeList .push_back (CodePointRange (32 , 126 ));
519+ }
520+
521+ int32 max_height = 0 , max_width = 0 ;
522+ uint32 glyphCount = 0 ;
523+ #ifdef HAVE_FREETYPE
524+ // ManualResourceLoader implementation - load the texture
525+ FT_Library ftLibrary;
526+ // Init freetype
527+ if ( FT_Init_FreeType ( &ftLibrary ) )
528+ OGRE_EXCEPT ( Exception::ERR_INTERNAL_ERROR, " Could not init FreeType library" );
529+
530+ std::vector<void *> faces;
531+ faces.push_back (_prepareFont (ftLibrary, glyphCount, max_height, max_width));
532+
533+ for (const auto & font : mMergeFonts )
534+ {
535+ faces.push_back (font->_prepareFont (ftLibrary, glyphCount, max_height, max_width));
536+ font->mTtfMaxBearingY = mTtfMaxBearingY = std::max (font->mTtfMaxBearingY , mTtfMaxBearingY );
537+ }
538+ #else
539+ stbtt_fontinfo font;
540+ auto face = _prepareFont (&font, glyphCount, max_height, max_width);
541+ #endif
542+ uint char_spacer = 1 ;
543+
544+ // Now work out how big our texture needs to be
545+ size_t rawSize = (max_width + char_spacer) * (max_height + char_spacer) * glyphCount;
546+
547+ uint32 tex_side = static_cast <uint32>(Math::Sqrt ((Real)rawSize));
548+ // Now round up to nearest power of two
549+ uint32 roundUpSize = Bitwise::firstPO2From (tex_side);
550+
551+ // Would we benefit from using a non-square texture (2X width)
552+ uint32 finalWidth, finalHeight;
553+ if (roundUpSize * roundUpSize * 0.5 >= rawSize)
554+ {
555+ finalHeight = static_cast <uint32>(roundUpSize * 0.5 );
556+ }
557+ else
558+ {
559+ finalHeight = roundUpSize;
560+ }
561+ finalWidth = roundUpSize;
562+
563+ Image img (PF_BYTE_LA, finalWidth, finalHeight);
564+ // Reset content (transparent)
565+ img.setTo (ColourValue::ZERO);
566+
567+ uint32 l = 0 , m = 0 ;
568+ _loadGlyphs (faces[0 ], max_height, img, l, m);
569+ int j = 1 ;
570+ for (const auto & font : mMergeFonts )
571+ {
572+ font->_loadGlyphs (faces[j++], max_height, img, l, m);
573+ mCodePointMap .insert (font->mCodePointMap .begin (), font->mCodePointMap .end ());
574+ }
575+
540576#ifdef HAVE_FREETYPE
541577 FT_Done_FreeType (ftLibrary);
542578#endif
0 commit comments