Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenbreaking.c
Go to the documentation of this file.
00001 /* 00002 * Implementation of line breaking algorithm 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 extern const unsigned short wine_linebreak_table[]; 00040 00041 enum breaking_types { b_BK=1, b_CR, b_LF, b_CM, b_SG, b_GL, b_CB, b_SP, b_ZW, b_NL, b_WJ, b_JL, b_JV, b_JT, b_H2, b_H3, b_XX, b_OP, b_CL, b_CP, b_QU, b_NS, b_EX, b_SY, b_IS, b_PR, b_PO, b_NU, b_AL, b_ID, b_IN, b_HY, b_BB, b_BA, b_SA, b_AI, b_B2}; 00042 00043 enum breaking_class {b_r=1, b_s, b_x}; 00044 00045 static void debug_output_breaks(const short* breaks, int count) 00046 { 00047 if (TRACE_ON(uniscribe)) 00048 { 00049 int i; 00050 TRACE("["); 00051 for (i = 0; i < count && i < 200; i++) 00052 { 00053 switch (breaks[i]) 00054 { 00055 case b_x: TRACE("x"); break; 00056 case b_r: TRACE("!"); break; 00057 case b_s: TRACE("+"); break; 00058 default: TRACE("*"); 00059 } 00060 } 00061 if (i == 200) 00062 TRACE("..."); 00063 TRACE("]\n"); 00064 } 00065 } 00066 00067 static inline void else_break(short* before, short class) 00068 { 00069 if (*before == 0) *before = class; 00070 } 00071 00072 void BREAK_line(const WCHAR *chars, int count, const SCRIPT_ANALYSIS *sa, SCRIPT_LOGATTR *la) 00073 { 00074 int i,j; 00075 short *break_class; 00076 short *break_before; 00077 00078 TRACE("In %s\n",debugstr_wn(chars,count)); 00079 00080 break_class = HeapAlloc(GetProcessHeap(),0, count * sizeof(short)); 00081 break_before = HeapAlloc(GetProcessHeap(),0, count * sizeof(short)); 00082 00083 for (i = 0; i < count; i++) 00084 { 00085 break_class[i] = get_table_entry( wine_linebreak_table, chars[i] ); 00086 break_before[i] = 0; 00087 00088 memset(&la[i],0,sizeof(SCRIPT_LOGATTR)); 00089 00090 la[i].fCharStop = TRUE; 00091 switch (break_class[i]) 00092 { 00093 case b_BK: 00094 case b_ZW: 00095 case b_SP: 00096 la[i].fWhiteSpace = TRUE; 00097 break; 00098 case b_CM: 00099 la[i].fCharStop = FALSE; 00100 } 00101 } 00102 00103 /* LB1 */ 00104 /* TODO: Have outside algorithms for these scripts */ 00105 for (i = 0; i < count; i++) 00106 { 00107 switch(break_class[i]) 00108 { 00109 case b_AI: 00110 case b_SA: 00111 case b_SG: 00112 case b_XX: 00113 break_class[i] = b_AL; 00114 } 00115 } 00116 00117 /* LB2 - LB3 */ 00118 break_before[0] = b_x; 00119 for (i = 0; i < count; i++) 00120 { 00121 switch(break_class[i]) 00122 { 00123 /* LB4 - LB6 */ 00124 case b_CR: 00125 if (i < count-1 && break_class[i+1] == b_LF) 00126 { 00127 else_break(&break_before[i],b_x); 00128 else_break(&break_before[i+1],b_x); 00129 break; 00130 } 00131 case b_LF: 00132 case b_NL: 00133 case b_BK: 00134 if (i < count-1) else_break(&break_before[i+1],b_r); 00135 else_break(&break_before[i],b_x); 00136 break; 00137 /* LB7 */ 00138 case b_SP: 00139 else_break(&break_before[i],b_x); 00140 break; 00141 case b_ZW: 00142 else_break(&break_before[i],b_x); 00143 /* LB8 */ 00144 while (i < count-1 && break_class[i+1] == b_SP) 00145 i++; 00146 else_break(&break_before[i],b_s); 00147 break; 00148 } 00149 } 00150 00151 debug_output_breaks(break_before,count); 00152 00153 /* LB9 - LB10 */ 00154 for (i = 0; i < count; i++) 00155 { 00156 if (break_class[i] == b_CM) 00157 { 00158 if (i > 0) 00159 { 00160 switch (break_class[i-1]) 00161 { 00162 case b_SP: 00163 case b_BK: 00164 case b_CR: 00165 case b_LF: 00166 case b_NL: 00167 case b_ZW: 00168 break_class[i] = b_AL; 00169 break; 00170 default: 00171 break_class[i] = break_class[i-1]; 00172 } 00173 } 00174 else break_class[i] = b_AL; 00175 } 00176 } 00177 00178 for (i = 0; i < count; i++) 00179 { 00180 switch(break_class[i]) 00181 { 00182 /* LB11 */ 00183 case b_WJ: 00184 else_break(&break_before[i],b_x); 00185 if (i < count-1) 00186 else_break(&break_before[i+1],b_x); 00187 break; 00188 /* LB12 */ 00189 case b_GL: 00190 if (i < count-1) 00191 else_break(&break_before[i+1],b_x); 00192 /* LB12a */ 00193 if (i > 0) 00194 { 00195 if (break_class[i-1] != b_SP && 00196 break_class[i-1] != b_BA && 00197 break_class[i-1] != b_HY) 00198 else_break(&break_before[i],b_x); 00199 } 00200 break; 00201 /* LB13 */ 00202 case b_CL: 00203 case b_CP: 00204 case b_EX: 00205 case b_IS: 00206 case b_SY: 00207 else_break(&break_before[i],b_x); 00208 break; 00209 /* LB14 */ 00210 case b_OP: 00211 while (i < count-1 && break_class[i+1] == b_SP) 00212 { 00213 else_break(&break_before[i+1],b_x); 00214 i++; 00215 } 00216 else_break(&break_before[i+1],b_x); 00217 break; 00218 /* LB15 */ 00219 case b_QU: 00220 j = i+1; 00221 while (j < count-1 && break_class[j] == b_SP) 00222 j++; 00223 if (break_class[j] == b_OP) 00224 { 00225 for (; j > i; j--) 00226 else_break(&break_before[j],b_x); 00227 } 00228 break; 00229 /* LB16 */ 00230 case b_NS: 00231 j = i-1; 00232 while(j > 0 && break_class[j] == b_SP) 00233 j--; 00234 if (break_class[j] == b_CL || break_class[j] == b_CP) 00235 { 00236 for (j++; j <= i; j++) 00237 else_break(&break_before[j],b_x); 00238 } 00239 break; 00240 /* LB17 */ 00241 case b_B2: 00242 j = i+1; 00243 while (j < count && break_class[j] == b_SP) 00244 j++; 00245 if (break_class[j] == b_B2) 00246 { 00247 for (; j > i; j--) 00248 else_break(&break_before[j],b_x); 00249 } 00250 break; 00251 } 00252 } 00253 00254 debug_output_breaks(break_before,count); 00255 00256 for (i = 0; i < count; i++) 00257 { 00258 switch(break_class[i]) 00259 { 00260 /* LB18 */ 00261 case b_SP: 00262 if (i < count-1) 00263 else_break(&break_before[i+1],b_s); 00264 break; 00265 /* LB19 */ 00266 case b_QU: 00267 else_break(&break_before[i],b_x); 00268 if (i < count-1) 00269 else_break(&break_before[i+1],b_x); 00270 break; 00271 /* LB20 */ 00272 case b_CB: 00273 else_break(&break_before[i],b_s); 00274 if (i < count-1) 00275 else_break(&break_before[i+1],b_s); 00276 /* LB21 */ 00277 case b_BA: 00278 case b_HY: 00279 case b_NS: 00280 else_break(&break_before[i],b_x); 00281 break; 00282 case b_BB: 00283 if (i < count-1) 00284 else_break(&break_before[i+1],b_x); 00285 break; 00286 /* LB22 */ 00287 case b_IN: 00288 if (i > 0) 00289 { 00290 switch (break_class[i-1]) 00291 { 00292 case b_AL: 00293 case b_ID: 00294 case b_IN: 00295 case b_NU: 00296 else_break(&break_before[i], b_x); 00297 } 00298 } 00299 break; 00300 } 00301 00302 if (i < count-1) 00303 { 00304 /* LB23 */ 00305 if ((break_class[i] == b_ID && break_class[i+1] == b_PO) || 00306 (break_class[i] == b_AL && break_class[i+1] == b_NU) || 00307 (break_class[i] == b_NU && break_class[i+1] == b_AL)) 00308 else_break(&break_before[i+1],b_x); 00309 /* LB24 */ 00310 if ((break_class[i] == b_PR && break_class[i+1] == b_ID) || 00311 (break_class[i] == b_PR && break_class[i+1] == b_AL) || 00312 (break_class[i] == b_PO && break_class[i+1] == b_AL)) 00313 else_break(&break_before[i+1],b_x); 00314 00315 /* LB25 */ 00316 if ((break_class[i] == b_CL && break_class[i+1] == b_PO) || 00317 (break_class[i] == b_CP && break_class[i+1] == b_PO) || 00318 (break_class[i] == b_CL && break_class[i+1] == b_PR) || 00319 (break_class[i] == b_CP && break_class[i+1] == b_PR) || 00320 (break_class[i] == b_NU && break_class[i+1] == b_PO) || 00321 (break_class[i] == b_NU && break_class[i+1] == b_PR) || 00322 (break_class[i] == b_PO && break_class[i+1] == b_OP) || 00323 (break_class[i] == b_PO && break_class[i+1] == b_NU) || 00324 (break_class[i] == b_PR && break_class[i+1] == b_OP) || 00325 (break_class[i] == b_PR && break_class[i+1] == b_NU) || 00326 (break_class[i] == b_HY && break_class[i+1] == b_NU) || 00327 (break_class[i] == b_IS && break_class[i+1] == b_NU) || 00328 (break_class[i] == b_NU && break_class[i+1] == b_NU) || 00329 (break_class[i] == b_SY && break_class[i+1] == b_NU)) 00330 else_break(&break_before[i+1],b_x); 00331 00332 /* LB26 */ 00333 if (break_class[i] == b_JL) 00334 { 00335 switch (break_class[i+1]) 00336 { 00337 case b_JL: 00338 case b_JV: 00339 case b_H2: 00340 case b_H3: 00341 else_break(&break_before[i+1],b_x); 00342 } 00343 } 00344 if ((break_class[i] == b_JV || break_class[i] == b_H2) && 00345 (break_class[i+1] == b_JV || break_class[i+1] == b_JT)) 00346 else_break(&break_before[i+1],b_x); 00347 if ((break_class[i] == b_JT || break_class[i] == b_H3) && 00348 break_class[i+1] == b_JT) 00349 else_break(&break_before[i+1],b_x); 00350 00351 /* LB27 */ 00352 switch (break_class[i]) 00353 { 00354 case b_JL: 00355 case b_JV: 00356 case b_JT: 00357 case b_H2: 00358 case b_H3: 00359 if (break_class[i+1] == b_IN || break_class[i+1] == b_PO) 00360 else_break(&break_before[i+1],b_x); 00361 } 00362 if (break_class[i] == b_PO) 00363 { 00364 switch (break_class[i+1]) 00365 { 00366 case b_JL: 00367 case b_JV: 00368 case b_JT: 00369 case b_H2: 00370 case b_H3: 00371 else_break(&break_before[i+1],b_x); 00372 } 00373 } 00374 00375 /* LB28 */ 00376 if (break_class[i] == b_AL && break_class[i+1] == b_AL) 00377 else_break(&break_before[i+1],b_x); 00378 00379 /* LB29 */ 00380 if (break_class[i] == b_IS && break_class[i+1] == b_AL) 00381 else_break(&break_before[i+1],b_x); 00382 00383 /* LB30 */ 00384 if ((break_class[i] == b_AL || break_class[i] == b_NU) && 00385 break_class[i+1] == b_OP) 00386 else_break(&break_before[i+1],b_x); 00387 if (break_class[i] == b_CP && 00388 (break_class[i+1] == b_AL || break_class[i] == b_NU)) 00389 else_break(&break_before[i+1],b_x); 00390 } 00391 } 00392 debug_output_breaks(break_before,count); 00393 00394 /* LB31 */ 00395 for (i = 0; i < count-1; i++) 00396 else_break(&break_before[i+1],b_s); 00397 00398 debug_output_breaks(break_before,count); 00399 for (i = 0; i < count; i++) 00400 { 00401 if (break_before[i] != b_x) 00402 { 00403 la[i].fSoftBreak = TRUE; 00404 la[i].fWordStop = TRUE; 00405 } 00406 } 00407 00408 HeapFree(GetProcessHeap(), 0, break_before); 00409 HeapFree(GetProcessHeap(), 0, break_class); 00410 } Generated on Sun May 27 2012 04:26:43 for ReactOS by
1.7.6.1
|