1 /* 2 * Copyright (c) 2010, 2014, 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.io.*; 29 30 /** 31 * Stores glyph-related data, used in the pure-java glyphcache. 32 * 33 * @author Clemens Eisserer 34 */ 35 36 public class XRGlyphCacheEntry { 37 long glyphInfoPtr; 38 39 int lastUsed; 40 boolean pinned; 41 42 int xOff; 43 int yOff; 44 45 int glyphSet; 46 47 public XRGlyphCacheEntry(long glyphInfoPtr, GlyphList gl) { 48 this.glyphInfoPtr = glyphInfoPtr; 49 50 /* TODO: Does it make sence to cache results? */ 51 xOff = Math.round(getXAdvance()); 52 yOff = Math.round(getYAdvance()); 53 } 54 55 public int getXOff() { 56 return xOff; 57 } 58 59 public int getYOff() { 60 return yOff; 61 } 62 63 public void setGlyphSet(int glyphSet) { 64 this.glyphSet = glyphSet; 65 } 66 67 public int getGlyphSet() { 68 return glyphSet; 69 } 70 71 public static int getGlyphID(long glyphInfoPtr) { 72 // We need to access the GlyphID with Unsafe.getAddress() because the 73 // corresponding field in the underlying C data-structure is of type 74 // 'void*' (see field 'cellInfo' of struct 'GlyphInfo' 75 // in src/share/native/sun/font/fontscalerdefs.h). 76 // On 64-bit Big-endian architectures it would be wrong to access this 77 // field with Unsafe.getInt(). 78 return (int) StrikeCache.unsafe.getAddress(glyphInfoPtr + 79 StrikeCache.cacheCellOffset); 80 } 81 82 public static void setGlyphID(long glyphInfoPtr, int id) { 83 // We need to access the GlyphID with Unsafe.putAddress() because the 84 // corresponding field in the underlying C data-structure is of type 85 // 'void*' (see field 'cellInfo' of struct 'GlyphInfo' in 86 // src/share/native/sun/font/fontscalerdefs.h). 87 // On 64-bit Big-endian architectures it would be wrong to write this 88 // field with Unsafe.putInt() because it is also accessed from native 89 // code as a 'long'. 90 // See Java_sun_java2d_xr_XRBackendNative_XRAddGlyphsNative() 91 // in src/solaris/native/sun/java2d/x11/XRBackendNative.c 92 StrikeCache.unsafe.putAddress(glyphInfoPtr + 93 StrikeCache.cacheCellOffset, (long)id); 94 } 95 96 public int getGlyphID() { 97 return getGlyphID(glyphInfoPtr); 98 } 99 100 public void setGlyphID(int id) { 101 setGlyphID(glyphInfoPtr, id); 102 } 103 104 public float getXAdvance() { 105 return StrikeCache.unsafe.getFloat(glyphInfoPtr + StrikeCache.xAdvanceOffset); 106 } 107 108 public float getYAdvance() { 109 return StrikeCache.unsafe.getFloat(glyphInfoPtr + StrikeCache.yAdvanceOffset); 110 } 111 112 public int getSourceRowBytes() { 113 return StrikeCache.unsafe.getShort(glyphInfoPtr + StrikeCache.rowBytesOffset); 114 } 115 116 public int getWidth() { 117 return StrikeCache.unsafe.getShort(glyphInfoPtr + StrikeCache.widthOffset); 118 } 119 120 public int getHeight() { 121 return StrikeCache.unsafe.getShort(glyphInfoPtr + StrikeCache.heightOffset); 122 } 123 124 public void writePixelData(ByteArrayOutputStream os, boolean uploadAsLCD) { 125 long pixelDataAddress = 126 StrikeCache.unsafe.getAddress(glyphInfoPtr + 127 StrikeCache.pixelDataOffset); 128 if (pixelDataAddress == 0L) { 129 return; 130 } 131 132 int width = getWidth(); 133 int height = getHeight(); 134 int rowBytes = getSourceRowBytes(); 135 int paddedWidth = getPaddedWidth(uploadAsLCD); 136 137 if (!uploadAsLCD) { 138 for (int line = 0; line < height; line++) { 139 for(int x = 0; x < paddedWidth; x++) { 140 if(x < width) { 141 os.write(StrikeCache.unsafe.getByte(pixelDataAddress + (line * rowBytes + x))); 142 }else { 143 /*pad to multiple of 4 bytes per line*/ 144 os.write(0); 145 } 146 } 147 } 148 } else { 149 for (int line = 0; line < height; line++) { 150 int rowStart = line * rowBytes; 151 int rowBytesWidth = width * 3; 152 int srcpix = 0; 153 while (srcpix < rowBytesWidth) { 154 os.write(StrikeCache.unsafe.getByte 155 (pixelDataAddress + (rowStart + srcpix + 2))); 156 os.write(StrikeCache.unsafe.getByte 157 (pixelDataAddress + (rowStart + srcpix + 1))); 158 os.write(StrikeCache.unsafe.getByte 159 (pixelDataAddress + (rowStart + srcpix + 0))); 160 os.write(255); 161 srcpix += 3; 162 } 163 } 164 } 165 } 166 167 public float getTopLeftXOffset() { 168 return StrikeCache.unsafe.getFloat(glyphInfoPtr + StrikeCache.topLeftXOffset); 169 } 170 171 public float getTopLeftYOffset() { 172 return StrikeCache.unsafe.getFloat(glyphInfoPtr + StrikeCache.topLeftYOffset); 173 } 174 175 public long getGlyphInfoPtr() { 176 return glyphInfoPtr; 177 } 178 179 public boolean isGrayscale(boolean listContainsLCDGlyphs) { 180 return getSourceRowBytes() == getWidth() && !(getWidth() == 0 && getHeight() == 0 && listContainsLCDGlyphs); 181 } 182 183 public int getPaddedWidth(boolean listContainsLCDGlyphs) { 184 int width = getWidth(); 185 return isGrayscale(listContainsLCDGlyphs) ? (int) Math.ceil(width / 4.0) * 4 : width; 186 } 187 188 public int getDestinationRowBytes(boolean listContainsLCDGlyphs) { 189 boolean grayscale = isGrayscale(listContainsLCDGlyphs); 190 return grayscale ? getPaddedWidth(grayscale) : getWidth() * 4; 191 } 192 193 public int getGlyphDataLenth(boolean listContainsLCDGlyphs) { 194 return getDestinationRowBytes(listContainsLCDGlyphs) * getHeight(); 195 } 196 197 public void setPinned() { 198 pinned = true; 199 } 200 201 public void setUnpinned() { 202 pinned = false; 203 } 204 205 public int getLastUsed() { 206 return lastUsed; 207 } 208 209 public void setLastUsed(int lastUsed) { 210 this.lastUsed = lastUsed; 211 } 212 213 public int getPixelCnt() { 214 return getWidth() * getHeight(); 215 } 216 217 public boolean isPinned() { 218 return pinned; 219 } 220 }