< 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 >