Skip to content

Commit a629043

Browse files
jukziniraj-modi
authored andcommitted
resolveTextDirection using Character.getDirectionality (solves #90)
prevent slow systemcalls for every character. Does change the returned direction for many special characters in windows, however it is now conform to the javadoc - that only strong directions are used to determine the direction.
1 parent 479cfe7 commit a629043

File tree

1 file changed

+55
-44
lines changed
  • bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal

1 file changed

+55
-44
lines changed

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/BidiUtil.java

Lines changed: 55 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -456,66 +456,77 @@ public static void removeLanguageListener (long hwnd) {
456456
public static void removeLanguageListener (Control control) {
457457
removeLanguageListener(control.handle);
458458
}
459+
459460
/**
460461
* Determine the base direction for the given text. The direction is derived
461-
* from that of the first strong bidirectional character. In case the text
462-
* doesn't contain any strong characters, the base direction is to be
463-
* derived from a higher-level protocol (e.g. the widget orientation).
462+
* from the first strong bidirectional RIGHT_TO_LEFT character. Or if that does
463+
* not exist from the first strong LEFT_TO_RIGHT character
464464
* <p>
465465
*
466-
* @param text
467-
* Text base direction should be resolved for.
466+
* @param text Text base direction should be resolved for.
468467
* @return SWT#LEFT_RIGHT or SWT#RIGHT_TO_LEFT if the text contains strong
469468
* characters and thus the direction can be resolved, SWT#NONE
470469
* otherwise.
471470
* @since 3.105
472471
*/
473-
public static int resolveTextDirection (String text) {
474-
if (text == null) return SWT.NONE;
475-
int length = text.length();
476-
if (length == 0) return SWT.NONE;
477-
char[] rtlProbe = {' ', ' ', '1'};
478-
char[] ltrProbe = {'\u202b', 'a', ' '};
479-
char[] numberProbe = {'\u05d0', ' ', ' '};
480-
GCP_RESULTS result = new GCP_RESULTS();
481-
result.lStructSize = GCP_RESULTS.sizeof;
482-
int nGlyphs = result.nGlyphs = ltrProbe.length;
483-
long hHeap = OS.GetProcessHeap();
484-
long lpOrder = result.lpOrder = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, nGlyphs * 4);
485-
long hdc = OS.GetDC(0);
486-
int[] order = new int[1];
472+
public static int resolveTextDirection(String text) {
473+
if (text == null)
474+
return SWT.NONE;
487475
int textDirection = SWT.NONE;
488-
for (int i = 0; i < length; i++) {
489-
char ch = text.charAt(i);
490-
rtlProbe[0] = ch;
491-
OS.GetCharacterPlacement(hdc, rtlProbe, rtlProbe.length, 0, result, OS.GCP_REORDER);
492-
OS.MoveMemory(order, result.lpOrder, 4);
493-
if (order[0] == 2) {
494-
textDirection = SWT.RIGHT_TO_LEFT;
495-
break;
496-
}
497-
if (textDirection == SWT.LEFT_TO_RIGHT) {
498-
// If textDirection is already LTR, skip probing for LTR again.
499-
continue;
476+
for (int i = 0; i < text.length(); i++) {
477+
char c = text.charAt(i);
478+
byte directionality = Character.getDirectionality(c);
479+
int strongDirection = getStrongDirection(directionality);
480+
if (strongDirection != SWT.NONE) {
481+
textDirection = strongDirection;
500482
}
501-
ltrProbe[2] = ch;
502-
OS.GetCharacterPlacement(hdc, ltrProbe, ltrProbe.length, 0, result, OS.GCP_REORDER);
503-
OS.MoveMemory(order, result.lpOrder + 4, 4);
504-
if (order[0] == 1) {
505-
numberProbe[2] = ch;
506-
OS.GetCharacterPlacement(hdc, numberProbe, numberProbe.length, 0, result, OS.GCP_REORDER);
507-
OS.MoveMemory(order, result.lpOrder, 4);
508-
if (order[0] == 0) {
509-
textDirection = SWT.LEFT_TO_RIGHT;
510-
// Do-not break here, instead scan the complete text for any RTL possibility
511-
}
483+
if (textDirection == SWT.RIGHT_TO_LEFT) {
484+
break;
512485
}
513486
}
514-
OS.ReleaseDC (0, hdc);
515-
OS.HeapFree(hHeap, 0, lpOrder);
516487
return textDirection;
488+
}
489+
490+
static int getStrongDirection(byte directionality) {
491+
switch (directionality) {
492+
// Strong bidirectional character types in the Unicode specification:
493+
case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
494+
return SWT.LEFT_TO_RIGHT;
495+
case Character.DIRECTIONALITY_RIGHT_TO_LEFT:
496+
case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:
497+
return SWT.RIGHT_TO_LEFT;
498+
499+
// Weak:
500+
// case Character.DIRECTIONALITY_EUROPEAN_NUMBER: return SWT.NONE;
501+
// case Character.DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR: return SWT.NONE;
502+
// case Character.DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR: return SWT.NONE;
503+
// XXX Arabic Number is not a strong direction, however former windows algorithm
504+
// would detect some as LEFT_TO_RIGHT and some as RIGHT_TO_LEFT:
505+
// case Character.DIRECTIONALITY_ARABIC_NUMBER: return SWT.RIGHT_TO_LEFT;
506+
// case Character.DIRECTIONALITY_COMMON_NUMBER_SEPARATOR: return SWT.NONE;
507+
// case Character.DIRECTIONALITY_NONSPACING_MARK: return SWT.LEFT_TO_RIGHT;
508+
// case Character.DIRECTIONALITY_BOUNDARY_NEUTRAL: return SWT.NONE;
517509

510+
// Neutral:
511+
// case Character.DIRECTIONALITY_PARAGRAPH_SEPARATOR: return SWT.LEFT_TO_RIGHT;
512+
// case Character.DIRECTIONALITY_SEGMENT_SEPARATOR: return SWT.LEFT_TO_RIGHT;
513+
// case Character.DIRECTIONALITY_WHITESPACE: return SWT.NONE;
514+
// case Character.DIRECTIONALITY_OTHER_NEUTRALS: return SWT.NONE;
515+
516+
// Explicit Formatting:
517+
// case Character.DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING: return SWT.LEFT_TO_RIGHT;
518+
// case Character.DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE: return SWT.LEFT_TO_RIGHT;
519+
// case Character.DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING: return SWT.LEFT_TO_RIGHT;
520+
// case Character.DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE: return SWT.LEFT_TO_RIGHT;
521+
// case Character.DIRECTIONALITY_POP_DIRECTIONAL_FORMAT: return SWT.LEFT_TO_RIGHT;
522+
// case Character.DIRECTIONALITY_LEFT_TO_RIGHT_ISOLATE: return SWT.LEFT_TO_RIGHT;
523+
// case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ISOLATE: return SWT.LEFT_TO_RIGHT;
524+
// case Character.DIRECTIONALITY_FIRST_STRONG_ISOLATE: return SWT.LEFT_TO_RIGHT;
525+
// case Character.DIRECTIONALITY_POP_DIRECTIONAL_ISOLATE: return SWT.LEFT_TO_RIGHT;
526+
}
527+
return SWT.NONE;
518528
}
529+
519530
/**
520531
* Switch the keyboard language to the specified language type. We do
521532
* not distinguish between multiple bidi or multiple non-bidi languages, so

0 commit comments

Comments
 (0)