Lines 12-17
Link Here
|
12 |
|
12 |
|
13 |
import org.eclipse.equinox.bidi.STextEngine; |
13 |
import org.eclipse.equinox.bidi.STextEngine; |
14 |
import org.eclipse.equinox.bidi.STextEnvironment; |
14 |
import org.eclipse.equinox.bidi.STextEnvironment; |
|
|
15 |
import org.eclipse.equinox.bidi.custom.STextDirections; |
15 |
import org.eclipse.equinox.bidi.custom.STextProcessor; |
16 |
import org.eclipse.equinox.bidi.custom.STextProcessor; |
16 |
|
17 |
|
17 |
/** |
18 |
/** |
Lines 25-36
Link Here
|
25 |
public class STextImpl { |
26 |
public class STextImpl { |
26 |
|
27 |
|
27 |
static final String EMPTY_STRING = ""; //$NON-NLS-1$ |
28 |
static final String EMPTY_STRING = ""; //$NON-NLS-1$ |
|
|
29 |
|
30 |
// In the following lines, B, L, R and AL represent bidi categories |
31 |
// as defined in the Unicode Bidirectional Algorithm |
32 |
// ( http://www.unicode.org/reports/tr9/ ). |
33 |
// B represents the category Block Separator. |
34 |
// L represents the category Left to Right character. |
35 |
// R represents the category Right to Left character. |
36 |
// AL represents the category Arabic Letter. |
37 |
// AN represents the category Arabic Number. |
38 |
// EN represents the category European Number. |
28 |
static final byte B = Character.DIRECTIONALITY_PARAGRAPH_SEPARATOR; |
39 |
static final byte B = Character.DIRECTIONALITY_PARAGRAPH_SEPARATOR; |
29 |
static final byte L = Character.DIRECTIONALITY_LEFT_TO_RIGHT; |
40 |
static final byte L = Character.DIRECTIONALITY_LEFT_TO_RIGHT; |
30 |
static final byte R = Character.DIRECTIONALITY_RIGHT_TO_LEFT; |
41 |
static final byte R = Character.DIRECTIONALITY_RIGHT_TO_LEFT; |
31 |
static final byte AL = Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC; |
42 |
static final byte AL = Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC; |
32 |
static final byte AN = Character.DIRECTIONALITY_ARABIC_NUMBER; |
43 |
static final byte AN = Character.DIRECTIONALITY_ARABIC_NUMBER; |
33 |
static final byte EN = Character.DIRECTIONALITY_EUROPEAN_NUMBER; |
44 |
static final byte EN = Character.DIRECTIONALITY_EUROPEAN_NUMBER; |
|
|
45 |
|
34 |
static final char LRM = 0x200E; |
46 |
static final char LRM = 0x200E; |
35 |
static final char RLM = 0x200F; |
47 |
static final char RLM = 0x200F; |
36 |
static final char LRE = 0x202A; |
48 |
static final char LRE = 0x202A; |
Lines 42-48
Link Here
|
42 |
static final int PREFIX_LENGTH = 2; |
54 |
static final int PREFIX_LENGTH = 2; |
43 |
static final int SUFFIX_LENGTH = 2; |
55 |
static final int SUFFIX_LENGTH = 2; |
44 |
static final int FIXES_LENGTH = PREFIX_LENGTH + SUFFIX_LENGTH; |
56 |
static final int FIXES_LENGTH = PREFIX_LENGTH + SUFFIX_LENGTH; |
45 |
static final int DIRPROPS_ADD = 2; |
|
|
46 |
static final int OFFSETS_SHIFT = 3; |
57 |
static final int OFFSETS_SHIFT = 3; |
47 |
static final int[] EMPTY_INT_ARRAY = new int[0]; |
58 |
static final int[] EMPTY_INT_ARRAY = new int[0]; |
48 |
static final STextEnvironment IGNORE_ENVIRONMENT = new STextEnvironment(null, false, STextEnvironment.ORIENT_IGNORE); |
59 |
static final STextEnvironment IGNORE_ENVIRONMENT = new STextEnvironment(null, false, STextEnvironment.ORIENT_IGNORE); |
Lines 54-60
Link Here
|
54 |
// nothing to do |
65 |
// nothing to do |
55 |
} |
66 |
} |
56 |
|
67 |
|
57 |
static long computeNextLocation(STextProcessor processor, STextEnvironment environment, String text, byte[] dirProps, int[] offsets, int[] locations, int[] state, int curPos) { |
68 |
static long computeNextLocation(STextProcessor processor, STextEnvironment environment, String text, STextDirections dirProps, int[] offsets, int[] locations, int[] state, int curPos) { |
58 |
String separators = processor.getSeparators(environment, text, dirProps); |
69 |
String separators = processor.getSeparators(environment, text, dirProps); |
59 |
int separCount = separators.length(); |
70 |
int separCount = separators.length(); |
60 |
int specialsCount = processor.getSpecialsCount(environment, text, dirProps); |
71 |
int specialsCount = processor.getSpecialsCount(environment, text, dirProps); |
Lines 91-197
Link Here
|
91 |
} |
102 |
} |
92 |
} |
103 |
} |
93 |
return nextLocation + (((long) idxLocation) << 32); |
104 |
return nextLocation + (((long) idxLocation) << 32); |
94 |
} |
|
|
95 |
|
96 |
static int getCurOrient(STextEnvironment environment, String text, byte[] dirProps) { |
97 |
int orient = environment.getOrientation(); |
98 |
if ((orient & STextEnvironment.ORIENT_CONTEXTUAL_LTR) == 0) { |
99 |
// absolute orientation |
100 |
return orient; |
101 |
} |
102 |
// contextual orientation |
103 |
int len = text.length(); |
104 |
byte dirProp; |
105 |
for (int i = 0; i < len; i++) { |
106 |
// In the following lines, B, L, R and AL represent bidi categories |
107 |
// as defined in the Unicode Bidirectional Algorithm |
108 |
// ( http://www.unicode.org/reports/tr9/ ). |
109 |
// B represents the category Block Separator. |
110 |
// L represents the category Left to Right character. |
111 |
// R represents the category Right to Left character. |
112 |
// AL represents the category Arabic Letter. |
113 |
dirProp = dirProps[i]; |
114 |
if (dirProp == 0) { |
115 |
dirProp = Character.getDirectionality(text.charAt(i)); |
116 |
if (dirProp == B) // B char resolves to L or R depending on orientation |
117 |
continue; |
118 |
dirProps[i] = (byte) (dirProp + DIRPROPS_ADD); |
119 |
} else { |
120 |
dirProp -= DIRPROPS_ADD; |
121 |
} |
122 |
if (dirProp == L) |
123 |
return STextEnvironment.ORIENT_LTR; |
124 |
if (dirProp == R || dirProp == AL) |
125 |
return STextEnvironment.ORIENT_RTL; |
126 |
} |
127 |
// return the default orientation corresponding to the contextual orientation |
128 |
return orient & 1; |
129 |
} |
130 |
|
131 |
/** |
132 |
* @see STextEngine#getCurDirection STextEngine.getCurDirection |
133 |
*/ |
134 |
public static int getCurDirection(STextProcessor processor, STextEnvironment environment, String text, byte[] dirProps) { |
135 |
return processor.getDirection(environment, text, dirProps); |
136 |
} |
137 |
|
138 |
/** |
139 |
* @see STextProcessor#getDirProp STextProcessor.getDirProp |
140 |
*/ |
141 |
public static byte getDirProp(String text, byte[] dirProps, int index) { |
142 |
byte dirProp = dirProps == null ? 0 : dirProps[index]; |
143 |
if (dirProp == 0) { |
144 |
// In the following lines, B, L and R represent bidi categories |
145 |
// as defined in the Unicode Bidirectional Algorithm |
146 |
// ( http://www.unicode.org/reports/tr9/ ). |
147 |
// B represents the category Block Separator. |
148 |
// L represents the category Left to Right character. |
149 |
// R represents the category Right to Left character. |
150 |
dirProp = Character.getDirectionality(text.charAt(index)); |
151 |
if (dirProp == B && dirProps != null) { |
152 |
// the last entry of dirProps contains the current component orientation |
153 |
byte orient = dirProps[dirProps.length - 1]; |
154 |
if (orient == -1) |
155 |
return B; |
156 |
dirProp = orient == STextEnvironment.ORIENT_RTL ? R : L; |
157 |
} |
158 |
if (dirProps != null) |
159 |
dirProps[index] = (byte) (dirProp + DIRPROPS_ADD); |
160 |
return dirProp; |
161 |
} |
162 |
return (byte) (dirProp - DIRPROPS_ADD); |
163 |
} |
164 |
|
165 |
/** |
166 |
* @see STextProcessor#setDirProp STextProcessor.setDirProp |
167 |
*/ |
168 |
public static void setDirProp(byte[] dirProps, int index, byte dirProp) { |
169 |
dirProps[index] = (byte) (dirProp + DIRPROPS_ADD); |
170 |
} |
105 |
} |
171 |
|
106 |
|
172 |
/** |
107 |
/** |
173 |
* @see STextProcessor#processSeparator STextProcessor.processSeparator |
108 |
* @see STextProcessor#processSeparator STextProcessor.processSeparator |
174 |
*/ |
109 |
*/ |
175 |
public static void processSeparator(String text, byte[] dirProps, int[] offsets, int separLocation) { |
110 |
public static void processSeparator(String text, STextDirections dirProps, int[] offsets, int separLocation) { |
176 |
// In this method, L, R, AL, AN and EN represent bidi categories |
|
|
177 |
// as defined in the Unicode Bidirectional Algorithm |
178 |
// ( http://www.unicode.org/reports/tr9/ ). |
179 |
// L represents the category Left to Right character. |
180 |
// R represents the category Right to Left character. |
181 |
// AL represents the category Arabic Letter. |
182 |
// AN represents the category Arabic Number. |
183 |
// EN represents the category European Number. |
184 |
int len = text.length(); |
111 |
int len = text.length(); |
185 |
// offsets[2] contains the structured text direction |
112 |
// offsets[2] contains the structured text direction |
186 |
if (offsets[2] == STextEngine.DIR_RTL) { |
113 |
if (offsets[2] == STextEngine.DIR_RTL) { |
187 |
// the structured text base direction is RTL |
114 |
// the structured text base direction is RTL |
188 |
for (int i = separLocation - 1; i >= 0; i--) { |
115 |
for (int i = separLocation - 1; i >= 0; i--) { |
189 |
byte dirProp = getDirProp(text, dirProps, i); |
116 |
byte dirProp = dirProps.getOrientationAt(i); |
190 |
if (dirProp == R || dirProp == AL) |
117 |
if (dirProp == R || dirProp == AL) |
191 |
return; |
118 |
return; |
192 |
if (dirProp == L) { |
119 |
if (dirProp == L) { |
193 |
for (int j = separLocation; j < len; j++) { |
120 |
for (int j = separLocation; j < len; j++) { |
194 |
dirProp = getDirProp(text, dirProps, j); |
121 |
dirProp = dirProps.getOrientationAt(j); |
195 |
if (dirProp == R || dirProp == AL) |
122 |
if (dirProp == R || dirProp == AL) |
196 |
return; |
123 |
return; |
197 |
if (dirProp == L || dirProp == EN) { |
124 |
if (dirProp == L || dirProp == EN) { |
Lines 208-219
Link Here
|
208 |
// the structured text base direction is LTR |
135 |
// the structured text base direction is LTR |
209 |
boolean doneAN = false; |
136 |
boolean doneAN = false; |
210 |
for (int i = separLocation - 1; i >= 0; i--) { |
137 |
for (int i = separLocation - 1; i >= 0; i--) { |
211 |
byte dirProp = getDirProp(text, dirProps, i); |
138 |
byte dirProp = dirProps.getOrientationAt(i); |
212 |
if (dirProp == L) |
139 |
if (dirProp == L) |
213 |
return; |
140 |
return; |
214 |
if (dirProp == R || dirProp == AL) { |
141 |
if (dirProp == R || dirProp == AL) { |
215 |
for (int j = separLocation; j < len; j++) { |
142 |
for (int j = separLocation; j < len; j++) { |
216 |
dirProp = getDirProp(text, dirProps, j); |
143 |
dirProp = dirProps.getOrientationAt(j); |
217 |
if (dirProp == L) |
144 |
if (dirProp == L) |
218 |
return; |
145 |
return; |
219 |
if (dirProp == R || dirProp == EN || dirProp == AL || dirProp == AN) { |
146 |
if (dirProp == R || dirProp == EN || dirProp == AL || dirProp == AN) { |
Lines 225-231
Link Here
|
225 |
} |
152 |
} |
226 |
if (dirProp == AN && !doneAN) { |
153 |
if (dirProp == AN && !doneAN) { |
227 |
for (int j = separLocation; j < len; j++) { |
154 |
for (int j = separLocation; j < len; j++) { |
228 |
dirProp = getDirProp(text, dirProps, j); |
155 |
dirProp = dirProps.getOrientationAt(j); |
229 |
if (dirProp == L) |
156 |
if (dirProp == L) |
230 |
return; |
157 |
return; |
231 |
if (dirProp == AL || dirProp == AN || dirProp == R) { |
158 |
if (dirProp == AL || dirProp == AN || dirProp == R) { |
Lines 285-291
Link Here
|
285 |
int len = text.length(); |
212 |
int len = text.length(); |
286 |
if (len == 0) |
213 |
if (len == 0) |
287 |
return text; |
214 |
return text; |
288 |
byte[] dirProps = new byte[len + 1]; |
215 |
STextDirections dirProps = new STextDirections(text); |
289 |
int[] offsets = leanToFullCommon(processor, environment, text, state, dirProps); |
216 |
int[] offsets = leanToFullCommon(processor, environment, text, state, dirProps); |
290 |
int prefixLength = offsets[1]; |
217 |
int prefixLength = offsets[1]; |
291 |
int count = offsets[0] - OFFSETS_SHIFT; |
218 |
int count = offsets[0] - OFFSETS_SHIFT; |
Lines 336-342
Link Here
|
336 |
int len = text.length(); |
263 |
int len = text.length(); |
337 |
if (len == 0) |
264 |
if (len == 0) |
338 |
return EMPTY_INT_ARRAY; |
265 |
return EMPTY_INT_ARRAY; |
339 |
byte[] dirProps = new byte[len + 1]; |
266 |
STextDirections dirProps = new STextDirections(text); |
340 |
int[] offsets = leanToFullCommon(processor, environment, text, state, dirProps); |
267 |
int[] offsets = leanToFullCommon(processor, environment, text, state, dirProps); |
341 |
int prefixLength = offsets[1]; |
268 |
int prefixLength = offsets[1]; |
342 |
int[] map = new int[len]; |
269 |
int[] map = new int[len]; |
Lines 359-365
Link Here
|
359 |
int len = text.length(); |
286 |
int len = text.length(); |
360 |
if (len == 0) |
287 |
if (len == 0) |
361 |
return EMPTY_INT_ARRAY; |
288 |
return EMPTY_INT_ARRAY; |
362 |
byte[] dirProps = new byte[len + 1]; |
289 |
STextDirections dirProps = new STextDirections(text); |
363 |
int[] offsets = leanToFullCommon(processor, environment, text, state, dirProps); |
290 |
int[] offsets = leanToFullCommon(processor, environment, text, state, dirProps); |
364 |
// offsets[0] contains the number of used entries |
291 |
// offsets[0] contains the number of used entries |
365 |
int count = offsets[0] - OFFSETS_SHIFT; |
292 |
int count = offsets[0] - OFFSETS_SHIFT; |
Lines 368-374
Link Here
|
368 |
return result; |
295 |
return result; |
369 |
} |
296 |
} |
370 |
|
297 |
|
371 |
static int[] leanToFullCommon(STextProcessor processor, STextEnvironment environment, String text, int[] state, byte[] dirProps) { |
298 |
static int[] leanToFullCommon(STextProcessor processor, STextEnvironment environment, String text, int[] state, STextDirections dirProps) { |
372 |
if (environment == null) |
299 |
if (environment == null) |
373 |
environment = STextEnvironment.DEFAULT; |
300 |
environment = STextEnvironment.DEFAULT; |
374 |
if (state == null) { |
301 |
if (state == null) { |
Lines 376-384
Link Here
|
376 |
state[0] = STextEngine.STATE_INITIAL; |
303 |
state[0] = STextEngine.STATE_INITIAL; |
377 |
} |
304 |
} |
378 |
int len = text.length(); |
305 |
int len = text.length(); |
379 |
// dirProps: 1 byte for each char in text, + 1 byte = current orientation |
306 |
int orient = dirProps.getBaseOrientation(environment); |
380 |
int orient = getCurOrient(environment, text, dirProps); |
|
|
381 |
dirProps[len] = (byte) orient; |
382 |
int direction = processor.getDirection(environment, text, dirProps); |
307 |
int direction = processor.getDirection(environment, text, dirProps); |
383 |
// offsets of marks to add. Entry 0 is the number of used slots; |
308 |
// offsets of marks to add. Entry 0 is the number of used slots; |
384 |
// entry 1 is reserved to pass prefixLength. |
309 |
// entry 1 is reserved to pass prefixLength. |
Lines 428-435
Link Here
|
428 |
offsets[1] = 0; |
353 |
offsets[1] = 0; |
429 |
else { |
354 |
else { |
430 |
// recompute orient since it may have changed if contextual |
355 |
// recompute orient since it may have changed if contextual |
431 |
orient = getCurOrient(environment, text, dirProps); |
356 |
orient = dirProps.getBaseOrientation(environment); |
432 |
dirProps[len] = (byte) orient; |
|
|
433 |
if (orient == direction && orient != STextEnvironment.ORIENT_UNKNOWN) |
357 |
if (orient == direction && orient != STextEnvironment.ORIENT_UNKNOWN) |
434 |
offsets[1] = 0; |
358 |
offsets[1] = 0; |
435 |
else if ((environment.getOrientation() & STextEnvironment.ORIENT_CONTEXTUAL_LTR) != 0) |
359 |
else if ((environment.getOrientation() & STextEnvironment.ORIENT_CONTEXTUAL_LTR) != 0) |
Lines 452-458
Link Here
|
452 |
state = new int[1]; |
376 |
state = new int[1]; |
453 |
state[0] = STextEngine.STATE_INITIAL; |
377 |
state[0] = STextEngine.STATE_INITIAL; |
454 |
} |
378 |
} |
455 |
int dir = processor.getDirection(environment, text, null); |
379 |
int dir = processor.getDirection(environment, text, new STextDirections(text)); |
456 |
char curMark = MARKS[dir]; |
380 |
char curMark = MARKS[dir]; |
457 |
char curEmbed = EMBEDS[dir]; |
381 |
char curEmbed = EMBEDS[dir]; |
458 |
int i; // used as loop index |
382 |
int i; // used as loop index |
Lines 544-550
Link Here
|
544 |
return EMPTY_INT_ARRAY; |
468 |
return EMPTY_INT_ARRAY; |
545 |
String lean = fullToLeanText(processor, environment, full, state); |
469 |
String lean = fullToLeanText(processor, environment, full, state); |
546 |
int lenLean = lean.length(); |
470 |
int lenLean = lean.length(); |
547 |
int dir = processor.getDirection(environment, lean, null); |
471 |
int dir = processor.getDirection(environment, lean, new STextDirections(lean)); |
548 |
char curMark = MARKS[dir]; |
472 |
char curMark = MARKS[dir]; |
549 |
char curEmbed = EMBEDS[dir]; |
473 |
char curEmbed = EMBEDS[dir]; |
550 |
int[] map = new int[lenFull]; |
474 |
int[] map = new int[lenFull]; |
Lines 581-598
Link Here
|
581 |
offsets[0] = OFFSETS_SHIFT; |
505 |
offsets[0] = OFFSETS_SHIFT; |
582 |
int lenLean = lean.length(); |
506 |
int lenLean = lean.length(); |
583 |
int idxLean, idxFull; |
507 |
int idxLean, idxFull; |
|
|
508 |
STextDirections dirProps = new STextDirections(full); |
584 |
// lean must be a subset of Full, so we only check on iLean < leanLen |
509 |
// lean must be a subset of Full, so we only check on iLean < leanLen |
585 |
for (idxLean = idxFull = 0; idxLean < lenLean; idxFull++) { |
510 |
for (idxLean = idxFull = 0; idxLean < lenLean; idxFull++) { |
586 |
if (full.charAt(idxFull) == lean.charAt(idxLean)) |
511 |
if (full.charAt(idxFull) == lean.charAt(idxLean)) |
587 |
idxLean++; |
512 |
idxLean++; |
588 |
else { |
513 |
else { |
589 |
offsets = ensureRoomInOffsets(offsets); |
514 |
offsets = ensureRoomInOffsets(offsets); |
590 |
insertMark(lean, null, offsets, idxFull); |
515 |
insertMark(lean, dirProps, offsets, idxFull); |
591 |
} |
516 |
} |
592 |
} |
517 |
} |
593 |
for (; idxFull < lenFull; idxFull++) { |
518 |
for (; idxFull < lenFull; idxFull++) { |
594 |
offsets = ensureRoomInOffsets(offsets); |
519 |
offsets = ensureRoomInOffsets(offsets); |
595 |
insertMark(lean, null, offsets, idxFull); |
520 |
insertMark(lean, dirProps, offsets, idxFull); |
596 |
} |
521 |
} |
597 |
int[] result = new int[offsets[0] - OFFSETS_SHIFT]; |
522 |
int[] result = new int[offsets[0] - OFFSETS_SHIFT]; |
598 |
System.arraycopy(offsets, OFFSETS_SHIFT, result, 0, result.length); |
523 |
System.arraycopy(offsets, OFFSETS_SHIFT, result, 0, result.length); |
Lines 612-618
Link Here
|
612 |
/** |
537 |
/** |
613 |
* @see STextProcessor#insertMark STextProcessor.insertMark |
538 |
* @see STextProcessor#insertMark STextProcessor.insertMark |
614 |
*/ |
539 |
*/ |
615 |
public static void insertMark(String text, byte[] dirProps, int[] offsets, int offset) { |
540 |
public static void insertMark(String text, STextDirections dirProps, int[] offsets, int offset) { |
616 |
int count = offsets[0];// number of used entries |
541 |
int count = offsets[0];// number of used entries |
617 |
int index = count - 1; // index of greatest member <= offset |
542 |
int index = count - 1; // index of greatest member <= offset |
618 |
// look up after which member the new offset should be inserted |
543 |
// look up after which member the new offset should be inserted |
Lines 634-650
Link Here
|
634 |
if (dirProps == null || offset < 1) |
559 |
if (dirProps == null || offset < 1) |
635 |
return; |
560 |
return; |
636 |
|
561 |
|
637 |
byte dirProp = getDirProp(text, dirProps, offset); |
562 |
byte dirProp = dirProps.getOrientationAt(offset); |
638 |
// if the current char is a strong one or a digit, we change the |
563 |
// if the current char is a strong one or a digit, we change the |
639 |
// dirProp of the previous char to account for the inserted mark. |
564 |
// dirProp of the previous char to account for the inserted mark. |
640 |
// In the following lines, L, R, AL, AN and EN represent bidi categories |
|
|
641 |
// as defined in the Unicode Bidirectional Algorithm |
642 |
// ( http://www.unicode.org/reports/tr9/ ). |
643 |
// L represents the category Left to Right character. |
644 |
// R represents the category Right to Left character. |
645 |
// AL represents the category Arabic Letter. |
646 |
// AN represents the category Arabic Number. |
647 |
// EN represents the category European Number. |
648 |
if (dirProp == L || dirProp == R || dirProp == AL || dirProp == EN || dirProp == AN) |
565 |
if (dirProp == L || dirProp == R || dirProp == AL || dirProp == EN || dirProp == AN) |
649 |
index = offset - 1; |
566 |
index = offset - 1; |
650 |
else |
567 |
else |
Lines 652-658
Link Here
|
652 |
index = offset; |
569 |
index = offset; |
653 |
|
570 |
|
654 |
int dir = offsets[2]; // current structured text direction |
571 |
int dir = offsets[2]; // current structured text direction |
655 |
setDirProp(dirProps, index, STRONGS[dir]); |
572 |
dirProps.setOrientationAt(index, STRONGS[dir]); |
656 |
return; |
573 |
return; |
657 |
} |
574 |
} |
658 |
|
575 |
|