1 /* 2 * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Sun designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Sun in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 22 * CA 95054 USA or visit www.sun.com if you need additional information or 23 * have any questions. 24 */ 25 26 package sun.font; 27 28 /* 29 * This isn't a critical performance case, so don't do any 30 * char->glyph map caching for Type1 fonts. The ones that are used 31 * in composites will be cached there. 32 */ 33 34 public final class Type1GlyphMapper extends CharToGlyphMapper { 35 36 Type1Font font; 37 FontScaler scaler; 38 39 public Type1GlyphMapper(Type1Font font) { 40 this.font = font; 41 initMapper(); 42 } 43 44 private void initMapper() { 45 scaler = font.getScaler(); 46 try { 47 missingGlyph = scaler.getMissingGlyphCode(); 48 } catch (FontScalerException fe) { 49 scaler = FontScaler.getNullScaler(); 50 try { 51 missingGlyph = scaler.getMissingGlyphCode(); 52 } catch (FontScalerException e) { //should not happen 53 missingGlyph = 0; 54 } 55 } 56 } 57 58 public int getNumGlyphs() { 59 try { 60 return scaler.getNumGlyphs(); 61 } catch (FontScalerException e) { 62 scaler = FontScaler.getNullScaler(); 63 return getNumGlyphs(); 64 } 65 } 66 67 public int getMissingGlyphCode() { 68 return missingGlyph; 69 } 70 71 public boolean canDisplay(char ch) { 72 try { 73 return scaler.getGlyphCode(ch) != missingGlyph; 74 } catch(FontScalerException e) { 75 scaler = FontScaler.getNullScaler(); 76 return canDisplay(ch); 77 } 78 } 79 80 public int charToGlyph(char ch) { 81 try { 82 return scaler.getGlyphCode(ch); 83 } catch (FontScalerException e) { 84 scaler = FontScaler.getNullScaler(); 85 return charToGlyph(ch); 86 } 87 } 88 89 public int charToGlyph(int ch) { 90 if (ch < 0 || ch > 0xffff) { 91 return missingGlyph; 92 } else { 93 try { 94 return scaler.getGlyphCode((char)ch); 95 } catch (FontScalerException e) { 96 scaler = FontScaler.getNullScaler(); 97 return charToGlyph(ch); 98 } 99 } 100 } 101 102 public void charsToGlyphs(int count, char[] unicodes, int[] glyphs) { 103 /* The conversion into surrogates is misleading. 104 * The Type1 glyph mapper only accepts 16 bit unsigned shorts. 105 * If its > not in the range it can use assign the missing glyph. 106 */ 107 for (int i=0; i<count; i++) { 108 int code = unicodes[i]; // char is unsigned. 109 110 if (code >= HI_SURROGATE_START && 111 code <= HI_SURROGATE_END && i < count - 1) { 112 char low = unicodes[i + 1]; 113 114 if (low >= LO_SURROGATE_START && 115 low <= LO_SURROGATE_END) { 116 code = (code - HI_SURROGATE_START) * 117 0x400 + low - LO_SURROGATE_START + 0x10000; 118 glyphs[i + 1] = 0xFFFF; // invisible glyph 119 } 120 } 121 glyphs[i] = charToGlyph(code); 122 if (code >= 0x10000) { 123 i += 1; // Empty glyph slot after surrogate 124 } 125 } 126 } 127 128 public void charsToGlyphs(int count, int[] unicodes, int[] glyphs) { 129 /* I believe this code path is never exercised. Its there mainly 130 * for surrogates and/or the opentype engine which aren't likely 131 * to be an issue for Type1 fonts. So no need to optimise it. 132 */ 133 for (int i=0; i<count; i++) { 134 glyphs[i] = charToGlyph(unicodes[i]); 135 } 136 } 137 138 139 /* This variant checks if shaping is needed and immediately 140 * returns true if it does. A caller of this method should be expecting 141 * to check the return type because it needs to know how to handle 142 * the character data for display. 143 */ 144 public boolean charsToGlyphsNS(int count, char[] unicodes, int[] glyphs) { 145 146 for (int i=0; i<count; i++) { 147 int code = unicodes[i]; // char is unsigned. 148 149 if (code >= HI_SURROGATE_START && 150 code <= HI_SURROGATE_END && i < count - 1) { 151 char low = unicodes[i + 1]; 152 153 if (low >= LO_SURROGATE_START && 154 low <= LO_SURROGATE_END) { 155 code = (code - HI_SURROGATE_START) * 156 0x400 + low - LO_SURROGATE_START + 0x10000; 157 glyphs[i + 1] = INVISIBLE_GLYPH_ID; 158 } 159 } 160 161 glyphs[i] = charToGlyph(code); 162 163 if (code < FontUtilities.MIN_LAYOUT_CHARCODE) { 164 continue; 165 } 166 else if (FontUtilities.isComplexCharCode(code)) { 167 return true; 168 } 169 else if (code >= 0x10000) { 170 i += 1; // Empty glyph slot after surrogate 171 continue; 172 } 173 } 174 175 return false; 176 } 177 }