1/* 2 * Copyright (c) 2002, 2006, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26/* 27 */ 28 29package sun.font; 30 31import java.nio.ByteBuffer; 32import java.nio.CharBuffer; 33import java.nio.charset.Charset; 34import java.nio.charset.CharsetEncoder; 35import java.nio.charset.CoderResult; 36import sun.nio.cs.Surrogate; 37 38public abstract class DoubleByteEncoder 39 extends CharsetEncoder 40{ 41 42 private short index1[]; 43 private String index2[]; 44 45 private final Surrogate.Parser sgp = new Surrogate.Parser(); 46 47 protected DoubleByteEncoder(Charset cs, 48 short[] index1, String[] index2) 49 { 50 super(cs, 2.0f, 2.0f); 51 this.index1 = index1; 52 this.index2 = index2; 53 } 54 55 protected DoubleByteEncoder(Charset cs, 56 short[] index1, String[] index2, 57 float avg, float max) 58 { 59 super(cs, avg, max); 60 this.index1 = index1; 61 this.index2 = index2; 62 } 63 64 protected DoubleByteEncoder(Charset cs, 65 short[] index1, String[] index2, byte[] repl) 66 { 67 super(cs, 2.0f, 2.0f, repl); 68 this.index1 = index1; 69 this.index2 = index2; 70 } 71 72 73 protected DoubleByteEncoder(Charset cs, 74 short[] index1, String[] index2, 75 byte[] repl, float avg, float max) 76 { 77 super(cs, avg, max,repl); 78 this.index1 = index1; 79 this.index2 = index2; 80 } 81 82 public boolean canEncode(char c) { 83 return (encodeSingle(c) != -1 || 84 encodeDouble(c) != 0); 85 } 86 87 private CoderResult encodeArrayLoop(CharBuffer src, ByteBuffer dst) { 88 char[] sa = src.array(); 89 int sp = src.arrayOffset() + src.position(); 90 int sl = src.arrayOffset() + src.limit(); 91 byte[] da = dst.array(); 92 int dp = dst.arrayOffset() + dst.position(); 93 int dl = dst.arrayOffset() + dst.limit(); 94 95 try { 96 while (sp < sl) { 97 char c = sa[sp]; 98 if (Character.isSurrogate(c)) { 99 if (sgp.parse(c, sa, sp, sl) < 0) 100 return sgp.error(); 101 if (sl - sp < 2) 102 return CoderResult.UNDERFLOW; 103 char c2 = sa[sp + 1]; 104 105 byte[] outputBytes = new byte[2]; 106 outputBytes = encodeSurrogate(c, c2); 107 108 if (outputBytes == null) { 109 return sgp.unmappableResult(); 110 } 111 else { 112 if (dl - dp < 2) 113 return CoderResult.OVERFLOW; 114 da[dp++] = outputBytes[0]; 115 da[dp++] = outputBytes[1]; 116 sp += 2; 117 continue; 118 } 119 } 120 if (c >= '\uFFFE') 121 return CoderResult.unmappableForLength(1); 122 123 int b = encodeSingle(c); 124 if (b != -1) { // Single Byte 125 if (dl - dp < 1) 126 return CoderResult.OVERFLOW; 127 da[dp++] = (byte)b; 128 sp++; 129 continue; 130 } 131 132 int ncode = encodeDouble(c); 133 if (ncode != 0 && c != '\u0000' ) { 134 if (dl - dp < 2) 135 return CoderResult.OVERFLOW; 136 da[dp++] = (byte) ((ncode & 0xff00) >> 8); 137 da[dp++] = (byte) (ncode & 0xff); 138 sp++; 139 continue; 140 } 141 return CoderResult.unmappableForLength(1); 142 } 143 return CoderResult.UNDERFLOW; 144 } finally { 145 src.position(sp - src.arrayOffset()); 146 dst.position(dp - dst.arrayOffset()); 147 } 148 } 149 150 private CoderResult encodeBufferLoop(CharBuffer src, ByteBuffer dst) { 151 int mark = src.position(); 152 153 try { 154 while (src.hasRemaining()) { 155 char c = src.get(); 156 if (Character.isSurrogate(c)) { 157 int surr; 158 if ((surr = sgp.parse(c, src)) < 0) 159 return sgp.error(); 160 char c2 = Surrogate.low(surr); 161 byte[] outputBytes = new byte[2]; 162 outputBytes = encodeSurrogate(c, c2); 163 164 if (outputBytes == null) { 165 return sgp.unmappableResult(); 166 } else { 167 if (dst.remaining() < 2) 168 return CoderResult.OVERFLOW; 169 mark += 2; 170 dst.put(outputBytes[0]); 171 dst.put(outputBytes[1]); 172 continue; 173 } 174 } 175 if (c >= '\uFFFE') 176 return CoderResult.unmappableForLength(1); 177 int b = encodeSingle(c); 178 179 if (b != -1) { // Single-byte character 180 if (dst.remaining() < 1) 181 return CoderResult.OVERFLOW; 182 mark++; 183 dst.put((byte)b); 184 continue; 185 } 186 // Double Byte character 187 188 int ncode = encodeDouble(c); 189 if (ncode != 0 && c != '\u0000') { 190 if (dst.remaining() < 2) 191 return CoderResult.OVERFLOW; 192 mark++; 193 dst.put((byte) ((ncode & 0xff00) >> 8)); 194 dst.put((byte) ncode); 195 continue; 196 } 197 return CoderResult.unmappableForLength(1); 198 } 199 200 return CoderResult.UNDERFLOW; 201 } finally { 202 src.position(mark); 203 } 204 } 205 206 protected CoderResult encodeLoop(CharBuffer src, ByteBuffer dst) { 207 if (true && src.hasArray() && dst.hasArray()) 208 return encodeArrayLoop(src, dst); 209 else 210 return encodeBufferLoop(src, dst); 211 } 212 213 /* 214 * Can be changed by subclass 215 */ 216 protected int encodeDouble(char ch) { 217 int offset = index1[((ch & 0xff00) >> 8 )] << 8; 218 return index2[offset >> 12].charAt((offset & 0xfff) + (ch & 0xff)); 219 } 220 221 /* 222 * Can be changed by subclass 223 */ 224 protected int encodeSingle(char inputChar) { 225 if (inputChar < 0x80) 226 return (byte)inputChar; 227 else 228 return -1; 229 } 230 231 /** 232 * Protected method which should be overridden by concrete DBCS 233 * CharsetEncoder classes which included supplementary characters 234 * within their mapping coverage. 235 * null return value indicates surrogate values could not be 236 * handled or encoded. 237 */ 238 protected byte[] encodeSurrogate(char highSurrogate, char lowSurrogate) { 239 return null; 240 } 241} 242