ReactOS 0.4.17-dev-966-gf06eace
breaking.c
Go to the documentation of this file.
1/*
2 * Implementation of line breaking algorithm 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
39extern const unsigned short wine_linebreak_table[];
40
45};
46
48
49static void debug_output_breaks(const short* breaks, int count)
50{
51 if (TRACE_ON(uniscribe))
52 {
53 int i;
54 TRACE("[");
55 for (i = 0; i < count && i < 200; i++)
56 {
57 switch (breaks[i])
58 {
59 case b_x: TRACE("x"); break;
60 case b_r: TRACE("!"); break;
61 case b_s: TRACE("+"); break;
62 default: TRACE("*");
63 }
64 }
65 if (i == 200)
66 TRACE("...");
67 TRACE("]\n");
68 }
69}
70
71static inline void else_break(short* before, short class)
72{
73 if (*before == 0) *before = class;
74}
75
76void BREAK_line(const WCHAR *chars, int count, const SCRIPT_ANALYSIS *sa, SCRIPT_LOGATTR *la)
77{
78 int i,j;
79 short *break_class;
80 short *break_before;
81
82 TRACE("In %s\n",debugstr_wn(chars,count));
83
84 break_class = malloc(count * sizeof(*break_class));
85 break_before = malloc(count * sizeof(*break_before));
86
87 for (i = 0; i < count; i++)
88 {
89 break_class[i] = get_table_entry_32( wine_linebreak_table, chars[i] );
90 break_before[i] = 0;
91
92 memset(&la[i],0,sizeof(SCRIPT_LOGATTR));
93
94 la[i].fCharStop = TRUE;
95 switch (break_class[i])
96 {
97 case b_BK:
98 case b_ZW:
99 case b_SP:
100 la[i].fWhiteSpace = TRUE;
101 break;
102 case b_CM:
103 la[i].fCharStop = FALSE;
104 break;
105 }
106 }
107
108 /* LB1 */
109 /* TODO: Have outside algorithms for these scripts */
110 for (i = 0; i < count; i++)
111 {
112 switch(break_class[i])
113 {
114 case b_AI:
115 case b_SA:
116 case b_SG:
117 case b_XX:
118 break_class[i] = b_AL;
119 break;
120 case b_CJ:
121 break_class[i] = b_NS;
122 break;
123 }
124 }
125
126 /* LB2 - LB3 */
127 break_before[0] = b_x;
128 for (i = 0; i < count; i++)
129 {
130 switch(break_class[i])
131 {
132 /* LB4 - LB6 */
133 case b_CR:
134 if (i < count-1 && break_class[i+1] == b_LF)
135 {
136 else_break(&break_before[i],b_x);
137 else_break(&break_before[i+1],b_x);
138 break;
139 }
140 case b_LF:
141 case b_NL:
142 case b_BK:
143 if (i < count-1) else_break(&break_before[i+1],b_r);
144 else_break(&break_before[i],b_x);
145 break;
146 /* LB7 */
147 case b_SP:
148 else_break(&break_before[i],b_x);
149 break;
150 case b_ZW:
151 else_break(&break_before[i],b_x);
152 /* LB8 */
153 while (i < count-1 && break_class[i+1] == b_SP)
154 i++;
155 else_break(&break_before[i],b_s);
156 break;
157 }
158 }
159
160 debug_output_breaks(break_before,count);
161
162 /* LB9 - LB10 */
163 for (i = 0; i < count; i++)
164 {
165 if (break_class[i] == b_CM)
166 {
167 if (i > 0)
168 {
169 switch (break_class[i-1])
170 {
171 case b_SP:
172 case b_BK:
173 case b_CR:
174 case b_LF:
175 case b_NL:
176 case b_ZW:
177 break_class[i] = b_AL;
178 break;
179 default:
180 break_class[i] = break_class[i-1];
181 }
182 }
183 else break_class[i] = b_AL;
184 }
185 }
186
187 for (i = 0; i < count; i++)
188 {
189 switch(break_class[i])
190 {
191 /* LB11 */
192 case b_WJ:
193 else_break(&break_before[i],b_x);
194 if (i < count-1)
195 else_break(&break_before[i+1],b_x);
196 break;
197 /* LB12 */
198 case b_GL:
199 if (i < count-1)
200 else_break(&break_before[i+1],b_x);
201 /* LB12a */
202 if (i > 0)
203 {
204 if (break_class[i-1] != b_SP &&
205 break_class[i-1] != b_BA &&
206 break_class[i-1] != b_HY &&
207 break_class[i-1] != b_HH)
208 else_break(&break_before[i],b_x);
209 }
210 break;
211 /* LB13 */
212 case b_CL:
213 case b_CP:
214 case b_EX:
215 case b_IS:
216 case b_SY:
217 else_break(&break_before[i],b_x);
218 break;
219 /* LB14 */
220 case b_OP:
221 while (i < count-1 && break_class[i+1] == b_SP)
222 {
223 else_break(&break_before[i+1],b_x);
224 i++;
225 }
226 else_break(&break_before[i+1],b_x);
227 break;
228 /* LB15 */
229 case b_QU:
230 j = i+1;
231 while (j < count-1 && break_class[j] == b_SP)
232 j++;
233 if (break_class[j] == b_OP)
234 {
235 for (; j > i; j--)
236 else_break(&break_before[j],b_x);
237 }
238 break;
239 /* LB16 */
240 case b_NS:
241 j = i-1;
242 while(j > 0 && break_class[j] == b_SP)
243 j--;
244 if (break_class[j] == b_CL || break_class[j] == b_CP)
245 {
246 for (j++; j <= i; j++)
247 else_break(&break_before[j],b_x);
248 }
249 break;
250 /* LB17 */
251 case b_B2:
252 j = i+1;
253 while (j < count && break_class[j] == b_SP)
254 j++;
255 if (break_class[j] == b_B2)
256 {
257 for (; j > i; j--)
258 else_break(&break_before[j],b_x);
259 }
260 break;
261 }
262 }
263
264 debug_output_breaks(break_before,count);
265
266 for (i = 0; i < count; i++)
267 {
268 switch(break_class[i])
269 {
270 /* LB18 */
271 case b_SP:
272 if (i < count-1)
273 else_break(&break_before[i+1],b_s);
274 break;
275 /* LB19 */
276 case b_QU:
277 else_break(&break_before[i],b_x);
278 if (i < count-1)
279 else_break(&break_before[i+1],b_x);
280 break;
281 /* LB20 */
282 case b_CB:
283 else_break(&break_before[i],b_s);
284 if (i < count-1)
285 else_break(&break_before[i+1],b_s);
286 break;
287 /* LB21 */
288 case b_BA:
289 case b_HY:
290 case b_HH:
291 case b_NS:
292 else_break(&break_before[i],b_x);
293 break;
294 case b_BB:
295 if (i < count-1)
296 else_break(&break_before[i+1],b_x);
297 break;
298 /* LB21a */
299 case b_HL:
300 if (i < count-2)
301 switch (break_class[i+1])
302 {
303 case b_HY:
304 case b_HH:
305 case b_BA:
306 else_break(&break_before[i+2], b_x);
307 }
308 break;
309 /* LB22 */
310 case b_IN:
311 if (i > 0)
312 {
313 switch (break_class[i-1])
314 {
315 case b_AL:
316 case b_HL:
317 case b_ID:
318 case b_IN:
319 case b_NU:
320 else_break(&break_before[i], b_x);
321 }
322 }
323 break;
324 }
325
326 if (i < count-1)
327 {
328 /* LB23 */
329 if ((break_class[i] == b_ID && break_class[i+1] == b_PO) ||
330 (break_class[i] == b_AL && break_class[i+1] == b_NU) ||
331 (break_class[i] == b_HL && break_class[i+1] == b_NU) ||
332 (break_class[i] == b_NU && break_class[i+1] == b_AL) ||
333 (break_class[i] == b_NU && break_class[i+1] == b_HL))
334 else_break(&break_before[i+1],b_x);
335 /* LB24 */
336 if ((break_class[i] == b_PR && break_class[i+1] == b_ID) ||
337 (break_class[i] == b_PR && break_class[i+1] == b_AL) ||
338 (break_class[i] == b_PR && break_class[i+1] == b_HL) ||
339 (break_class[i] == b_PO && break_class[i+1] == b_AL) ||
340 (break_class[i] == b_PO && break_class[i+1] == b_HL))
341 else_break(&break_before[i+1],b_x);
342
343 /* LB25 */
344 if ((break_class[i] == b_CL && break_class[i+1] == b_PO) ||
345 (break_class[i] == b_CP && break_class[i+1] == b_PO) ||
346 (break_class[i] == b_CL && break_class[i+1] == b_PR) ||
347 (break_class[i] == b_CP && break_class[i+1] == b_PR) ||
348 (break_class[i] == b_NU && break_class[i+1] == b_PO) ||
349 (break_class[i] == b_NU && break_class[i+1] == b_PR) ||
350 (break_class[i] == b_PO && break_class[i+1] == b_OP) ||
351 (break_class[i] == b_PO && break_class[i+1] == b_NU) ||
352 (break_class[i] == b_PR && break_class[i+1] == b_OP) ||
353 (break_class[i] == b_PR && break_class[i+1] == b_NU) ||
354 (break_class[i] == b_HY && break_class[i+1] == b_NU) ||
355 (break_class[i] == b_IS && break_class[i+1] == b_NU) ||
356 (break_class[i] == b_NU && break_class[i+1] == b_NU) ||
357 (break_class[i] == b_SY && break_class[i+1] == b_NU))
358 else_break(&break_before[i+1],b_x);
359
360 /* LB26 */
361 if (break_class[i] == b_JL)
362 {
363 switch (break_class[i+1])
364 {
365 case b_JL:
366 case b_JV:
367 case b_H2:
368 case b_H3:
369 else_break(&break_before[i+1],b_x);
370 }
371 }
372 if ((break_class[i] == b_JV || break_class[i] == b_H2) &&
373 (break_class[i+1] == b_JV || break_class[i+1] == b_JT))
374 else_break(&break_before[i+1],b_x);
375 if ((break_class[i] == b_JT || break_class[i] == b_H3) &&
376 break_class[i+1] == b_JT)
377 else_break(&break_before[i+1],b_x);
378
379 /* LB27 */
380 switch (break_class[i])
381 {
382 case b_JL:
383 case b_JV:
384 case b_JT:
385 case b_H2:
386 case b_H3:
387 if (break_class[i+1] == b_IN || break_class[i+1] == b_PO)
388 else_break(&break_before[i+1],b_x);
389 }
390 if (break_class[i] == b_PR)
391 {
392 switch (break_class[i+1])
393 {
394 case b_JL:
395 case b_JV:
396 case b_JT:
397 case b_H2:
398 case b_H3:
399 else_break(&break_before[i+1],b_x);
400 }
401 }
402
403 /* LB28 */
404 if ((break_class[i] == b_AL && break_class[i+1] == b_AL) ||
405 (break_class[i] == b_AL && break_class[i+1] == b_HL) ||
406 (break_class[i] == b_HL && break_class[i+1] == b_AL) ||
407 (break_class[i] == b_HL && break_class[i+1] == b_HL))
408 else_break(&break_before[i+1],b_x);
409
410 /* LB29 */
411 if ((break_class[i] == b_IS && break_class[i+1] == b_AL) ||
412 (break_class[i] == b_IS && break_class[i+1] == b_HL))
413 else_break(&break_before[i+1],b_x);
414
415 /* LB30 */
416 if ((break_class[i] == b_AL || break_class[i] == b_HL || break_class[i] == b_NU) &&
417 break_class[i+1] == b_OP)
418 else_break(&break_before[i+1],b_x);
419 if (break_class[i] == b_CP &&
420 (break_class[i+1] == b_AL || break_class[i+1] == b_HL || break_class[i+1] == b_NU))
421 else_break(&break_before[i+1],b_x);
422
423 /* LB30a */
424 if (break_class[i] == b_RI && break_class[i+1] == b_RI)
425 else_break(&break_before[i+1],b_x);
426 }
427 }
428 debug_output_breaks(break_before,count);
429
430 /* LB31 */
431 for (i = 0; i < count-1; i++)
432 else_break(&break_before[i+1],b_s);
433
434 debug_output_breaks(break_before,count);
435 for (i = 0; i < count; i++)
436 {
437 if (break_before[i] != b_x)
438 {
439 la[i].fSoftBreak = TRUE;
440 la[i].fWordStop = TRUE;
441 }
442 }
443
444 free(break_before);
445 free(break_class);
446}
static struct sockaddr_in sa
Definition: adnsresfilter.c:69
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
static void else_break(short *before, short class)
Definition: breaking.c:71
static void debug_output_breaks(const short *breaks, int count)
Definition: breaking.c:49
breaking_class
Definition: breaking.c:47
@ b_s
Definition: breaking.c:47
@ b_r
Definition: breaking.c:47
@ b_x
Definition: breaking.c:47
void BREAK_line(const WCHAR *chars, int count, const SCRIPT_ANALYSIS *sa, SCRIPT_LOGATTR *la)
Definition: breaking.c:76
const unsigned short wine_linebreak_table[]
Definition: linebreak.c:7
breaking_types
Definition: breaking.c:41
@ b_H2
Definition: breaking.c:42
@ b_IS
Definition: breaking.c:43
@ b_JL
Definition: breaking.c:42
@ b_CB
Definition: breaking.c:42
@ b_OP
Definition: breaking.c:42
@ b_CJ
Definition: breaking.c:44
@ b_ID
Definition: breaking.c:43
@ b_QU
Definition: breaking.c:43
@ b_HY
Definition: breaking.c:43
@ b_AS
Definition: breaking.c:44
@ b_SY
Definition: breaking.c:43
@ b_NL
Definition: breaking.c:42
@ b_WJ
Definition: breaking.c:42
@ b_EX
Definition: breaking.c:43
@ b_BB
Definition: breaking.c:43
@ b_XX
Definition: breaking.c:42
@ b_HL
Definition: breaking.c:43
@ b_PO
Definition: breaking.c:43
@ b_ZW
Definition: breaking.c:42
@ b_JT
Definition: breaking.c:42
@ b_LF
Definition: breaking.c:42
@ b_CL
Definition: breaking.c:42
@ b_GL
Definition: breaking.c:42
@ b_HH
Definition: breaking.c:44
@ b_PR
Definition: breaking.c:43
@ b_ZWJ
Definition: breaking.c:44
@ b_CM
Definition: breaking.c:42
@ b_VI
Definition: breaking.c:44
@ b_RI
Definition: breaking.c:44
@ b_BA
Definition: breaking.c:43
@ b_JV
Definition: breaking.c:42
@ b_VF
Definition: breaking.c:44
@ b_AP
Definition: breaking.c:44
@ b_BK
Definition: breaking.c:42
@ b_CP
Definition: breaking.c:43
@ b_CR
Definition: breaking.c:42
@ b_EM
Definition: breaking.c:44
@ b_AI
Definition: breaking.c:43
@ b_NU
Definition: breaking.c:43
@ b_SA
Definition: breaking.c:43
@ b_H3
Definition: breaking.c:42
@ b_AK
Definition: breaking.c:44
@ b_SG
Definition: breaking.c:42
@ b_AL
Definition: breaking.c:43
@ b_NS
Definition: breaking.c:43
@ b_SP
Definition: breaking.c:42
@ b_B2
Definition: breaking.c:43
@ b_EB
Definition: breaking.c:44
@ b_IN
Definition: breaking.c:43
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define TRACE_ON(x)
Definition: compat.h:75
static unsigned short get_table_entry_32(const unsigned short *table, UINT ch)
GLuint GLuint GLsizei count
Definition: gl.h:1545
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
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 GLint GLint j
Definition: glfuncs.h:250
#define debugstr_wn
Definition: kernel32.h:33
short WCHAR
Definition: pedump.c:58
#define memset(x, y, z)
Definition: compat.h:39
#define TRACE(s)
Definition: solgame.cpp:4
BYTE fWhiteSpace
Definition: usp10.h:188
__inline int before(__u32 seq1, __u32 seq2)
Definition: tcpcore.h:2390