1 /* 2 * Copyright (c) 1998, 2015, 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 * (C) Copyright IBM Corp. 1998-2003 - All Rights Reserved 28 */ 29 30 package sun.font; 31 32 import java.awt.Font; 33 import java.awt.font.FontRenderContext; 34 import java.awt.font.LineMetrics; 35 36 final class StandardTextSource extends TextSource { 37 38 private final char[] chars; 39 private final int start; 40 private final int len; 41 private final int cstart; 42 private final int clen; 43 private final int level; // assumed all uniform 44 private final int flags; // see GlyphVector.java 45 private final Font font; 46 private final FontRenderContext frc; 47 private final CoreMetrics cm; 48 49 /** 50 * Create a simple implementation of a TextSource. 51 * 52 * Chars is an array containing clen chars in the context, in 53 * logical order, contiguously starting at cstart. Start and len 54 * represent that portion of the context representing the true 55 * source; start, like cstart, is relative to the start of the 56 * character array. 57 * 58 * Level is the bidi level (0-63 for the entire context. Flags is 59 * the layout flags. Font is the font, frc is the render context, 60 * and lm is the line metrics for the entire source text, but not 61 * necessarily the context. 62 */ StandardTextSource(char[] chars, int start, int len, int cstart, int clen, int level, int flags, Font font, FontRenderContext frc, CoreMetrics cm)63 StandardTextSource(char[] chars, 64 int start, 65 int len, 66 int cstart, 67 int clen, 68 int level, 69 int flags, 70 Font font, 71 FontRenderContext frc, 72 CoreMetrics cm) { 73 if (chars == null) { 74 throw new IllegalArgumentException("bad chars: null"); 75 } 76 if (cstart < 0) { 77 throw new IllegalArgumentException("bad cstart: " + cstart); 78 } 79 if (start < cstart) { 80 throw new IllegalArgumentException("bad start: " + start + " for cstart: " + cstart); 81 } 82 if (clen < 0) { 83 throw new IllegalArgumentException("bad clen: " + clen); 84 } 85 if (cstart + clen > chars.length) { 86 throw new IllegalArgumentException("bad clen: " + clen + " cstart: " + cstart + " for array len: " + chars.length); 87 } 88 if (len < 0) { 89 throw new IllegalArgumentException("bad len: " + len); 90 } 91 if ((start + len) > (cstart + clen)) { 92 throw new IllegalArgumentException("bad len: " + len + " start: " + start + " for cstart: " + cstart + " clen: " + clen); 93 } 94 if (font == null) { 95 throw new IllegalArgumentException("bad font: null"); 96 } 97 if (frc == null) { 98 throw new IllegalArgumentException("bad frc: null"); 99 } 100 101 this.chars = chars; 102 this.start = start; 103 this.len = len; 104 this.cstart = cstart; 105 this.clen = clen; 106 this.level = level; 107 this.flags = flags; 108 this.font = font; 109 this.frc = frc; 110 111 if (cm != null) { 112 this.cm = cm; 113 } else { 114 LineMetrics metrics = font.getLineMetrics(chars, cstart, clen, frc); 115 this.cm = ((FontLineMetrics)metrics).cm; 116 } 117 } 118 119 // TextSource API 120 getChars()121 public char[] getChars() { 122 return chars; 123 } 124 getStart()125 public int getStart() { 126 return start; 127 } 128 getLength()129 public int getLength() { 130 return len; 131 } 132 getContextStart()133 public int getContextStart() { 134 return cstart; 135 } 136 getContextLength()137 public int getContextLength() { 138 return clen; 139 } 140 getLayoutFlags()141 public int getLayoutFlags() { 142 return flags; 143 } 144 getBidiLevel()145 public int getBidiLevel() { 146 return level; 147 } 148 getFont()149 public Font getFont() { 150 return font; 151 } 152 getFRC()153 public FontRenderContext getFRC() { 154 return frc; 155 } 156 getCoreMetrics()157 public CoreMetrics getCoreMetrics() { 158 return cm; 159 } 160 getSubSource(int start, int length, int dir)161 public TextSource getSubSource(int start, int length, int dir) { 162 if (start < 0 || length < 0 || (start + length) > len) { 163 throw new IllegalArgumentException("bad start (" + start + ") or length (" + length + ")"); 164 } 165 166 int level = this.level; 167 if (dir != TextLineComponent.UNCHANGED) { 168 boolean ltr = (flags & 0x8) == 0; 169 if (!(dir == TextLineComponent.LEFT_TO_RIGHT && ltr) && 170 !(dir == TextLineComponent.RIGHT_TO_LEFT && !ltr)) { 171 throw new IllegalArgumentException("direction flag is invalid"); 172 } 173 level = ltr? 0 : 1; 174 } 175 176 return new StandardTextSource(chars, this.start + start, length, cstart, clen, level, flags, font, frc, cm); 177 } 178 toString()179 public String toString() { 180 return toString(WITH_CONTEXT); 181 } 182 toString(boolean withContext)183 public String toString(boolean withContext) { 184 StringBuilder sb = new StringBuilder(super.toString()); 185 sb.append("[start:"); 186 sb.append(start); 187 sb.append(", len:" ); 188 sb.append(len); 189 sb.append(", cstart:"); 190 sb.append(cstart); 191 sb.append(", clen:" ); 192 sb.append(clen); 193 sb.append(", chars:\""); 194 int chStart, chLimit; 195 if (withContext == WITH_CONTEXT) { 196 chStart = cstart; 197 chLimit = cstart + clen; 198 } 199 else { 200 chStart = start; 201 chLimit = start + len; 202 } 203 for (int i = chStart; i < chLimit; ++i) { 204 if (i > chStart) { 205 sb.append(" "); 206 } 207 sb.append(Integer.toHexString(chars[i])); 208 } 209 sb.append("\""); 210 sb.append(", level:"); 211 sb.append(level); 212 sb.append(", flags:"); 213 sb.append(flags); 214 sb.append(", font:"); 215 sb.append(font); 216 sb.append(", frc:"); 217 sb.append(frc); 218 sb.append(", cm:"); 219 sb.append(cm); 220 sb.append("]"); 221 222 return sb.toString(); 223 } 224 } 225