diff --git a/arm9/source/font.cpp b/arm9/source/font.cpp index ef5631e..a4aaeba 100644 --- a/arm9/source/font.cpp +++ b/arm9/source/font.cpp @@ -7,14 +7,20 @@ #include #include #include -#include + u8 Font::textBuf[2][256 * 192]; bool Font::mainScreen = false; Font *font = nullptr; +// Specifically the Arabic letters that have supported presentation forms +bool Font::isArabic(char16_t c) { + return c >= 0x0622 && c <= 0x064A; +} + bool Font::isStrongRTL(char16_t c) { - return (c >= 0x0590 && c <= 0x05FF) || c == 0x200F; + // Hebrew, Arabic, or RLM + return (c >= 0x0590 && c <= 0x05FF) || (c >= 0x0600 && c <= 0x06FF) || c == 0x200F; } bool Font::isWeak(char16_t c) { @@ -25,6 +31,25 @@ bool Font::isNumber(char16_t c) { return c >= '0' && c <= '9'; } +char16_t Font::arabicForm(char16_t current, char16_t prev, char16_t next) { + if(isArabic(current)) { + // If previous should be connected to + if((prev >= 0x626 && prev <= 0x62E && prev != 0x627 && prev != 0x629) || (prev >= 0x633 && prev <= 0x64A && prev != 0x647)) { + if(isArabic(next)) // If next is arabic, medial + return arabicPresentationForms[current - 0x622][1]; + else // If not, final + return arabicPresentationForms[current - 0x622][2]; + } else { + if(isArabic(next)) // If next is arabic, initial + return arabicPresentationForms[current - 0x622][0]; + else // If not, isolated + return current; + } + } + + return current; +} + bool Font::load(const char *path) { FILE *file = fopen(path, "rb"); @@ -395,7 +420,7 @@ ITCM_CODE void Font::print(int xPos, int yPos, bool top, std::u16string_view tex index = getCharIndex('<'); break; default: - index = getCharIndex(*it); + index = getCharIndex(arabicForm(*it, *(it - 1), *(it + 1))); break; } } else { @@ -403,7 +428,7 @@ ITCM_CODE void Font::print(int xPos, int yPos, bool top, std::u16string_view tex } // Don't draw off screen chars - if(x >= 0 && y >= 0 && y + tileHeight <= 192) { + if(x >= 0 && x + tileWidth <= 256 && y >= 0 && y + tileHeight <= 192) { u8 *dst = textBuf[top] + x; for(int i = 0; i < tileHeight; i++) { u8 px = fontTiles[(index * tileHeight) + i]; diff --git a/arm9/source/font.h b/arm9/source/font.h index d2224f3..599de89 100644 --- a/arm9/source/font.h +++ b/arm9/source/font.h @@ -34,10 +34,58 @@ enum class Palette : u8 { }; class Font { + constexpr static char16_t arabicPresentationForms[][3] = { + // Initial, Medial, Final + {u'آ', u'ﺂ', u'ﺂ'}, // Alef with madda above + {u'أ', u'ﺄ', u'ﺄ'}, // Alef with hamza above + {u'ؤ', u'ﺆ', u'ﺆ'}, // Waw with hamza above + {u'إ', u'ﺈ', u'ﺈ'}, // Alef with hamza below + {u'ﺋ', u'ﺌ', u'ﺊ'}, // Yeh with hamza above + {u'ا', u'ﺎ', u'ﺎ'}, // Alef + {u'ﺑ', u'ﺒ', u'ﺐ'}, // Beh + {u'ة', u'ﺔ', u'ﺔ'}, // Teh marbuta + {u'ﺗ', u'ﺘ', u'ﺖ'}, // Teh + {u'ﺛ', u'ﺜ', u'ﺚ'}, // Theh + {u'ﺟ', u'ﺠ', u'ﺞ'}, // Jeem + {u'ﺣ', u'ﺤ', u'ﺢ'}, // Hah + {u'ﺧ', u'ﺨ', u'ﺦ'}, // Khah + {u'د', u'ﺪ', u'ﺪ'}, // Dal + {u'ذ', u'ﺬ', u'ﺬ'}, // Thal + {u'ر', u'ﺮ', u'ﺮ'}, // Reh + {u'ز', u'ﺰ', u'ﺰ'}, // Zain + {u'ﺳ', u'ﺴ', u'ﺲ'}, // Seen + {u'ﺷ', u'ﺸ', u'ﺶ'}, // Sheen + {u'ﺻ', u'ﺼ', u'ﺺ'}, // Sad + {u'ﺿ', u'ﻀ', u'ﺾ'}, // Dad + {u'ﻃ', u'ﻄ', u'ﻂ'}, // Tah + {u'ﻇ', u'ﻈ', u'ﻆ'}, // Zah + {u'ﻋ', u'ﻌ', u'ﻊ'}, // Ain + {u'ﻏ', u'ﻐ', u'ﻎ'}, // Ghain + {u'ػ', u'ػ', u'ػ'}, // Keheh with two dots above + {u'ؼ', u'ؼ', u'ؼ'}, // Keheh with three dots below + {u'ؽ', u'ؽ', u'ؽ'}, // Farsi yeh with inverted v + {u'ؾ', u'ؾ', u'ؾ'}, // Farsi yeh with two dots above + {u'ؿ', u'ؿ', u'ؿ'}, // Farsi yeh with three docs above + {u'ـ', u'ـ', u'ـ'}, // Tatweel + {u'ﻓ', u'ﻔ', u'ﻒ'}, // Feh + {u'ﻗ', u'ﻘ', u'ﻖ'}, // Qaf + {u'ﻛ', u'ﻜ', u'ﻚ'}, // Kaf + {u'ﻟ', u'ﻠ', u'ﻞ'}, // Lam + {u'ﻣ', u'ﻤ', u'ﻢ'}, // Meem + {u'ﻧ', u'ﻨ', u'ﻦ'}, // Noon + {u'ﻫ', u'ﻬ', u'ﻪ'}, // Heh + {u'و', u'ﻮ', u'ﻮ'}, // Waw + {u'ﯨ', u'ﯩ', u'ﻰ'}, // Alef maksura + {u'ﻳ', u'ﻴ', u'ﻲ'}, // Yeh + }; + + static bool isArabic(char16_t c); static bool isStrongRTL(char16_t c); static bool isWeak(char16_t c); static bool isNumber(char16_t c); + static char16_t arabicForm(char16_t current, char16_t prev, char16_t next); + static constexpr u16 palette[16][2] = { {0x0000, 0x7FFF}, // White {0x0000, 0x3DEF}, // Gray