ReactOS 0.4.17-dev-966-gf06eace
indic.c
Go to the documentation of this file.
1/*
2 * Implementation of Indic Syllables for the Uniscribe Script Processor
3 *
4 * Copyright 2011 CodeWeavers, Aric Stewart
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 *
20 */
21
22#include <stdarg.h>
23#include <stdio.h>
24#include <stdlib.h>
25
26#include "windef.h"
27#include "winbase.h"
28#include "winuser.h"
29#include "wingdi.h"
30#include "winnls.h"
31#include "usp10.h"
32#include "winternl.h"
33
34#include "wine/debug.h"
35#include "usp10_internal.h"
36
38
39static void debug_output_string(const WCHAR *str, unsigned int char_count, lexical_function f)
40{
41 int i;
42 if (TRACE_ON(uniscribe))
43 {
44 for (i = 0; i < char_count; ++i)
45 {
46 switch (f(str[i]))
47 {
48 case lex_Consonant: TRACE("C"); break;
49 case lex_Ra: TRACE("Ra"); break;
50 case lex_Vowel: TRACE("V"); break;
51 case lex_Nukta: TRACE("N"); break;
52 case lex_Halant: TRACE("H"); break;
53 case lex_ZWNJ: TRACE("Zwnj"); break;
54 case lex_ZWJ: TRACE("Zwj"); break;
55 case lex_Matra_post: TRACE("Mp");break;
56 case lex_Matra_above: TRACE("Ma");break;
57 case lex_Matra_below: TRACE("Mb");break;
58 case lex_Matra_pre: TRACE("Mm");break;
59 case lex_Modifier: TRACE("Sm"); break;
60 case lex_Vedic: TRACE("Vd"); break;
61 case lex_Anudatta: TRACE("A"); break;
62 case lex_Composed_Vowel: TRACE("t"); break;
63 default:
64 TRACE("X"); break;
65 }
66 }
67 TRACE("\n");
68 }
69}
70
71static inline BOOL is_matra( int type )
72{
73 return (type == lex_Matra_above || type == lex_Matra_below ||
76}
77
78static inline BOOL is_joiner( int type )
79{
80 return (type == lex_ZWJ || type == lex_ZWNJ);
81}
82
83static int consonant_header(const WCHAR *input, unsigned int cChar,
84 unsigned int start, unsigned int next, lexical_function lex)
85{
86 if (!is_consonant( lex(input[next]) )) return -1;
87 next++;
88 if ((next < cChar) && lex(input[next]) == lex_Nukta)
89 next++;
90 if ((next < cChar) && lex(input[next])==lex_Halant)
91 {
92 next++;
93 if((next < cChar) && is_joiner( lex(input[next]) ))
94 next++;
95 if ((next < cChar) && is_consonant( lex(input[next]) ))
96 return next;
97 }
98 else if ((next < cChar) && is_joiner( lex(input[next]) ) && lex(input[next+1])==lex_Halant)
99 {
100 next+=2;
101 if ((next < cChar) && is_consonant( lex(input[next]) ))
102 return next;
103 }
104 return -1;
105}
106
107static int parse_consonant_syllable(const WCHAR *input, unsigned int cChar,
108 unsigned int start, unsigned int *main, unsigned int next, lexical_function lex)
109{
110 int check;
111 int headers = 0;
112 do
113 {
115 if (check != -1)
116 {
117 next = check;
118 headers++;
119 }
120 } while (check != -1);
121 if (headers || is_consonant( lex(input[next]) ))
122 {
123 *main = next;
124 next++;
125 }
126 else
127 return -1;
128 if ((next < cChar) && lex(input[next]) == lex_Nukta)
129 next++;
130 if ((next < cChar) && lex(input[next]) == lex_Anudatta)
131 next++;
132
133 if ((next < cChar) && lex(input[next]) == lex_Halant)
134 {
135 next++;
136 if((next < cChar) && is_joiner( lex(input[next]) ))
137 next++;
138 }
139 else if (next < cChar)
140 {
141 while((next < cChar) && is_matra( lex(input[next]) ))
142 next++;
143 if ((next < cChar) && lex(input[next]) == lex_Nukta)
144 next++;
145 if ((next < cChar) && lex(input[next]) == lex_Halant)
146 next++;
147 }
148 if ((next < cChar) && lex(input[next]) == lex_Modifier)
149 next++;
150 if ((next < cChar) && lex(input[next]) == lex_Vedic)
151 next++;
152 return next;
153}
154
155static int parse_vowel_syllable(const WCHAR *input, unsigned int cChar,
156 unsigned int start, unsigned int next, lexical_function lex)
157{
158 if ((next < cChar) && lex(input[next]) == lex_Nukta)
159 next++;
160 if ((next < cChar) && is_joiner( lex(input[next]) ) && lex(input[next+1])==lex_Halant && is_consonant( lex(input[next+2]) ))
161 next+=3;
162 else if ((next < cChar) && lex(input[next])==lex_Halant && is_consonant( lex(input[next+1]) ))
163 next+=2;
164 else if ((next < cChar) && lex(input[next])==lex_ZWJ && is_consonant( lex(input[next+1]) ))
165 next+=2;
166
167 if ((next < cChar) && is_matra( lex(input[next]) ))
168 {
169 while((next < cChar) && is_matra( lex(input[next]) ))
170 next++;
171 if ((next < cChar) && lex(input[next]) == lex_Nukta)
172 next++;
173 if ((next < cChar) && lex(input[next]) == lex_Halant)
174 next++;
175 }
176
177 if ((next < cChar) && lex(input[next]) == lex_Modifier)
178 next++;
179 if ((next < cChar) && lex(input[next]) == lex_Vedic)
180 next++;
181 return next;
182}
183
184static int Indic_process_next_syllable(const WCHAR *input, unsigned int cChar,
185 unsigned int start, unsigned int *main, unsigned int next, lexical_function lex)
186{
187 if (lex(input[next])==lex_Vowel)
188 {
189 *main = next;
190 return parse_vowel_syllable(input, cChar, start, next+1, lex);
191 }
192 else if ((cChar > next+3) && lex(input[next]) == lex_Ra && lex(input[next+1]) == lex_Halant && lex(input[next+2]) == lex_Vowel)
193 {
194 *main = next+2;
195 return parse_vowel_syllable(input, cChar, start, next+3, lex);
196 }
197
198 else if (start == next && lex(input[next])==lex_NBSP)
199 {
200 *main = next;
201 return parse_vowel_syllable(input, cChar, start, next+1, lex);
202 }
203 else if (start == next && (cChar > next+3) && lex(input[next]) == lex_Ra && lex(input[next+1]) == lex_Halant && lex(input[next+2]) == lex_NBSP)
204 {
205 *main = next+2;
206 return parse_vowel_syllable(input, cChar, start, next+3, lex);
207 }
208
209 return parse_consonant_syllable(input, cChar, start, main, next, lex);
210}
211
213 const WCHAR *pwChar, const IndicSyllable *s, lexical_function lexical, BOOL modern)
214{
215 if (is_consonant(lexical(pwChar[s->base])) && s->base > s->start && lexical(pwChar[s->base-1]) == lex_Halant)
216 {
217 if (modern)
218 return (SHAPE_does_GSUB_feature_apply_to_chars(hdc, psa, psc, &pwChar[s->base-1], 1, 2, "pstf") > 0);
219 else
220 {
221 WCHAR cc[2];
222 cc[0] = pwChar[s->base];
223 cc[1] = pwChar[s->base-1];
224 return (SHAPE_does_GSUB_feature_apply_to_chars(hdc, psa, psc, cc, 1, 2, "pstf") > 0);
225 }
226 }
227 return FALSE;
228}
229
231 const WCHAR *pwChar, const IndicSyllable *s, lexical_function lexical, BOOL modern)
232{
233 if (is_consonant(lexical(pwChar[s->base])) && s->base > s->start && lexical(pwChar[s->base-1]) == lex_Halant)
234 {
235 if (modern)
236 return (SHAPE_does_GSUB_feature_apply_to_chars(hdc, psa, psc, &pwChar[s->base-1], 1, 2, "blwf") > 0);
237 else
238 {
239 WCHAR cc[2];
240 cc[0] = pwChar[s->base];
241 cc[1] = pwChar[s->base-1];
242 return (SHAPE_does_GSUB_feature_apply_to_chars(hdc, psa, psc, cc, 1, 2, "blwf") > 0);
243 }
244 }
245 return FALSE;
246}
247
249 const WCHAR *pwChar, const IndicSyllable *s, lexical_function lexical, BOOL modern)
250{
251 if (is_consonant(lexical(pwChar[s->base])) && s->base > s->start && lexical(pwChar[s->base-1]) == lex_Halant)
252 {
253 if (modern)
254 return (SHAPE_does_GSUB_feature_apply_to_chars(hdc, psa, psc, &pwChar[s->base-1], 1, 2, "pref") > 0);
255 else
256 {
257 WCHAR cc[2];
258 cc[0] = pwChar[s->base];
259 cc[1] = pwChar[s->base-1];
260 return (SHAPE_does_GSUB_feature_apply_to_chars(hdc, psa, psc, cc, 1, 2, "pref") > 0);
261 }
262 }
263 return FALSE;
264}
265
267 const WCHAR *pwChar, const IndicSyllable *s, lexical_function lexical)
268{
269 if ((lexical(pwChar[s->start])==lex_Ra) && s->end > s->start && lexical(pwChar[s->start+1]) == lex_Halant)
270 return (SHAPE_does_GSUB_feature_apply_to_chars(hdc, psa, psc, &pwChar[s->start], 1, 2, "rphf") > 0);
271 return FALSE;
272}
273
275 const WCHAR *input, IndicSyllable *s, lexical_function lex, BOOL modern)
276{
277 int i;
278 BOOL blwf = FALSE;
279 BOOL pref = FALSE;
280
281 /* remove ralf from consideration */
282 if (Consonant_is_ralf(hdc, psa, psc, input, s, lex))
283 {
284 s->ralf = s->start;
285 s->start+=2;
286 }
287
288 /* try to find a base consonant */
289 if (!is_consonant( lex(input[s->base]) ))
290 {
291 for (i = s->end; i >= s->start; i--)
292 if (is_consonant( lex(input[i]) ))
293 {
294 s->base = i;
295 break;
296 }
297 }
298
299 while ((blwf = Consonant_is_below_base_form(hdc, psa, psc, input, s, lex, modern)) || Consonant_is_post_base_form(hdc, psa, psc, input, s, lex, modern) || (pref = Consonant_is_pre_base_form(hdc, psa, psc, input, s, lex, modern)))
300 {
301 if (blwf && s->blwf == -1)
302 s->blwf = s->base - 1;
303 if (pref && s->pref == -1)
304 s->pref = s->base - 1;
305
306 for (i = s->base-1; i >= s->start; i--)
307 if (is_consonant( lex(input[i]) ))
308 {
309 s->base = i;
310 break;
311 }
312 }
313
314 if (s->ralf >= 0)
315 s->start = s->ralf;
316
317 if (s->ralf == s->base)
318 s->ralf = -1;
319
320 return s->base;
321}
322
323void Indic_ParseSyllables(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache *psc, const WCHAR *input, unsigned int cChar,
324 IndicSyllable **syllables, int *syllable_count, lexical_function lex, BOOL modern)
325{
326 unsigned int center = 0;
327 int index = 0;
328 int next = 0;
329
330 *syllable_count = 0;
331
332 if (!lex)
333 {
334 ERR("Failure to have required functions\n");
335 return;
336 }
337
338 debug_output_string(input, cChar, lex);
339 while (next != -1)
340 {
341 while((next < cChar) && lex(input[next]) == lex_Generic)
342 next++;
343 index = next;
344 if (next >= cChar)
345 break;
346 next = Indic_process_next_syllable(input, cChar, 0, &center, index, lex);
347 if (next != -1)
348 {
349 *syllables = realloc(*syllables, sizeof(IndicSyllable)*(*syllable_count+1));
350 (*syllables)[*syllable_count].start = index;
351 (*syllables)[*syllable_count].base = center;
352 (*syllables)[*syllable_count].ralf = -1;
353 (*syllables)[*syllable_count].blwf = -1;
354 (*syllables)[*syllable_count].pref = -1;
355 (*syllables)[*syllable_count].end = next-1;
356 FindBaseConsonant(hdc, psa, psc, input, &(*syllables)[*syllable_count], lex, modern);
357 index = next;
358 *syllable_count = (*syllable_count)+1;
359 }
360 else if (index < cChar)
361 {
362 TRACE("Processing failed at %i\n",index);
363 next = ++index;
364 }
365 }
366 TRACE("Processed %i of %i characters into %i syllables\n",index,cChar,*syllable_count);
367}
368
369void Indic_ReorderCharacters(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache *psc, WCHAR *input, unsigned int cChar,
370 IndicSyllable **syllables, int *syllable_count, lexical_function lex, reorder_function reorder_f, BOOL modern)
371{
372 int i;
373
374 if (!reorder_f)
375 {
376 ERR("Failure to have required functions\n");
377 return;
378 }
379
380 Indic_ParseSyllables(hdc, psa, psc, input, cChar, syllables, syllable_count, lex, modern);
381 for (i = 0; i < *syllable_count; i++)
382 reorder_f(input, &(*syllables)[i], lex);
383}
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define index(s, c)
Definition: various.h:29
#define ERR(fmt,...)
Definition: precomp.h:57
#define realloc
Definition: debug_ros.c:6
#define FALSE
Definition: types.h:117
#define TRACE_ON(x)
Definition: compat.h:75
#define check(expected, result)
Definition: dplayx.c:43
int main()
Definition: test.c:6
unsigned int BOOL
Definition: ntddk_ex.h:94
GLuint start
Definition: gl.h:1545
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLdouble s
Definition: gl.h:2039
GLuint index
Definition: glext.h:6031
GLfloat f
Definition: glext.h:7540
GLenum GLenum GLenum input
Definition: glext.h:9031
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static BOOL Consonant_is_ralf(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache *psc, const WCHAR *pwChar, const IndicSyllable *s, lexical_function lexical)
Definition: indic.c:266
static int parse_vowel_syllable(const WCHAR *input, unsigned int cChar, unsigned int start, unsigned int next, lexical_function lex)
Definition: indic.c:155
static BOOL Consonant_is_post_base_form(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache *psc, const WCHAR *pwChar, const IndicSyllable *s, lexical_function lexical, BOOL modern)
Definition: indic.c:212
void Indic_ReorderCharacters(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache *psc, WCHAR *input, unsigned int cChar, IndicSyllable **syllables, int *syllable_count, lexical_function lex, reorder_function reorder_f, BOOL modern)
Definition: indic.c:369
static int Indic_process_next_syllable(const WCHAR *input, unsigned int cChar, unsigned int start, unsigned int *main, unsigned int next, lexical_function lex)
Definition: indic.c:184
static int FindBaseConsonant(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache *psc, const WCHAR *input, IndicSyllable *s, lexical_function lex, BOOL modern)
Definition: indic.c:274
static int parse_consonant_syllable(const WCHAR *input, unsigned int cChar, unsigned int start, unsigned int *main, unsigned int next, lexical_function lex)
Definition: indic.c:107
static BOOL Consonant_is_below_base_form(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache *psc, const WCHAR *pwChar, const IndicSyllable *s, lexical_function lexical, BOOL modern)
Definition: indic.c:230
void Indic_ParseSyllables(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache *psc, const WCHAR *input, unsigned int cChar, IndicSyllable **syllables, int *syllable_count, lexical_function lex, BOOL modern)
Definition: indic.c:323
static BOOL is_matra(int type)
Definition: indic.c:71
static BOOL is_joiner(int type)
Definition: indic.c:78
static int consonant_header(const WCHAR *input, unsigned int cChar, unsigned int start, unsigned int next, lexical_function lex)
Definition: indic.c:83
static void debug_output_string(const WCHAR *str, unsigned int char_count, lexical_function f)
Definition: indic.c:39
static BOOL Consonant_is_pre_base_form(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache *psc, const WCHAR *pwChar, const IndicSyllable *s, lexical_function lexical, BOOL modern)
Definition: indic.c:248
uint32_t cc
Definition: isohybrid.c:75
#define f
Definition: ke_i.h:83
HDC hdc
Definition: main.c:9
static HDC
Definition: imagelist.c:88
short WCHAR
Definition: pedump.c:58
static unsigned __int64 next
Definition: rand_nt.c:6
const WCHAR * str
vector< Header * > headers
Definition: sdkparse.cpp:39
#define TRACE(s)
Definition: solgame.cpp:4
static BOOL is_consonant(int type)
void(* reorder_function)(WCHAR *chars, IndicSyllable *syllable, lexical_function lex)
int(* lexical_function)(WCHAR c)
@ lex_Nukta
@ lex_Anudatta
@ lex_Matra_above
@ lex_Matra_below
@ lex_ZWJ
@ lex_Consonant
@ lex_Vowel
@ lex_Ra
@ lex_Modifier
@ lex_Generic
@ lex_NBSP
@ lex_Vedic
@ lex_Composed_Vowel
@ lex_Matra_post
@ lex_ZWNJ
@ lex_Halant
@ lex_Matra_pre
int SHAPE_does_GSUB_feature_apply_to_chars(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache *psc, const WCHAR *chars, int write_dir, int count, const char *feature)
Definition: shape.c:723