Skip to content

Commit 8552941

Browse files
committed
emscripten-fs.html: Added CC0 license.
FontTrueType: some performance optimizations and fixed a bug when mixing fonts in a same Page. Font::isEmojiCodePoint: Minor optimization. ecode: Allow arguments in emscripten build.
1 parent 9c6251d commit 8552941

File tree

6 files changed

+136
-38
lines changed

6 files changed

+136
-38
lines changed

bin/emscripten-fs.html

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<!DOCTYPE html>
2+
<!-- This file license is CC0 (https://creativecommons.org/publicdomain/zero/1.0/). -->
23
<html lang="en-us">
34
<head>
45
<meta charset="utf-8">
@@ -63,7 +64,7 @@
6364
function getDemoScript(name) {
6465
if (name)
6566
return name;
66-
return "eepp-test-debug.js";
67+
return "ecode.js";
6768
}
6869

6970
function getParameter(name) {
@@ -108,8 +109,9 @@
108109
monitorRunDependencies: function(left) {
109110
// no run dependencies to log
110111
},
111-
};
112-
window.onerror = function() {
112+
arguments: window.location.search.substr(1).split('&')
113+
};
114+
window.onerror = function() {
113115
console.log("onerror: " + event);
114116
};
115117

include/eepp/graphics/fonttruetype.hpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <eepp/graphics/base.hpp>
55
#include <eepp/graphics/font.hpp>
66
#include <eepp/graphics/texture.hpp>
7+
#include <memory>
78

89
namespace EE { namespace System {
910
class Pack;
@@ -65,10 +66,14 @@ class EE_API FontTrueType : public Font {
6566

6667
bool isMonospace() const;
6768

68-
bool isEmojiFont() const { return mIsEmojiFont; }
69+
bool isEmojiFont() const;
6970

7071
bool hasGlyph( Uint32 codePoint ) const;
7172

73+
void setIsColorEmojiFont( bool isColorEmojiFont );
74+
75+
void setIsEmojiFont( bool isEmojiFont );
76+
7277
protected:
7378
explicit FontTrueType( const std::string& FontName );
7479

@@ -85,7 +90,7 @@ class EE_API FontTrueType : public Font {
8590
typedef std::map<Uint64, GlyphDrawable*> GlyphDrawableTable;
8691

8792
struct Page {
88-
Page();
93+
Page( const Uint32 fontInternalId );
8994

9095
~Page();
9196

@@ -95,6 +100,7 @@ class EE_API FontTrueType : public Font {
95100
Texture* texture; ///< Texture containing the pixels of the glyphs
96101
unsigned int nextRow; ///< Y position of the next new row in the texture
97102
std::vector<Row> rows; ///< List containing the position of all the existing rows
103+
Uint32 fontInternalId{ 0 };
98104
};
99105

100106
void cleanup();
@@ -106,14 +112,18 @@ class EE_API FontTrueType : public Font {
106112
const Glyph& getGlyph( Uint32 codePoint, unsigned int characterSize, bool bold,
107113
Float outlineThickness, Page& page, const Float& forzeSize ) const;
108114

115+
Uint32 getGlyphIndex( const Uint32& codePoint ) const;
116+
109117
Glyph loadGlyph( Uint32 codePoint, unsigned int characterSize, bool bold,
110118
Float outlineThickness, Page& page, const Float& forceSize = 0.f ) const;
111119

112120
Rect findGlyphRect( Page& page, unsigned int width, unsigned int height ) const;
113121

114122
bool setCurrentSize( unsigned int characterSize ) const;
115123

116-
typedef std::map<unsigned int, Page>
124+
Page& getPage( unsigned int characterSize ) const;
125+
126+
typedef std::map<unsigned int, std::unique_ptr<Page>>
117127
PageTable; ///< Table mapping a character size to its page (texture)
118128

119129
void* mLibrary; ///< Pointer to the internal library interface (it is typeless to avoid exposing
@@ -134,8 +144,10 @@ class EE_API FontTrueType : public Font {
134144
bool mIsColorEmojiFont{ false };
135145
bool mIsEmojiFont{ false };
136146
mutable std::map<unsigned int, unsigned int> mClosestCharacterSize;
147+
mutable std::map<Uint32, Uint32> mCodePointIndexCache;
137148

138-
Uint64 getIndexKey( Uint32 index, bool bold, Float outlineThickness ) const;
149+
Uint64 getIndexKey( Uint32 fontInternalId, Uint32 index, bool bold,
150+
Float outlineThickness ) const;
139151
};
140152

141153
}} // namespace EE::Graphics

src/eepp/graphics/font.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ bool Font::isEmojiCodePoint( const Uint32& codePoint ) {
1212
const Uint32 rangeMax2 = 127569;
1313
const Uint32 rangeMin3 = 8987;
1414
const Uint32 rangeMax3 = 12953;
15-
return ( ( rangeMin <= codePoint && codePoint <= rangeMax ) ||
16-
( rangeMin2 <= codePoint && codePoint <= rangeMax2 ) ||
17-
( rangeMin3 <= codePoint && codePoint <= rangeMax3 ) );
15+
return codePoint > 8987 && ( ( rangeMin <= codePoint && codePoint <= rangeMax ) ||
16+
( rangeMin2 <= codePoint && codePoint <= rangeMax2 ) ||
17+
( rangeMin3 <= codePoint && codePoint <= rangeMax3 ) );
1818
}
1919

2020
bool Font::containsEmojiCodePoint( const String& string ) {

src/eepp/graphics/fonttruetype.cpp

Lines changed: 74 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include FT_BITMAP_H
1515
#include FT_STROKER_H
1616
#include FT_TRUETYPE_TABLES_H
17+
#include <atomic>
1718
#include <cstdlib>
1819
#include <cstring>
1920

@@ -43,15 +44,20 @@ template <typename T, typename U> inline T reinterpret( const U& input ) {
4344
}
4445

4546
// Combine outline thickness, boldness and font glyph index into a single 64-bit key
46-
EE::Uint64 combine( float outlineThickness, bool bold, EE::Uint32 index ) {
47-
return ( static_cast<EE::Uint64>( reinterpret<EE::Uint32>( outlineThickness * 100 ) ) << 33 ) |
47+
EE::Uint64 combine( float outlineThickness, bool bold, EE::Uint32 index,
48+
EE::Uint32 fontInternalId ) {
49+
return ( static_cast<EE::Uint64>( reinterpret<EE::Uint32>( fontInternalId ) ) << 48 ) |
50+
( static_cast<EE::Uint64>( reinterpret<EE::Uint32>( outlineThickness * 100 ) ) << 33 ) |
4851
( static_cast<EE::Uint64>( bold ) << 32 ) | index;
4952
}
5053

5154
} // namespace
5255

5356
namespace EE { namespace Graphics {
5457

58+
static std::map<std::string, Uint32> fontsInternalIds;
59+
static std::atomic<Uint32> fontInternalIdCounter{ 0 };
60+
5561
FontTrueType* FontTrueType::New( const std::string& FontName ) {
5662
return eeNew( FontTrueType, ( FontName ) );
5763
}
@@ -156,6 +162,10 @@ bool FontTrueType::loadFromFile( const std::string& filename ) {
156162
// Store the font information
157163
mInfo.family = face->family_name ? face->family_name : std::string();
158164

165+
auto fontInternalId = fontsInternalIds.find( mInfo.family );
166+
if ( fontsInternalIds.end() == fontInternalId )
167+
fontsInternalIds[mInfo.family] = ++fontInternalIdCounter;
168+
159169
sendEvent( Event::Load );
160170

161171
return true;
@@ -226,6 +236,10 @@ bool FontTrueType::loadFromMemory( const void* data, std::size_t sizeInBytes, bo
226236
// Store the font information
227237
mInfo.family = face->family_name ? face->family_name : std::string();
228238

239+
auto fontInternalId = fontsInternalIds.find( mInfo.family );
240+
if ( fontsInternalIds.end() == fontInternalId )
241+
fontsInternalIds[mInfo.family] = ++fontInternalIdCounter;
242+
229243
sendEvent( Event::Load );
230244

231245
return true;
@@ -309,6 +323,10 @@ bool FontTrueType::loadFromStream( IOStream& stream ) {
309323
// Store the font information
310324
mInfo.family = face->family_name ? face->family_name : std::string();
311325

326+
auto fontInternalId = fontsInternalIds.find( mInfo.family );
327+
if ( fontsInternalIds.end() == fontInternalId )
328+
fontsInternalIds[mInfo.family] = ++fontInternalIdCounter;
329+
312330
sendEvent( Event::Load );
313331

314332
return true;
@@ -333,18 +351,30 @@ const FontTrueType::Info& FontTrueType::getInfo() const {
333351
return mInfo;
334352
}
335353

336-
Uint64 FontTrueType::getIndexKey( Uint32 index, bool bold, Float outlineThickness ) const {
337-
return combine( outlineThickness, bold, index );
354+
Uint64 FontTrueType::getIndexKey( Uint32 fontInternalId, Uint32 index, bool bold,
355+
Float outlineThickness ) const {
356+
return combine( outlineThickness, bold, index, fontInternalId );
338357
}
339358

340359
bool FontTrueType::hasGlyph( Uint32 codePoint ) const {
341-
return FT_Get_Char_Index( static_cast<FT_Face>( mFace ), codePoint ) != 0;
360+
return getGlyphIndex( codePoint ) != 0;
361+
}
362+
363+
Uint32 FontTrueType::getGlyphIndex( const Uint32& codePoint ) const {
364+
Uint32 index;
365+
auto indexIter = mCodePointIndexCache.find( codePoint );
366+
if ( mCodePointIndexCache.end() != indexIter ) {
367+
index = indexIter->second;
368+
} else {
369+
index = FT_Get_Char_Index( static_cast<FT_Face>( mFace ), codePoint );
370+
mCodePointIndexCache[codePoint] = index;
371+
}
372+
return index;
342373
}
343374

344375
const Glyph& FontTrueType::getGlyph( Uint32 codePoint, unsigned int characterSize, bool bold,
345376
Float outlineThickness ) const {
346-
FT_Face face = static_cast<FT_Face>( mFace );
347-
Uint32 index = FT_Get_Char_Index( face, codePoint );
377+
Uint32 index = getGlyphIndex( codePoint );
348378

349379
if ( Font::isEmojiCodePoint( codePoint ) && !mIsColorEmojiFont && !mIsEmojiFont ) {
350380
if ( !mIsColorEmojiFont && FontManager::instance()->getColorEmojiFont() != nullptr &&
@@ -360,7 +390,7 @@ const Glyph& FontTrueType::getGlyph( Uint32 codePoint, unsigned int characterSiz
360390
FontTrueType* fontEmoji =
361391
static_cast<FontTrueType*>( FontManager::instance()->getColorEmojiFont() );
362392
return fontEmoji->getGlyph( codePoint, characterSize, bold, outlineThickness,
363-
mPages[characterSize], maxWidth );
393+
getPage( characterSize ), maxWidth );
364394
} else if ( !mIsEmojiFont && FontManager::instance()->getEmojiFont() != nullptr &&
365395
FontManager::instance()->getEmojiFont()->getType() == FontType::TTF ) {
366396

@@ -370,11 +400,10 @@ const Glyph& FontTrueType::getGlyph( Uint32 codePoint, unsigned int characterSiz
370400
Glyph monospaceGlyph = getGlyph( ' ', characterSize, bold, outlineThickness );
371401
maxWidth = monospaceGlyph.advance;
372402
}
373-
374403
FontTrueType* fontEmoji =
375404
static_cast<FontTrueType*>( FontManager::instance()->getEmojiFont() );
376405
return fontEmoji->getGlyph( codePoint, characterSize, bold, outlineThickness,
377-
mPages[characterSize], maxWidth );
406+
getPage( characterSize ), maxWidth );
378407
}
379408
}
380409

@@ -384,8 +413,7 @@ const Glyph& FontTrueType::getGlyph( Uint32 codePoint, unsigned int characterSiz
384413
const Glyph& FontTrueType::getGlyph( Uint32 codePoint, unsigned int characterSize, bool bold,
385414
Float outlineThickness, Page& page,
386415
const Float& forzeSize ) const {
387-
FT_Face face = static_cast<FT_Face>( mFace );
388-
Uint32 index = FT_Get_Char_Index( face, codePoint );
416+
Uint32 index = getGlyphIndex( codePoint );
389417
return getGlyphByIndex( index, characterSize, bold, outlineThickness, page, forzeSize );
390418
}
391419

@@ -396,7 +424,7 @@ const Glyph& FontTrueType::getGlyphByIndex( Uint32 index, unsigned int character
396424
GlyphTable& glyphs = page.glyphs;
397425

398426
// Build the key by combining the code point, bold flag, and outline thickness
399-
Uint64 key = getIndexKey( index, bold, outlineThickness );
427+
Uint64 key = getIndexKey( fontsInternalIds[mInfo.family], index, bold, outlineThickness );
400428

401429
// Search the glyph into the cache
402430
GlyphTable::const_iterator it = glyphs.find( key );
@@ -413,22 +441,23 @@ const Glyph& FontTrueType::getGlyphByIndex( Uint32 index, unsigned int character
413441

414442
const Glyph& FontTrueType::getGlyphByIndex( Uint32 index, unsigned int characterSize, bool bold,
415443
Float outlineThickness ) const {
416-
return getGlyphByIndex( index, characterSize, bold, outlineThickness, mPages[characterSize],
444+
return getGlyphByIndex( index, characterSize, bold, outlineThickness, getPage( characterSize ),
417445
0.f );
418446
}
419447

420448
GlyphDrawable* FontTrueType::getGlyphDrawable( Uint32 codePoint, unsigned int characterSize,
421449
bool bold, Float outlineThickness ) const {
422-
GlyphDrawableTable& drawables = mPages[characterSize].drawables;
450+
GlyphDrawableTable& drawables = getPage( characterSize ).drawables;
423451

424-
Uint64 key = getIndexKey( codePoint, bold, outlineThickness );
452+
Uint64 key = getIndexKey( getPage( characterSize ).fontInternalId, getGlyphIndex( codePoint ),
453+
bold, outlineThickness );
425454

426455
auto it = drawables.find( key );
427456
if ( it != drawables.end() ) {
428457
return it->second;
429458
} else {
430459
const Glyph& glyph = getGlyph( codePoint, characterSize, bold, outlineThickness );
431-
auto& page = mPages[characterSize];
460+
auto& page = getPage( characterSize );
432461
GlyphDrawable* region = GlyphDrawable::New(
433462
page.texture, glyph.textureRect,
434463
String::format( "%s_%d_%u", mFontName.c_str(), characterSize, codePoint ) );
@@ -442,15 +471,15 @@ GlyphDrawable* FontTrueType::getGlyphDrawable( Uint32 codePoint, unsigned int ch
442471
Float FontTrueType::getKerning( Uint32 first, Uint32 second, unsigned int characterSize,
443472
bool bold ) const {
444473
// Special case where first or second is 0 (null character)
445-
if ( first == 0 || second == 0 )
474+
if ( first == 0 || second == 0 || isMonospace() )
446475
return 0.f;
447476

448477
FT_Face face = static_cast<FT_Face>( mFace );
449478

450479
if ( face && setCurrentSize( characterSize ) ) {
451480
// Convert the characters to indices
452-
FT_UInt index1 = FT_Get_Char_Index( face, first );
453-
FT_UInt index2 = FT_Get_Char_Index( face, second );
481+
FT_UInt index1 = getGlyphIndex( first );
482+
FT_UInt index2 = getGlyphIndex( second );
454483

455484
// Retrieve position compensation deltas generated by FT_LOAD_FORCE_AUTOHINT flag
456485
auto firstRsbDelta = static_cast<float>( getGlyph( first, characterSize, bold ).rsbDelta );
@@ -543,7 +572,7 @@ Float FontTrueType::getUnderlineThickness( unsigned int characterSize ) const {
543572
}
544573

545574
Texture* FontTrueType::getTexture( unsigned int characterSize ) const {
546-
return mPages[characterSize].texture;
575+
return getPage( characterSize ).texture;
547576
}
548577

549578
bool FontTrueType::loaded() const {
@@ -998,6 +1027,24 @@ bool FontTrueType::setCurrentSize( unsigned int characterSize ) const {
9981027
}
9991028
}
10001029

1030+
FontTrueType::Page& FontTrueType::getPage( unsigned int characterSize ) const {
1031+
auto pageIt = mPages.find( characterSize );
1032+
if ( pageIt == mPages.end() ) {
1033+
mPages.insert( std::make_pair( characterSize,
1034+
std::make_unique<Page>( fontsInternalIds[mInfo.family] ) ) );
1035+
pageIt = mPages.find( characterSize );
1036+
}
1037+
return *pageIt->second;
1038+
}
1039+
1040+
void FontTrueType::setIsEmojiFont( bool isEmojiFont ) {
1041+
mIsEmojiFont = isEmojiFont;
1042+
}
1043+
1044+
void FontTrueType::setIsColorEmojiFont( bool isColorEmojiFont ) {
1045+
mIsColorEmojiFont = isColorEmojiFont;
1046+
}
1047+
10011048
bool FontTrueType::isColorEmojiFont() const {
10021049
return mIsColorEmojiFont;
10031050
}
@@ -1006,6 +1053,10 @@ bool FontTrueType::isMonospace() const {
10061053
return FT_IS_FIXED_WIDTH( static_cast<FT_Face>( mFace ) );
10071054
}
10081055

1056+
bool FontTrueType::isEmojiFont() const {
1057+
return mIsEmojiFont;
1058+
}
1059+
10091060
bool FontTrueType::getBoldAdvanceSameAsRegular() const {
10101061
return mBoldAdvanceSameAsRegular;
10111062
}
@@ -1014,7 +1065,8 @@ void FontTrueType::setBoldAdvanceSameAsRegular( bool boldAdvanceSameAsRegular )
10141065
mBoldAdvanceSameAsRegular = boldAdvanceSameAsRegular;
10151066
}
10161067

1017-
FontTrueType::Page::Page() : texture( NULL ), nextRow( 3 ) {
1068+
FontTrueType::Page::Page( const Uint32 fontInternalId ) :
1069+
texture( NULL ), nextRow( 3 ), fontInternalId( fontInternalId ) {
10181070
// Make sure that the texture is initialized by default
10191071
Image image;
10201072
image.create( 128, 128, 4 );

0 commit comments

Comments
 (0)