Merge branch 'text-shape' into develop
@@ -204,7 +204,7 @@
|
||||
},
|
||||
"run": [
|
||||
{
|
||||
"args": "",
|
||||
"args": "--text-shaper",
|
||||
"command": "${project_root}/bin/ecode-debug",
|
||||
"name": "ecode-debug",
|
||||
"working_dir": "${project_root}/bin"
|
||||
|
||||
BIN
bin/unit_tests/assets/fontrendering/eepp-text-style-bold.webp
Normal file
|
After Width: | Height: | Size: 7.8 KiB |
BIN
bin/unit_tests/assets/fontrendering/eepp-text-style-italic.webp
Normal file
|
After Width: | Height: | Size: 9.2 KiB |
BIN
bin/unit_tests/assets/fontrendering/eepp-text-style-outline.webp
Normal file
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 7.6 KiB |
|
After Width: | Height: | Size: 7.6 KiB |
BIN
bin/unit_tests/assets/fontrendering/eepp-text-style-regular.webp
Normal file
|
After Width: | Height: | Size: 7.7 KiB |
BIN
bin/unit_tests/assets/fontrendering/eepp-text-style-shadow.webp
Normal file
|
After Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 7.2 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 7.7 KiB |
|
After Width: | Height: | Size: 7.7 KiB |
|
After Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
BIN
bin/unit_tests/assets/fonts/NotoNaskhArabic-Regular.ttf
Normal file
BIN
bin/unit_tests/assets/fonts/NotoSansBengali-Regular.ttf
Normal file
@@ -0,0 +1 @@
|
||||
اسکم شاخ و دم نداره همین که کاربر شبکه خودت. کسی که رو شبکه تو فی داده سالها زحمت کشیده رو نادیده میگیری و به کاربر یه شبکه دیگه توکن سنگین میدی میشه اسکم علنی. باید کاری باهاش کنیم که مثل استارک به غلط کردن بیافته اره تو endgame هستی اخر اسکمرایی
|
||||
1
bin/unit_tests/assets/textfiles/test-arabic-simple.uext
Normal file
@@ -0,0 +1 @@
|
||||
مَرْحَبًا بِالْعَالَم
|
||||
@@ -1 +1,24 @@
|
||||
اسکم شاخ و دم نداره همین که کاربر شبکه خودت. کسی که رو شبکه تو فی داده سالها زحمت کشیده رو نادیده میگیری و به کاربر یه شبکه دیگه توکن سنگین میدی میشه اسکم علنی. باید کاری باهاش کنیم که مثل استارک به غلط کردن بیافته اره تو endgame هستی اخر اسکمرایی
|
||||
Hello: مرحبا
|
||||
Good morning: صباح الخير
|
||||
Good night: تصبح على خير
|
||||
Thank you: شكراً
|
||||
You're welcome: عفواً
|
||||
Yes / No: نعم / لا
|
||||
Please: من فضلك
|
||||
Excuse me / Sorry: عفواً / آسف
|
||||
How are you?: كيف حالك؟
|
||||
I'm fine. And you?: أنا بخير. وأنت؟
|
||||
What's your name?: ما اسمك؟
|
||||
My name is...: اسمي...
|
||||
Nice to meet you: تشرفت بلقائك
|
||||
Where are you from?: من أين أنت؟
|
||||
I'm from...: أنا من...
|
||||
Do you speak English?: هل تتحدث الإنجليزية؟
|
||||
I don't understand: لا أفهم
|
||||
Please speak more slowly: من فضلك تكلم ببطء أكثر
|
||||
Please write it down: من فضلك اكتبه
|
||||
How much is this?: كم سعره؟
|
||||
Where is the bathroom?: أين الحمام؟
|
||||
Help!: المساعدة!
|
||||
Stop!: توقف!
|
||||
Call the police!: اتصل بالشرطة!
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
Hello: হ্যালো / নমস্কার
|
||||
Good morning: সুপ্রভাত
|
||||
Good night: শুভ রাত্রি
|
||||
Thank you: ধন্যবাদ
|
||||
You're welcome: আপনি স্বাগত জানাই
|
||||
Yes / No: হ্যাঁ / না
|
||||
Please: অনুগ্রহ করে
|
||||
Excuse me / Sorry: মাফ করবেন / দুঃখিত
|
||||
How are you?: আপনি কেমন আছেন?
|
||||
I'm fine. And you?: আমি ভালো আছি। এবং আপনি?
|
||||
What's your name?: আপনার নাম কি?
|
||||
My name is...: আমার নাম...
|
||||
Nice to meet you: আপনার সাথে দেখা করে খুশি
|
||||
Where are you from?: আপনি কোথা থেকে এসেছেন?
|
||||
I'm from...: আমি ... থেকে এসেছি।
|
||||
Do you speak English?: আপনি কি ইংরেজি বলতে পারেন?
|
||||
I don't understand: আমি বুঝতে পারছি না।
|
||||
Please speak more slowly: অনুগ্রহ করে ধীরে বলুন।
|
||||
Please write it down: অনুগ্রহ করে এটি লিখে দিন।
|
||||
How much is this?: এটার দাম কত?
|
||||
Where is the bathroom?: বাথরুম কোথায়?
|
||||
Help!: বাঁচাও!
|
||||
Stop!: থামুন!
|
||||
Call the police!: পুলিশ ডাকুন!
|
||||
Hello: হ্যালো / নমস্কার
|
||||
Good morning: সুপ্রভাত
|
||||
Good night: শুভ রাত্রি
|
||||
Thank you: ধন্যবাদ
|
||||
You're welcome: আপনি স্বাগত জানাই
|
||||
Yes / No: হ্যাঁ / না
|
||||
Please: অনুগ্রহ করে
|
||||
Excuse me / Sorry: মাফ করবেন / দুঃখিত
|
||||
How are you?: আপনি কেমন আছেন?
|
||||
I'm fine. And you?: আমি ভালো আছি। এবং আপনি?
|
||||
What's your name?: আপনার নাম কি?
|
||||
My name is...: আমার নাম...
|
||||
Nice to meet you: আপনার সাথে দেখা করে খুশি
|
||||
Where are you from?: আপনি কোথা থেকে এসেছেন?
|
||||
I'm from...: আমি ... থেকে এসেছি।
|
||||
Do you speak English?: আপনি কি ইংরেজি বলতে পারেন?
|
||||
I don't understand: আমি বুঝতে পারছি না।
|
||||
Please speak more slowly: অনুগ্রহ করে ধীরে বলুন।
|
||||
Please write it down: অনুগ্রহ করে এটি লিখে দিন।
|
||||
How much is this?: এটার দাম কত?
|
||||
Where is the bathroom?: বাথরুম কোথায়?
|
||||
Help!: বাঁচাও!
|
||||
Stop!: থামুন!
|
||||
Call the police!: পুলিশ ডাকুন!
|
||||
|
||||
@@ -154,6 +154,7 @@ class EE_API FontTrueType : public Font {
|
||||
|
||||
protected:
|
||||
friend class Text;
|
||||
friend class TextLayouter;
|
||||
|
||||
explicit FontTrueType( const std::string& FontName );
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
namespace EE { namespace Graphics {
|
||||
|
||||
class FontTrueType;
|
||||
|
||||
enum class CharacterAlignment : Uint32 { Left = 0, Center = 1, Right = 2 };
|
||||
|
||||
struct WhitespaceDisplayConfig {
|
||||
@@ -20,9 +22,76 @@ struct WhitespaceDisplayConfig {
|
||||
std::optional<Float> tabOffset;
|
||||
};
|
||||
|
||||
struct ShapedGlyph {
|
||||
FontTrueType* font{ nullptr };
|
||||
Uint32 glyphIndex{ 0 };
|
||||
Uint32 stringIndex{ 0 };
|
||||
Vector2f position;
|
||||
};
|
||||
|
||||
struct TextLayout {
|
||||
std::vector<ShapedGlyph> shapedGlyphs;
|
||||
std::vector<Float> linesWidth;
|
||||
Sizef size;
|
||||
};
|
||||
|
||||
class EE_API TextLayouter {
|
||||
public:
|
||||
static TextLayout layout( const String& string, Font* font, const Uint32& fontSize,
|
||||
const Uint32& style, const Uint32& tabWidth = 4,
|
||||
const Float& outlineThickness = 0.f,
|
||||
std::optional<Float> tabOffset = {}, Uint32 textDrawHints = 0 );
|
||||
|
||||
static TextLayout layout( const String::View& string, Font* font, const Uint32& fontSize,
|
||||
const Uint32& style, const Uint32& tabWidth = 4,
|
||||
const Float& outlineThickness = 0.f,
|
||||
std::optional<Float> tabOffset = {}, Uint32 textDrawHints = 0 );
|
||||
|
||||
protected:
|
||||
template <typename StringType>
|
||||
static TextLayout layout( const StringType& string, Font* font, const Uint32& fontSize,
|
||||
const Uint32& style, const Uint32& tabWidth = 4,
|
||||
const Float& outlineThickness = 0.f,
|
||||
std::optional<Float> tabOffset = {}, Uint32 textDrawHints = 0 );
|
||||
};
|
||||
|
||||
// helper class that divides the string into lines and font runs.
|
||||
class EE_API TextShapeRun {
|
||||
public:
|
||||
TextShapeRun( String::View str, FontTrueType* font, Uint32 characterSize, Uint32 style,
|
||||
Float outlineThickness );
|
||||
|
||||
String::View curRun() const;
|
||||
|
||||
bool hasNext() const;
|
||||
|
||||
std::size_t pos() const;
|
||||
|
||||
void next();
|
||||
|
||||
bool runIsNewLine() const;
|
||||
|
||||
FontTrueType* font();
|
||||
|
||||
protected:
|
||||
void findNextEnd();
|
||||
|
||||
String::View mString;
|
||||
std::size_t mIndex{ 0 };
|
||||
std::size_t mLen{ 0 };
|
||||
Font* mFont{ nullptr };
|
||||
Uint32 mCharacterSize;
|
||||
Uint32 mStyle;
|
||||
Float mOutlineThickness;
|
||||
Font* mCurFont{ nullptr };
|
||||
Font* mStartFont{ nullptr };
|
||||
bool mIsNewLine{ false };
|
||||
};
|
||||
|
||||
class EE_API Text {
|
||||
public:
|
||||
static bool TextShaperEnabled;
|
||||
static bool TextShaperOptimizations;
|
||||
static Uint32 GlobalInvalidationId;
|
||||
|
||||
enum Style {
|
||||
@@ -98,14 +167,16 @@ class EE_API Text {
|
||||
const Uint32& fontSize, const String& string,
|
||||
const Uint32& style, const Uint32& tabWidth = 4,
|
||||
const Float& outlineThickness = 0.f,
|
||||
std::optional<Float> tabOffset = {} );
|
||||
std::optional<Float> tabOffset = {},
|
||||
Uint32 textDrawHints = 0 );
|
||||
|
||||
static Vector2f findCharacterPos( std::size_t index, Font* font, const Uint32& fontSize,
|
||||
const String& string, const Uint32& style,
|
||||
const Uint32& tabWidth = 4,
|
||||
const Float& outlineThickness = 0.f,
|
||||
std::optional<Float> tabOffset = {},
|
||||
bool allowNewLine = true );
|
||||
bool allowNewLine = true,
|
||||
Uint32 textDrawHints = 0 );
|
||||
|
||||
static std::size_t findLastCharPosWithinLength( Font* font, const Uint32& fontSize,
|
||||
const String& string, Float maxWidth,
|
||||
|
||||
@@ -79,6 +79,8 @@ template <typename T> class tRECT {
|
||||
|
||||
T getHeight() const;
|
||||
|
||||
void normalize();
|
||||
|
||||
tRECT<T> ceil() const;
|
||||
|
||||
tRECT<T> floor() const;
|
||||
@@ -265,6 +267,11 @@ template <typename T> tSize<T> tRECT<T>::getSize() const {
|
||||
return tSize<T>( eeabs( Right - Left ), eeabs( Bottom - Top ) );
|
||||
}
|
||||
|
||||
template <typename T> void tRECT<T>::normalize() {
|
||||
if ( Left > Right ) std::swap( Left, Right );
|
||||
if ( Top > Bottom ) std::swap( Top, Bottom );
|
||||
}
|
||||
|
||||
template <typename T> T tRECT<T>::getWidth() const {
|
||||
return eeabs( Right - Left );
|
||||
}
|
||||
|
||||
@@ -540,11 +540,13 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client {
|
||||
|
||||
size_t characterWidth( const String& str ) const;
|
||||
|
||||
Float getTextWidth( const String& text, std::optional<Float> tabOffset = {} ) const;
|
||||
Float getTextWidth( const String& text, std::optional<Float> tabOffset = {},
|
||||
Uint32 textHints = 0 ) const;
|
||||
|
||||
size_t characterWidth( const String::View& str ) const;
|
||||
|
||||
Float getTextWidth( const String::View& text, std::optional<Float> tabOffset ) const;
|
||||
Float getTextWidth( const String::View& text, std::optional<Float> tabOffset,
|
||||
Uint32 textHints = 0 ) const;
|
||||
|
||||
Float getLineHeight() const;
|
||||
|
||||
@@ -1131,13 +1133,13 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client {
|
||||
|
||||
template <typename StringType>
|
||||
Float getTextWidth( const StringType& text, bool fromMonospaceLine,
|
||||
std::optional<Float> tabOffset ) const;
|
||||
std::optional<Float> tabOffset, Uint32 textHints = 0 ) const;
|
||||
|
||||
Float getTextWidth( const String& text, bool fromMonospaceLine,
|
||||
std::optional<Float> tabOffset ) const;
|
||||
Float getTextWidth( const String& text, bool fromMonospaceLine, std::optional<Float> tabOffset,
|
||||
Uint32 textHints = 0 ) const;
|
||||
|
||||
Float getTextWidth( const String::View& text, bool fromMonospaceLine,
|
||||
std::optional<Float> tabOffset ) const;
|
||||
std::optional<Float> tabOffset, Uint32 textHints = 0 ) const;
|
||||
|
||||
void updateIMELocation();
|
||||
|
||||
|
||||
@@ -1290,11 +1290,17 @@ bool FontTrueType::setCurrentSize( unsigned int characterSize ) const {
|
||||
}
|
||||
} else if ( characterSize != currentSize &&
|
||||
( result = FT_Set_Pixel_Sizes( face, 0, it->second ) ) == FT_Err_Ok ) {
|
||||
#ifdef EE_TEXT_SHAPER_ENABLED
|
||||
hb_ft_font_changed( (hb_font_t*)mHBFont );
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef EE_TEXT_SHAPER_ENABLED
|
||||
hb_ft_font_changed( (hb_font_t*)mHBFont );
|
||||
#endif
|
||||
return result == FT_Err_Ok;
|
||||
} else {
|
||||
return true;
|
||||
|
||||
@@ -2080,7 +2080,8 @@ Float UICodeEditor::getLineWidth( const Int64& docLine ) {
|
||||
auto len =
|
||||
i + 1 < vline.visualLines.size() ? vline.visualLines[i + 1].column() : line.size();
|
||||
auto vlineStr = line.view().substr( pos, len - pos );
|
||||
auto curWidth = getTextWidth( vlineStr, isMonospaceLine );
|
||||
auto curWidth =
|
||||
getTextWidth( vlineStr, isMonospaceLine, {}, mDoc->line( docLine ).getTextHints() );
|
||||
width = eemax( width, curWidth );
|
||||
}
|
||||
|
||||
@@ -2096,13 +2097,15 @@ Float UICodeEditor::getLineWidth( const Int64& docLine ) {
|
||||
auto found = mLinesWidthCache.find( docLine );
|
||||
if ( found != mLinesWidthCache.end() && line.getHash() == found->second.first )
|
||||
return found->second.second;
|
||||
Float width = getTextWidth( line.getText(), {}, mTabStops ? 0 : std::optional<Float>{} );
|
||||
Float width = getTextWidth( line.getText(), {}, mTabStops ? 0 : std::optional<Float>{},
|
||||
line.getTextHints() );
|
||||
mLinesWidthCache[docLine] = { line.getHash(), width };
|
||||
return width;
|
||||
}
|
||||
|
||||
return getTextWidth( mDoc->line( docLine ).getText(), isMonospaceLine,
|
||||
mTabStops ? 0 : std::optional<Float>{} );
|
||||
mTabStops ? 0 : std::optional<Float>{},
|
||||
mDoc->line( docLine ).getTextHints() );
|
||||
}
|
||||
|
||||
void UICodeEditor::updateScrollBar() {
|
||||
@@ -2530,12 +2533,12 @@ Vector2d UICodeEditor::getTextPositionOffset( const TextPosition& position,
|
||||
const auto& line = mDoc->line( position.line() ).getText();
|
||||
auto partialLine =
|
||||
line.view().substr( info.range.start().column(), info.range.end().column() );
|
||||
Float x =
|
||||
Text::findCharacterPos( position.column() - info.range.start().column(), mFont,
|
||||
getCharacterSize(), partialLine, mFontStyleConfig.Style,
|
||||
mTabWidth, mFontStyleConfig.OutlineThickness,
|
||||
mTabStops ? 0 : std::optional<Float>(), false )
|
||||
.x;
|
||||
Float x = Text::findCharacterPos(
|
||||
position.column() - info.range.start().column(), mFont,
|
||||
getCharacterSize(), partialLine, mFontStyleConfig.Style, mTabWidth,
|
||||
mFontStyleConfig.OutlineThickness, mTabStops ? 0 : std::optional<Float>(),
|
||||
false, mDoc->line( position.line() ).getTextHints() )
|
||||
.x;
|
||||
if ( visualizeNewLine && allowVisualLineEnd &&
|
||||
position.column() == (Int64)mDoc->line( position.line() ).getText().size() - 1 )
|
||||
x += getGlyphWidth();
|
||||
@@ -2567,7 +2570,8 @@ Vector2d UICodeEditor::getTextPositionOffset( const TextPosition& position,
|
||||
Text::findCharacterPos(
|
||||
isLastChar ? position.column() - 1 : position.column(), mFont, getCharacterSize(),
|
||||
mDoc->line( position.line() ).getText(), mFontStyleConfig.Style, mTabWidth,
|
||||
mFontStyleConfig.OutlineThickness, mTabStops ? 0 : std::optional<Float>(), false )
|
||||
mFontStyleConfig.OutlineThickness, mTabStops ? 0 : std::optional<Float>(), false,
|
||||
mDoc->line( position.line() ).getTextHints() )
|
||||
.x;
|
||||
if ( visualizeNewLine && isLastChar )
|
||||
x += getGlyphWidth();
|
||||
@@ -2600,34 +2604,36 @@ size_t UICodeEditor::characterWidth( const String& str ) const {
|
||||
return characterWidth<String>( str );
|
||||
}
|
||||
|
||||
Float UICodeEditor::getTextWidth( const String& text, std::optional<Float> tabOffset ) const {
|
||||
return getTextWidth<String>( text, false, tabOffset );
|
||||
Float UICodeEditor::getTextWidth( const String& text, std::optional<Float> tabOffset,
|
||||
Uint32 textHints ) const {
|
||||
return getTextWidth<String>( text, false, tabOffset, textHints );
|
||||
}
|
||||
|
||||
size_t UICodeEditor::characterWidth( const String::View& str ) const {
|
||||
return characterWidth<String::View>( str );
|
||||
}
|
||||
|
||||
Float UICodeEditor::getTextWidth( const String::View& text, std::optional<Float> tabOffset ) const {
|
||||
return getTextWidth<String::View>( text, false, tabOffset );
|
||||
Float UICodeEditor::getTextWidth( const String::View& text, std::optional<Float> tabOffset,
|
||||
Uint32 textHints ) const {
|
||||
return getTextWidth<String::View>( text, false, tabOffset, textHints );
|
||||
}
|
||||
|
||||
Float UICodeEditor::getTextWidth( const String& text, bool fromMonospaceLine,
|
||||
std::optional<Float> tabOffset ) const {
|
||||
return getTextWidth<String>( text, fromMonospaceLine, tabOffset );
|
||||
std::optional<Float> tabOffset, Uint32 textHints ) const {
|
||||
return getTextWidth<String>( text, fromMonospaceLine, tabOffset, textHints );
|
||||
}
|
||||
|
||||
Float UICodeEditor::getTextWidth( const String::View& text, bool fromMonospaceLine,
|
||||
std::optional<Float> tabOffset ) const {
|
||||
return getTextWidth<String::View>( text, fromMonospaceLine, tabOffset );
|
||||
std::optional<Float> tabOffset, Uint32 textHints ) const {
|
||||
return getTextWidth<String::View>( text, fromMonospaceLine, tabOffset, textHints );
|
||||
}
|
||||
|
||||
template <typename StringType>
|
||||
Float UICodeEditor::getTextWidth( const StringType& line, bool fromMonospaceLine,
|
||||
std::optional<Float> tabOffset ) const {
|
||||
std::optional<Float> tabOffset, Uint32 textHints ) const {
|
||||
if ( !fromMonospaceLine && isNotMonospace() ) {
|
||||
return Text::getTextWidth( mFont, getCharacterSize(), line, mFontStyleConfig.Style,
|
||||
mTabWidth, 0.f, 0, tabOffset );
|
||||
mTabWidth, 0.f, textHints, tabOffset );
|
||||
}
|
||||
|
||||
Float glyphWidth = getGlyphWidth();
|
||||
@@ -3204,7 +3210,8 @@ Int64 UICodeEditor::getColFromXOffset( VisibleIndex visibleIndex, const Float& x
|
||||
Text::findCharacterFromPos( Vector2i( eemax( -xOffset + x, 0.f ), 0 ), true,
|
||||
mFont, getCharacterSize(), line,
|
||||
mFontStyleConfig.Style, mTabWidth, 0.f,
|
||||
mTabStops ? 0 : std::optional<Float>() );
|
||||
mTabStops ? 0 : std::optional<Float>(),
|
||||
mDoc->line( pos.line() ).getTextHints() );
|
||||
}
|
||||
|
||||
Int64 len = line.length();
|
||||
@@ -3230,7 +3237,8 @@ Int64 UICodeEditor::getColFromXOffset( VisibleIndex visibleIndex, const Float& x
|
||||
if ( !isMonospaceLine( pos.line() ) ) {
|
||||
return Text::findCharacterFromPos(
|
||||
Vector2i( x, 0 ), true, mFont, getCharacterSize(), mDoc->line( pos.line() ).getText(),
|
||||
mFontStyleConfig.Style, mTabWidth, 0.f, mTabStops ? 0 : std::optional<Float>() );
|
||||
mFontStyleConfig.Style, mTabWidth, 0.f, mTabStops ? 0 : std::optional<Float>(),
|
||||
mDoc->line( pos.line() ).getTextHints() );
|
||||
}
|
||||
|
||||
const String& line = mDoc->line( pos.line() ).getText();
|
||||
@@ -4193,6 +4201,7 @@ std::vector<Rectf> UICodeEditor::getTextRangeRectangles(
|
||||
}
|
||||
}
|
||||
selRect.Right = startScroll.x + endOffset.x;
|
||||
selRect.normalize();
|
||||
rects.push_back( selRect );
|
||||
}
|
||||
} else {
|
||||
@@ -4232,6 +4241,7 @@ std::vector<Rectf> UICodeEditor::getTextRangeRectangles(
|
||||
lh, false, visualizeNewLines )
|
||||
.x;
|
||||
}
|
||||
selRect.normalize();
|
||||
rects.push_back( selRect );
|
||||
}
|
||||
}
|
||||
@@ -5365,7 +5375,8 @@ void UICodeEditor::setTabIndentAlignment( CharacterAlignment alignment ) {
|
||||
}
|
||||
|
||||
bool UICodeEditor::isMonospaceLine( Int64 lineIndex ) const {
|
||||
return mFont && ( mFont->isMonospace() ||
|
||||
return mFont && ( ( mFont->isMonospace() &&
|
||||
( !Text::TextShaperEnabled || mDoc->line( lineIndex ).isAscii() ) ) ||
|
||||
( mFont->getType() == FontType::TTF &&
|
||||
static_cast<FontTrueType*>( mFont )->isIdentifiedAsMonospace() &&
|
||||
mDoc->line( lineIndex ).isAscii() ) );
|
||||
|
||||
@@ -152,6 +152,42 @@ void mainLoop() {
|
||||
}
|
||||
|
||||
EE_MAIN_FUNC int main( int, char*[] ) {
|
||||
{
|
||||
Text::TextShaperEnabled = false;
|
||||
UIApplication app( WindowSettings( 1024, 650, "eepp - TextEdit", WindowStyle::Default,
|
||||
WindowBackend::Default, 32, {}, 1, false, true ),
|
||||
UIApplication::Settings( {}, 1.5f ) );
|
||||
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
|
||||
auto ll = UILinearLayout::NewVertical();
|
||||
ll->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent );
|
||||
auto editor = UICodeEditor::New();
|
||||
editor->setShowLineNumber( false );
|
||||
editor->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent );
|
||||
editor->setParent( ll );
|
||||
// editor->setFontSize( PixelDensity::dpToPx( 32 ) );
|
||||
/* FontManager::instance()->addFallbackFont(
|
||||
FontTrueType::New( "arabic", "unit_tests/assets/fonts/NotoNaskhArabic-Regular.ttf" ) ); */
|
||||
FontManager::instance()->addFallbackFont( FontTrueType::New(
|
||||
"NotoSerifBengali-Regular", "unit_tests/assets/fonts/NotoSansBengali-Regular.ttf" ) );
|
||||
// editor->setLineWrapMode( LineWrapMode::Word );
|
||||
// editor->setFont( FontManager::instance()->getByName( "monospace" ) );
|
||||
// editor->loadFromFile( "unit_tests/assets/textfiles/test-arabic-simple.uext" );
|
||||
editor->loadFromFile( "unit_tests/assets/textfiles/test-arabic.uext" );
|
||||
// editor->loadFromFile( "unit_tests/assets/textfiles/test-bengali.uext" );
|
||||
// editor->loadFromFile( "unit_tests/assets/textfiles/test-flags.uext" );
|
||||
// editor->loadFromFile( "unit_tests/assets/textformat/english.utf8.lf.nobom.txt" );
|
||||
// editor->getDocument().textInput( "اسمي..." );
|
||||
// editor->getDocument().textInput( " হ্যাঁ " );
|
||||
editor->setFont( app.getUI()->getUIThemeManager()->getDefaultFont() );
|
||||
editor->on( Event::KeyUp, [&]( const Event* event ) {
|
||||
if ( event->asKeyEvent()->getKeyCode() == KEY_F1 ){
|
||||
Text::TextShaperEnabled = !Text::TextShaperEnabled;
|
||||
app.getUI()->getRoot()->invalidateDraw();
|
||||
}
|
||||
} );
|
||||
return app.run();
|
||||
}
|
||||
|
||||
win = Engine::instance()->createWindow( WindowSettings( 1366, 768, "eepp - UI Perf Test" ),
|
||||
ContextSettings( false ) );
|
||||
|
||||
@@ -199,50 +235,50 @@ EE_MAIN_FUNC int main( int, char*[] ) {
|
||||
->setDefaultFont( font )
|
||||
->add( theme );
|
||||
|
||||
/*
|
||||
auto* vlay = UILinearLayout::NewVertical();
|
||||
vlay->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent );
|
||||
/*
|
||||
auto* vlay = UILinearLayout::NewVertical();
|
||||
vlay->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent );
|
||||
|
||||
Clock clock;
|
||||
auto model = FileSystemModel::New( "." ); // std::make_shared<TestModel>();
|
||||
// UITreeView* view = UITreeView::New();
|
||||
UITableView* view = UITableView::New();
|
||||
// view->setExpanderIconSize( PixelDensity::dpToPx( 20 ) );
|
||||
view->setId( "treeview" );
|
||||
view->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent );
|
||||
view->setParent( vlay );
|
||||
view->setModel( SortingProxyModel::New( model ) );
|
||||
Log::notice( "Total time: %.2fms", clock.getElapsedTime().asMilliseconds() );
|
||||
*/
|
||||
Clock clock;
|
||||
auto model = FileSystemModel::New( "." ); // std::make_shared<TestModel>();
|
||||
// UITreeView* view = UITreeView::New();
|
||||
UITableView* view = UITableView::New();
|
||||
// view->setExpanderIconSize( PixelDensity::dpToPx( 20 ) );
|
||||
view->setId( "treeview" );
|
||||
view->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent );
|
||||
view->setParent( vlay );
|
||||
view->setModel( SortingProxyModel::New( model ) );
|
||||
Log::notice( "Total time: %.2fms", clock.getElapsedTime().asMilliseconds() );
|
||||
*/
|
||||
|
||||
/* ListBox test */
|
||||
/*
|
||||
std::vector<String> strings;
|
||||
for ( size_t i = 0; i < 10000; i++ )
|
||||
strings.emplace_back( String::format(
|
||||
"This is a very long string number %ld. Cover the full width of the listbox.",
|
||||
i ) );
|
||||
auto* lbox = UIListBox::New();
|
||||
std::cout << "Time New: " << clock.getElapsedTime().asMilliseconds() << " ms" << std::endl;
|
||||
lbox->setParent( vlay );
|
||||
std::cout << "Time setParent: " << clock.getElapsedTime().asMilliseconds() << " ms"
|
||||
<< std::endl;
|
||||
lbox->setLayoutMargin( Rectf( 4, 4, 4, 4 ) );
|
||||
std::cout << "Time setLayoutMargin: " << clock.getElapsedTime().asMilliseconds() << " ms"
|
||||
<< std::endl;
|
||||
lbox->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent );
|
||||
std::cout << "Time setLayoutSizePolicy: " << clock.getElapsedTime().asMilliseconds()
|
||||
<< " ms" << std::endl;
|
||||
for ( size_t i = 0; i < 10; i++ )
|
||||
lbox->addListBoxItem( String::format(
|
||||
"This is a very long string number %ld. Cover the full width of the listbox.",
|
||||
i ) );
|
||||
std::cout << "Time addListBoxItem: " << clock.getElapsedTime().asMilliseconds() << " ms"
|
||||
<< std::endl;
|
||||
lbox->addListBoxItems( strings );
|
||||
std::cout << "Time addListBoxItems: " << clock.getElapsedTime().asMilliseconds() << " ms"
|
||||
<< std::endl;
|
||||
*/
|
||||
/*
|
||||
std::vector<String> strings;
|
||||
for ( size_t i = 0; i < 10000; i++ )
|
||||
strings.emplace_back( String::format(
|
||||
"This is a very long string number %ld. Cover the full width of the
|
||||
listbox.", i ) ); auto* lbox = UIListBox::New(); std::cout << "Time New: " <<
|
||||
clock.getElapsedTime().asMilliseconds() << " ms" << std::endl; lbox->setParent( vlay );
|
||||
std::cout << "Time setParent: " << clock.getElapsedTime().asMilliseconds() << " ms"
|
||||
<< std::endl;
|
||||
lbox->setLayoutMargin( Rectf( 4, 4, 4, 4 ) );
|
||||
std::cout << "Time setLayoutMargin: " << clock.getElapsedTime().asMilliseconds() <<
|
||||
" ms"
|
||||
<< std::endl;
|
||||
lbox->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent );
|
||||
std::cout << "Time setLayoutSizePolicy: " << clock.getElapsedTime().asMilliseconds()
|
||||
<< " ms" << std::endl;
|
||||
for ( size_t i = 0; i < 10; i++ )
|
||||
lbox->addListBoxItem( String::format(
|
||||
"This is a very long string number %ld. Cover the full width of the
|
||||
listbox.", i ) ); std::cout << "Time addListBoxItem: " <<
|
||||
clock.getElapsedTime().asMilliseconds() << " ms"
|
||||
<< std::endl;
|
||||
lbox->addListBoxItems( strings );
|
||||
std::cout << "Time addListBoxItems: " << clock.getElapsedTime().asMilliseconds() <<
|
||||
" ms"
|
||||
<< std::endl;
|
||||
*/
|
||||
|
||||
Clock total;
|
||||
/* Create Widget test */
|
||||
@@ -277,7 +313,8 @@ EE_MAIN_FUNC int main( int, char*[] ) {
|
||||
but->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent );
|
||||
but->setParent( parent )->clipEnable();
|
||||
}
|
||||
std::cout << "Time 10k UIPushButton total: " << total.getElapsedTime().toString() << std::endl;
|
||||
std::cout << "Time 10k UIPushButton total: " << total.getElapsedTime().toString()
|
||||
<< std::endl;
|
||||
|
||||
// uiSceneNode->getRoot()->closeAllChildren();
|
||||
total.restart();
|
||||
@@ -285,115 +322,117 @@ EE_MAIN_FUNC int main( int, char*[] ) {
|
||||
std::cout << "SceneManager::instance()->update(): " << total.getElapsedTime().toString()
|
||||
<< std::endl;
|
||||
|
||||
/*
|
||||
auto* main = UIRelativeLayout::New();
|
||||
main->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent );
|
||||
auto* sv = UIScrollView::New();
|
||||
sv->setParent( main );
|
||||
sv->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent );
|
||||
sv->setPixelsSize( win->getSize().asFloat() );
|
||||
auto* vlay = UILinearLayout::NewVertical();
|
||||
vlay->setParent( sv );
|
||||
vlay->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent );
|
||||
/*
|
||||
auto* main = UIRelativeLayout::New();
|
||||
main->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent );
|
||||
auto* sv = UIScrollView::New();
|
||||
sv->setParent( main );
|
||||
sv->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent );
|
||||
sv->setPixelsSize( win->getSize().asFloat() );
|
||||
auto* vlay = UILinearLayout::NewVertical();
|
||||
vlay->setParent( sv );
|
||||
vlay->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent );
|
||||
|
||||
total.restart();
|
||||
for ( size_t i = 0; i < 100000; i++ ) {
|
||||
auto* widget = UIWidget::New();
|
||||
widget->setParent( vlay );
|
||||
widget->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::Fixed );
|
||||
widget->setSize( Sizef( 0, 4 ) );
|
||||
Colorf col;
|
||||
col.hsv.h = Math::randf( 0, 360 );
|
||||
col.hsv.s = 1;
|
||||
col.hsv.v = 1;
|
||||
col.hsv.a = 1;
|
||||
widget->setBackgroundColor( Color::fromHsv( col ) );
|
||||
}
|
||||
std::cout << "Time UIWidget total: " << total.getElapsedTime().asMilliseconds() << " ms"
|
||||
<< std::endl;
|
||||
*/
|
||||
/*
|
||||
UIWindow* wind = UIWindow::New();
|
||||
wind->setSize( 500, 500 );
|
||||
wind->setWindowFlags( UI_WIN_DEFAULT_FLAGS | UI_WIN_RESIZEABLE | UI_WIN_MAXIMIZE_BUTTON );
|
||||
total.restart();
|
||||
for ( size_t i = 0; i < 100000; i++ ) {
|
||||
auto* widget = UIWidget::New();
|
||||
widget->setParent( vlay );
|
||||
widget->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::Fixed );
|
||||
widget->setSize( Sizef( 0, 4 ) );
|
||||
Colorf col;
|
||||
col.hsv.h = Math::randf( 0, 360 );
|
||||
col.hsv.s = 1;
|
||||
col.hsv.v = 1;
|
||||
col.hsv.a = 1;
|
||||
widget->setBackgroundColor( Color::fromHsv( col ) );
|
||||
}
|
||||
std::cout << "Time UIWidget total: " << total.getElapsedTime().asMilliseconds() << "
|
||||
ms"
|
||||
<< std::endl;
|
||||
*/
|
||||
/*
|
||||
UIWindow* wind = UIWindow::New();
|
||||
wind->setSize( 500, 500 );
|
||||
wind->setWindowFlags( UI_WIN_DEFAULT_FLAGS | UI_WIN_RESIZEABLE |
|
||||
UI_WIN_MAXIMIZE_BUTTON );
|
||||
|
||||
UILinearLayout* layWin = UILinearLayout::NewVertical();
|
||||
layWin->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent );
|
||||
layWin->setParent( wind );
|
||||
UILinearLayout* layWin = UILinearLayout::NewVertical();
|
||||
layWin->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent );
|
||||
layWin->setParent( wind );
|
||||
|
||||
UILinearLayout* layPar = UILinearLayout::NewHorizontal();
|
||||
layPar->setParent( layWin );
|
||||
layPar->setLayoutMargin( Rectf( 10, 10, 10, 10 ) );
|
||||
layPar->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent );
|
||||
layPar->setLayoutGravity( UI_VALIGN_CENTER | UI_HALIGN_CENTER );
|
||||
layPar->setBackgroundColor( 0x999999FF );
|
||||
UILinearLayout* layPar = UILinearLayout::NewHorizontal();
|
||||
layPar->setParent( layWin );
|
||||
layPar->setLayoutMargin( Rectf( 10, 10, 10, 10 ) );
|
||||
layPar->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent );
|
||||
layPar->setLayoutGravity( UI_VALIGN_CENTER | UI_HALIGN_CENTER );
|
||||
layPar->setBackgroundColor( 0x999999FF );
|
||||
|
||||
UILinearLayout* lay = UILinearLayout::NewVertical();
|
||||
lay->setLayoutGravity( UI_HALIGN_CENTER | UI_VALIGN_CENTER );
|
||||
lay->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent );
|
||||
lay->setBackgroundColor( 0x333333FF );
|
||||
lay->setLayoutWeight( 0.7f );
|
||||
UILinearLayout* lay = UILinearLayout::NewVertical();
|
||||
lay->setLayoutGravity( UI_HALIGN_CENTER | UI_VALIGN_CENTER );
|
||||
lay->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent );
|
||||
lay->setBackgroundColor( 0x333333FF );
|
||||
lay->setLayoutWeight( 0.7f );
|
||||
|
||||
UITextView::New()
|
||||
->setText( "Text on test 1" )
|
||||
->setLayoutMargin( Rectf( 10, 10, 10, 10 ) )
|
||||
->setLayoutSizePolicy( SizePolicy::WrapContent, SizePolicy::WrapContent )
|
||||
->setParent( lay );
|
||||
UITextView::New()
|
||||
->setText( "Text on test 2" )
|
||||
->setLayoutMargin( Rectf( 10, 10, 10, 10 ) )
|
||||
->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent )
|
||||
->setParent( lay );
|
||||
UICheckBox::New()
|
||||
->setText( "Checkbox" )
|
||||
->setLayoutMargin( Rectf( 10, 10, 10, 10 ) )
|
||||
->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent )
|
||||
->setParent( lay );
|
||||
UITextView::New()
|
||||
->setText( "Text on test 3" )
|
||||
->setLayoutMargin( Rectf( 10, 10, 10, 10 ) )
|
||||
->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent )
|
||||
->setParent( lay );
|
||||
UITextView::New()
|
||||
->setText( "Text on test 4" )
|
||||
->setLayoutMargin( Rectf( 10, 10, 10, 10 ) )
|
||||
->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent )
|
||||
->setParent( lay );
|
||||
UITextInput::New()
|
||||
->setLayoutMargin( Rectf( 10, 10, 10, 10 ) )
|
||||
->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent )
|
||||
->setParent( lay );
|
||||
UITextView::New()
|
||||
->setText( "Text on test 1" )
|
||||
->setLayoutMargin( Rectf( 10, 10, 10, 10 ) )
|
||||
->setLayoutSizePolicy( SizePolicy::WrapContent, SizePolicy::WrapContent )
|
||||
->setParent( lay );
|
||||
UITextView::New()
|
||||
->setText( "Text on test 2" )
|
||||
->setLayoutMargin( Rectf( 10, 10, 10, 10 ) )
|
||||
->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent )
|
||||
->setParent( lay );
|
||||
UICheckBox::New()
|
||||
->setText( "Checkbox" )
|
||||
->setLayoutMargin( Rectf( 10, 10, 10, 10 ) )
|
||||
->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent )
|
||||
->setParent( lay );
|
||||
UITextView::New()
|
||||
->setText( "Text on test 3" )
|
||||
->setLayoutMargin( Rectf( 10, 10, 10, 10 ) )
|
||||
->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent )
|
||||
->setParent( lay );
|
||||
UITextView::New()
|
||||
->setText( "Text on test 4" )
|
||||
->setLayoutMargin( Rectf( 10, 10, 10, 10 ) )
|
||||
->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent )
|
||||
->setParent( lay );
|
||||
UITextInput::New()
|
||||
->setLayoutMargin( Rectf( 10, 10, 10, 10 ) )
|
||||
->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent )
|
||||
->setParent( lay );
|
||||
|
||||
UILinearLayout* lay2 = UILinearLayout::NewVertical();
|
||||
lay2->setId( "hardlay" );
|
||||
lay2->setLayoutGravity( UI_HALIGN_CENTER | UI_VALIGN_CENTER );
|
||||
lay2->setLayoutSizePolicy( SizePolicy::Fixed, SizePolicy::WrapContent );
|
||||
lay2->setBackgroundColor( Color::Black );
|
||||
lay2->setLayoutWeight( 0.3f );
|
||||
UILinearLayout* lay2 = UILinearLayout::NewVertical();
|
||||
lay2->setId( "hardlay" );
|
||||
lay2->setLayoutGravity( UI_HALIGN_CENTER | UI_VALIGN_CENTER );
|
||||
lay2->setLayoutSizePolicy( SizePolicy::Fixed, SizePolicy::WrapContent );
|
||||
lay2->setBackgroundColor( Color::Black );
|
||||
lay2->setLayoutWeight( 0.3f );
|
||||
|
||||
UIPushButton::New()
|
||||
->setText( "PushButton" )
|
||||
->setLayoutMargin( Rectf( 10, 10, 10, 10 ) )
|
||||
->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent )
|
||||
->setLayoutGravity( UI_VALIGN_CENTER )
|
||||
->setParent( lay2 );
|
||||
UIListBox* lbox = UIListBox::New();
|
||||
lbox->setLayoutMargin( Rectf( 10, 10, 10, 10 ) )
|
||||
->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::Fixed )
|
||||
->setSize( 0, 105 )
|
||||
->setParent( lay2 );
|
||||
lbox->addListBoxItems( { "This", "is", "a", "ListBox" } );
|
||||
lay2->setParent( layPar );
|
||||
lay->setParent( layPar );
|
||||
UIPushButton::New()
|
||||
->setText( "PushButton" )
|
||||
->setLayoutMargin( Rectf( 10, 10, 10, 10 ) )
|
||||
->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent )
|
||||
->setLayoutGravity( UI_VALIGN_CENTER )
|
||||
->setParent( lay2 );
|
||||
UIListBox* lbox = UIListBox::New();
|
||||
lbox->setLayoutMargin( Rectf( 10, 10, 10, 10 ) )
|
||||
->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::Fixed )
|
||||
->setSize( 0, 105 )
|
||||
->setParent( lay2 );
|
||||
lbox->addListBoxItems( { "This", "is", "a", "ListBox" } );
|
||||
lay2->setParent( layPar );
|
||||
lay->setParent( layPar );
|
||||
|
||||
UIDropDownList* drop = UIDropDownList::New();
|
||||
drop->setLayoutMargin( Rectf( 10, 10, 10, 10 ) )
|
||||
->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent )
|
||||
->setParent( layWin );
|
||||
drop->getListBox()->addListBoxItems( { "Car", "Bus", "Plane", "Submarine" } );
|
||||
drop->getListBox()->setSelected( 0 );
|
||||
wind->show();
|
||||
*/
|
||||
UIDropDownList* drop = UIDropDownList::New();
|
||||
drop->setLayoutMargin( Rectf( 10, 10, 10, 10 ) )
|
||||
->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent )
|
||||
->setParent( layWin );
|
||||
drop->getListBox()->addListBoxItems( { "Car", "Bus", "Plane", "Submarine" } );
|
||||
drop->getListBox()->setSelected( 0 );
|
||||
wind->show();
|
||||
*/
|
||||
|
||||
win->runMainLoop( &mainLoop );
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "eepp/ui/uithememanager.hpp"
|
||||
#include "utest.hpp"
|
||||
|
||||
#include <eepp/graphics/fontbmfont.hpp>
|
||||
#include <eepp/graphics/fontfamily.hpp>
|
||||
#include <eepp/graphics/fontmanager.hpp>
|
||||
#include <eepp/graphics/fontsprite.hpp>
|
||||
#include <eepp/graphics/fonttruetype.hpp>
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <eepp/ui/uiscenenode.hpp>
|
||||
#include <eepp/ui/uitextedit.hpp>
|
||||
#include <eepp/ui/uitextview.hpp>
|
||||
#include <eepp/ui/uithememanager.hpp>
|
||||
#include <eepp/window/engine.hpp>
|
||||
|
||||
#include <iostream>
|
||||
@@ -52,7 +53,10 @@ static void compareImages( utest_state_s& utest_state, int* utest_result, EE::Wi
|
||||
EXPECT_TRUE( result.areSame() );
|
||||
if ( !result.areSame() ) {
|
||||
auto saveExt( Image::saveTypeToExtension( saveType ) );
|
||||
std::string withTextShaper = Text::TextShaperEnabled ? "_text_shape" : "";
|
||||
std::string withTextShaper =
|
||||
Text::TextShaperEnabled
|
||||
? ( Text::TextShaperOptimizations ? "_text_shape_no_opt" : "_text_shape" )
|
||||
: "";
|
||||
std::cerr << "Test FAILED: " << result.numDifferentPixels << " pixels differ." << std::endl;
|
||||
std::cerr << "Maximum perceptual difference (Delta E): " << result.maxDeltaE << std::endl;
|
||||
if ( !FileSystem::fileExists( "output" ) )
|
||||
@@ -183,6 +187,10 @@ UTEST( FontRendering, fontsTest ) {
|
||||
{
|
||||
BoolScopedOp op( Text::TextShaperEnabled, true );
|
||||
runTest();
|
||||
|
||||
UTEST_PRINT_STEP( "Text Shaper enabled w/o optimizations" );
|
||||
BoolScopedOp op2( Text::TextShaperOptimizations, false );
|
||||
runTest();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,6 +219,10 @@ UTEST( FontRendering, editorTest ) {
|
||||
{
|
||||
BoolScopedOp op( Text::TextShaperEnabled, true );
|
||||
runTest();
|
||||
|
||||
UTEST_PRINT_STEP( "Text Shaper enabled w/o optimizations" );
|
||||
BoolScopedOp op2( Text::TextShaperOptimizations, false );
|
||||
runTest();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,6 +248,10 @@ UTEST( FontRendering, textEditTest ) {
|
||||
{
|
||||
BoolScopedOp op( Text::TextShaperEnabled, true );
|
||||
runTest();
|
||||
|
||||
UTEST_PRINT_STEP( "Text Shaper enabled w/o optimizations" );
|
||||
BoolScopedOp op2( Text::TextShaperOptimizations, false );
|
||||
runTest();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +264,7 @@ UTEST( FontRendering, tabsTest ) {
|
||||
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
|
||||
auto* editor = UICodeEditor::New();
|
||||
editor->setPixelsSize( app.getUI()->getPixelsSize() );
|
||||
editor->loadFromFile( "assets/fontrendering/tabs_test.txt" );
|
||||
editor->loadFromFile( "assets/textfiles/test-tabs.txt" );
|
||||
SceneManager::instance()->update();
|
||||
SceneManager::instance()->draw();
|
||||
compareImages( utest_state, utest_result, app.getWindow(),
|
||||
@@ -262,6 +278,10 @@ UTEST( FontRendering, tabsTest ) {
|
||||
{
|
||||
BoolScopedOp op( Text::TextShaperEnabled, true );
|
||||
runTest();
|
||||
|
||||
UTEST_PRINT_STEP( "Text Shaper enabled w/o optimizations" );
|
||||
BoolScopedOp op2( Text::TextShaperOptimizations, false );
|
||||
runTest();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,7 +295,7 @@ UTEST( FontRendering, tabStopTest ) {
|
||||
auto* editor = UICodeEditor::New();
|
||||
editor->setTabStops( true );
|
||||
editor->setPixelsSize( app.getUI()->getPixelsSize() );
|
||||
editor->loadFromFile( "assets/fontrendering/tabs_test.txt" );
|
||||
editor->loadFromFile( "assets/textfiles/test-tabs.txt" );
|
||||
SceneManager::instance()->update();
|
||||
SceneManager::instance()->draw();
|
||||
compareImages( utest_state, utest_result, app.getWindow(),
|
||||
@@ -289,6 +309,10 @@ UTEST( FontRendering, tabStopTest ) {
|
||||
{
|
||||
BoolScopedOp op( Text::TextShaperEnabled, true );
|
||||
runTest();
|
||||
|
||||
UTEST_PRINT_STEP( "Text Shaper enabled w/o optimizations" );
|
||||
BoolScopedOp op2( Text::TextShaperOptimizations, false );
|
||||
runTest();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -301,7 +325,7 @@ UTEST( FontRendering, tabsTextEditTest ) {
|
||||
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
|
||||
auto* editor = UITextEdit::New();
|
||||
editor->setPixelsSize( app.getUI()->getPixelsSize() );
|
||||
editor->loadFromFile( "assets/fontrendering/tabs_test.txt" );
|
||||
editor->loadFromFile( "assets/textfiles/test-tabs.txt" );
|
||||
SceneManager::instance()->update();
|
||||
SceneManager::instance()->draw();
|
||||
compareImages( utest_state, utest_result, app.getWindow(), "eepp-text-edit-tabs-test" );
|
||||
@@ -314,6 +338,10 @@ UTEST( FontRendering, tabsTextEditTest ) {
|
||||
{
|
||||
BoolScopedOp op( Text::TextShaperEnabled, true );
|
||||
runTest();
|
||||
|
||||
UTEST_PRINT_STEP( "Text Shaper enabled w/o optimizations" );
|
||||
BoolScopedOp op2( Text::TextShaperOptimizations, false );
|
||||
runTest();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,7 +355,7 @@ UTEST( FontRendering, tabStopTextEditTest ) {
|
||||
auto* editor = UITextEdit::New();
|
||||
editor->setTabStops( true );
|
||||
editor->setPixelsSize( app.getUI()->getPixelsSize() );
|
||||
editor->loadFromFile( "assets/fontrendering/tabs_test.txt" );
|
||||
editor->loadFromFile( "assets/textfiles/test-tabs.txt" );
|
||||
SceneManager::instance()->update();
|
||||
SceneManager::instance()->draw();
|
||||
compareImages( utest_state, utest_result, app.getWindow(), "eepp-text-edit-tab-stop-test" );
|
||||
@@ -340,6 +368,10 @@ UTEST( FontRendering, tabStopTextEditTest ) {
|
||||
{
|
||||
BoolScopedOp op( Text::TextShaperEnabled, true );
|
||||
runTest();
|
||||
|
||||
UTEST_PRINT_STEP( "Text Shaper enabled w/o optimizations" );
|
||||
BoolScopedOp op2( Text::TextShaperOptimizations, false );
|
||||
runTest();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,6 +399,10 @@ UTEST( FontRendering, textViewTest ) {
|
||||
{
|
||||
BoolScopedOp op( Text::TextShaperEnabled, true );
|
||||
runTest();
|
||||
|
||||
UTEST_PRINT_STEP( "Text Shaper enabled w/o optimizations" );
|
||||
BoolScopedOp op2( Text::TextShaperOptimizations, false );
|
||||
runTest();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,8 +413,8 @@ UTEST( FontRendering, textEditBengaliTest ) {
|
||||
WindowBackend::Default, 32, {}, 1, false, true ),
|
||||
UIApplication::Settings( Sys::getProcessPath() + ".." + FileSystem::getOSSlash(), 1.5f ) );
|
||||
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
|
||||
FontTrueType* bengaliFont = FontTrueType::New( "NotoSerifBengali-Regular",
|
||||
"assets/fonts/NotoSerifBengali-Regular.ttf" );
|
||||
FontTrueType* bengaliFont =
|
||||
FontTrueType::New( "NotoSansBengali-Regular", "assets/fonts/NotoSansBengali-Regular.ttf" );
|
||||
FontManager::instance()->addFallbackFont( bengaliFont );
|
||||
UTEST_PRINT_STEP( "Text Shaper enabled" );
|
||||
auto* editor = UITextEdit::New();
|
||||
@@ -396,6 +432,8 @@ UTEST( FontRendering, textSizes ) {
|
||||
|
||||
ASSERT_TRUE_MSG( win->isOpen(), "Failed to create Window" );
|
||||
|
||||
Text::TextShaperEnabled = false;
|
||||
|
||||
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
|
||||
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
|
||||
|
||||
@@ -417,6 +455,12 @@ UTEST( FontRendering, textSizes ) {
|
||||
EXPECT_EQ( 96, size.getHeight() );
|
||||
EXPECT_EQ( 445, Text::getTextWidth( txt, config ) );
|
||||
|
||||
Vector2i topPos{ 120, 0 };
|
||||
EXPECT_EQ( 19, Text::findCharacterFromPos( topPos, true, config.Font, config.CharacterSize,
|
||||
txt, 0 ) );
|
||||
EXPECT_EQ( 19, Text::findCharacterFromPos( topPos, false, config.Font, config.CharacterSize,
|
||||
txt, 0 ) );
|
||||
|
||||
Vector2i startPos{ 120, 7 };
|
||||
EXPECT_EQ( 19, Text::findCharacterFromPos( startPos, true, config.Font,
|
||||
config.CharacterSize, txt, 0 ) );
|
||||
@@ -427,7 +471,7 @@ UTEST( FontRendering, textSizes ) {
|
||||
EXPECT_EQ( 242, Text::findCharacterFromPos( middlePos, true, config.Font,
|
||||
config.CharacterSize, txt, 0 ) );
|
||||
EXPECT_EQ( 242, Text::findCharacterFromPos( middlePos, false, config.Font,
|
||||
config.CharacterSize, txt, 0 ) );
|
||||
config.CharacterSize, txt, 0 ) );
|
||||
|
||||
Vector2i endPos{ 120, 103 };
|
||||
EXPECT_EQ( 395, Text::findCharacterFromPos( endPos, true, config.Font, config.CharacterSize,
|
||||
@@ -436,6 +480,8 @@ UTEST( FontRendering, textSizes ) {
|
||||
txt, 0 ) );
|
||||
|
||||
EXPECT_EQ( 18ul, Text::findLastCharPosWithinLength( txt, 120, config ) );
|
||||
EXPECT_EQ( 446ul, Text::findLastCharPosWithinLength( txt, 1000, config ) );
|
||||
|
||||
Vector2f pos = Text::findCharacterPos( 19, config.Font, config.CharacterSize, txt, 0 );
|
||||
EXPECT_EQ( 120, pos.x );
|
||||
EXPECT_EQ( 0, pos.y );
|
||||
@@ -467,5 +513,89 @@ UTEST( FontRendering, textSizes ) {
|
||||
runTest();
|
||||
}
|
||||
|
||||
UTEST_PRINT_STEP( "Text Shaper enabled w/o optimizations" );
|
||||
{
|
||||
BoolScopedOp op( Text::TextShaperEnabled, true );
|
||||
BoolScopedOp op2( Text::TextShaperOptimizations, false );
|
||||
runTest();
|
||||
}
|
||||
|
||||
Engine::destroySingleton();
|
||||
}
|
||||
|
||||
UTEST( FontRendering, textStyles ) {
|
||||
auto win = Engine::instance()->createWindow(
|
||||
WindowSettings( 1024, 230, "eepp - Text Styles", WindowStyle::Default,
|
||||
WindowBackend::Default, 32, {}, 1, false, true ) );
|
||||
|
||||
ASSERT_TRUE_MSG( win->isOpen(), "Failed to create Window" );
|
||||
|
||||
Text::TextShaperEnabled = false;
|
||||
|
||||
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
|
||||
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
|
||||
FontFamily::loadFromRegular( font );
|
||||
|
||||
win->setClearColor( RGB( 255, 255, 255 ) );
|
||||
|
||||
FontStyleConfig config;
|
||||
config.Font = font;
|
||||
config.FontColor = Color::Black;
|
||||
config.CharacterSize = 20;
|
||||
config.OutlineColor = Color::Black;
|
||||
config.ShadowColor = Color::lightgray;
|
||||
|
||||
String txt( "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod\n"
|
||||
"tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,\n"
|
||||
"quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo\n"
|
||||
"consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n"
|
||||
"cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non\n"
|
||||
"proident, sunt in culpa qui officia deserunt mollit anim id est laborum." );
|
||||
|
||||
const auto runTest = [&]( std::string_view styleName, Uint32 textAlign ) {
|
||||
win->clear();
|
||||
Text text;
|
||||
text.setStyleConfig( config );
|
||||
text.setString( txt );
|
||||
text.setAlign( textAlign );
|
||||
text.draw( 32, 32 );
|
||||
compareImages( utest_state, utest_result, win, "eepp-text-style-" + styleName );
|
||||
};
|
||||
|
||||
const auto runTestSuite = [&]( Uint32 style, std::string_view styleName,
|
||||
Uint32 textAlign = TEXT_ALIGN_LEFT ) {
|
||||
config.Style = style;
|
||||
|
||||
UTEST_PRINT_STEP( styleName.data() );
|
||||
UTEST_PRINT_STEP( " Text Shaper disabled" );
|
||||
runTest( styleName, textAlign );
|
||||
|
||||
UTEST_PRINT_STEP( " Text Shaper enabled" );
|
||||
BoolScopedOp op( Text::TextShaperEnabled, true );
|
||||
runTest( styleName, textAlign );
|
||||
|
||||
UTEST_PRINT_STEP( " Text Shaper enabled w/o optimizations" );
|
||||
BoolScopedOp op2( Text::TextShaperOptimizations, false );
|
||||
runTest( styleName, textAlign );
|
||||
};
|
||||
|
||||
runTestSuite( Text::Regular, "regular" );
|
||||
runTestSuite( Text::Bold, "bold" );
|
||||
runTestSuite( Text::Italic, "italic" );
|
||||
runTestSuite( Text::Underlined, "underline" );
|
||||
runTestSuite( Text::StrikeThrough, "strikethrough" );
|
||||
runTestSuite( Text::Shadow, "shadow" );
|
||||
config.FontColor = Color::White;
|
||||
config.OutlineThickness = 1;
|
||||
runTestSuite( Text::Regular, "outline" );
|
||||
config.FontColor = Color::Black;
|
||||
config.OutlineThickness = 0;
|
||||
runTestSuite( Text::Regular, "regular-center", TEXT_ALIGN_CENTER );
|
||||
runTestSuite( Text::Regular, "regular-right", TEXT_ALIGN_RIGHT );
|
||||
runTestSuite( Text::Underlined, "underline-center", TEXT_ALIGN_CENTER );
|
||||
runTestSuite( Text::Underlined, "underline-right", TEXT_ALIGN_RIGHT );
|
||||
runTestSuite( Text::StrikeThrough, "strikethrough-center", TEXT_ALIGN_CENTER );
|
||||
runTestSuite( Text::StrikeThrough, "strikethrough-right", TEXT_ALIGN_RIGHT );
|
||||
|
||||
Engine::destroySingleton();
|
||||
}
|
||||
|
||||