diff --git a/javafx-font/src/com/sun/javafx/text/PrismTextLayout.java b/javafx-font/src/com/sun/javafx/text/PrismTextLayout.java --- a/javafx-font/src/com/sun/javafx/text/PrismTextLayout.java +++ b/javafx-font/src/com/sun/javafx/text/PrismTextLayout.java @@ -27,6 +27,14 @@ import java.text.Bidi; import java.text.BreakIterator; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; public class PrismTextLayout implements TextLayout { private static final BaseTransform IDENTITY = BaseTransform.IDENTITY_TRANSFORM; @@ -909,15 +917,128 @@ } return 8 * spaceAdvance; } + + public static HashMap map = new HashMap<>(); + static Map sortByValue(Map map) { + List list = new LinkedList(map.entrySet()); + Collections.sort(list, new Comparator() { + public int compare(Object o1, Object o2) { + return ((Comparable) ((Map.Entry) (o2)).getValue()).compareTo(((Map.Entry) (o1)).getValue()); + } + }); + Map result = new LinkedHashMap(); + for (Iterator it = list.iterator(); it.hasNext();) { + Map.Entry entry = (Map.Entry)it.next(); + result.put(entry.getKey(), entry.getValue()); + } + return result; + } + + static final boolean GATHER_STATS = false; + static final boolean USE_CONSTANT_STRING = false; + static boolean HookAdded = false; + static final String DEFAULT_TEXT = "Malkovich"; + static TextRun EmptyText, DefaultText; + + static final boolean USE_CACHE = false; + static class RunCache { + int runCount; + TextRun[] runs; + } + static HashMap Cache = new HashMap<>(); + private void layout() { char[] chars = getText(); + + if (GATHER_STATS) { + String value = new String(chars); + Integer count = map.get(value); + if (count == null) { + map.put(value, 1); + } else { + map.put(value, count + 1); + } + if (!HookAdded) { + HookAdded = true; + Runtime.getRuntime().addShutdownHook(new Thread() { + public void run () { + int sum = 0; + for (Integer c : map.values()) { + sum += c; + } + //System.out.println("WOW"); + System.out.println("\nUnique: " + map.size() + ", Total: " + sum + ", %: " + (100.0 * map.size()) / sum); + Map newMap = sortByValue(map); + int c = 0; + for (Object key : newMap.keySet()) { + System.out.println("\t\"" + key + "\" -> " + newMap.get(key)); + if (c++ > 20) break; + } + System.out.println("..."); + } + }); + } + /* + if (map.size() % 100 == 0) { + if (map.size() >= 24000) { + int sum = 0; + for (Integer c : map.values()) { + sum += c; + } + System.out.println("WOW"); + System.out.println("\nUnique: " + map.size() + ", Total: " + sum + ", %: " + (100.0 * map.size()) / sum); + Map newMap = sortByValue(map); + int c = 0; + for (Object key : newMap.keySet()) { + System.out.println("\t\"" + key + "\" -> " + newMap.get(key)); + if (c++ > 20) break; + } + System.out.println("..."); + } + } + */ + } /* runs and runCount are set in reuseRuns or buildRuns */ - if ((flags & FLAGS_ANALYSIS_VALID) != 0 && isSimpleLayout()) { - reuseRuns(); + if (USE_CONSTANT_STRING) { + if (DefaultText != null) { + runCount = 1; + if (runs == null) runs = new TextRun[1]; + runs[0] = chars.length == 0 ? EmptyText : DefaultText; + } else { + chars = new char [0]; + buildRuns(chars); + EmptyText = runs [0]; + chars = DEFAULT_TEXT.toCharArray(); + buildRuns(chars); + DefaultText = runs [0]; + } } else { - buildRuns(chars); + if (USE_CACHE) { + String key = new String(chars); + RunCache entry = Cache.get(key); + if (entry != null) { + runCount = entry.runCount; + runs = entry.runs; + } else { + if ((flags & FLAGS_ANALYSIS_VALID) != 0 && isSimpleLayout()) { + reuseRuns(); + } else { + buildRuns(chars); + } + entry = new RunCache(); + entry.runCount = runCount; + entry.runs = runs; + Cache.put(key, entry); + } + } else { + if ((flags & FLAGS_ANALYSIS_VALID) != 0 && isSimpleLayout()) { + reuseRuns(); + } else { + buildRuns(chars); + } + } } GlyphLayout layout = null;