ReactOS 0.4.15-dev-7887-g64a59a1
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 "wine/heap.h"
36#include "usp10_internal.h"
37
39
40extern const unsigned short wine_linebreak_table[] DECLSPEC_HIDDEN;
41
46};
47
49
50static void debug_output_breaks(const short* breaks, int count)
51{
52 if (TRACE_ON(uniscribe))
53 {
54 int i;
55 TRACE("[");
56 for (i = 0; i < count && i < 200; i++)
57 {
58 switch (breaks[i])
59 {
60 case b_x: TRACE("x"); break;
61 case b_r: TRACE("!"); break;
62 case b_s: TRACE("+"); break;
63 default: TRACE("*");
64 }
65 }
66 if (i == 200)
67 TRACE("...");
68 TRACE("]\n");
69 }
70}
71
72static inline void else_break(short* before, short class)
73{
74 if (*before == 0) *before = class;
75}
76
77void BREAK_line(const WCHAR *chars, int count, const SCRIPT_ANALYSIS *sa, SCRIPT_LOGATTR *la)
78{
79 int i,j;
80 short *break_class;
81 short *break_before;
82
83 TRACE("In %s\n",debugstr_wn(chars,count));
84
85 break_class = heap_alloc(count * sizeof(*break_class));
86 break_before = heap_alloc(count * sizeof(*break_before));
87
88 for (i = 0; i < count; i++)
89 {
90 break_class[i] = get_table_entry( wine_linebreak_table, chars[i] );
91 break_before[i] = 0;
92
93 memset(&la[i],0,sizeof(SCRIPT_LOGATTR));
94
95 la[i].fCharStop = TRUE;
96 switch (break_class[i])
97 {
98 case b_BK:
99 case b_ZW:
100 case b_SP:
101 la[i].fWhiteSpace = TRUE;
102 break;
103 case b_CM:
104 la[i].fCharStop = FALSE;
105 break;
106 }
107 }
108
109 /* LB1 */
110 /* TODO: Have outside algorithms for these scripts */
111 for (i = 0; i < count; i++)
112 {
113 switch(break_class[i])
114 {
115 case b_AI:
116 case b_SA:
117 case b_SG:
118 case b_XX:
119 break_class[i] = b_AL;
120 break;
121 case b_CJ:
122 break_class[i] = b_NS;
123 break;
124 }
125 }
126
127 /* LB2 - LB3 */
128 break_before[0] = b_x;
129 for (i = 0; i < count; i++)
130 {
131 switch(break_class[i])
132 {
133 /* LB4 - LB6 */
134 case b_CR:
135 if (i < count-1 && break_class[i+1] == b_LF)
136 {
137 else_break(&break_before[i],b_x);
138 else_break(&break_before[i+1],b_x);
139 break;
140 }
141 case b_LF:
142 case b_NL:
143 case b_BK:
144 if (i < count-1) else_break(&break_before[i+1],b_r);
145 else_break(&break_before[i],b_x);
146 break;
147 /* LB7 */
148 case b_SP:
149 else_break(&break_before[i],b_x);
150 break;
151 case b_ZW:
152 else_break(&break_before[i],b_x);
153 /* LB8 */
154 while (i < count-1 && break_class[i+1] == b_SP)
155 i++;
156 else_break(&break_before[i],b_s);
157 break;
158 }
159 }
160
161 debug_output_breaks(break_before,count);
162
163 /* LB9 - LB10 */
164 for (i = 0; i < count; i++)
165 {
166 if (break_class[i] == b_CM)
167 {
168 if (i > 0)
169 {
170 switch (break_class[i-1])
171 {
172 case b_SP:
173 case b_BK:
174 case b_CR:
175 case b_LF:
176 case b_NL:
177 case b_ZW:
178 break_class[i] = b_AL;
179 break;
180 default:
181 break_class[i] = break_class[i-1];
182 }
183 }
184 else break_class[i] = b_AL;
185 }
186 }
187
188 for (i = 0; i < count; i++)
189 {
190 switch(break_class[i])
191 {
192 /* LB11 */
193 case b_WJ:
194 else_break(&break_before[i],b_x);
195 if (i < count-1)
196 else_break(&break_before[i+1],b_x);
197 break;
198 /* LB12 */
199 case b_GL:
200 if (i < count-1)
201 else_break(&break_before[i+1],b_x);
202 /* LB12a */
203 if (i > 0)
204 {
205 if (break_class[i-1] != b_SP &&
206 break_class[i-1] != b_BA &&
207 break_class[i-1] != b_HY)
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_NS:
291 else_break(&break_before[i],b_x);
292 break;
293 case b_BB:
294 if (i < count-1)
295 else_break(&break_before[i+1],b_x);
296 break;
297 /* LB21a */
298 case b_HL:
299 if (i < count-2)
300 switch (break_class[i+1])
301 {
302 case b_HY:
303 case b_BA:
304 else_break(&break_before[i+2], b_x);
305 }
306 break;
307 /* LB22 */
308 case b_IN:
309 if (i > 0)
310 {
311 switch (break_class[i-1])
312 {
313 case b_AL:
314 case b_HL:
315 case b_ID:
316 case b_IN:
317 case b_NU:
318 else_break(&break_before[i], b_x);
319 }
320 }
321 break;
322 }
323
324 if (i < count-1)
325 {
326 /* LB23 */
327 if ((break_class[i] == b_ID && break_class[i+1] == b_PO) ||
328 (break_class[i] == b_AL && break_class[i+1] == b_NU) ||
329 (break_class[i] == b_HL && break_class[i+1] == b_NU) ||
330 (break_class[i] == b_NU && break_class[i+1] == b_AL) ||
331 (break_class[i] == b_NU && break_class[i+1] == b_HL))
332 else_break(&break_before[i+1],b_x);
333 /* LB24 */
334 if ((break_class[i] == b_PR && break_class[i+1] == b_ID) ||
335 (break_class[i] == b_PR && break_class[i+1] == b_AL) ||
336 (break_class[i] == b_PR && break_class[i+1] == b_HL) ||
337 (break_class[i] == b_PO && break_class[i+1] == b_AL) ||
338 (break_class[i] == b_PO && break_class[i+1] == b_HL))
339 else_break(&break_before[i+1],b_x);
340
341 /* LB25 */
342 if ((break_class[i] == b_CL && break_class[i+1] == b_PO) ||
343 (break_class[i] == b_CP && break_class[i+1] == b_PO) ||
344 (break_class[i] == b_CL && break_class[i+1] == b_PR) ||
345 (break_class[i] == b_CP && break_class[i+1] == b_PR) ||
346 (break_class[i] == b_NU && break_class[i+1] == b_PO) ||
347 (break_class[i] == b_NU && break_class[i+1] == b_PR) ||
348 (break_class[i] == b_PO && break_class[i+1] == b_OP) ||
349 (break_class[i] == b_PO && break_class[i+1] == b_NU) ||
350 (break_class[i] == b_PR && break_class[i+1] == b_OP) ||
351 (break_class[i] == b_PR && break_class[i+1] == b_NU) ||
352 (break_class[i] == b_HY && break_class[i+1] == b_NU) ||
353 (break_class[i] == b_IS && break_class[i+1] == b_NU) ||
354 (break_class[i] == b_NU && break_class[i+1] == b_NU) ||
355 (break_class[i] == b_SY && break_class[i+1] == b_NU))
356 else_break(&break_before[i+1],b_x);
357
358 /* LB26 */
359 if (break_class[i] == b_JL)
360 {
361 switch (break_class[i+1])
362 {
363 case b_JL:
364 case b_JV:
365 case b_H2:
366 case b_H3:
367 else_break(&break_before[i+1],b_x);
368 }
369 }
370 if ((break_class[i] == b_JV || break_class[i] == b_H2) &&
371 (break_class[i+1] == b_JV || break_class[i+1] == b_JT))
372 else_break(&break_before[i+1],b_x);
373 if ((break_class[i] == b_JT || break_class[i] == b_H3) &&
374 break_class[i+1] == b_JT)
375 else_break(&break_before[i+1],b_x);
376
377 /* LB27 */
378 switch (break_class[i])
379 {
380 case b_JL:
381 case b_JV:
382 case b_JT:
383 case b_H2:
384 case b_H3:
385 if (break_class[i+1] == b_IN || break_class[i+1] == b_PO)
386 else_break(&break_before[i+1],b_x);
387 }
388 if (break_class[i] == b_PR)
389 {
390 switch (break_class[i+1])
391 {
392 case b_JL:
393 case b_JV:
394 case b_JT:
395 case b_H2:
396 case b_H3:
397 else_break(&break_before[i+1],b_x);
398 }
399 }
400
401 /* LB28 */
402 if ((break_class[i] == b_AL && break_class[i+1] == b_AL) ||
403 (break_class[i] == b_AL && break_class[i+1] == b_HL) ||
404 (break_class[i] == b_HL && break_class[i+1] == b_AL) ||
405 (break_class[i] == b_HL && break_class[i+1] == b_HL))
406 else_break(&break_before[i+1],b_x);
407
408 /* LB29 */
409 if ((break_class[i] == b_IS && break_class[i+1] == b_AL) ||
410 (break_class[i] == b_IS && break_class[i+1] == b_HL))
411 else_break(&break_before[i+1],b_x);
412
413 /* LB30 */
414 if ((break_class[i] == b_AL || break_class[i] == b_HL || break_class[i] == b_NU) &&
415 break_class[i+1] == b_OP)
416 else_break(&break_before[i+1],b_x);
417 if (break_class[i] == b_CP &&
418 (break_class[i+1] == b_AL || break_class[i+1] == b_HL || break_class[i+1] == b_NU))
419 else_break(&break_before[i+1],b_x);
420
421 /* LB30a */
422 if (break_class[i] == b_RI && break_class[i+1] == b_RI)
423 else_break(&break_before[i+1],b_x);
424 }
425 }
426 debug_output_breaks(break_before,count);
427
428 /* LB31 */
429 for (i = 0; i < count-1; i++)
430 else_break(&break_before[i+1],b_s);
431
432 debug_output_breaks(break_before,count);
433 for (i = 0; i < count; i++)
434 {
435 if (break_before[i] != b_x)
436 {
437 la[i].fSoftBreak = TRUE;
438 la[i].fWordStop = TRUE;
439 }
440 }
441
442 heap_free(break_before);
443 heap_free(break_class);
444}
static unsigned short get_table_entry(const unsigned short *table, WCHAR ch)
Definition: IdnToAscii.c:32
static struct sockaddr_in sa
Definition: adnsresfilter.c:69
static void * heap_alloc(size_t len)
Definition: appwiz.h:66
static BOOL heap_free(void *mem)
Definition: appwiz.h:76
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
static void else_break(short *before, short class)
Definition: breaking.c:72
static void debug_output_breaks(const short *breaks, int count)
Definition: breaking.c:50
const unsigned short wine_linebreak_table[] DECLSPEC_HIDDEN
breaking_class
Definition: breaking.c:48
@ b_s
Definition: breaking.c:48
@ b_r
Definition: breaking.c:48
@ b_x
Definition: breaking.c:48
void BREAK_line(const WCHAR *chars, int count, const SCRIPT_ANALYSIS *sa, SCRIPT_LOGATTR *la)
Definition: breaking.c:77
breaking_types
Definition: breaking.c:42
@ b_H2
Definition: breaking.c:43
@ b_IS
Definition: breaking.c:44
@ b_JL
Definition: breaking.c:43
@ b_CB
Definition: breaking.c:43
@ b_OP
Definition: breaking.c:43
@ b_CJ
Definition: breaking.c:45
@ b_ID
Definition: breaking.c:44
@ b_QU
Definition: breaking.c:44
@ b_HY
Definition: breaking.c:44
@ b_SY
Definition: breaking.c:44
@ b_NL
Definition: breaking.c:43
@ b_WJ
Definition: breaking.c:43
@ b_EX
Definition: breaking.c:44
@ b_BB
Definition: breaking.c:44
@ b_XX
Definition: breaking.c:43
@ b_HL
Definition: breaking.c:44
@ b_PO
Definition: breaking.c:44
@ b_ZW
Definition: breaking.c:43
@ b_JT
Definition: breaking.c:43
@ b_LF
Definition: breaking.c:43
@ b_CL
Definition: breaking.c:43
@ b_GL
Definition: breaking.c:43
@ b_PR
Definition: breaking.c:44
@ b_ZWJ
Definition: breaking.c:45
@ b_CM
Definition: breaking.c:43
@ b_RI
Definition: breaking.c:45
@ b_BA
Definition: breaking.c:44
@ b_JV
Definition: breaking.c:43
@ b_BK
Definition: breaking.c:43
@ b_CP
Definition: breaking.c:44
@ b_CR
Definition: breaking.c:43
@ b_EM
Definition: breaking.c:45
@ b_AI
Definition: breaking.c:44
@ b_NU
Definition: breaking.c:44
@ b_SA
Definition: breaking.c:44
@ b_H3
Definition: breaking.c:43
@ b_SG
Definition: breaking.c:43
@ b_AL
Definition: breaking.c:44
@ b_NS
Definition: breaking.c:44
@ b_SP
Definition: breaking.c:43
@ b_B2
Definition: breaking.c:44
@ b_EB
Definition: breaking.c:45
@ b_IN
Definition: breaking.c:44
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define TRACE_ON(x)
Definition: compat.h:75
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
const unsigned short DECLSPEC_HIDDEN wine_linebreak_table[7216]
Definition: linebreak.c:7
#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
__wchar_t WCHAR
Definition: xmlstorage.h:180