summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelipe Heidrich <fheidric>2008-05-28 22:22:50 +0000
committerFelipe Heidrich <fheidric>2008-05-28 22:22:50 +0000
commite42c019f2a285ee0693f813be28788620d9b1560 (patch)
treed44c4984dfc73384862ce1ae9f635b77ed13fff6
parent10946719389470f65e13f1be11fcaf6eb8e0708e (diff)
downloadeclipse.platform.swt-e42c019f2a285ee0693f813be28788620d9b1560.tar.gz
eclipse.platform.swt-e42c019f2a285ee0693f813be28788620d9b1560.tar.xz
eclipse.platform.swt-e42c019f2a285ee0693f813be28788620d9b1560.zip
Bug 233638 Extreme performance degradation in TextLayout.shape()
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/TextLayout.java60
1 files changed, 39 insertions, 21 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/TextLayout.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/TextLayout.java
index 4a83312ad4..f235b0a85a 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/TextLayout.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/TextLayout.java
@@ -2698,10 +2698,7 @@ public void setWidth (int width) {
}
boolean shape (int /*long*/ hdc, StyleItem run, char[] chars, int[] glyphCount, int maxGlyphs, SCRIPT_PROPERTIES sp) {
- boolean useCMAPcheck = !sp.fComplex && !sp.fPrivateUseArea;
- SCRIPT_FONTPROPERTIES fp = new SCRIPT_FONTPROPERTIES ();
- fp.cBytes = SCRIPT_FONTPROPERTIES.sizeof;
- OS.ScriptGetFontProperties(hdc, run.psc, fp);
+ boolean useCMAPcheck = !sp.fComplex && !run.analysis.fNoGlyphIndex;
if (useCMAPcheck) {
short[] glyphs = new short[chars.length];
if (OS.ScriptGetCMap(hdc, run.psc, chars, chars.length, 0, glyphs) != OS.S_OK) {
@@ -2718,6 +2715,10 @@ boolean shape (int /*long*/ hdc, StyleItem run, char[] chars, int[] glyphCount,
if (useCMAPcheck) return true;
if (hr != OS.USP_E_SCRIPT_NOT_IN_FONT) {
+ if (run.analysis.fNoGlyphIndex) return true;
+ SCRIPT_FONTPROPERTIES fp = new SCRIPT_FONTPROPERTIES ();
+ fp.cBytes = SCRIPT_FONTPROPERTIES.sizeof;
+ OS.ScriptGetFontProperties(hdc, run.psc, fp);
short[] glyphs = new short[glyphCount[0]];
OS.MoveMemory(glyphs, run.glyphs, glyphs.length * 2);
int i;
@@ -2743,17 +2744,6 @@ void shape (final int /*long*/ hdc, final StyleItem run) {
final char[] chars = new char[run.length];
segmentsText.getChars(run.start, run.start + run.length, chars, 0);
-
- /*
- * Feature in Uniscribe, the U+FEFF is not supported by
- * some fonts in the system causing the remaining chars in
- * the run not to draw, even though the font supports them.
- * The fix is to replace U+FEFF by U+200B (ZERO-WIDTH SPACE).
- */
- for (int i = 0; i < chars.length; i++) {
- if (chars[i] == '\uFEFF') chars[i] = '\u200B';
- }
-
final int maxGlyphs = (chars.length * 3 / 2) + 16;
int /*long*/ hHeap = OS.GetProcessHeap();
run.glyphs = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, maxGlyphs * 2);
@@ -2770,14 +2760,42 @@ void shape (final int /*long*/ hdc, final StyleItem run) {
boolean shapeSucceed = shape(hdc, run, chars, buffer, maxGlyphs, sp);
if (!shapeSucceed) {
- /*
- * Shape failed.
- * Try to shape with fNoGlyphIndex when the run is in the
- * Private Use Area. This allows for end-user-defined character (EUDC).
- */
- if (sp.fPrivateUseArea) {
+ boolean useGDI = !sp.fComplex;
+ /*
+ * Bug in Windows. There are non-complex scripts that are
+ * not supported by GDI. The fix is to detect these scripts
+ * by checking the Unicode ranges and use Uniscribe instead.
+ *
+ * These are the scripts:
+ * 0x0530..0x058F is Armenian
+ * 0x10A0..0x10FF is Georgian
+ * 0xA000..0xA4CF is Yi
+ */
+ char c = chars[0];
+ if (0x0530 <= c && c <= 0x058F || 0x10A0 <= c && c <= 0x10FF || 0xA000 <= c && c <= 0xA4CF) {
+ useGDI = false;
+ }
+ if (useGDI) {
+ int /*long*/ hFont = OS.GetCurrentObject(hdc, OS.OBJ_FONT);
+ LOGFONT logFont = OS.IsUnicode ? (LOGFONT)new LOGFONTW () : new LOGFONTA ();
+ OS.GetObject(hFont, LOGFONT.sizeof, logFont);
+ LOGFONT systemLogFont = OS.IsUnicode ? (LOGFONT)new LOGFONTW () : new LOGFONTA ();
+ OS.GetObject(device.systemFont.handle, LOGFONT.sizeof, systemLogFont);
+ systemLogFont.lfHeight = logFont.lfHeight;
+ systemLogFont.lfWeight = logFont.lfWeight;
+ systemLogFont.lfItalic = logFont.lfItalic;
+ systemLogFont.lfWidth = logFont.lfWidth;
+ int /*long*/ newFont = OS.CreateFontIndirect (systemLogFont);
+ OS.SelectObject(hdc, newFont);
run.analysis.fNoGlyphIndex = true;
shapeSucceed = shape(hdc, run, chars, buffer, maxGlyphs, sp);
+ if (shapeSucceed) {
+ run.fallbackFont = newFont;
+ } else {
+ OS.SelectObject(hdc, hFont);
+ OS.DeleteObject(newFont);
+ run.analysis.fNoGlyphIndex = false;
+ }
}
}