549 /*
550 System.err.println("segcount="+segCount);
551 System.err.println("entrySelector="+entrySelector);
552 System.err.println("rangeShift="+rangeShift);
553 for (int j=0;j<segCount;j++) {
554 System.err.println("j="+j+ " sc="+(int)(startCount[j]&0xffff)+
555 " ec="+(int)(endCount[j]&0xffff)+
556 " delta="+idDelta[j] +
557 " ro="+(int)idRangeOffset[j]);
558 }
559
560 //System.err.println("numglyphs="+glyphIds.length);
561 for (int i=0;i<numGlyphIds;i++) {
562 System.err.println("gid["+i+"]="+(int)glyphIds[i]);
563 }
564 */
565 }
566
567 char getGlyph(int charCode) {
568
569 int index = 0;
570 char glyphCode = 0;
571
572 int controlGlyph = getControlCodeGlyph(charCode, true);
573 if (controlGlyph >= 0) {
574 return (char)controlGlyph;
575 }
576
577 /* presence of translation array indicates that this
578 * cmap is in some other (non-unicode encoding).
579 * In order to look-up a char->glyph mapping we need to
580 * translate the unicode code point to the encoding of
581 * the cmap.
582 * REMIND: VALID CHARCODES??
583 */
584 if (xlat != null) {
585 charCode = xlat[charCode];
586 }
587
588 /*
620 if (rangeOffset == 0) {
621 glyphCode = (char)(charCode + idDelta[index]);
622 } else {
623 /* Calculate an index into the glyphIds array */
624
625 /*
626 System.err.println("rangeoffset="+rangeOffset+
627 " charCode=" + charCode +
628 " scnt["+index+"]="+(int)startCount[index] +
629 " segCnt="+segCount);
630 */
631
632 int glyphIDIndex = rangeOffset - segCount + index
633 + (charCode - startCount[index]);
634 glyphCode = glyphIds[glyphIDIndex];
635 if (glyphCode != 0) {
636 glyphCode = (char)(glyphCode + idDelta[index]);
637 }
638 }
639 }
640 if (glyphCode != 0) {
641 //System.err.println("cc="+Integer.toHexString((int)charCode) + " gc="+(int)glyphCode);
642 }
643 return glyphCode;
644 }
645 }
646
647 // Format 0: Byte Encoding table
648 static class CMapFormat0 extends CMap {
649 byte [] cmap;
650
651 CMapFormat0(ByteBuffer buffer, int offset) {
652
653 /* skip 6 bytes of format, length, and version */
654 int len = buffer.getChar(offset+2);
655 cmap = new byte[len-6];
656 buffer.position(offset+6);
657 buffer.get(cmap);
658 }
659
660 char getGlyph(int charCode) {
661 if (charCode < 256) {
787 idRangeOffSetArray = new char[numSubHeaders];
788 for (int i=0; i<numSubHeaders; i++) {
789 firstCodeArray[i] = cBuffer.get();
790 entryCountArray[i] = cBuffer.get();
791 idDeltaArray[i] = (short)cBuffer.get();
792 idRangeOffSetArray[i] = cBuffer.get();
793 // System.out.println("sh["+i+"]:fc="+(int)firstCodeArray[i]+
794 // " ec="+(int)entryCountArray[i]+
795 // " delta="+(int)idDeltaArray[i]+
796 // " offset="+(int)idRangeOffSetArray[i]);
797 }
798
799 int glyphIndexArrSize = (tableLen-518-numSubHeaders*8)/2;
800 glyphIndexArray = new char[glyphIndexArrSize];
801 for (int i=0; i<glyphIndexArrSize;i++) {
802 glyphIndexArray[i] = cBuffer.get();
803 }
804 }
805
806 char getGlyph(int charCode) {
807 int controlGlyph = getControlCodeGlyph(charCode, true);
808 if (controlGlyph >= 0) {
809 return (char)controlGlyph;
810 }
811
812 if (xlat != null) {
813 charCode = xlat[charCode];
814 }
815
816 char highByte = (char)(charCode >> 8);
817 char lowByte = (char)(charCode & 0xff);
818 int key = subHeaderKey[highByte]>>3; // index into subHeaders
819 char mapMe;
820
821 if (key != 0) {
822 mapMe = lowByte;
823 } else {
824 mapMe = highByte;
825 if (mapMe == 0) {
826 mapMe = lowByte;
842 * the number of bytes from that location in the table where
843 * the subarray of glyphIndexes starting at "firstCode" begins.
844 * Each entry in the subHeader table is 8 bytes, and the
845 * idRangeOffSetArray field is at offset 6 in the entry.
846 * The glyphIndexArray immediately follows the subHeaders.
847 * So if there are "N" entries then the number of bytes to the
848 * start of glyphIndexArray is (N-key)*8-6.
849 * Subtract this from the idRangeOffSetArray value to get
850 * the number of bytes into glyphIndexArray and divide by 2 to
851 * get the (char) array index.
852 */
853 int glyphArrayOffset = ((idRangeOffSetArray.length-key)*8)-6;
854 int glyphSubArrayStart =
855 (idRangeOffSetArray[key] - glyphArrayOffset)/2;
856 char glyphCode = glyphIndexArray[glyphSubArrayStart+mapMe];
857 if (glyphCode != 0) {
858 glyphCode += idDeltaArray[key]; //idDelta
859 return glyphCode;
860 }
861 }
862 return 0;
863 }
864 }
865
866 // Format 6: Trimmed table mapping
867 static class CMapFormat6 extends CMap {
868
869 char firstCode;
870 char entryCount;
871 char[] glyphIdArray;
872
873 CMapFormat6(ByteBuffer bbuffer, int offset, char[] xlat) {
874
875 bbuffer.position(offset+6);
876 CharBuffer buffer = bbuffer.asCharBuffer();
877 firstCode = buffer.get();
878 entryCount = buffer.get();
879 glyphIdArray = new char[entryCount];
880 for (int i=0; i< entryCount; i++) {
881 glyphIdArray[i] = buffer.get();
882 }
883 }
884
885 char getGlyph(int charCode) {
886 int controlGlyph = getControlCodeGlyph(charCode, true);
887 if (controlGlyph >= 0) {
888 return (char)controlGlyph;
889 }
890
891 if (xlat != null) {
892 charCode = xlat[charCode];
893 }
894
895 charCode -= firstCode;
896 if (charCode < 0 || charCode >= entryCount) {
897 return 0;
898 } else {
899 return glyphIdArray[charCode];
900 }
901 }
902 }
903
904 // Format 8: mixed 16-bit and 32-bit coverage
905 // Seems unlikely this code will ever get tested as we look for
906 // MS platform Cmaps and MS states (in the Opentype spec on their website)
907 // that MS doesn't support this format
908 static class CMapFormat8 extends CMap {
909 byte[] is32 = new byte[8192];
910 int nGroups;
911 int[] startCharCode;
912 int[] endCharCode;
913 int[] startGlyphID;
914
915 CMapFormat8(ByteBuffer bbuffer, int offset, char[] xlat) {
916
917 bbuffer.position(12);
1015 if (value >= 1 << 4) {
1016 value >>= 4;
1017 highBit += 4;
1018 }
1019
1020 if (value >= 1 << 2) {
1021 value >>= 2;
1022 highBit += 2;
1023 }
1024
1025 if (value >= 1 << 1) {
1026 value >>= 1;
1027 highBit += 1;
1028 }
1029
1030 power = 1 << highBit;
1031 extra = numGroups - power;
1032 }
1033
1034 char getGlyph(int charCode) {
1035 int controlGlyph = getControlCodeGlyph(charCode, false);
1036 if (controlGlyph >= 0) {
1037 return (char)controlGlyph;
1038 }
1039 int probe = power;
1040 int range = 0;
1041
1042 if (startCharCode[extra] <= charCode) {
1043 range = extra;
1044 }
1045
1046 while (probe > 1) {
1047 probe >>= 1;
1048
1049 if (startCharCode[range+probe] <= charCode) {
1050 range += probe;
1051 }
1052 }
1053
1054 if (startCharCode[range] <= charCode &&
1055 endCharCode[range] >= charCode) {
1056 return (char)
1057 (startGlyphID[range] + (charCode - startCharCode[range]));
1058 }
1059
1060 return 0;
1061 }
1062
1063 }
1064
1065 /* Used to substitute for bad Cmaps. */
1066 static class NullCMapClass extends CMap {
1067
1068 char getGlyph(int charCode) {
1069 return 0;
1070 }
1071 }
1072
1073 public static final NullCMapClass theNullCmap = new NullCMapClass();
1074
1075 final int getControlCodeGlyph(int charCode, boolean noSurrogates) {
1076 if (charCode < 0x0010) {
1077 switch (charCode) {
1078 case 0x0009:
1079 case 0x000a:
1080 case 0x000d: return CharToGlyphMapper.INVISIBLE_GLYPH_ID;
1081 }
1082 } else if (charCode >= 0x200c) {
1083 if ((charCode <= 0x200f) ||
1084 (charCode >= 0x2028 && charCode <= 0x202e) ||
1085 (charCode >= 0x206a && charCode <= 0x206f)) {
1086 return CharToGlyphMapper.INVISIBLE_GLYPH_ID;
1087 } else if (noSurrogates && charCode >= 0xFFFF) {
1088 return 0;
1089 }
1090 }
1091 return -1;
1092 }
1093
1094 static class UVS {
1095 int numSelectors;
1096 int[] selector;
1097
1098 //for Non-Default UVS Table
1099 int[] numUVSMapping;
1100 int[][] unicodeValue;
1101 char[][] glyphID;
1102
1103 UVS(ByteBuffer buffer, int offset) {
1104 numSelectors = buffer.getInt(offset+6);
1105 selector = new int[numSelectors];
1106 numUVSMapping = new int[numSelectors];
1107 unicodeValue = new int[numSelectors][];
1108 glyphID = new char[numSelectors][];
1109
1110 for (int i = 0; i < numSelectors; i++) {
1111 buffer.position(offset + 10 + i * 11);
|
549 /*
550 System.err.println("segcount="+segCount);
551 System.err.println("entrySelector="+entrySelector);
552 System.err.println("rangeShift="+rangeShift);
553 for (int j=0;j<segCount;j++) {
554 System.err.println("j="+j+ " sc="+(int)(startCount[j]&0xffff)+
555 " ec="+(int)(endCount[j]&0xffff)+
556 " delta="+idDelta[j] +
557 " ro="+(int)idRangeOffset[j]);
558 }
559
560 //System.err.println("numglyphs="+glyphIds.length);
561 for (int i=0;i<numGlyphIds;i++) {
562 System.err.println("gid["+i+"]="+(int)glyphIds[i]);
563 }
564 */
565 }
566
567 char getGlyph(int charCode) {
568
569 final int origCharCode = charCode;
570 int index = 0;
571 char glyphCode = 0;
572
573 int controlGlyph = getControlCodeGlyph(charCode, true);
574 if (controlGlyph >= 0) {
575 return (char)controlGlyph;
576 }
577
578 /* presence of translation array indicates that this
579 * cmap is in some other (non-unicode encoding).
580 * In order to look-up a char->glyph mapping we need to
581 * translate the unicode code point to the encoding of
582 * the cmap.
583 * REMIND: VALID CHARCODES??
584 */
585 if (xlat != null) {
586 charCode = xlat[charCode];
587 }
588
589 /*
621 if (rangeOffset == 0) {
622 glyphCode = (char)(charCode + idDelta[index]);
623 } else {
624 /* Calculate an index into the glyphIds array */
625
626 /*
627 System.err.println("rangeoffset="+rangeOffset+
628 " charCode=" + charCode +
629 " scnt["+index+"]="+(int)startCount[index] +
630 " segCnt="+segCount);
631 */
632
633 int glyphIDIndex = rangeOffset - segCount + index
634 + (charCode - startCount[index]);
635 glyphCode = glyphIds[glyphIDIndex];
636 if (glyphCode != 0) {
637 glyphCode = (char)(glyphCode + idDelta[index]);
638 }
639 }
640 }
641 if (glyphCode == 0) {
642 glyphCode = getFormatCharGlyph(origCharCode);
643 }
644 return glyphCode;
645 }
646 }
647
648 // Format 0: Byte Encoding table
649 static class CMapFormat0 extends CMap {
650 byte [] cmap;
651
652 CMapFormat0(ByteBuffer buffer, int offset) {
653
654 /* skip 6 bytes of format, length, and version */
655 int len = buffer.getChar(offset+2);
656 cmap = new byte[len-6];
657 buffer.position(offset+6);
658 buffer.get(cmap);
659 }
660
661 char getGlyph(int charCode) {
662 if (charCode < 256) {
788 idRangeOffSetArray = new char[numSubHeaders];
789 for (int i=0; i<numSubHeaders; i++) {
790 firstCodeArray[i] = cBuffer.get();
791 entryCountArray[i] = cBuffer.get();
792 idDeltaArray[i] = (short)cBuffer.get();
793 idRangeOffSetArray[i] = cBuffer.get();
794 // System.out.println("sh["+i+"]:fc="+(int)firstCodeArray[i]+
795 // " ec="+(int)entryCountArray[i]+
796 // " delta="+(int)idDeltaArray[i]+
797 // " offset="+(int)idRangeOffSetArray[i]);
798 }
799
800 int glyphIndexArrSize = (tableLen-518-numSubHeaders*8)/2;
801 glyphIndexArray = new char[glyphIndexArrSize];
802 for (int i=0; i<glyphIndexArrSize;i++) {
803 glyphIndexArray[i] = cBuffer.get();
804 }
805 }
806
807 char getGlyph(int charCode) {
808 final int origCharCode = charCode;
809 int controlGlyph = getControlCodeGlyph(charCode, true);
810 if (controlGlyph >= 0) {
811 return (char)controlGlyph;
812 }
813
814 if (xlat != null) {
815 charCode = xlat[charCode];
816 }
817
818 char highByte = (char)(charCode >> 8);
819 char lowByte = (char)(charCode & 0xff);
820 int key = subHeaderKey[highByte]>>3; // index into subHeaders
821 char mapMe;
822
823 if (key != 0) {
824 mapMe = lowByte;
825 } else {
826 mapMe = highByte;
827 if (mapMe == 0) {
828 mapMe = lowByte;
844 * the number of bytes from that location in the table where
845 * the subarray of glyphIndexes starting at "firstCode" begins.
846 * Each entry in the subHeader table is 8 bytes, and the
847 * idRangeOffSetArray field is at offset 6 in the entry.
848 * The glyphIndexArray immediately follows the subHeaders.
849 * So if there are "N" entries then the number of bytes to the
850 * start of glyphIndexArray is (N-key)*8-6.
851 * Subtract this from the idRangeOffSetArray value to get
852 * the number of bytes into glyphIndexArray and divide by 2 to
853 * get the (char) array index.
854 */
855 int glyphArrayOffset = ((idRangeOffSetArray.length-key)*8)-6;
856 int glyphSubArrayStart =
857 (idRangeOffSetArray[key] - glyphArrayOffset)/2;
858 char glyphCode = glyphIndexArray[glyphSubArrayStart+mapMe];
859 if (glyphCode != 0) {
860 glyphCode += idDeltaArray[key]; //idDelta
861 return glyphCode;
862 }
863 }
864 return getFormatCharGlyph(origCharCode);
865 }
866 }
867
868 // Format 6: Trimmed table mapping
869 static class CMapFormat6 extends CMap {
870
871 char firstCode;
872 char entryCount;
873 char[] glyphIdArray;
874
875 CMapFormat6(ByteBuffer bbuffer, int offset, char[] xlat) {
876
877 bbuffer.position(offset+6);
878 CharBuffer buffer = bbuffer.asCharBuffer();
879 firstCode = buffer.get();
880 entryCount = buffer.get();
881 glyphIdArray = new char[entryCount];
882 for (int i=0; i< entryCount; i++) {
883 glyphIdArray[i] = buffer.get();
884 }
885 }
886
887 char getGlyph(int charCode) {
888 final int origCharCode = charCode;
889 int controlGlyph = getControlCodeGlyph(charCode, true);
890 if (controlGlyph >= 0) {
891 return (char)controlGlyph;
892 }
893
894 if (xlat != null) {
895 charCode = xlat[charCode];
896 }
897
898 charCode -= firstCode;
899 if (charCode < 0 || charCode >= entryCount) {
900 return getFormatCharGlyph(origCharCode);
901 } else {
902 return glyphIdArray[charCode];
903 }
904 }
905 }
906
907 // Format 8: mixed 16-bit and 32-bit coverage
908 // Seems unlikely this code will ever get tested as we look for
909 // MS platform Cmaps and MS states (in the Opentype spec on their website)
910 // that MS doesn't support this format
911 static class CMapFormat8 extends CMap {
912 byte[] is32 = new byte[8192];
913 int nGroups;
914 int[] startCharCode;
915 int[] endCharCode;
916 int[] startGlyphID;
917
918 CMapFormat8(ByteBuffer bbuffer, int offset, char[] xlat) {
919
920 bbuffer.position(12);
1018 if (value >= 1 << 4) {
1019 value >>= 4;
1020 highBit += 4;
1021 }
1022
1023 if (value >= 1 << 2) {
1024 value >>= 2;
1025 highBit += 2;
1026 }
1027
1028 if (value >= 1 << 1) {
1029 value >>= 1;
1030 highBit += 1;
1031 }
1032
1033 power = 1 << highBit;
1034 extra = numGroups - power;
1035 }
1036
1037 char getGlyph(int charCode) {
1038 final int origCharCode = charCode;
1039 int controlGlyph = getControlCodeGlyph(charCode, false);
1040 if (controlGlyph >= 0) {
1041 return (char)controlGlyph;
1042 }
1043 int probe = power;
1044 int range = 0;
1045
1046 if (startCharCode[extra] <= charCode) {
1047 range = extra;
1048 }
1049
1050 while (probe > 1) {
1051 probe >>= 1;
1052
1053 if (startCharCode[range+probe] <= charCode) {
1054 range += probe;
1055 }
1056 }
1057
1058 if (startCharCode[range] <= charCode &&
1059 endCharCode[range] >= charCode) {
1060 return (char)
1061 (startGlyphID[range] + (charCode - startCharCode[range]));
1062 }
1063
1064 return getFormatCharGlyph(origCharCode);
1065 }
1066
1067 }
1068
1069 /* Used to substitute for bad Cmaps. */
1070 static class NullCMapClass extends CMap {
1071
1072 char getGlyph(int charCode) {
1073 return 0;
1074 }
1075 }
1076
1077 public static final NullCMapClass theNullCmap = new NullCMapClass();
1078
1079 final int getControlCodeGlyph(int charCode, boolean noSurrogates) {
1080 if (charCode < 0x0010) {
1081 switch (charCode) {
1082 case 0x0009:
1083 case 0x000a:
1084 case 0x000d: return CharToGlyphMapper.INVISIBLE_GLYPH_ID;
1085 }
1086 } else if (noSurrogates && charCode >= 0xFFFF) {
1087 return 0;
1088 }
1089 return -1;
1090 }
1091
1092 final char getFormatCharGlyph(int charCode) {
1093 if (charCode >= 0x200c) {
1094 if ((charCode <= 0x200f) ||
1095 (charCode >= 0x2028 && charCode <= 0x202e) ||
1096 (charCode >= 0x206a && charCode <= 0x206f)) {
1097 return (char)CharToGlyphMapper.INVISIBLE_GLYPH_ID;
1098 }
1099 }
1100 return 0;
1101 }
1102
1103 static class UVS {
1104 int numSelectors;
1105 int[] selector;
1106
1107 //for Non-Default UVS Table
1108 int[] numUVSMapping;
1109 int[][] unicodeValue;
1110 char[][] glyphID;
1111
1112 UVS(ByteBuffer buffer, int offset) {
1113 numSelectors = buffer.getInt(offset+6);
1114 selector = new int[numSelectors];
1115 numUVSMapping = new int[numSelectors];
1116 unicodeValue = new int[numSelectors][];
1117 glyphID = new char[numSelectors][];
1118
1119 for (int i = 0; i < numSelectors; i++) {
1120 buffer.position(offset + 10 + i * 11);
|