1 /* 2 * Copyright (c) 2000, 2013, 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 package sun.font; 27 28 import java.awt.Font; 29 import java.awt.font.GlyphVector; 30 import java.awt.font.FontRenderContext; 31 import java.util.concurrent.atomic.AtomicBoolean; 32 import sun.java2d.loops.FontInfo; 33 34 /* 35 * This class represents a list of actual renderable glyphs. 36 * It can be constructed from a number of text sources, representing 37 * the various ways in which a programmer can ask a Graphics2D object 38 * to render some text. Once constructed, it provides a way of iterating 39 * through the device metrics and graybits of the individual glyphs that 40 * need to be rendered to the screen. 41 * 42 * Note that this class holds pointers to native data which must be 43 * disposed. It is not marked as finalizable since it is intended 44 * to be very lightweight and finalization is a comparitively expensive 45 * procedure. The caller must specifically use try{} finally{} to 46 * manually ensure that the object is disposed after use, otherwise 47 * native data structures might be leaked. 48 * 49 * Here is a code sample for using this class: 50 * 51 * public void drawString(String str, FontInfo info, float x, float y) { 52 * GlyphList gl = GlyphList.getInstance(); 53 * try { 54 * gl.setFromString(info, str, x, y); 55 * int strbounds[] = gl.getBounds(); 56 * int numglyphs = gl.getNumGlyphs(); 57 * for (int i = 0; i < numglyphs; i++) { 58 * gl.setGlyphIndex(i); 59 * int metrics[] = gl.getMetrics(); 60 * byte bits[] = gl.getGrayBits(); 61 * int glyphx = metrics[0]; 62 * int glyphy = metrics[1]; 63 * int glyphw = metrics[2]; 64 * int glyphh = metrics[3]; 65 * int off = 0; 66 * for (int j = 0; j < glyphh; j++) { 67 * for (int i = 0; i < glyphw; i++) { 68 * int dx = glyphx + i; 69 * int dy = glyphy + j; 70 * int alpha = bits[off++]; 71 * drawPixel(alpha, dx, dy); 72 * } 73 * } 74 * } 75 * } finally { 76 * gl.dispose(); 77 * } 78 * } 79 */ 80 public final class GlyphList { 81 private static final int MINGRAYLENGTH = 1024; 82 private static final int MAXGRAYLENGTH = 8192; 83 private static final int DEFAULT_LENGTH = 32; 84 85 int glyphindex; 86 int metrics[]; 87 byte graybits[]; 88 89 /* A reference to the strike is needed for the case when the GlyphList 90 * may be added to a queue for batch processing, (e.g. OpenGL) and we need 91 * to be completely certain that the strike is still valid when the glyphs 92 * images are later referenced. This does mean that if such code discards 93 * GlyphList and places only the data it contains on the queue, that the 94 * strike needs to be part of that data held by a strong reference. 95 * In the cases of drawString() and drawChars(), this is a single strike, 96 * although it may be a composite strike. In the case of 97 * drawGlyphVector() it may be a single strike, or a list of strikes. 98 */ 99 Object strikelist; // hold multiple strikes during rendering of complex gv 100 101 /* In normal usage, the same GlyphList will get recycled, so 102 * it makes sense to allocate arrays that will get reused along with 103 * it, rather than generating garbage. Garbage will be generated only 104 * in MP envts where multiple threads are executing. Throughput should 105 * still be higher in those cases. 106 */ 107 int len = 0; 108 int maxLen = 0; 109 int maxPosLen = 0; 110 int glyphData[]; 111 char chData[]; 112 long images[]; 113 float positions[]; 114 float x, y; 115 float gposx, gposy; 116 boolean usePositions; 117 118 /* lcdRGBOrder is used only by LCD text rendering. Its here because 119 * the Graphics may have a different hint value than the one used 120 * by a GlyphVector, so it has to be stored here - and is obtained 121 * from the right FontInfo. Another approach would have been to have 122 * install a separate pipe for that case but that's a lot of extra 123 * code when a simple boolean will suffice. The overhead to non-LCD 124 * text is a redundant boolean assign per call. 125 */ 126 boolean lcdRGBOrder; 127 128 /* 129 * lcdSubPixPos is used only by LCD text rendering. Its here because 130 * the Graphics may have a different hint value than the one used 131 * by a GlyphVector, so it has to be stored here - and is obtained 132 * from the right FontInfo. Its also needed by the code which 133 * calculates glyph positions which already needs to access this 134 * GlyphList and would otherwise need the FontInfo. 135 * This is true only if LCD text and fractional metrics hints 136 * are selected on the graphics. 137 * When this is true and the glyph positions as determined by the 138 * advances are non-integral, it requests adjustment of the positions. 139 * Setting this for surfaces which do not support it through accelerated 140 * loops may cause a slow-down as software loops are invoked instead. 141 */ 142 boolean lcdSubPixPos; 143 144 /* This scheme creates a singleton GlyphList which is checked out 145 * for use. Callers who find its checked out create one that after use 146 * is discarded. This means that in a MT-rendering environment, 147 * there's no need to synchronise except for that one instance. 148 * Fewer threads will then need to synchronise, perhaps helping 149 * throughput on a MP system. If for some reason the reusable 150 * GlyphList is checked out for a long time (or never returned?) then 151 * we would end up always creating new ones. That situation should not 152 * occur and if it did, it would just lead to some extra garbage being 153 * created. 154 */ 155 private static final GlyphList reusableGL = new GlyphList(); 156 private static final AtomicBoolean inUse = new AtomicBoolean(); 157 158 159 void ensureCapacity(int len) { 160 /* Note len must not be -ve! only setFromChars should be capable 161 * of passing down a -ve len, and this guards against it. 162 */ 163 if (len < 0) { 164 len = 0; 165 } 166 if (usePositions && len > maxPosLen) { 167 positions = new float[len * 2 + 2]; 168 maxPosLen = len; 169 } 170 171 if (maxLen == 0 || len > maxLen) { 172 glyphData = new int[len]; 173 chData = new char[len]; 174 images = new long[len]; 175 maxLen = len; 176 } 177 } 178 179 private GlyphList() { 180 // ensureCapacity(DEFAULT_LENGTH); 181 } 182 183 // private GlyphList(int arraylen) { 184 // ensureCapacity(arraylen); 185 // } 186 187 public static GlyphList getInstance() { 188 if (inUse.compareAndSet(false, true)) { 189 return reusableGL; 190 } else { 191 return new GlyphList(); 192 } 193 } 194 195 /* In some cases the caller may be able to estimate the size of 196 * array needed, and it will usually be long enough. This avoids 197 * the unnecessary reallocation that occurs if our default 198 * values are too small. This is useful because this object 199 * will be discarded so the re-allocation overhead is high. 200 */ 201 // public static GlyphList getInstance(int sz) { 202 // if (inUse.compareAndSet(false, true) { 203 // return reusableGL; 204 // } else { 205 // return new GlyphList(sz); 206 // } 207 // } 208 209 /* GlyphList is in an invalid state until setFrom* method is called. 210 * After obtaining a new GlyphList it is the caller's responsibility 211 * that one of these methods is executed before handing off the 212 * GlyphList 213 */ 214 215 public boolean setFromString(FontInfo info, String str, float x, float y) { 216 this.x = x; 217 this.y = y; 218 this.strikelist = info.fontStrike; 219 this.lcdRGBOrder = info.lcdRGBOrder; 220 this.lcdSubPixPos = info.lcdSubPixPos; 221 len = str.length(); 222 ensureCapacity(len); 223 str.getChars(0, len, chData, 0); 224 return mapChars(info, len); 225 } 226 227 public boolean setFromChars(FontInfo info, char[] chars, int off, int alen, 228 float x, float y) { 229 this.x = x; 230 this.y = y; 231 this.strikelist = info.fontStrike; 232 this.lcdRGBOrder = info.lcdRGBOrder; 233 this.lcdSubPixPos = info.lcdSubPixPos; 234 len = alen; 235 if (alen < 0) { 236 len = 0; 237 } else { 238 len = alen; 239 } 240 ensureCapacity(len); 241 System.arraycopy(chars, off, chData, 0, len); 242 return mapChars(info, len); 243 } 244 245 private boolean mapChars(FontInfo info, int len) { 246 /* REMIND.Is it worthwhile for the iteration to convert 247 * chars to glyph ids to directly map to images? 248 */ 249 if (info.font2D.getMapper().charsToGlyphsNS(len, chData, glyphData)) { 250 return false; 251 } 252 info.fontStrike.getGlyphImagePtrs(glyphData, images, len); 253 glyphindex = -1; 254 return true; 255 } 256 257 258 public void setFromGlyphVector(FontInfo info, GlyphVector gv, 259 float x, float y) { 260 this.x = x; 261 this.y = y; 262 this.lcdRGBOrder = info.lcdRGBOrder; 263 this.lcdSubPixPos = info.lcdSubPixPos; 264 /* A GV may be rendered in different Graphics. It is possible it is 265 * used for one case where LCD text is available, and another where 266 * it is not. Pass in the "info". to ensure get a suitable one. 267 */ 268 StandardGlyphVector sgv = StandardGlyphVector.getStandardGV(gv, info); 269 // call before ensureCapacity :- 270 usePositions = sgv.needsPositions(info.devTx); 271 len = sgv.getNumGlyphs(); 272 ensureCapacity(len); 273 strikelist = sgv.setupGlyphImages(images, 274 usePositions ? positions : null, 275 info.devTx); 276 glyphindex = -1; 277 } 278 279 public int[] getBounds() { 280 /* We co-opt the 5 element array that holds per glyph metrics in order 281 * to return the bounds. So a caller must copy the data out of the 282 * array before calling any other methods on this GlyphList 283 */ 284 if (glyphindex >= 0) { 285 throw new InternalError("calling getBounds after setGlyphIndex"); 286 } 287 if (metrics == null) { 288 metrics = new int[5]; 289 } 290 /* gposx and gposy are used to accumulate the advance. 291 * Add 0.5f for consistent rounding to pixel position. */ 292 gposx = x + 0.5f; 293 gposy = y + 0.5f; 294 fillBounds(metrics); 295 return metrics; 296 } 297 298 /* This method now assumes "state", so must be called 0->len 299 * The metrics it returns are accumulated on the fly 300 * So it could be renamed "nextGlyph()". 301 * Note that a laid out GlyphVector which has assigned glyph positions 302 * doesn't have this stricture.. 303 */ 304 public void setGlyphIndex(int i) { 305 glyphindex = i; 306 float gx = 307 StrikeCache.unsafe.getFloat(images[i]+StrikeCache.topLeftXOffset); 308 float gy = 309 StrikeCache.unsafe.getFloat(images[i]+StrikeCache.topLeftYOffset); 310 311 if (usePositions) { 312 metrics[0] = (int)Math.floor(positions[(i<<1)] + gposx + gx); 313 metrics[1] = (int)Math.floor(positions[(i<<1)+1] + gposy + gy); 314 } else { 315 metrics[0] = (int)Math.floor(gposx + gx); 316 metrics[1] = (int)Math.floor(gposy + gy); 317 /* gposx and gposy are used to accumulate the advance */ 318 gposx += StrikeCache.unsafe.getFloat 319 (images[i]+StrikeCache.xAdvanceOffset); 320 gposy += StrikeCache.unsafe.getFloat 321 (images[i]+StrikeCache.yAdvanceOffset); 322 } 323 metrics[2] = 324 StrikeCache.unsafe.getChar(images[i]+StrikeCache.widthOffset); 325 metrics[3] = 326 StrikeCache.unsafe.getChar(images[i]+StrikeCache.heightOffset); 327 metrics[4] = 328 StrikeCache.unsafe.getChar(images[i]+StrikeCache.rowBytesOffset); 329 } 330 331 public int[] getMetrics() { 332 return metrics; 333 } 334 335 public byte[] getGrayBits() { 336 int len = metrics[4] * metrics[3]; 337 if (graybits == null) { 338 graybits = new byte[Math.max(len, MINGRAYLENGTH)]; 339 } else { 340 if (len > graybits.length) { 341 graybits = new byte[len]; 342 } 343 } 344 long pixelDataAddress = 345 StrikeCache.unsafe.getAddress(images[glyphindex] + 346 StrikeCache.pixelDataOffset); 347 348 if (pixelDataAddress == 0L) { 349 return graybits; 350 } 351 /* unsafe is supposed to be fast, but I doubt if this loop can beat 352 * a native call which does a getPrimitiveArrayCritical and a 353 * memcpy for the typical amount of image data (30-150 bytes) 354 * Consider a native method if there is a performance problem (which 355 * I haven't seen so far). 356 */ 357 for (int i=0; i<len; i++) { 358 graybits[i] = StrikeCache.unsafe.getByte(pixelDataAddress+i); 359 } 360 return graybits; 361 } 362 363 public long[] getImages() { 364 return images; 365 } 366 367 public boolean usePositions() { 368 return usePositions; 369 } 370 371 public float[] getPositions() { 372 return positions; 373 } 374 375 public float getX() { 376 return x; 377 } 378 379 public float getY() { 380 return y; 381 } 382 383 public Object getStrike() { 384 return strikelist; 385 } 386 387 public boolean isSubPixPos() { 388 return lcdSubPixPos; 389 } 390 391 public boolean isRGBOrder() { 392 return lcdRGBOrder; 393 } 394 395 /* There's a reference equality test overhead here, but it allows us 396 * to avoid synchronizing for GL's that will just be GC'd. This 397 * helps MP throughput. 398 */ 399 public void dispose() { 400 if (this == reusableGL) { 401 if (graybits != null && graybits.length > MAXGRAYLENGTH) { 402 graybits = null; 403 } 404 usePositions = false; 405 strikelist = null; // remove reference to the strike list 406 inUse.set(false); 407 } 408 } 409 410 /* The value here is for use by the rendering engine as it reflects 411 * the number of glyphs in the array to be blitted. Surrogates pairs 412 * may have two slots (the second of these being a dummy entry of the 413 * invisible glyph), whereas an application client would expect only 414 * one glyph. In other words don't propagate this value up to client code. 415 * 416 * {dlf} an application client should have _no_ expectations about the 417 * number of glyphs per char. This ultimately depends on the font 418 * technology and layout process used, which in general clients will 419 * know nothing about. 420 */ 421 public int getNumGlyphs() { 422 return len; 423 } 424 425 /* We re-do all this work as we iterate through the glyphs 426 * but it seems unavoidable without re-working the Java TextRenderers. 427 */ 428 private void fillBounds(int[] bounds) { 429 /* Faster to access local variables in the for loop? */ 430 int xOffset = StrikeCache.topLeftXOffset; 431 int yOffset = StrikeCache.topLeftYOffset; 432 int wOffset = StrikeCache.widthOffset; 433 int hOffset = StrikeCache.heightOffset; 434 int xAdvOffset = StrikeCache.xAdvanceOffset; 435 int yAdvOffset = StrikeCache.yAdvanceOffset; 436 437 if (len == 0) { 438 bounds[0] = bounds[1] = bounds[2] = bounds[3] = 0; 439 return; 440 } 441 float bx0, by0, bx1, by1; 442 bx0 = by0 = Float.POSITIVE_INFINITY; 443 bx1 = by1 = Float.NEGATIVE_INFINITY; 444 445 int posIndex = 0; 446 float glx = x + 0.5f; 447 float gly = y + 0.5f; 448 char gw, gh; 449 float gx, gy, gx0, gy0, gx1, gy1; 450 for (int i=0; i<len; i++) { 451 gx = StrikeCache.unsafe.getFloat(images[i]+xOffset); 452 gy = StrikeCache.unsafe.getFloat(images[i]+yOffset); 453 gw = StrikeCache.unsafe.getChar(images[i]+wOffset); 454 gh = StrikeCache.unsafe.getChar(images[i]+hOffset); 455 456 if (usePositions) { 457 gx0 = positions[posIndex++] + gx + glx; 458 gy0 = positions[posIndex++] + gy + gly; 459 } else { 460 gx0 = glx + gx; 461 gy0 = gly + gy; 462 glx += StrikeCache.unsafe.getFloat(images[i]+xAdvOffset); 463 gly += StrikeCache.unsafe.getFloat(images[i]+yAdvOffset); 464 } 465 gx1 = gx0 + gw; 466 gy1 = gy0 + gh; 467 if (bx0 > gx0) bx0 = gx0; 468 if (by0 > gy0) by0 = gy0; 469 if (bx1 < gx1) bx1 = gx1; 470 if (by1 < gy1) by1 = gy1; 471 } 472 /* floor is safe and correct because all glyph widths, heights 473 * and offsets are integers 474 */ 475 bounds[0] = (int)Math.floor(bx0); 476 bounds[1] = (int)Math.floor(by0); 477 bounds[2] = (int)Math.floor(bx1); 478 bounds[3] = (int)Math.floor(by1); 479 } 480 }