Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenindic.c
Go to the documentation of this file.
00001 /* 00002 * Implementation of Indic Syllables for the Uniscribe Script Processor 00003 * 00004 * Copyright 2011 CodeWeavers, Aric Stewart 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 * 00020 */ 00021 #include "config.h" 00022 #include <stdarg.h> 00023 #include <stdio.h> 00024 #include <stdlib.h> 00025 00026 #include "windef.h" 00027 #include "winbase.h" 00028 #include "winuser.h" 00029 #include "wingdi.h" 00030 #include "winnls.h" 00031 #include "usp10.h" 00032 #include "winternl.h" 00033 00034 #include "wine/debug.h" 00035 #include "usp10_internal.h" 00036 00037 WINE_DEFAULT_DEBUG_CHANNEL(uniscribe); 00038 00039 static void debug_output_string(LPCWSTR str, int cChar, lexical_function f) 00040 { 00041 int i; 00042 if (TRACE_ON(uniscribe)) 00043 { 00044 for (i = 0; i < cChar; i++) 00045 { 00046 switch (f(str[i])) 00047 { 00048 case lex_Consonant: TRACE("C"); break; 00049 case lex_Ra: TRACE("Ra"); break; 00050 case lex_Vowel: TRACE("V"); break; 00051 case lex_Nukta: TRACE("N"); break; 00052 case lex_Halant: TRACE("H"); break; 00053 case lex_ZWNJ: TRACE("Zwnj"); break; 00054 case lex_ZWJ: TRACE("Zwj"); break; 00055 case lex_Matra_post: TRACE("Mp");break; 00056 case lex_Matra_above: TRACE("Ma");break; 00057 case lex_Matra_below: TRACE("Mb");break; 00058 case lex_Matra_pre: TRACE("Mm");break; 00059 case lex_Modifier: TRACE("Sm"); break; 00060 case lex_Vedic: TRACE("Vd"); break; 00061 case lex_Anudatta: TRACE("A"); break; 00062 case lex_Composed_Vowel: TRACE("t"); break; 00063 default: 00064 TRACE("X"); break; 00065 } 00066 } 00067 TRACE("\n"); 00068 } 00069 } 00070 00071 static inline BOOL is_matra( int type ) 00072 { 00073 return (type == lex_Matra_above || type == lex_Matra_below || 00074 type == lex_Matra_pre || type == lex_Matra_post || 00075 type == lex_Composed_Vowel); 00076 } 00077 00078 static inline BOOL is_joiner( int type ) 00079 { 00080 return (type == lex_ZWJ || type == lex_ZWNJ); 00081 } 00082 00083 static INT consonant_header(LPCWSTR input, INT cChar, INT start, INT next, 00084 lexical_function lex) 00085 { 00086 if (!is_consonant( lex(input[next]) )) return -1; 00087 next++; 00088 if ((next < cChar) && lex(input[next]) == lex_Nukta) 00089 next++; 00090 if ((next < cChar) && lex(input[next])==lex_Halant) 00091 { 00092 next++; 00093 if((next < cChar) && is_joiner( lex(input[next]) )) 00094 next++; 00095 if ((next < cChar) && is_consonant( lex(input[next]) )) 00096 return next; 00097 } 00098 else if ((next < cChar) && is_joiner( lex(input[next]) ) && lex(input[next+1])==lex_Halant) 00099 { 00100 next+=2; 00101 if ((next < cChar) && is_consonant( lex(input[next]) )) 00102 return next; 00103 } 00104 return -1; 00105 } 00106 00107 static INT parse_consonant_syllable(LPCWSTR input, INT cChar, INT start, 00108 INT *main, INT next, lexical_function lex) 00109 { 00110 int check; 00111 int headers = 0; 00112 do 00113 { 00114 check = consonant_header(input,cChar,start,next,lex); 00115 if (check != -1) 00116 { 00117 next = check; 00118 headers++; 00119 } 00120 } while (check != -1); 00121 if (headers || is_consonant( lex(input[next]) )) 00122 { 00123 *main = next; 00124 next++; 00125 } 00126 else 00127 return -1; 00128 if ((next < cChar) && lex(input[next]) == lex_Nukta) 00129 next++; 00130 if ((next < cChar) && lex(input[next]) == lex_Anudatta) 00131 next++; 00132 00133 if ((next < cChar) && lex(input[next]) == lex_Halant) 00134 { 00135 next++; 00136 if((next < cChar) && is_joiner( lex(input[next]) )) 00137 next++; 00138 } 00139 else if (next < cChar) 00140 { 00141 while((next < cChar) && is_matra( lex(input[next]) )) 00142 next++; 00143 if ((next < cChar) && lex(input[next]) == lex_Nukta) 00144 next++; 00145 if ((next < cChar) && lex(input[next]) == lex_Halant) 00146 next++; 00147 } 00148 if ((next < cChar) && lex(input[next]) == lex_Modifier) 00149 next++; 00150 if ((next < cChar) && lex(input[next]) == lex_Vedic) 00151 next++; 00152 return next; 00153 } 00154 00155 static INT parse_vowel_syllable(LPCWSTR input, INT cChar, INT start, 00156 INT next, lexical_function lex) 00157 { 00158 if ((next < cChar) && lex(input[next]) == lex_Nukta) 00159 next++; 00160 if ((next < cChar) && is_joiner( lex(input[next]) ) && lex(input[next+1])==lex_Halant && is_consonant( lex(input[next+2]) )) 00161 next+=3; 00162 else if ((next < cChar) && lex(input[next])==lex_Halant && is_consonant( lex(input[next+1]) )) 00163 next+=2; 00164 else if ((next < cChar) && lex(input[next])==lex_ZWJ && is_consonant( lex(input[next+1]) )) 00165 next+=2; 00166 00167 if ((next < cChar) && is_matra( lex(input[next]) )) 00168 { 00169 while((next < cChar) && is_matra( lex(input[next]) )) 00170 next++; 00171 if ((next < cChar) && lex(input[next]) == lex_Nukta) 00172 next++; 00173 if ((next < cChar) && lex(input[next]) == lex_Halant) 00174 next++; 00175 } 00176 00177 if ((next < cChar) && lex(input[next]) == lex_Modifier) 00178 next++; 00179 if ((next < cChar) && lex(input[next]) == lex_Vedic) 00180 next++; 00181 return next; 00182 } 00183 00184 static INT Indic_process_next_syllable( LPCWSTR input, INT cChar, INT start, INT* main, INT next, lexical_function lex ) 00185 { 00186 if (lex(input[next])==lex_Vowel) 00187 { 00188 *main = next; 00189 return parse_vowel_syllable(input, cChar, start, next+1, lex); 00190 } 00191 else if ((cChar > next+3) && lex(input[next]) == lex_Ra && lex(input[next+1]) == lex_Halant && lex(input[next+2]) == lex_Vowel) 00192 { 00193 *main = next+2; 00194 return parse_vowel_syllable(input, cChar, start, next+3, lex); 00195 } 00196 00197 else if (start == next && lex(input[next])==lex_NBSP) 00198 { 00199 *main = next; 00200 return parse_vowel_syllable(input, cChar, start, next+1, lex); 00201 } 00202 else if (start == next && (cChar > next+3) && lex(input[next]) == lex_Ra && lex(input[next+1]) == lex_Halant && lex(input[next+2]) == lex_NBSP) 00203 { 00204 *main = next+2; 00205 return parse_vowel_syllable(input, cChar, start, next+3, lex); 00206 } 00207 00208 return parse_consonant_syllable(input, cChar, start, main, next, lex); 00209 } 00210 00211 static BOOL Consonent_is_post_base_form(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPCWSTR pwChar, IndicSyllable *s, lexical_function lexical, BOOL modern) 00212 { 00213 if (is_consonant(lexical(pwChar[s->base])) && s->base > s->start && lexical(pwChar[s->base-1]) == lex_Halant) 00214 { 00215 if (modern) 00216 return (SHAPE_does_GSUB_feature_apply_to_chars(hdc, psa, psc, &pwChar[s->base-1], 1, 2, "pstf") > 0); 00217 else 00218 { 00219 WCHAR cc[2]; 00220 cc[0] = pwChar[s->base]; 00221 cc[1] = pwChar[s->base-1]; 00222 return (SHAPE_does_GSUB_feature_apply_to_chars(hdc, psa, psc, cc, 1, 2, "pstf") > 0); 00223 } 00224 } 00225 return FALSE; 00226 } 00227 00228 static BOOL Consonent_is_below_base_form(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPCWSTR pwChar, IndicSyllable *s, lexical_function lexical, BOOL modern) 00229 { 00230 if (is_consonant(lexical(pwChar[s->base])) && s->base > s->start && lexical(pwChar[s->base-1]) == lex_Halant) 00231 { 00232 if (modern) 00233 return (SHAPE_does_GSUB_feature_apply_to_chars(hdc, psa, psc, &pwChar[s->base-1], 1, 2, "blwf") > 0); 00234 else 00235 { 00236 WCHAR cc[2]; 00237 cc[0] = pwChar[s->base]; 00238 cc[1] = pwChar[s->base-1]; 00239 return (SHAPE_does_GSUB_feature_apply_to_chars(hdc, psa, psc, cc, 1, 2, "blwf") > 0); 00240 } 00241 } 00242 return FALSE; 00243 } 00244 00245 static BOOL Consonent_is_pre_base_form(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPCWSTR pwChar, IndicSyllable *s, lexical_function lexical, BOOL modern) 00246 { 00247 if (is_consonant(lexical(pwChar[s->base])) && s->base > s->start && lexical(pwChar[s->base-1]) == lex_Halant) 00248 { 00249 if (modern) 00250 return (SHAPE_does_GSUB_feature_apply_to_chars(hdc, psa, psc, &pwChar[s->base-1], 1, 2, "pref") > 0); 00251 else 00252 { 00253 WCHAR cc[2]; 00254 cc[0] = pwChar[s->base]; 00255 cc[1] = pwChar[s->base-1]; 00256 return (SHAPE_does_GSUB_feature_apply_to_chars(hdc, psa, psc, cc, 1, 2, "pref") > 0); 00257 } 00258 } 00259 return FALSE; 00260 } 00261 00262 static BOOL Consonent_is_ralf(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPCWSTR pwChar, IndicSyllable *s, lexical_function lexical) 00263 { 00264 if ((lexical(pwChar[s->start])==lex_Ra) && s->end > s->start && lexical(pwChar[s->start+1]) == lex_Halant) 00265 return (SHAPE_does_GSUB_feature_apply_to_chars(hdc, psa, psc, &pwChar[s->start], 1, 2, "rphf") > 0); 00266 return FALSE; 00267 } 00268 00269 static int FindBaseConsonant(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPCWSTR input, IndicSyllable *s, lexical_function lex, BOOL modern) 00270 { 00271 int i; 00272 BOOL blwf = FALSE; 00273 BOOL pref = FALSE; 00274 00275 /* remove ralf from consideration */ 00276 if (Consonent_is_ralf(hdc, psa, psc, input, s, lex)) 00277 { 00278 s->ralf = s->start; 00279 s->start+=2; 00280 } 00281 00282 /* try to find a base consonant */ 00283 if (!is_consonant( lex(input[s->base]) )) 00284 { 00285 for (i = s->end; i >= s->start; i--) 00286 if (is_consonant( lex(input[i]) )) 00287 { 00288 s->base = i; 00289 break; 00290 } 00291 } 00292 00293 while ((blwf = Consonent_is_below_base_form(hdc, psa, psc, input, s, lex, modern)) || Consonent_is_post_base_form(hdc, psa, psc, input, s, lex, modern) || (pref = Consonent_is_pre_base_form(hdc, psa, psc, input, s, lex, modern))) 00294 { 00295 if (blwf && s->blwf == -1) 00296 s->blwf = s->base - 1; 00297 if (pref && s->pref == -1) 00298 s->pref = s->base - 1; 00299 00300 for (i = s->base-1; i >= s->start; i--) 00301 if (is_consonant( lex(input[i]) )) 00302 { 00303 s->base = i; 00304 break; 00305 } 00306 } 00307 00308 if (s->ralf >= 0) 00309 s->start = s->ralf; 00310 00311 if (s->ralf == s->base) 00312 s->ralf = -1; 00313 00314 return s->base; 00315 } 00316 00317 void Indic_ParseSyllables( HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPCWSTR input, const int cChar, IndicSyllable **syllables, int *syllable_count, lexical_function lex, BOOL modern) 00318 { 00319 int index = 0; 00320 int next = 0; 00321 int center = 0; 00322 00323 *syllable_count = 0; 00324 00325 if (!lex) 00326 { 00327 ERR("Failure to have required functions\n"); 00328 return; 00329 } 00330 00331 debug_output_string(input, cChar, lex); 00332 while (next != -1) 00333 { 00334 while((next < cChar) && lex(input[next]) == lex_Generic) 00335 next++; 00336 index = next; 00337 if (next >= cChar) 00338 break; 00339 next = Indic_process_next_syllable(input, cChar, 0, ¢er, index, lex); 00340 if (next != -1) 00341 { 00342 if (*syllable_count) 00343 *syllables = HeapReAlloc(GetProcessHeap(),0,*syllables, sizeof(IndicSyllable)*(*syllable_count+1)); 00344 else 00345 *syllables = HeapAlloc(GetProcessHeap(),0,sizeof(IndicSyllable)); 00346 (*syllables)[*syllable_count].start = index; 00347 (*syllables)[*syllable_count].base = center; 00348 (*syllables)[*syllable_count].ralf = -1; 00349 (*syllables)[*syllable_count].blwf = -1; 00350 (*syllables)[*syllable_count].pref = -1; 00351 (*syllables)[*syllable_count].end = next-1; 00352 FindBaseConsonant(hdc, psa, psc, input, &(*syllables)[*syllable_count], lex, modern); 00353 index = next; 00354 *syllable_count = (*syllable_count)+1; 00355 } 00356 else if (index < cChar) 00357 { 00358 TRACE("Processing failed at %i\n",index); 00359 next = ++index; 00360 } 00361 } 00362 TRACE("Processed %i of %i characters into %i syllables\n",index,cChar,*syllable_count); 00363 } 00364 00365 void Indic_ReorderCharacters( HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPWSTR input, int cChar, IndicSyllable **syllables, int *syllable_count, lexical_function lex, reorder_function reorder_f, BOOL modern) 00366 { 00367 int i; 00368 00369 if (!reorder_f) 00370 { 00371 ERR("Failure to have required functions\n"); 00372 return; 00373 } 00374 00375 Indic_ParseSyllables(hdc, psa, psc, input, cChar, syllables, syllable_count, lex, modern); 00376 for (i = 0; i < *syllable_count; i++) 00377 reorder_f(input, &(*syllables)[i], lex); 00378 } Generated on Sat May 26 2012 04:25:18 for ReactOS by
1.7.6.1
|