src/macosx/classes/sun/font/CCharToGlyphMapper.java

Print this page

        

*** 128,148 **** return glyphArray[0]; } public synchronized int charToGlyph(int unicode) { return charToGlyph((char)unicode); } public synchronized void charsToGlyphs(int count, char[] unicodes, int[] glyphs) { cache.get(count, unicodes, glyphs); } public synchronized void charsToGlyphs(int count, int[] unicodes, int[] glyphs) { ! final char[] unicodeChars = new char[count]; ! for (int i = 0; i < count; i++) unicodeChars[i] = (char)unicodes[i]; ! cache.get(count, unicodeChars, glyphs); } // This mapper returns either the glyph code, or if the character can be // replaced on-the-fly using CoreText substitution; the negative unicode // value. If this "glyph code int" is treated as an opaque code, it will --- 128,157 ---- return glyphArray[0]; } public synchronized int charToGlyph(int unicode) { + if (unicode >= 0x10000) { + int[] glyphs = new int[2]; + char[] surrogates = new char[2]; + int base = unicode - 0x10000; + surrogates[0] = (char)((base >>> 10) + HI_SURROGATE_START); + surrogates[1] = (char)((base % 0x400) + LO_SURROGATE_START); + charsToGlyphs(2, surrogates, glyphs); + return glyphs[0]; + } else return charToGlyph((char)unicode); } public synchronized void charsToGlyphs(int count, char[] unicodes, int[] glyphs) { cache.get(count, unicodes, glyphs); } public synchronized void charsToGlyphs(int count, int[] unicodes, int[] glyphs) { ! for (int i = 0; i < count; i++) { ! glyphs[i] = charToGlyph(unicodes[i]); ! }; } // This mapper returns either the glyph code, or if the character can be // replaced on-the-fly using CoreText substitution; the negative unicode // value. If this "glyph code int" is treated as an opaque code, it will
*** 164,174 **** Cache() { // <rdar://problem/5331678> need to prevent getting '-1' stuck in the cache firstLayerCache[1] = 1; } ! public int get(final char index) { if (index < FIRST_LAYER_SIZE) { // catch common glyphcodes return firstLayerCache[index]; } --- 173,183 ---- Cache() { // <rdar://problem/5331678> need to prevent getting '-1' stuck in the cache firstLayerCache[1] = 1; } ! public synchronized int get(final int index) { if (index < FIRST_LAYER_SIZE) { // catch common glyphcodes return firstLayerCache[index]; }
*** 177,192 **** if (secondLayerCache == null) return 0; return secondLayerCache.get(index); } if (generalCache == null) return 0; ! final Integer value = generalCache.get(new Integer(index)); if (value == null) return 0; return value.intValue(); } ! public void put(final char index, final int value) { if (index < FIRST_LAYER_SIZE) { // catch common glyphcodes firstLayerCache[index] = value; return; } --- 186,201 ---- if (secondLayerCache == null) return 0; return secondLayerCache.get(index); } if (generalCache == null) return 0; ! final Integer value = generalCache.get(index); if (value == null) return 0; return value.intValue(); } ! public synchronized void put(final int index, final int value) { if (index < FIRST_LAYER_SIZE) { // catch common glyphcodes firstLayerCache[index] = value; return; }
*** 202,212 **** if (generalCache == null) { generalCache = new HashMap<Integer, Integer>(); } ! generalCache.put(new Integer(index), new Integer(value)); } private class SparseBitShiftingTwoLayerArray { final int[][] cache; final int shift; --- 211,221 ---- if (generalCache == null) { generalCache = new HashMap<Integer, Integer>(); } ! generalCache.put(index, value); } private class SparseBitShiftingTwoLayerArray { final int[][] cache; final int shift;
*** 218,314 **** this.shift = shift; this.cache = new int[1 << shift][]; this.secondLayerLength = size >> shift; } ! public int get(final char index) { final int firstIndex = index >> shift; final int[] firstLayerRow = cache[firstIndex]; if (firstLayerRow == null) return 0; return firstLayerRow[index - (firstIndex * (1 << shift))]; } ! public void put(final char index, final int value) { final int firstIndex = index >> shift; int[] firstLayerRow = cache[firstIndex]; if (firstLayerRow == null) { cache[firstIndex] = firstLayerRow = new int[secondLayerLength]; } firstLayerRow[index - (firstIndex * (1 << shift))] = value; } } ! public void get(int count, char[] indicies, int[] values){ int missed = 0; ! for(int i = 0; i < count; i++){ ! char code = indicies[i]; final int value = get(code); ! if(value != 0){ values[i] = value; ! }else{ ! // zero this element out, because the caller does not ! // promise to keep it clean values[i] = 0; missed++; } } ! if (missed == 0) return; // horray! everything is already cached! ! ! final char[] filteredCodes = new char[missed]; // all index codes requested (partially filled) ! final int[] filteredIndicies = new int[missed]; // local indicies into filteredCodes array (totally filled) ! ! // scan, mark, and store the index codes again to send into native ! int j = 0; ! int dupes = 0; ! for (int i = 0; i < count; i++){ ! if (values[i] != 0L) continue; // already filled ! ! final char code = indicies[i]; ! ! // we have already promised to fill this code - this is a dupe ! if (get(code) == -1){ ! filteredIndicies[j] = -1; ! dupes++; ! j++; ! continue; ! } ! ! // this is a code we have not obtained before ! // mark this one as "promise to get" in the global cache with a -1 ! final int k = j - dupes; ! filteredCodes[k] = code; ! put(code, -1); ! filteredIndicies[j] = k; ! j++; } ! final int filteredRunLen = j - dupes; ! final int[] filteredValues = new int[filteredRunLen]; ! ! // bulk call to fill in the distinct values ! nativeCharsToGlyphs(fFont.getNativeFontPtr(), filteredRunLen, filteredCodes, filteredValues); ! // scan the requested list, and fill in values from our ! // distinct code list which has been filled from "getDistinct" ! j = 0; ! for (int i = 0; i < count; i++){ ! if (values[i] != 0L && values[i] != -1L) continue; // already placed ! ! final int k = filteredIndicies[j]; // index into filteredImages array ! final char code = indicies[i]; ! if(k == -1L){ ! // we should have already filled the cache with this value ! values[i] = get(code); ! }else{ ! // fill the particular code request, and store in the cache ! final int ptr = filteredValues[k]; ! values[i] = ptr; ! put(code, ptr); } - - j++; } } } } --- 227,327 ---- this.shift = shift; this.cache = new int[1 << shift][]; this.secondLayerLength = size >> shift; } ! public int get(final int index) { final int firstIndex = index >> shift; final int[] firstLayerRow = cache[firstIndex]; if (firstLayerRow == null) return 0; return firstLayerRow[index - (firstIndex * (1 << shift))]; } ! public void put(final int index, final int value) { final int firstIndex = index >> shift; int[] firstLayerRow = cache[firstIndex]; if (firstLayerRow == null) { cache[firstIndex] = firstLayerRow = new int[secondLayerLength]; } firstLayerRow[index - (firstIndex * (1 << shift))] = value; } } ! public synchronized void get(int count, char[] indicies, int[] values) ! { ! // "missed" is the count of 'char' that are not mapped. ! // Surrogates count for 2. ! // unmappedChars is the unique list of these chars. ! // unmappedCharIndices is the location in the original array int missed = 0; ! char[] unmappedChars = null; ! int [] unmappedCharIndices = null; ! ! for (int i = 0; i < count; i++){ ! int code = indicies[i]; ! if (code >= HI_SURROGATE_START && ! code <= HI_SURROGATE_END && i < count - 1) ! { ! char low = indicies[i + 1]; ! if (low >= LO_SURROGATE_START && low <= LO_SURROGATE_END) { ! code = (code - HI_SURROGATE_START) * 0x400 + ! low - LO_SURROGATE_START + 0x10000; ! } ! } final int value = get(code); ! if (value != 0 && value != -1) { values[i] = value; ! if (code >= 0x10000) { ! values[i+1] = INVISIBLE_GLYPH_ID; ! i++; ! } ! } else { values[i] = 0; + put(code, -1); + if (unmappedChars == null) { + // This is likely to be longer than we need, + // but is the simplest and cheapest option. + unmappedChars = new char[indicies.length]; + unmappedCharIndices = new int[indicies.length]; + } + unmappedChars[missed] = indicies[i]; + unmappedCharIndices[missed] = i; + if (code >= 0x10000) { // was a surrogate pair + unmappedChars[++missed] = indicies[++i]; + } missed++; } } ! if (missed == 0) { ! return; } ! final int[] glyphCodes = new int[missed]; ! // bulk call to fill in the unmapped code points. ! nativeCharsToGlyphs(fFont.getNativeFontPtr(), ! missed, unmappedChars, glyphCodes); ! ! for (int m = 0; m < missed; m++){ ! int i = unmappedCharIndices[m]; ! int code = unmappedChars[m]; ! if (code >= HI_SURROGATE_START && ! code <= HI_SURROGATE_END && m < missed - 1) ! { ! char low = indicies[m + 1]; ! if (low >= LO_SURROGATE_START && low <= LO_SURROGATE_END) { ! code = (code - HI_SURROGATE_START) * 0x400 + ! low - LO_SURROGATE_START + 0x10000; ! } ! } ! values[i] = glyphCodes[m]; ! put(code, values[i]); ! if (code >= 0x10000) { ! m++; ! values[i + 1] = INVISIBLE_GLYPH_ID; } } } } }