From 490b536bf20d9115fa6ed3dc2f2be562e99c481a Mon Sep 17 00:00:00 2001 From: Pk11 Date: Thu, 2 Sep 2021 11:01:49 -0500 Subject: [PATCH] Copy over Arabic support from TWiLight Currently not really needed, but if we make GM9i translatable (which I'll prolly do after this PR is merged) it'll be needed so might as well just do it now --- arm9/source/font.cpp | 33 ++++++++++++++++++++++++++---- arm9/source/font.h | 48 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 4 deletions(-) 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