@@ -328,114 +328,85 @@ namespace Ogre
328
328
mTexture ->load ();
329
329
}
330
330
// ---------------------------------------------------------------------
331
- void Font::loadResource (Resource* res )
331
+ DataStreamPtr Font::_getTTFData ( )
332
332
{
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
+ }
339
337
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
+ {
345
340
float vpScale = OverlayManager::getSingleton ().getPixelRatio ();
341
+ MemoryDataStream ttfchunk (_getTTFData (), false );
346
342
#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);
354
344
FT_Face face;
355
345
356
346
// 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" );
361
349
362
350
// Convert our point size to freetype 26.6 fixed point format
363
351
FT_F26Dot6 ftSize = (FT_F26Dot6)(mTtfSize * (1 << 6 ));
364
352
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" );
370
354
371
355
// Calculate maximum width, height and bearing
372
- size_t glyphCount = 0 ;
373
356
for (const CodePointRange& range : mCodePointRangeList )
374
357
{
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)
376
360
{
377
361
FT_Load_Char ( face, cp, FT_LOAD_RENDER );
378
362
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);
380
364
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);
382
366
}
383
-
384
367
}
368
+
369
+ return face;
385
370
#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 );
390
373
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 );
394
376
for (const CodePointRange& range : mCodePointRangeList )
395
377
{
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)
397
380
{
398
- int idx = stbtt_FindGlyphIndex (& font, cp);
381
+ int idx = stbtt_FindGlyphIndex (font, cp);
399
382
if (!idx) // It is actually in the font?
400
383
continue ;
401
384
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 );
403
386
max_height = std::max (r.height (), max_height);
404
387
mTtfMaxBearingY = std::max (-r.top , mTtfMaxBearingY );
405
388
max_width = std::max (r.width (), max_width);
406
389
}
407
390
}
408
391
409
392
max_height *= 1.125 ;
393
+ return font;
410
394
#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
+ }
431
396
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;
433
403
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
437
409
438
- uint32 l = 0 , m = 0 ;
439
410
for (const CodePointRange& range : mCodePointRangeList )
440
411
{
441
412
for (CodePoint cp = range.first ; cp <= range.second ; ++cp )
@@ -464,7 +435,7 @@ namespace Ogre
464
435
FT_Pos y_bearing = mTtfMaxBearingY - (face->glyph ->metrics .horiBearingY >> 6 );
465
436
FT_Pos x_bearing = face->glyph ->metrics .horiBearingX >> 6 ;
466
437
#else
467
- int idx = stbtt_FindGlyphIndex (& font, cp);
438
+ int idx = stbtt_FindGlyphIndex (font, cp);
468
439
if (!idx)
469
440
{
470
441
LogManager::getSingleton ().logWarning (
@@ -473,20 +444,20 @@ namespace Ogre
473
444
}
474
445
475
446
if (cp == ' ' ) // should figure out how advance works for stbtt..
476
- idx = stbtt_FindGlyphIndex (& font, ' 0' );
447
+ idx = stbtt_FindGlyphIndex (font, ' 0' );
477
448
478
449
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 );
480
451
481
452
uint width = r.width ();
482
453
483
454
int y_bearing = mTtfMaxBearingY + r.top ;
484
455
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);
486
457
487
458
int advance = xoff + width, x_bearing = xoff;
488
459
// 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);
490
461
#endif
491
462
// If at end of row
492
463
if ( finalWidth - 1 < l + width )
@@ -532,11 +503,76 @@ namespace Ogre
532
503
#ifndef HAVE_FREETYPE
533
504
if (buffer != NULL )
534
505
{
535
- STBTT_free (buffer, font. userdata );
506
+ STBTT_free (buffer, font-> userdata );
536
507
}
537
508
#endif
538
509
}
539
510
}
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
+
540
576
#ifdef HAVE_FREETYPE
541
577
FT_Done_FreeType (ftLibrary);
542
578
#endif
0 commit comments