< prev index next >

src/java.desktop/share/classes/sun/font/CMap.java

Print this page

        

*** 138,156 **** --- 138,158 ---- * Unicode->other encoding translation array. A pre-computed look up * which can be shared across all fonts using that encoding. * Using this saves running character coverters repeatedly. */ char[] xlat; + UVS uvs = null; static CMap initialize(TrueTypeFont font) { CMap cmap = null; int offset, platformID, encodingID=-1; int three0=0, three1=0, three2=0, three3=0, three4=0, three5=0, three6=0, three10=0; + int zero5 = 0; // for Unicode Variation Sequences boolean threeStar = false; ByteBuffer cmapBuffer = font.getTableBuffer(TrueTypeFont.cmapTag); int cmapTableOffset = font.getTableSize(TrueTypeFont.cmapTag); short numberSubTables = cmapBuffer.getShort(2);
*** 171,180 **** --- 173,188 ---- case 4: three4 = offset; break; // Big 5 cmap case 5: three5 = offset; break; // Wansung case 6: three6 = offset; break; // Johab case 10: three10 = offset; break; // MS Unicode surrogates } + } else if (platformID == 0) { + encodingID = cmapBuffer.getShort(); + offset = cmapBuffer.getInt(); + if (encodingID == 5) { + zero5 = offset; + } } } /* This defines the preference order for cmap subtables */ if (threeStar) {
*** 260,269 **** --- 268,281 ---- * table listed. Not very useful but maybe better than * rejecting the font entirely? */ cmap = createCMap(cmapBuffer, cmapBuffer.getInt(8), null); } + // For Unicode Variation Sequences + if (cmap != null && zero5 != 0) { + cmap.createUVS(cmapBuffer, zero5); + } return cmap; } /* speed up the converting by setting the range for double * byte characters;
*** 422,431 **** --- 434,462 ---- default: throw new RuntimeException("Cmap format unimplemented: " + (int)buffer.getChar(offset)); } } + private void createUVS(ByteBuffer buffer, int offset) { + int subtableFormat = buffer.getChar(offset); + if (subtableFormat == 14) { + long subtableLength = buffer.getInt(offset + 2) & INTMASK; + if (offset + subtableLength > buffer.capacity()) { + if (FontUtilities.isLogging()) { + FontUtilities.getLogger() + .warning("Cmap UVS subtable overflows buffer."); + } + } + try { + this.uvs = new UVS(buffer, offset); + } catch (Throwable t) { + t.printStackTrace(); + } + } + return; + } + /* final char charVal(byte[] cmap, int index) { return (char)(((0xff & cmap[index]) << 8)+(0xff & cmap[index+1])); }
*** 1057,1062 **** --- 1088,1226 ---- return 0; } } return -1; } + + static class UVS { + int numSelectors; + int[] selector; + + //for Default UVS Table + int[] numUnicodeValueRanges; + int[][] startUnicodeValue; + short[][] additionalCount; + //for Non-Default UVS Table + int[] numUVSMapping; + int[][] unicodeValue; + char[][] glyphID; + + UVS(ByteBuffer buffer, int offset) { + numSelectors = buffer.getInt(offset+6); + selector = new int[numSelectors]; + numUnicodeValueRanges = new int[numSelectors]; + startUnicodeValue = new int[numSelectors][]; + additionalCount = new short[numSelectors][]; + numUVSMapping = new int[numSelectors]; + unicodeValue = new int[numSelectors][]; + glyphID = new char[numSelectors][]; + + for (int i = 0; i < numSelectors; i++) { + buffer.position(offset + 10 + i * 11); + selector[i] = (buffer.get() & 0xff) << 16; //UINT24 + selector[i] += (buffer.get() & 0xff) << 8; + selector[i] += buffer.get() & 0xff; + + //for Default UVS Table + int tableOffset = buffer.getInt(offset + 10 + i * 11 + 3); + if (tableOffset == 0) { + numUnicodeValueRanges[i] = 0; + } else if (tableOffset > 0) { + buffer.position(offset+tableOffset); + numUnicodeValueRanges[i] = buffer.getInt() & INTMASK; + + startUnicodeValue[i] = new int[numUnicodeValueRanges[i]]; + additionalCount[i] = new short[numUnicodeValueRanges[i]]; + + for (int j = 0; j < numUnicodeValueRanges[i]; j++) { + int temp = (buffer.get() & 0xff) << 16; //UINT24 + temp += (buffer.get() & 0xff) << 8; + temp += buffer.get() & 0xff; + startUnicodeValue[i][j] = temp; + additionalCount[i][j] = (short)(buffer.get() & 0xff); + } + } + + //for Non-Default UVS Table + tableOffset = buffer.getInt(offset + 10 + i * 11 + 7); + if (tableOffset == 0) { + numUVSMapping[i] = 0; + } else if (tableOffset > 0) { + buffer.position(offset+tableOffset); + numUVSMapping[i] = buffer.getInt() & INTMASK; + unicodeValue[i] = new int[numUVSMapping[i]]; + glyphID[i] = new char[numUVSMapping[i]]; + + for (int j = 0; j < numUVSMapping[i]; j++) { + int temp = (buffer.get() & 0xff) << 16; //UINT24 + temp += (buffer.get() & 0xff) << 8; + temp += buffer.get() & 0xff; + unicodeValue[i][j] = temp; + glyphID[i][j] = buffer.getChar(); + } + } + } + } + + /* getGlyph for Variation selector + return value: + 0: A special glyph for the variation selector is Not found + -1: Default glyph should be used + 0>: A special glyph is found + */ + static final int VS_NOGLYPH = 0; + static final int VS_DEFAULT_GLYPH = -1; + private int getGlyph(int charCode, int variationSelector) { + int targetSelector = -1; + for (int i = 0; i < numSelectors; i++) { + if (selector[i] == variationSelector) { + targetSelector = i; + break; + } + } + if (targetSelector == -1) { + return VS_NOGLYPH; + } + if (numUnicodeValueRanges[targetSelector] > 0) { + int index = java.util.Arrays.binarySearch( + startUnicodeValue[targetSelector], charCode); + if (index >= 0) { + return VS_DEFAULT_GLYPH; + } else { + index = -index - 2; + if (index >= 0 && + charCode >= startUnicodeValue[targetSelector][index] && + charCode <= startUnicodeValue[targetSelector][index] + +additionalCount[targetSelector][index]) { + return VS_DEFAULT_GLYPH; + } + } + } + if (numUVSMapping[targetSelector] > 0) { + int index = java.util.Arrays.binarySearch( + unicodeValue[targetSelector], charCode); + if (index >= 0) { + return glyphID[targetSelector][index]; + } + } + return VS_NOGLYPH; + } + } + + char getGlyph(int charCode, int variationSelector, boolean allowFallback) { + char glyph = 0; + if (uvs == null) { + if (allowFallback) { + glyph = getGlyph(charCode); + } + } else { + int result = uvs.getGlyph(charCode, variationSelector); + if (result > 0) { + glyph = (char)(result & 0xFFFF); + } else if (result == UVS.VS_DEFAULT_GLYPH || + allowFallback) { + glyph = getGlyph(charCode); + } + } + return glyph; + } }
< prev index next >