https://www.cnblogs.com/MrLidx/p/8436089.html
Unity3d游戏中实现阿拉伯语文字正常显示
Unity3d游戏中实现阿拉伯语文字正常显示
由于项目需求要把游戏文字显示为维语版本(维语属于阿拉伯语系),我先把维语替换进去,之后发现文字是错的(每个字符都分开了,而且显示方向也不对)后来在网上查了一下发现阿拉伯语是从右往左读的,并且阿拉伯语的32个字符单说写法就有126种(同一个字符有多种写法)如下图:
部分维语字符的不同书写形式
首先我们来了解一下维语:
① 维文是以阿拉伯字母为基层的因素文字,由32个字母构成。分为元音、辅音两大类。
② 8个元音又分三类;3个前元音、3个后元音、2个央元音。 每个词的元音要么都是前元音,要么都是后元音。这8个元音中有4个同汉语元音等值完全相同,有4个相差较大。
③ 24个辅音又分为两类;分别为:10个清音、14个浊音。这24个辅音中有20个同汉语声母辅音等值完全相同,有4个相差较大。
④ 注有“新维文”字样的框格,代表发音相差较大。
书写规则:
【单立式】(又称独立式、独写体)用于词末尾单独构成一个音节时。
【后连式】(又称连首体)用于词首或音节首。
【双连式】(又称前后连式、中连式、连中体)用于两种书写形式的辅音字母之外的其余辅音字母的中间。
【隔音双连式】(又称隔音前后连式)用于词中的音节首。
【前连式】(又称连尾体)用于词末尾与前面的字母相连。
【隔音前连式】用于词末尾与前面的字母连写单独构成一个音节。
【简单单立式】用于词末尾而且是两种书写形式的辅音字母之后。
【简单后连式】用于词中间而且是两种书写形式的辅音字母之后。
上面这都是在网上看到的怎么感觉有点像我们小时候学习 a o e 一样了呢,哈哈.. 不得不说,真的看不懂!
其实看到这些字符我是一脸懵逼,不是龙舟就是战舰的,最主要的是不认识。
最开始我是在网上找了个插件(如果在看到我这篇博客之前你查过阿拉伯语的显示问题,你一定也在GitHub上看到过ArabicSupport这个插件吧),它不过也就是把文字显示方向可以修改过来,但是里边还是存在很多问题的,后来修改了他的源码,这才把项目里的阿拉伯语正常显示出来!当你仔细看他demo源码的时候就会发现,他的做法是把一句话的每个字符分别存到两个数组里,然后用Unicode编码进行比对、替换。打开一个阿拉伯语字体你会看到每一个字符都会有它对应的Unicode编码。如下图:
图一 图二
图二中一套字体里为什么会有长得一样的字符呢?点开一个字符,然后左下角你会发现对应的Unicode编码是不同的,并且一个是独立形式,另一个是非独立形式。然而那些错误的字符就是因为使用的非独立形式,才导致再次变形的时候出现错误,我们要做的就是要把这些读取出来的非独立形式转换为独立形式,做好映射!
然后在GitHub那个Demo的源码中我们看到他里面提供了几个接口,分别是判断当前字符要使用前连书体、后边书体、还是前后连书体或独立书体,修改代码如下:
1 /// <summary>
2 /// Checks if the letter at index value is a leading character in Arabic or not.
3 /// </summary>
4 /// <param name="letters">The whole word that contains the character to be checked</param>
5 /// <param name="index">The index of the character to be checked</param>
6 /// <returns>True if the character at index is a leading character, else, returns false</returns>
7 internal static bool IsLeadingLetter(char[] letters, int index)
8 {
9
10 bool lettersThatCannotBeBeforeALeadingLetter = index == 0
11 || letters[index - 1] == ' '
12 || letters[index - 1] == '*' // ??? Remove?
13 || letters[index - 1] == 'A' // ??? Remove?
14 || char.IsPunctuation(letters[index - 1])
15 || char.IsNumber(letters[index - 1])
16 || letters[index - 1] == '>'
17 || letters[index - 1] == '<'
18 || letters[index - 1] == (int)IsolatedArabicLetters.Alef
19 || letters[index - 1] == (int)IsolatedArabicLetters.Dal
20 || letters[index - 1] == (int)IsolatedArabicLetters.Thal
21 || letters[index - 1] == (int)IsolatedArabicLetters.Ra2
22 || letters[index - 1] == (int)IsolatedArabicLetters.Zeen
23 || letters[index - 1] == (int)IsolatedArabicLetters.PersianZe
24 //|| letters[index - 1] == (int)IsolatedArabicLetters.AlefMaksora
25 || letters[index - 1] == (int)IsolatedArabicLetters.Waw
26 || letters[index - 1] == (int)IsolatedArabicLetters.AlefMad
27 || letters[index - 1] == (int)IsolatedArabicLetters.AlefHamza
28 || letters[index - 1] == (int)IsolatedArabicLetters.AlefMaksoor
29 || letters[index - 1] == (int)IsolatedArabicLetters.WawHamza
30 || letters[index - 1] == (int)IsolatedArabicLetters.Ae
31 || letters[index - 1] == (int)IsolatedArabicLetters.U
32 || letters[index - 1] == (int)IsolatedArabicLetters.Yu
33 || letters[index - 1] == (int)IsolatedArabicLetters.Oe
34 || letters[index - 1] == (int)IsolatedArabicLetters.Ve;
35
36 bool lettersThatCannotBeALeadingLetter = letters[index] != ' '
37 && letters[index] != (int)IsolatedArabicLetters.Dal
38 && letters[index] != (int)IsolatedArabicLetters.Thal
39 && letters[index] != (int)IsolatedArabicLetters.Ra2
40 && letters[index] != (int)IsolatedArabicLetters.Zeen
41 && letters[index] != (int)IsolatedArabicLetters.PersianZe
42 && letters[index] != (int)IsolatedArabicLetters.Alef
43 && letters[index] != (int)IsolatedArabicLetters.AlefHamza
44 && letters[index] != (int)IsolatedArabicLetters.AlefMaksoor
45 && letters[index] != (int)IsolatedArabicLetters.AlefMad
46 && letters[index] != (int)IsolatedArabicLetters.WawHamza
47 && letters[index] != (int)IsolatedArabicLetters.Waw
48 && letters[index] != (int)IsolatedArabicLetters.Hamza
49 && letters[index] != (int)IsolatedArabicLetters.Ae
50 && letters[index] != (int)IsolatedArabicLetters.U
51 && letters[index] != (int)IsolatedArabicLetters.Yu
52 && letters[index] != (int)IsolatedArabicLetters.Oe
53 && letters[index] != (int)IsolatedArabicLetters.Ve;
54
55 bool lettersThatCannotBeAfterLeadingLetter = index < letters.Length - 1
56 && letters[index + 1] != ' '
57 && !char.IsPunctuation(letters[index + 1] )
58 && !char.IsNumber(letters[index + 1])
59 && !char.IsSymbol(letters[index + 1])
60 && !char.IsLower(letters[index + 1])
61 && !char.IsUpper(letters[index + 1])
62 && letters[index + 1] != (int)IsolatedArabicLetters.Hamza;
63
64 if(lettersThatCannotBeBeforeALeadingLetter && lettersThatCannotBeALeadingLetter && lettersThatCannotBeAfterLeadingLetter)
65 {
66 return true;
67 }
68 else
69 return false;
70 }
71
72 /// <summary>
73 /// Checks if the letter at index value is a finishing character in Arabic or not.
74 /// </summary>
75 /// <param name="letters">The whole word that contains the character to be checked</param>
76 /// <param name="index">The index of the character to be checked</param>
77 /// <returns>True if the character at index is a finishing character, else, returns false</returns>
78 internal static bool IsFinishingLetter(char[] letters, int index)
79 {
80 bool indexZero = index != 0;
81 bool lettersThatCannotBeBeforeAFinishingLetter = (index == 0) ? false :
82 letters[index - 1] != ' '
83 && letters[index - 1] != (int)IsolatedArabicLetters.Dal
84 && letters[index - 1] != (int)IsolatedArabicLetters.Thal
85 && letters[index - 1] != (int)IsolatedArabicLetters.Ra2
86 && letters[index - 1] != (int)IsolatedArabicLetters.Zeen
87 && letters[index - 1] != (int)IsolatedArabicLetters.PersianZe
88 //&& letters[index - 1] != (int)IsolatedArabicLetters.AlefMaksora
89 && letters[index - 1] != (int)IsolatedArabicLetters.Waw
90 && letters[index - 1] != (int)IsolatedArabicLetters.Alef
91 && letters[index - 1] != (int)IsolatedArabicLetters.AlefMad
92 && letters[index - 1] != (int)IsolatedArabicLetters.AlefHamza
93 && letters[index - 1] != (int)IsolatedArabicLetters.AlefMaksoor
94 && letters[index - 1] != (int)IsolatedArabicLetters.WawHamza
95 && letters[index - 1] != (int)IsolatedArabicLetters.Hamza
96 && letters[index - 1] != (int)IsolatedArabicLetters.Ae
97 && letters[index - 1] != (int)IsolatedArabicLetters.U
98 && letters[index - 1] != (int)IsolatedArabicLetters.Yu
99 && letters[index - 1] != (int)IsolatedArabicLetters.Oe
100 && letters[index - 1] != (int)IsolatedArabicLetters.Ve
101
102
103 && !char.IsNumber(letters[index - 1])
104 && !char.IsPunctuation(letters[index - 1])
105 && letters[index - 1] != '>'
106 && letters[index - 1] != '<';
107
108
109 bool lettersThatCannotBeFinishingLetters = letters[index] != ' ' && letters[index] != (int)IsolatedArabicLetters.Hamza;
110
111
112
113
114 if(lettersThatCannotBeBeforeAFinishingLetter && lettersThatCannotBeFinishingLetters)
115 {
116 return true;
117 }
118 else
119 return false;
120 }
121
122 /// <summary>
123 /// Checks if the letter at index value is a middle character in Arabic or not.
124 /// </summary>
125 /// <param name="letters">The whole word that contains the character to be checked</param>
126 /// <param name="index">The index of the character to be checked</param>
127 /// <returns>True if the character at index is a middle character, else, returns false</returns>
128 internal static bool IsMiddleLetter(char[] letters, int index)
129 {
130 bool lettersThatCannotBeMiddleLetters = (index == 0) ? false :
131 letters[index] != (int)IsolatedArabicLetters.Alef
132 && letters[index] != (int)IsolatedArabicLetters.Dal
133 && letters[index] != (int)IsolatedArabicLetters.Thal
134 && letters[index] != (int)IsolatedArabicLetters.Ra2
135 && letters[index] != (int)IsolatedArabicLetters.Zeen
136 && letters[index] != (int)IsolatedArabicLetters.PersianZe
137 //&& letters[index] != (int)IsolatedArabicLetters.AlefMaksora
138 && letters[index] != (int)IsolatedArabicLetters.Waw
139 && letters[index] != (int)IsolatedArabicLetters.AlefMad
140 && letters[index] != (int)IsolatedArabicLetters.AlefHamza
141 && letters[index] != (int)IsolatedArabicLetters.AlefMaksoor
142 && letters[index] != (int)IsolatedArabicLetters.WawHamza
143 && letters[index] != (int)IsolatedArabicLetters.Hamza
144 && letters[index] != (int)IsolatedArabicLetters.Ae
145 && letters[index] != (int)IsolatedArabicLetters.U
146 && letters[index] != (int)IsolatedArabicLetters.Yu
147 && letters[index] != (int)IsolatedArabicLetters.Oe
148 && letters[index] != (int)IsolatedArabicLetters.Ve;
149
150 bool lettersThatCannotBeBeforeMiddleCharacters = (index == 0) ? false :
151 letters[index - 1] != (int)IsolatedArabicLetters.Alef
152 && letters[index - 1] != (int)IsolatedArabicLetters.Dal
153 && letters[index - 1] != (int)IsolatedArabicLetters.Thal
154 && letters[index - 1] != (int)IsolatedArabicLetters.Ra2
155 && letters[index - 1] != (int)IsolatedArabicLetters.Zeen
156 && letters[index - 1] != (int)IsolatedArabicLetters.PersianZe
157 //&& letters[index - 1] != (int)IsolatedArabicLetters.AlefMaksora
158 && letters[index - 1] != (int)IsolatedArabicLetters.Waw
159 && letters[index - 1] != (int)IsolatedArabicLetters.AlefMad
160 && letters[index - 1] != (int)IsolatedArabicLetters.AlefHamza
161 && letters[index - 1] != (int)IsolatedArabicLetters.AlefMaksoor
162 && letters[index - 1] != (int)IsolatedArabicLetters.WawHamza
163 && letters[index - 1] != (int)IsolatedArabicLetters.Hamza
164 && letters[index - 1] != (int)IsolatedArabicLetters.Ae
165 && letters[index - 1] != (int)IsolatedArabicLetters.U
166 && letters[index - 1] != (int)IsolatedArabicLetters.Yu
167 && letters[index - 1] != (int)IsolatedArabicLetters.Oe
168 && letters[index - 1] != (int)IsolatedArabicLetters.Ve
169 && !char.IsNumber(letters[index - 1])
170 && !char.IsPunctuation(letters[index - 1])
171 && letters[index - 1] != '>'
172 && letters[index - 1] != '<'
173 && letters[index - 1] != ' '
174 && letters[index - 1] != '*';
175
176 bool lettersThatCannotBeAfterMiddleCharacters = (index >= letters.Length - 1) ? false :
177 letters[index + 1] != ' '
178 && letters[index + 1] != '\r'
179 && letters[index + 1] != (int)IsolatedArabicLetters.Hamza
180 && !char.IsNumber(letters[index + 1])
181 && !char.IsSymbol(letters[index + 1])
182 && !char.IsPunctuation(letters[index + 1]);
183 if(lettersThatCannotBeAfterMiddleCharacters && lettersThatCannotBeBeforeMiddleCharacters && lettersThatCannotBeMiddleLetters)
184 {
185 try
186 {
187 if (char.IsPunctuation(letters[index + 1]))
188 return false;
189 else
190 return true;
191 }
192 catch
193 {
194 return false;
195 }
196 //return true;
197 }
198 else
199 return false;
200 }
对照维语的Unicode编码总结出:
①独立形式Unicode编码的基础之上加1就是前连书体
②独立形式Unicode编码的基础之上加2就是后连书体
③独立形式Unicode编码的基础之上加3就是前后连书体
前面做好映射,有了上面这三个方法就能正常显示字符的书写形式了!(主要就是前连、后连、前后连这几种书写形体,其他形体不再多说)
看一下效果图:(文字看起来是不是舒服一些)
登录效果图
此篇文章经过自己归纳总结整理出来,仅供参考,如果大家有什么好的修改方式,或是好的意见或建议欢迎留言、交流,一起探讨!