mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-08-10 00:31:20 +03:00
More improvements for text shaping.
This commit is contained in:
@@ -133,6 +133,8 @@ class EE_API FontTrueType : public Font {
|
||||
|
||||
void* hb() const { return mHBFont; }
|
||||
|
||||
bool setCurrentSize( unsigned int characterSize ) const;
|
||||
|
||||
protected:
|
||||
friend class Text;
|
||||
|
||||
@@ -179,8 +181,6 @@ class EE_API FontTrueType : public Font {
|
||||
|
||||
Rect findGlyphRect( Page& page, unsigned int width, unsigned int height ) const;
|
||||
|
||||
bool setCurrentSize( unsigned int characterSize ) const;
|
||||
|
||||
Page& getPage( unsigned int characterSize ) const;
|
||||
|
||||
typedef UnorderedMap<unsigned int, std::unique_ptr<Page>>
|
||||
|
||||
@@ -21,10 +21,15 @@ namespace EE { namespace Graphics {
|
||||
|
||||
namespace {
|
||||
|
||||
#ifdef EE_TEXT_SHAPER_ENABLED
|
||||
static constexpr bool TextShaperEnabled = true;
|
||||
#endif
|
||||
|
||||
// helper class that divides the string into lines and font runs.
|
||||
class TextShapeRun {
|
||||
public:
|
||||
TextShapeRun( const String& str, FontStyleConfig& config ) : mString( str ), mConfig( config ) {
|
||||
TextShapeRun( const String& str, const FontStyleConfig& config ) :
|
||||
mString( str ), mConfig( config ) {
|
||||
findNextEnd();
|
||||
}
|
||||
|
||||
@@ -79,9 +84,48 @@ class TextShapeRun {
|
||||
Font* mFont{ nullptr };
|
||||
Font* mStartFont{ nullptr };
|
||||
bool mIsNewLine{ false };
|
||||
FontStyleConfig& mConfig;
|
||||
const FontStyleConfig& mConfig;
|
||||
};
|
||||
|
||||
static void shapeAndRun( const String& string, const FontStyleConfig& config,
|
||||
const std::function<void( hb_glyph_info_t*, hb_glyph_position_t*, Uint32,
|
||||
TextShapeRun& )>& cb ) {
|
||||
hb_buffer_t* hbBuffer = hb_buffer_create();
|
||||
TextShapeRun run( string, config );
|
||||
|
||||
while ( run.hasNext() ) {
|
||||
String::View curRun( run.curRun() );
|
||||
FontTrueType* font = run.font();
|
||||
font->setCurrentSize( config.CharacterSize );
|
||||
|
||||
hb_buffer_reset( hbBuffer );
|
||||
hb_buffer_add_utf32( hbBuffer, (Uint32*)curRun.data(), curRun.size(), 0, curRun.size() );
|
||||
hb_buffer_guess_segment_properties( hbBuffer );
|
||||
|
||||
// Enable kerning
|
||||
static const hb_feature_t features[] = {
|
||||
hb_feature_t{ HB_TAG( 'k', 'e', 'r', 'n' ), 1, HB_FEATURE_GLOBAL_START,
|
||||
HB_FEATURE_GLOBAL_END },
|
||||
};
|
||||
|
||||
// whitelist cross-platforms shapers only
|
||||
static const char* shaper_list[] = { "graphite2", "ot", "fallback", nullptr };
|
||||
|
||||
hb_shape_full( static_cast<hb_font_t*>( font->hb() ), hbBuffer, features, 1, shaper_list );
|
||||
|
||||
// from the shaped text we get the glyphs and positions
|
||||
unsigned int glyphCount;
|
||||
hb_glyph_info_t* glyphInfo = hb_buffer_get_glyph_infos( hbBuffer, &glyphCount );
|
||||
hb_glyph_position_t* glyphPos = hb_buffer_get_glyph_positions( hbBuffer, &glyphCount );
|
||||
|
||||
cb( glyphInfo, glyphPos, glyphCount, run );
|
||||
|
||||
run.next();
|
||||
}
|
||||
|
||||
hb_buffer_destroy( hbBuffer );
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::string Text::styleFlagToString( const Uint32& flags ) {
|
||||
@@ -992,16 +1036,66 @@ void Text::updateWidthCache() {
|
||||
|
||||
Float width = 0;
|
||||
Float maxWidth = 0;
|
||||
Uint32 rune;
|
||||
Uint32 prevChar = 0;
|
||||
bool bold = ( mFontStyleConfig.Style & Bold ) != 0;
|
||||
bool italic = ( mFontStyleConfig.Style & Italic ) != 0;
|
||||
|
||||
Float hspace = static_cast<Float>( mFontStyleConfig.Font
|
||||
->getGlyph( L' ', mFontStyleConfig.CharacterSize, bold,
|
||||
italic, mFontStyleConfig.OutlineThickness )
|
||||
.advance );
|
||||
|
||||
#ifdef EE_TEXT_SHAPER_ENABLED
|
||||
if ( TextShaperEnabled && mFontStyleConfig.Font->getType() == FontType::TTF ) {
|
||||
FontTrueType* rFont = static_cast<FontTrueType*>( mFontStyleConfig.Font );
|
||||
shapeAndRun( mString, mFontStyleConfig,
|
||||
[&]( hb_glyph_info_t* glyphInfo, hb_glyph_position_t*, Uint32 glyphCount,
|
||||
TextShapeRun& run ) {
|
||||
FontTrueType* font = run.font();
|
||||
Uint32 prevGlyphIndex = 0;
|
||||
|
||||
for ( std::size_t i = 0; i < glyphCount; ++i ) {
|
||||
hb_glyph_info_t curGlyph = glyphInfo[i];
|
||||
auto curChar = mString[curGlyph.cluster];
|
||||
|
||||
if ( curChar == '\t' ) {
|
||||
width += hspace * mTabWidth;
|
||||
prevGlyphIndex = curGlyph.codepoint;
|
||||
continue;
|
||||
}
|
||||
|
||||
const Glyph& glyph = font->getGlyphByIndex(
|
||||
curGlyph.codepoint, mFontStyleConfig.CharacterSize, bold, italic,
|
||||
0, rFont->getPage( mFontStyleConfig.CharacterSize ), 0 );
|
||||
|
||||
width += rFont->getKerningFromGlyphIndex(
|
||||
prevGlyphIndex, curGlyph.codepoint, mFontStyleConfig.CharacterSize,
|
||||
bold, italic, mFontStyleConfig.OutlineThickness );
|
||||
|
||||
width += font->isColorEmojiFont() && ' ' != curChar
|
||||
? glyph.size.getWidth()
|
||||
: glyph.advance;
|
||||
|
||||
if ( width > maxWidth )
|
||||
maxWidth = width;
|
||||
|
||||
prevGlyphIndex = curGlyph.codepoint;
|
||||
}
|
||||
|
||||
if ( run.runIsNewLine() ) {
|
||||
mLinesWidth.push_back( width );
|
||||
width = 0;
|
||||
}
|
||||
} );
|
||||
|
||||
if ( !mString.empty() && mString[mString.size() - 1] != '\n' )
|
||||
mLinesWidth.push_back( width );
|
||||
|
||||
mCachedWidth = maxWidth;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
Uint32 rune;
|
||||
Uint32 prevChar = 0;
|
||||
size_t size = mString.size();
|
||||
for ( std::size_t i = 0; i < size; ++i ) {
|
||||
rune = mString[i];
|
||||
@@ -1306,55 +1400,79 @@ void Text::ensureGeometryUpdate() {
|
||||
}
|
||||
|
||||
#ifdef EE_TEXT_SHAPER_ENABLED
|
||||
if ( mFontStyleConfig.Font->getType() == FontType::TTF ) {
|
||||
if ( TextShaperEnabled && mFontStyleConfig.Font->getType() == FontType::TTF ) {
|
||||
FontTrueType* rFont = static_cast<FontTrueType*>( mFontStyleConfig.Font );
|
||||
hb_buffer_t* hbBuffer = hb_buffer_create();
|
||||
TextShapeRun run( mString, mFontStyleConfig );
|
||||
|
||||
while ( run.hasNext() ) {
|
||||
String::View curRun( run.curRun() );
|
||||
FontTrueType* font = run.font();
|
||||
font->setCurrentSize( mFontStyleConfig.CharacterSize );
|
||||
shapeAndRun(
|
||||
mString, mFontStyleConfig,
|
||||
[&]( hb_glyph_info_t* glyphInfo, hb_glyph_position_t* glyphPos, Uint32 glyphCount,
|
||||
TextShapeRun& run ) {
|
||||
FontTrueType* font = run.font();
|
||||
Uint32 prevGlyphIndex = 0;
|
||||
|
||||
hb_buffer_reset( hbBuffer );
|
||||
hb_buffer_add_utf32( hbBuffer, (Uint32*)curRun.data(), curRun.size(), 0,
|
||||
curRun.size() );
|
||||
hb_buffer_guess_segment_properties( hbBuffer );
|
||||
for ( std::size_t i = 0; i < glyphCount; ++i ) {
|
||||
hb_glyph_info_t curGlyph = glyphInfo[i];
|
||||
hb_glyph_position_t curGlyphPos = glyphPos[i];
|
||||
auto curChar = mString[curGlyph.cluster];
|
||||
|
||||
// Enable kerning
|
||||
static const hb_feature_t features[] = {
|
||||
hb_feature_t{ HB_TAG( 'k', 'e', 'r', 'n' ), 1, HB_FEATURE_GLOBAL_START,
|
||||
HB_FEATURE_GLOBAL_END },
|
||||
};
|
||||
if ( curChar == '\t' ) {
|
||||
minX = std::min( minX, x );
|
||||
|
||||
// whitelist cross-platforms shapers only
|
||||
static const char* shaper_list[] = { "graphite2", "ot", "fallback", nullptr };
|
||||
if ( curChar == '\t' )
|
||||
x += hspace * mTabWidth;
|
||||
else
|
||||
x += hspace;
|
||||
|
||||
hb_shape_full( static_cast<hb_font_t*>( font->hb() ), hbBuffer, features, 1,
|
||||
shaper_list );
|
||||
maxX = std::max( maxX, x );
|
||||
|
||||
// from the shaped text we get the glyphs and positions
|
||||
Uint32 prevGlyphIndex = 0;
|
||||
unsigned int glyphCount;
|
||||
hb_glyph_info_t* glyphInfo = hb_buffer_get_glyph_infos( hbBuffer, &glyphCount );
|
||||
hb_glyph_position_t* glyphPos = hb_buffer_get_glyph_positions( hbBuffer, &glyphCount );
|
||||
if ( mCachedWidthNeedUpdate )
|
||||
maxW = std::max( maxW, x );
|
||||
|
||||
for ( std::size_t i = 0; i < glyphCount; ++i ) {
|
||||
hb_glyph_info_t curGlyph = glyphInfo[i];
|
||||
hb_glyph_position_t curGlyphPos = glyphPos[i];
|
||||
prevGlyphIndex = curGlyph.codepoint;
|
||||
continue;
|
||||
}
|
||||
|
||||
x += rFont->getKerningFromGlyphIndex(
|
||||
prevGlyphIndex, curGlyph.codepoint, mFontStyleConfig.CharacterSize, bold,
|
||||
reqItalic, mFontStyleConfig.OutlineThickness );
|
||||
x += rFont->getKerningFromGlyphIndex(
|
||||
prevGlyphIndex, curGlyph.codepoint, mFontStyleConfig.CharacterSize, bold,
|
||||
reqItalic, mFontStyleConfig.OutlineThickness );
|
||||
|
||||
Float currentX = x + ( curGlyphPos.x_offset / 64.f );
|
||||
Float currentY = y + ( curGlyphPos.y_offset / 64.f );
|
||||
Float currentX = x + ( curGlyphPos.x_offset / 64.f );
|
||||
Float currentY = y + ( curGlyphPos.y_offset / 64.f );
|
||||
|
||||
// Apply the outline
|
||||
if ( mFontStyleConfig.OutlineThickness != 0 ) {
|
||||
// Apply the outline
|
||||
if ( mFontStyleConfig.OutlineThickness != 0 ) {
|
||||
const Glyph& glyph = font->getGlyphByIndex(
|
||||
curGlyph.codepoint, mFontStyleConfig.CharacterSize, bold, reqItalic,
|
||||
mFontStyleConfig.OutlineThickness,
|
||||
rFont->getPage( mFontStyleConfig.CharacterSize ), 0 );
|
||||
|
||||
Float left = glyph.bounds.Left;
|
||||
Float top = glyph.bounds.Top;
|
||||
Float right = glyph.bounds.Left + glyph.bounds.Right;
|
||||
Float bottom = glyph.bounds.Top + glyph.bounds.Bottom;
|
||||
|
||||
// Add the outline glyph to the vertices
|
||||
if ( glyph.bounds.Right > 0 && glyph.bounds.Bottom > 0 ) {
|
||||
addGlyphQuad( mOutlineVertices, Vector2f( currentX, currentY ), glyph,
|
||||
italic, mFontStyleConfig.OutlineThickness, centerDiffX );
|
||||
}
|
||||
|
||||
// Update the current bounds with the outlined glyph bounds
|
||||
minX = std::min( minX, x + left - italic * bottom -
|
||||
mFontStyleConfig.OutlineThickness );
|
||||
maxX = std::max( maxX, x + right - italic * top -
|
||||
mFontStyleConfig.OutlineThickness );
|
||||
minY = std::min( minY, y + top - mFontStyleConfig.OutlineThickness );
|
||||
maxY = std::max( maxY, y + bottom - mFontStyleConfig.OutlineThickness );
|
||||
if ( mCachedWidthNeedUpdate ) {
|
||||
maxW = std::max( maxW, x + glyph.advance - italic * top -
|
||||
mFontStyleConfig.OutlineThickness );
|
||||
}
|
||||
}
|
||||
|
||||
// Extract the current glyph's description
|
||||
const Glyph& glyph = font->getGlyphByIndex(
|
||||
curGlyph.codepoint, mFontStyleConfig.CharacterSize, bold, reqItalic,
|
||||
mFontStyleConfig.OutlineThickness,
|
||||
curGlyph.codepoint, mFontStyleConfig.CharacterSize, bold, reqItalic, 0,
|
||||
rFont->getPage( mFontStyleConfig.CharacterSize ), 0 );
|
||||
|
||||
Float left = glyph.bounds.Left;
|
||||
@@ -1362,89 +1480,68 @@ void Text::ensureGeometryUpdate() {
|
||||
Float right = glyph.bounds.Left + glyph.bounds.Right;
|
||||
Float bottom = glyph.bounds.Top + glyph.bounds.Bottom;
|
||||
|
||||
// Add the outline glyph to the vertices
|
||||
// Add a quad for the current character
|
||||
if ( glyph.bounds.Right > 0 && glyph.bounds.Bottom > 0 ) {
|
||||
addGlyphQuad( mOutlineVertices, Vector2f( currentX, currentY ), glyph,
|
||||
italic, mFontStyleConfig.OutlineThickness, centerDiffX );
|
||||
addGlyphQuad( mVertices, Vector2f( currentX, currentY ), glyph, italic, 0,
|
||||
centerDiffX );
|
||||
}
|
||||
|
||||
// Update the current bounds with the outlined glyph bounds
|
||||
minX = std::min( minX, x + left - italic * bottom -
|
||||
mFontStyleConfig.OutlineThickness );
|
||||
maxX = std::max( maxX,
|
||||
x + right - italic * top - mFontStyleConfig.OutlineThickness );
|
||||
minY = std::min( minY, y + top - mFontStyleConfig.OutlineThickness );
|
||||
maxY = std::max( maxY, y + bottom - mFontStyleConfig.OutlineThickness );
|
||||
if ( mCachedWidthNeedUpdate ) {
|
||||
maxW = std::max( maxW, x + glyph.advance - italic * top -
|
||||
mFontStyleConfig.OutlineThickness );
|
||||
// Update the current bounds
|
||||
minX = std::min( minX, currentX + left - italic * bottom );
|
||||
maxX = std::max( maxX, currentX + right - italic * top );
|
||||
minY = std::min( minY, currentY + top );
|
||||
maxY = std::max( maxY, currentY + bottom );
|
||||
|
||||
// Advance to the next character
|
||||
x += font->isColorEmojiFont() && ' ' != curChar ? glyph.size.getWidth()
|
||||
: glyph.advance;
|
||||
|
||||
prevGlyphIndex = curGlyph.codepoint;
|
||||
}
|
||||
|
||||
// If we're using the underlined style, add the last line
|
||||
if ( underlined && run.runIsNewLine() ) {
|
||||
addLine( mVertices, x, y, underlineOffset, underlineThickness, 0, centerDiffX );
|
||||
|
||||
if ( mFontStyleConfig.OutlineThickness != 0 )
|
||||
addLine( mOutlineVertices, x, y, underlineOffset, underlineThickness,
|
||||
mFontStyleConfig.OutlineThickness, centerDiffX );
|
||||
}
|
||||
|
||||
// If we're using the strike through style, add the last line across all characters
|
||||
if ( strikeThrough && run.runIsNewLine() ) {
|
||||
addLine( mVertices, x, y, strikeThroughOffset, underlineThickness, 0,
|
||||
centerDiffX );
|
||||
|
||||
if ( mFontStyleConfig.OutlineThickness != 0 )
|
||||
addLine( mOutlineVertices, x, y, strikeThroughOffset, underlineThickness,
|
||||
mFontStyleConfig.OutlineThickness, centerDiffX );
|
||||
}
|
||||
|
||||
if ( mCachedWidthNeedUpdate )
|
||||
mLinesWidth.push_back( x );
|
||||
|
||||
// next line
|
||||
if ( run.runIsNewLine() ) {
|
||||
y += vspace;
|
||||
x = 0;
|
||||
switch ( Font::getHorizontalAlign( mAlign ) ) {
|
||||
case TEXT_ALIGN_CENTER:
|
||||
centerDiffX =
|
||||
line < mLinesWidth.size()
|
||||
? (Float)( (Int32)( ( mCachedWidth - mLinesWidth[line] ) *
|
||||
0.5f ) )
|
||||
: 0.f;
|
||||
line++;
|
||||
break;
|
||||
case TEXT_ALIGN_RIGHT:
|
||||
centerDiffX =
|
||||
line < mLinesWidth.size() ? mCachedWidth - mLinesWidth[line] : 0.f;
|
||||
line++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Extract the current glyph's description
|
||||
const Glyph& glyph = font->getGlyphByIndex(
|
||||
curGlyph.codepoint, mFontStyleConfig.CharacterSize, bold, reqItalic, 0,
|
||||
rFont->getPage( mFontStyleConfig.CharacterSize ), 0 );
|
||||
|
||||
Float left = glyph.bounds.Left;
|
||||
Float top = glyph.bounds.Top;
|
||||
Float right = glyph.bounds.Left + glyph.bounds.Right;
|
||||
Float bottom = glyph.bounds.Top + glyph.bounds.Bottom;
|
||||
|
||||
// Add a quad for the current character
|
||||
if ( glyph.bounds.Right > 0 && glyph.bounds.Bottom > 0 ) {
|
||||
addGlyphQuad( mVertices, Vector2f( currentX, currentY ), glyph, italic, 0,
|
||||
centerDiffX );
|
||||
}
|
||||
|
||||
// Update the current bounds
|
||||
minX = std::min( minX, currentX + left - italic * bottom );
|
||||
maxX = std::max( maxX, currentX + right - italic * top );
|
||||
minY = std::min( minY, currentY + top );
|
||||
maxY = std::max( maxY, currentY + bottom );
|
||||
|
||||
// Advance to the next character
|
||||
if ( font->isColorEmojiFont() ) {
|
||||
x += glyph.size.getWidth();
|
||||
y += ( curGlyphPos.y_advance / 64.f ) *
|
||||
( mFontStyleConfig.CharacterSize /
|
||||
static_cast<FT_Face>( font->face() )->available_sizes[0].height );
|
||||
} else {
|
||||
x += glyph.advance;
|
||||
y += curGlyphPos.y_advance / 64.f;
|
||||
}
|
||||
|
||||
prevGlyphIndex = curGlyph.codepoint;
|
||||
}
|
||||
|
||||
// If we're using the underlined style, add the last line
|
||||
if ( underlined && run.runIsNewLine() ) {
|
||||
addLine( mVertices, x, y, underlineOffset, underlineThickness, 0, centerDiffX );
|
||||
|
||||
if ( mFontStyleConfig.OutlineThickness != 0 )
|
||||
addLine( mOutlineVertices, x, y, underlineOffset, underlineThickness,
|
||||
mFontStyleConfig.OutlineThickness, centerDiffX );
|
||||
}
|
||||
|
||||
// If we're using the strike through style, add the last line across all characters
|
||||
if ( strikeThrough && run.runIsNewLine() ) {
|
||||
addLine( mVertices, x, y, strikeThroughOffset, underlineThickness, 0, centerDiffX );
|
||||
|
||||
if ( mFontStyleConfig.OutlineThickness != 0 )
|
||||
addLine( mOutlineVertices, x, y, strikeThroughOffset, underlineThickness,
|
||||
mFontStyleConfig.OutlineThickness, centerDiffX );
|
||||
}
|
||||
|
||||
if ( mCachedWidthNeedUpdate )
|
||||
mLinesWidth.push_back( x );
|
||||
|
||||
// next line
|
||||
if ( run.runIsNewLine() ) {
|
||||
y += vspace;
|
||||
x = 0;
|
||||
}
|
||||
run.next();
|
||||
}
|
||||
} );
|
||||
|
||||
// Update the bounding rectangle
|
||||
mBounds.Left = minX;
|
||||
@@ -1457,8 +1554,6 @@ void Text::ensureGeometryUpdate() {
|
||||
mCachedWidthNeedUpdate = false;
|
||||
}
|
||||
|
||||
hb_buffer_destroy( hbBuffer );
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,56 +1,8 @@
|
||||
#include <eepp/ee.hpp>
|
||||
|
||||
EE::Window::Window* win = NULL;
|
||||
FontTrueType* fontTest;
|
||||
FontTrueType* fontTest2;
|
||||
FontTrueType* fontEmoji;
|
||||
FontTrueType* fontEmojiColor;
|
||||
FontBMFont* fontBMFont;
|
||||
FontSprite* fontSprite;
|
||||
Text text;
|
||||
Text text2;
|
||||
Text text3;
|
||||
Text text4;
|
||||
Text text5;
|
||||
Text text6;
|
||||
Text text7;
|
||||
EE_MAIN_FUNC int main( int, char*[] ) {
|
||||
EE::Window::Window* win = NULL;
|
||||
|
||||
void mainLoop() {
|
||||
// Clear the screen buffer
|
||||
win->clear();
|
||||
|
||||
// Update the input
|
||||
win->getInput()->update();
|
||||
|
||||
// Check if ESCAPE key is pressed
|
||||
if ( win->getInput()->isKeyDown( KEY_ESCAPE ) ) {
|
||||
// Close the window
|
||||
win->close();
|
||||
}
|
||||
|
||||
text.draw( ( win->getWidth() - text.getTextWidth() ) * 0.5f, 32 );
|
||||
|
||||
text2.draw( ( win->getWidth() - text2.getTextWidth() ) * 0.5f, 300 );
|
||||
|
||||
text7.draw( ( win->getWidth() - text7.getTextWidth() ) * 0.5f, 400 );
|
||||
|
||||
// Text rotated and scaled
|
||||
text2.draw( ( win->getWidth() - text2.getTextWidth() ) * 0.5f, 430, Vector2f( 1.1f, 1.1f ),
|
||||
12.5f );
|
||||
|
||||
text3.draw( ( win->getWidth() - text3.getTextWidth() ) * 0.5f, 560 );
|
||||
|
||||
text4.draw( ( win->getWidth() - text4.getTextWidth() ) * 0.5f, 590 );
|
||||
|
||||
text5.draw( ( win->getWidth() - text5.getTextWidth() ) * 0.5f, 640 );
|
||||
|
||||
text6.draw( ( win->getWidth() - text6.getTextWidth() ) * 0.5f, 690 );
|
||||
|
||||
// Draw frame
|
||||
win->display();
|
||||
}
|
||||
|
||||
EE_MAIN_FUNC int main( int argc, char* argv[] ) {
|
||||
// Create a new window
|
||||
win = Engine::instance()->createWindow( WindowSettings( 1024, 768, "eepp - Fonts" ),
|
||||
ContextSettings( true ) );
|
||||
@@ -73,25 +25,26 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) {
|
||||
"cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non "
|
||||
"proident, sunt in culpa qui officia deserunt mollit anim id est laborum." );
|
||||
|
||||
fontTest = FontTrueType::New( "DejaVuSansMono" );
|
||||
FontTrueType* fontTest = FontTrueType::New( "DejaVuSansMono" );
|
||||
fontTest->loadFromFile( "assets/fonts/DejaVuSansMono.ttf" );
|
||||
|
||||
fontTest2 = FontTrueType::New( "NotoSans-Regular" );
|
||||
FontTrueType* fontTest2 = FontTrueType::New( "NotoSans-Regular" );
|
||||
fontTest2->loadFromFile( "assets/fonts/NotoSans-Regular.ttf" );
|
||||
|
||||
fontEmoji= FontTrueType::New( "NotoEmoji-Regular" );
|
||||
FontTrueType* fontEmoji = FontTrueType::New( "NotoEmoji-Regular" );
|
||||
fontEmoji->loadFromFile( "assets/fonts/NotoEmoji-Regular.ttf" );
|
||||
|
||||
fontEmojiColor = FontTrueType::New( "NotoColorEmoji" );
|
||||
FontTrueType* fontEmojiColor = FontTrueType::New( "NotoColorEmoji" );
|
||||
fontEmojiColor->loadFromFile( "assets/fonts/NotoColorEmoji.ttf" );
|
||||
|
||||
fontBMFont = FontBMFont::New( "bmfont" );
|
||||
FontBMFont* fontBMFont = FontBMFont::New( "bmfont" );
|
||||
fontBMFont->loadFromFile( "assets/fonts/bmfont.fnt" );
|
||||
|
||||
fontSprite = FontSprite::New(
|
||||
FontSprite* fontSprite = FontSprite::New(
|
||||
"alagard" ); // Alagard - Hewett Tsoi ( https://www.dafont.com/alagard.font )
|
||||
fontSprite->loadFromFile( "assets/fonts/custom_alagard.png", Color::Fuchsia, 32, -4 );
|
||||
|
||||
Text text;
|
||||
text.setFont( fontTest );
|
||||
text.setFontSize( 24 );
|
||||
text.setAlign( TEXT_ALIGN_CENTER );
|
||||
@@ -106,11 +59,13 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) {
|
||||
text.setFillColor( Color( 255 * i / size, 0, 0, 255 ), i, i + 1 );
|
||||
}
|
||||
|
||||
Text text2;
|
||||
text2.setFont( fontTest2 );
|
||||
text2.setString( "Lorem ipsum dolor sit amet, consectetur adipisicing elit. 👽" );
|
||||
text2.setFontSize( 32 );
|
||||
text2.setFillColor( Color::Black );
|
||||
|
||||
Text text3;
|
||||
text3.setFont( fontTest );
|
||||
text3.setString( text2.getString() );
|
||||
text3.setFontSize( 24 );
|
||||
@@ -118,19 +73,23 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) {
|
||||
text3.setOutlineThickness( 2 );
|
||||
text3.setOutlineColor( Color( 0, 0, 0, 255 ) );
|
||||
|
||||
Text text4;
|
||||
text4.setFont( fontBMFont );
|
||||
text4.setString( text2.getString() );
|
||||
text4.setFontSize( 45 );
|
||||
text4.setFillColor( Color::Black );
|
||||
|
||||
Text text5;
|
||||
text5.setFont( fontSprite );
|
||||
text5.setString( text2.getString() );
|
||||
text5.setFontSize( 38 );
|
||||
|
||||
Text text6;
|
||||
text6.setFont( fontEmojiColor );
|
||||
text6.setFontSize( 64 );
|
||||
text6.setString( "👽 😀 💩 😃 👻" );
|
||||
|
||||
Text text7;
|
||||
text7.setFont( fontEmoji );
|
||||
text7.setFontSize( 32 );
|
||||
text7.setString( "👽 😀 💩 😃 👻" );
|
||||
@@ -139,7 +98,40 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) {
|
||||
text7.setOutlineColor( Color( 0, 0, 0, 255 ) );
|
||||
|
||||
// Application loop
|
||||
win->runMainLoop( &mainLoop );
|
||||
win->runMainLoop( [&] {
|
||||
// Clear the screen buffer
|
||||
win->clear();
|
||||
|
||||
// Update the input
|
||||
win->getInput()->update();
|
||||
|
||||
// Check if ESCAPE key is pressed
|
||||
if ( win->getInput()->isKeyDown( KEY_ESCAPE ) ) {
|
||||
// Close the window
|
||||
win->close();
|
||||
}
|
||||
|
||||
text.draw( ( win->getWidth() - text.getTextWidth() ) * 0.5f, 32 );
|
||||
|
||||
text2.draw( ( win->getWidth() - text2.getTextWidth() ) * 0.5f, 300 );
|
||||
|
||||
text7.draw( ( win->getWidth() - text7.getTextWidth() ) * 0.5f, 400 );
|
||||
|
||||
// Text rotated and scaled
|
||||
text2.draw( ( win->getWidth() - text2.getTextWidth() ) * 0.5f, 430,
|
||||
Vector2f( 1.1f, 1.1f ), 12.5f );
|
||||
|
||||
text3.draw( ( win->getWidth() - text3.getTextWidth() ) * 0.5f, 560 );
|
||||
|
||||
text4.draw( ( win->getWidth() - text4.getTextWidth() ) * 0.5f, 590 );
|
||||
|
||||
text5.draw( ( win->getWidth() - text5.getTextWidth() ) * 0.5f, 640 );
|
||||
|
||||
text6.draw( ( win->getWidth() - text6.getTextWidth() ) * 0.5f, 690 );
|
||||
|
||||
// Draw frame
|
||||
win->display();
|
||||
} );
|
||||
}
|
||||
|
||||
// Destroy the engine instance. Destroys all the windows and engine singletons.
|
||||
|
||||
Reference in New Issue
Block a user