Skip to content

Commit 6ff4768

Browse files
committed
[Win32] Remove obsolete fallback for drawing text without GDI+
A check in GC.drawText() make the implementation fall back to the text rendering based on glyphs and their positions calculated by GDI even when GDI+ is used in all cases except when it contains specific characters that GDI cannot handle. This was necessary more than a decade ago because specific Chinese characters were not properly rendered by GDI+. But this is quite non-intuitive as in case GDI+/advance mode is enabled the consumer will usually expected GDI+ to be used for rendering. In addition, the problematic scenario from back then works fine now. This change thus adapts the GC.drawText() implementation to use plain GDI+ whenever it is enabled and removes all existing fallback code. It also adds a case for not drawing line delimiters when an according style flag is set, which was not considered by the GDI+ implementation yet. May fix #3091
1 parent 2d4d435 commit 6ff4768

File tree

1 file changed

+4
-190
lines changed
  • bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics

1 file changed

+4
-190
lines changed

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java

Lines changed: 4 additions & 190 deletions
Original file line numberDiff line numberDiff line change
@@ -2832,211 +2832,25 @@ private void drawTextInPixels (String string, int x, int y, int flags) {
28322832
OS.SetBkMode(handle, oldBkMode);
28332833
}
28342834

2835-
private boolean useGDIP (long hdc, char[] buffer) {
2836-
short[] glyphs = new short[buffer.length];
2837-
OS.GetGlyphIndices(hdc, buffer, buffer.length, glyphs, OS.GGI_MARK_NONEXISTING_GLYPHS);
2838-
for (int i = 0; i < glyphs.length; i++) {
2839-
if (glyphs [i] == -1) {
2840-
switch (buffer[i]) {
2841-
case '\t':
2842-
case '\n':
2843-
case '\r':
2844-
break;
2845-
default:
2846-
return true;
2847-
}
2848-
}
2849-
}
2850-
return false;
2851-
}
2852-
28532835
void drawText(long gdipGraphics, String string, int x, int y, int flags, Point size) {
2854-
int length = string.length();
2855-
char[] chars = string.toCharArray();
28562836
long hdc = Gdip.Graphics_GetHDC(gdipGraphics);
28572837
long hFont = data.hGDIFont;
28582838
if (hFont == 0 && data.font != null) hFont = SWTFontProvider.getFontHandle(data.font, data.nativeZoom);
28592839
long oldFont = 0;
28602840
if (hFont != 0) oldFont = OS.SelectObject(hdc, hFont);
28612841
TEXTMETRIC lptm = new TEXTMETRIC();
28622842
OS.GetTextMetrics(hdc, lptm);
2863-
boolean gdip = useGDIP(hdc, chars);
28642843
if (hFont != 0) OS.SelectObject(hdc, oldFont);
28652844
Gdip.Graphics_ReleaseHDC(gdipGraphics, hdc);
2866-
if (gdip) {
2867-
drawTextGDIP(gdipGraphics, string, x, y, flags, size == null, size);
2868-
return;
2869-
}
2870-
int i = 0, start = 0, end = 0, drawX = x, drawY = y, width = 0, mnemonicIndex = -1;
2871-
if ((flags & (SWT.DRAW_DELIMITER | SWT.DRAW_TAB | SWT.DRAW_MNEMONIC)) != 0) {
2872-
int tabWidth = lptm.tmAveCharWidth * 8;
2873-
while (i < length) {
2874-
char c = chars [end++] = chars [i++];
2875-
switch (c) {
2876-
case '\t':
2877-
if ((flags & SWT.DRAW_TAB) != 0) {
2878-
int l = end - start - 1;
2879-
RectF bounds = drawText(gdipGraphics, chars, start, l, drawX, drawY, flags, mnemonicIndex, lptm, size == null);
2880-
drawX += Math.ceil(bounds.Width);
2881-
drawX = x + (((drawX - x) / tabWidth) + 1) * tabWidth;
2882-
mnemonicIndex = -1;
2883-
start = end;
2884-
}
2885-
break;
2886-
case '&':
2887-
if ((flags & SWT.DRAW_MNEMONIC) != 0) {
2888-
if (i == length) {end--; continue;}
2889-
if (chars [i] == '&') {i++; continue;}
2890-
end--;
2891-
mnemonicIndex = end - start;
2892-
}
2893-
break;
2894-
case '\r':
2895-
case '\n':
2896-
if ((flags & SWT.DRAW_DELIMITER) != 0) {
2897-
int l = end - start - 1;
2898-
if (c == '\r' && end != length && chars[end] == '\n') {
2899-
end++;
2900-
i++;
2901-
}
2902-
RectF bounds = drawText(gdipGraphics, chars, start, l, drawX, drawY, flags, mnemonicIndex, lptm, size == null);
2903-
drawY += Math.ceil(bounds.Height);
2904-
width = Math.max(width, drawX + (int)Math.ceil(bounds.Width));
2905-
drawX = x;
2906-
mnemonicIndex = -1;
2907-
start = end;
2908-
}
2909-
break;
2910-
}
2911-
}
2912-
length = end;
2913-
}
2914-
RectF bounds = drawText(gdipGraphics, chars, start, length - start, drawX, drawY, flags, mnemonicIndex, lptm, size == null);
2915-
if (size != null) {
2916-
drawY += Math.ceil(bounds.Height);
2917-
width = Math.max(width, drawX + (int)Math.ceil(bounds.Width));
2918-
size.x = width;
2919-
size.y = drawY;
2920-
}
2921-
}
2922-
2923-
private RectF drawText(long gdipGraphics, char[] buffer, int start, int length, int x, int y, int flags, int mnemonicIndex, TEXTMETRIC lptm, boolean draw) {
2924-
boolean drawMnemonic = draw && mnemonicIndex != -1 && (data.uiState & OS.UISF_HIDEACCEL) == 0;
2925-
boolean needsBounds = !draw || drawMnemonic || (flags & SWT.DRAW_TRANSPARENT) == 0 || (data.style & SWT.MIRRORED) != 0 || (flags & SWT.DRAW_DELIMITER) != 0;
2926-
if (length <= 0) {
2927-
RectF bounds = null;
2928-
if (needsBounds) {
2929-
bounds = new RectF();
2930-
bounds.Height = lptm.tmHeight;
2931-
}
2932-
return bounds;
2933-
}
2934-
int nGlyphs = (length * 3 / 2) + 16;
2935-
GCP_RESULTS result = new GCP_RESULTS();
2936-
result.lStructSize = GCP_RESULTS.sizeof;
2937-
result.nGlyphs = nGlyphs;
2938-
long hHeap = OS.GetProcessHeap();
2939-
long lpDx = result.lpDx = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, nGlyphs * 4);
2940-
long lpGlyphs = result.lpGlyphs = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, nGlyphs * 2);
2941-
long lpOrder = 0;
2942-
int dwFlags = OS.GCP_GLYPHSHAPE | OS.GCP_REORDER | OS.GCP_LIGATE;
2943-
if (drawMnemonic) {
2944-
lpOrder = result.lpOrder = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, nGlyphs * 4);
2945-
}
2946-
long hdc = Gdip.Graphics_GetHDC(gdipGraphics);
2947-
long hFont = data.hGDIFont;
2948-
if (hFont == 0 && data.font != null) hFont = SWTFontProvider.getFontHandle(data.font, data.nativeZoom);
2949-
long oldFont = 0;
2950-
if (hFont != 0) oldFont = OS.SelectObject(hdc, hFont);
2951-
if (start != 0) {
2952-
char[] temp = new char[length];
2953-
System.arraycopy(buffer, start, temp, 0, length);
2954-
buffer = temp;
2955-
}
2956-
if ((data.style & SWT.MIRRORED) != 0) OS.SetLayout(hdc, OS.GetLayout(hdc) | OS.LAYOUT_RTL);
2957-
OS.GetCharacterPlacement(hdc, buffer, length, 0, result, dwFlags);
2958-
if ((data.style & SWT.MIRRORED) != 0) OS.SetLayout(hdc, OS.GetLayout(hdc) & ~OS.LAYOUT_RTL);
2959-
if (hFont != 0) OS.SelectObject(hdc, oldFont);
2960-
Gdip.Graphics_ReleaseHDC(gdipGraphics, hdc);
2961-
nGlyphs = result.nGlyphs;
2962-
int drawX = x, drawY = y + lptm.tmAscent;
2963-
int[] dx = new int[nGlyphs];
2964-
OS.MoveMemory(dx, result.lpDx, nGlyphs * 4);
2965-
float[] points = new float[dx.length * 2];
2966-
for (int i = 0, j = 0; i < dx.length; i++) {
2967-
points[j++] = drawX;
2968-
points[j++] = drawY;
2969-
drawX += dx[i];
2970-
}
2971-
RectF bounds = null;
2972-
if (needsBounds) {
2973-
bounds = new RectF();
2974-
Gdip.Graphics_MeasureDriverString(gdipGraphics, lpGlyphs, nGlyphs, data.gdipFont, points, 0, 0, bounds);
2975-
}
2976-
if (draw) {
2977-
if ((flags & SWT.DRAW_TRANSPARENT) == 0) {
2978-
Gdip.Graphics_FillRectangle(gdipGraphics, data.gdipBrush, x, y, (int)Math.ceil(bounds.Width), (int)Math.ceil(bounds.Height));
2979-
}
2980-
int gstate = 0;
2981-
long brush = getFgBrush();
2982-
if ((data.style & SWT.MIRRORED) != 0) {
2983-
switch (Gdip.Brush_GetType(brush)) {
2984-
case Gdip.BrushTypeLinearGradient:
2985-
Gdip.LinearGradientBrush_ScaleTransform(brush, -1, 1, Gdip.MatrixOrderPrepend);
2986-
Gdip.LinearGradientBrush_TranslateTransform(brush, - 2 * x - bounds.Width, 0, Gdip.MatrixOrderPrepend);
2987-
break;
2988-
case Gdip.BrushTypeTextureFill:
2989-
Gdip.TextureBrush_ScaleTransform(brush, -1, 1, Gdip.MatrixOrderPrepend);
2990-
Gdip.TextureBrush_TranslateTransform(brush, - 2 * x - bounds.Width, 0, Gdip.MatrixOrderPrepend);
2991-
break;
2992-
}
2993-
gstate = Gdip.Graphics_Save(gdipGraphics);
2994-
Gdip.Graphics_ScaleTransform(gdipGraphics, -1, 1, Gdip.MatrixOrderPrepend);
2995-
Gdip.Graphics_TranslateTransform(gdipGraphics, - 2 * x - bounds.Width, 0, Gdip.MatrixOrderPrepend);
2996-
}
2997-
Gdip.Graphics_DrawDriverString(gdipGraphics, lpGlyphs, result.nGlyphs, data.gdipFont, brush, points, 0, 0);
2998-
if ((data.style & SWT.MIRRORED) != 0) {
2999-
switch (Gdip.Brush_GetType(brush)) {
3000-
case Gdip.BrushTypeLinearGradient:
3001-
Gdip.LinearGradientBrush_ResetTransform(brush);
3002-
break;
3003-
case Gdip.BrushTypeTextureFill:
3004-
Gdip.TextureBrush_ResetTransform(brush);
3005-
break;
3006-
}
3007-
Gdip.Graphics_Restore(gdipGraphics, gstate);
3008-
}
3009-
if (drawMnemonic) {
3010-
long pen = Gdip.Pen_new(brush, 1);
3011-
if (pen != 0) {
3012-
int[] order = new int[1];
3013-
OS.MoveMemory(order, result.lpOrder + mnemonicIndex * 4, 4);
3014-
int mnemonicLeft, mnemonicRight;
3015-
if ((data.style & SWT.MIRRORED) != 0) {
3016-
mnemonicLeft = (int)Math.ceil(bounds.Width) - (int)points[order[0] * 2] + 2 * x;
3017-
mnemonicRight = mnemonicLeft - dx[order[0]];
3018-
} else {
3019-
mnemonicLeft = (int)points[order[0] * 2];
3020-
mnemonicRight = mnemonicLeft + dx[order[0]];
3021-
}
3022-
int mnemonicY = y + lptm.tmAscent + 2;
3023-
int smoothingMode = Gdip.Graphics_GetSmoothingMode(gdipGraphics);
3024-
Gdip.Graphics_SetSmoothingMode(gdipGraphics, Gdip.SmoothingModeNone);
3025-
Gdip.Graphics_DrawLine(gdipGraphics, pen, mnemonicLeft, mnemonicY, mnemonicRight, mnemonicY);
3026-
Gdip.Graphics_SetSmoothingMode(gdipGraphics, smoothingMode);
3027-
Gdip.Pen_delete(pen);
3028-
}
3029-
}
3030-
}
3031-
if (lpOrder != 0) OS.HeapFree(hHeap, 0, lpOrder);
3032-
OS.HeapFree(hHeap, 0, lpGlyphs);
3033-
OS.HeapFree(hHeap, 0, lpDx);
3034-
return bounds;
2845+
drawTextGDIP(gdipGraphics, string, x, y, flags, size == null, size);
30352846
}
30362847

30372848
private void drawTextGDIP(long gdipGraphics, String string, int x, int y, int flags, boolean draw, Point size) {
30382849
boolean needsBounds = !draw || (flags & SWT.DRAW_TRANSPARENT) == 0;
30392850
char[] buffer;
2851+
if ((flags & SWT.DRAW_DELIMITER) == 0) {
2852+
string = string.replace(System.lineSeparator(), "");
2853+
}
30402854
int length = string.length();
30412855
if (length != 0) {
30422856
buffer = string.toCharArray();

0 commit comments

Comments
 (0)