diff --git a/src/java.desktop/share/classes/sun/font/FileFontStrike.java b/src/java.desktop/share/classes/sun/font/FileFontStrike.java index bf98b8ca57863..e6d07026a55bc 100644 --- a/src/java.desktop/share/classes/sun/font/FileFontStrike.java +++ b/src/java.desktop/share/classes/sun/font/FileFontStrike.java @@ -315,8 +315,7 @@ long getGlyphImageFromWindows(int glyphCode) { * work to the FM case. */ float advance = getGlyphAdvance(glyphCode, false); - StrikeCache.unsafe.putFloat(ptr + StrikeCache.xAdvanceOffset, - advance); + StrikeCache.setGlyphXAdvance(ptr, advance); return ptr; } else { if (FontUtilities.isLogging()) { @@ -665,8 +664,7 @@ private float getGlyphAdvance(int glyphCode, boolean getUserAdv) { glyphPtr = getCachedGlyphPtr(glyphCode); } if (glyphPtr != 0L) { - advance = StrikeCache.unsafe.getFloat - (glyphPtr + StrikeCache.xAdvanceOffset); + advance = StrikeCache.getGlyphXAdvance(glyphPtr); } else { advance = fileFont.getGlyphAdvance(pScalerContext, glyphCode); @@ -726,15 +724,13 @@ void getGlyphImageBounds(int glyphCode, Point2D.Float pt, return; } - topLeftX = StrikeCache.unsafe.getFloat(ptr+StrikeCache.topLeftXOffset); - topLeftY = StrikeCache.unsafe.getFloat(ptr+StrikeCache.topLeftYOffset); + topLeftX = StrikeCache.getGlyphTopLeftX(ptr); + topLeftY = StrikeCache.getGlyphTopLeftY(ptr); result.x = (int)Math.floor(pt.x + topLeftX + 0.5f); result.y = (int)Math.floor(pt.y + topLeftY + 0.5f); - result.width = - StrikeCache.unsafe.getShort(ptr+StrikeCache.widthOffset) &0x0ffff; - result.height = - StrikeCache.unsafe.getShort(ptr+StrikeCache.heightOffset) &0x0ffff; + result.width = StrikeCache.getGlyphWidth(ptr) & 0x0ffff; + result.height = StrikeCache.getGlyphHeight(ptr) & 0x0ffff; /* HRGB LCD text may have padding that is empty. This is almost always * going to be when topLeftX is -2 or less. @@ -755,25 +751,22 @@ void getGlyphImageBounds(int glyphCode, Point2D.Float pt, private int getGlyphImageMinX(long ptr, int origMinX) { - int width = StrikeCache.unsafe.getChar(ptr+StrikeCache.widthOffset); - int height = StrikeCache.unsafe.getChar(ptr+StrikeCache.heightOffset); - int rowBytes = - StrikeCache.unsafe.getChar(ptr+StrikeCache.rowBytesOffset); + int width = StrikeCache.getGlyphWidth(ptr); + int height = StrikeCache.getGlyphHeight(ptr); + int rowBytes = StrikeCache.getGlyphRowBytes(ptr); if (rowBytes == width) { return origMinX; } - long pixelData = - StrikeCache.unsafe.getAddress(ptr + StrikeCache.pixelDataOffset); - - if (pixelData == 0L) { + if (StrikeCache.getGlyphImagePtr(ptr) == 0L) { return origMinX; } + byte[] pixelData = StrikeCache.getGlyphPixelBytes(ptr); for (int y=0;y<height;y++) { for (int x=0;x<3;x++) { - if (StrikeCache.unsafe.getByte(pixelData+y*rowBytes+x) != 0) { + if (pixelData[(y*rowBytes)+x] != 0) { return origMinX; } } @@ -819,10 +812,8 @@ private Point2D.Float getGlyphMetrics(int glyphCode, boolean getImage) { } if (glyphPtr != 0L) { metrics = new Point2D.Float(); - metrics.x = StrikeCache.unsafe.getFloat - (glyphPtr + StrikeCache.xAdvanceOffset); - metrics.y = StrikeCache.unsafe.getFloat - (glyphPtr + StrikeCache.yAdvanceOffset); + metrics.x = StrikeCache.getGlyphXAdvance(glyphPtr); + metrics.y = StrikeCache.getGlyphYAdvance(glyphPtr); /* advance is currently in device space, need to convert back * into user space. * This must not include the translation component. */ diff --git a/src/java.desktop/share/classes/sun/font/GlyphList.java b/src/java.desktop/share/classes/sun/font/GlyphList.java index 8d19d005b89d3..df6ca08586cf0 100644 --- a/src/java.desktop/share/classes/sun/font/GlyphList.java +++ b/src/java.desktop/share/classes/sun/font/GlyphList.java @@ -319,10 +319,9 @@ public void setGlyphIndex(int i) { metrics[4] = 0; return; } - float gx = - StrikeCache.unsafe.getFloat(images[i]+StrikeCache.topLeftXOffset); - float gy = - StrikeCache.unsafe.getFloat(images[i]+StrikeCache.topLeftYOffset); + + float gx = StrikeCache.getGlyphTopLeftX(images[i]); + float gy = StrikeCache.getGlyphTopLeftY(images[i]); if (usePositions) { metrics[0] = (int)Math.floor(positions[(i<<1)] + gposx + gx); @@ -331,17 +330,12 @@ public void setGlyphIndex(int i) { metrics[0] = (int)Math.floor(gposx + gx); metrics[1] = (int)Math.floor(gposy + gy); /* gposx and gposy are used to accumulate the advance */ - gposx += StrikeCache.unsafe.getFloat - (images[i]+StrikeCache.xAdvanceOffset); - gposy += StrikeCache.unsafe.getFloat - (images[i]+StrikeCache.yAdvanceOffset); + gposx += StrikeCache.getGlyphXAdvance(images[i]); + gposy += StrikeCache.getGlyphYAdvance(images[i]); } - metrics[2] = - StrikeCache.unsafe.getChar(images[i]+StrikeCache.widthOffset); - metrics[3] = - StrikeCache.unsafe.getChar(images[i]+StrikeCache.heightOffset); - metrics[4] = - StrikeCache.unsafe.getChar(images[i]+StrikeCache.rowBytesOffset); + metrics[2] = StrikeCache.getGlyphWidth(images[i]); + metrics[3] = StrikeCache.getGlyphHeight(images[i]); + metrics[4] = StrikeCache.getGlyphRowBytes(images[i]); } public int[] getMetrics() { @@ -360,22 +354,12 @@ public byte[] getGrayBits() { if (images[glyphindex] == 0L) { return graybits; } - long pixelDataAddress = - StrikeCache.unsafe.getAddress(images[glyphindex] + - StrikeCache.pixelDataOffset); - + long pixelDataAddress = StrikeCache.getGlyphImagePtr(images[glyphindex]); if (pixelDataAddress == 0L) { return graybits; } - /* unsafe is supposed to be fast, but I doubt if this loop can beat - * a native call which does a getPrimitiveArrayCritical and a - * memcpy for the typical amount of image data (30-150 bytes) - * Consider a native method if there is a performance problem (which - * I haven't seen so far). - */ - for (int i=0; i<len; i++) { - graybits[i] = StrikeCache.unsafe.getByte(pixelDataAddress+i); - } + byte[] bytes = StrikeCache.getGlyphPixelBytes(images[glyphindex]); + System.arraycopy(bytes, 0, graybits, 0, bytes.length); return graybits; } @@ -445,13 +429,6 @@ public int getNumGlyphs() { * but it seems unavoidable without re-working the Java TextRenderers. */ private void fillBounds(int[] bounds, int endGlyphIndex) { - /* Faster to access local variables in the for loop? */ - int xOffset = StrikeCache.topLeftXOffset; - int yOffset = StrikeCache.topLeftYOffset; - int wOffset = StrikeCache.widthOffset; - int hOffset = StrikeCache.heightOffset; - int xAdvOffset = StrikeCache.xAdvanceOffset; - int yAdvOffset = StrikeCache.yAdvanceOffset; int startGlyphIndex = glyphindex + 1; if (startGlyphIndex >= endGlyphIndex) { @@ -471,10 +448,10 @@ private void fillBounds(int[] bounds, int endGlyphIndex) { if (images[i] == 0L) { continue; } - gx = StrikeCache.unsafe.getFloat(images[i]+xOffset); - gy = StrikeCache.unsafe.getFloat(images[i]+yOffset); - gw = StrikeCache.unsafe.getChar(images[i]+wOffset); - gh = StrikeCache.unsafe.getChar(images[i]+hOffset); + gx = StrikeCache.getGlyphTopLeftX(images[i]); + gy = StrikeCache.getGlyphTopLeftY(images[i]); + gw = StrikeCache.getGlyphWidth(images[i]); + gh = StrikeCache.getGlyphHeight(images[i]); if (usePositions) { gx0 = positions[posIndex++] + gx + glx; @@ -482,8 +459,8 @@ private void fillBounds(int[] bounds, int endGlyphIndex) { } else { gx0 = glx + gx; gy0 = gly + gy; - glx += StrikeCache.unsafe.getFloat(images[i]+xAdvOffset); - gly += StrikeCache.unsafe.getFloat(images[i]+yAdvOffset); + glx += StrikeCache.getGlyphXAdvance(images[i]); + gly += StrikeCache.getGlyphYAdvance(images[i]); } gx1 = gx0 + gw; gy1 = gy0 + gh; @@ -506,10 +483,8 @@ public static boolean canContainColorGlyphs() { } public boolean isColorGlyph(int glyphIndex) { - int width = StrikeCache.unsafe.getChar(images[glyphIndex] + - StrikeCache.widthOffset); - int rowBytes = StrikeCache.unsafe.getChar(images[glyphIndex] + - StrikeCache.rowBytesOffset); + int width = StrikeCache.getGlyphWidth(images[glyphIndex]); + int rowBytes = StrikeCache.getGlyphRowBytes(images[glyphIndex]); return rowBytes == width * 4; } diff --git a/src/java.desktop/share/classes/sun/font/StrikeCache.java b/src/java.desktop/share/classes/sun/font/StrikeCache.java index 950ba5b3d465b..ea1369b4383ac 100644 --- a/src/java.desktop/share/classes/sun/font/StrikeCache.java +++ b/src/java.desktop/share/classes/sun/font/StrikeCache.java @@ -27,6 +27,16 @@ import java.awt.GraphicsConfiguration; import java.awt.GraphicsEnvironment; + +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemorySegment; +import static java.lang.foreign.MemorySegment.NULL; +import java.lang.foreign.StructLayout; +import java.lang.foreign.ValueLayout; +import static java.lang.foreign.ValueLayout.*; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; + import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; @@ -37,7 +47,6 @@ import sun.java2d.pipe.BufferedContext; import sun.java2d.pipe.RenderQueue; import sun.java2d.pipe.hw.AccelGraphicsConfig; -import jdk.internal.misc.Unsafe; /** @@ -63,8 +72,6 @@ public final class StrikeCache { - static final Unsafe unsafe = Unsafe.getUnsafe(); - static ReferenceQueue<Object> refQueue = Disposer.getQueue(); static ArrayList<GlyphDisposedListener> disposeListeners = new ArrayList<GlyphDisposedListener>(1); @@ -98,40 +105,159 @@ public final class StrikeCache { static boolean cacheRefTypeWeak; /* - * Native sizes and offsets for glyph cache - * There are 10 values. + * Native sizes and accessors for glyph cache structure. + * There are 10 values. Also need native address size and a long which + * references a memory address for a "null" glyph image. */ - static int nativeAddressSize; - static int glyphInfoSize; - static int xAdvanceOffset; - static int yAdvanceOffset; - static int boundsOffset; - static int widthOffset; - static int heightOffset; - static int rowBytesOffset; - static int topLeftXOffset; - static int topLeftYOffset; - static int pixelDataOffset; - static int cacheCellOffset; - static int managedOffset; - static long invisibleGlyphPtr; - - /* Native method used to return information used for unsafe - * access to native data. - * return values as follows:- - * arr[0] = size of an address/pointer. - * arr[1] = size of a GlyphInfo - * arr[2] = offset of advanceX - * arr[3] = offset of advanceY - * arr[4] = offset of width - * arr[5] = offset of height - * arr[6] = offset of rowBytes - * arr[7] = offset of topLeftX - * arr[8] = offset of topLeftY - * arr[9] = offset of pixel data. - * arr[10] = address of a GlyphImageRef representing the invisible glyph - */ - static native void getGlyphCacheDescription(long[] infoArray); + static final int nativeAddressSize = (int)ValueLayout.ADDRESS.byteSize(); + static final long invisibleGlyphPtr = getInvisibleGlyphPtr(); // a singleton. + + static native long getInvisibleGlyphPtr(); + + public static final StructLayout GlyphImageLayout = MemoryLayout.structLayout( + JAVA_FLOAT.withName("xAdvance"), // 0+4=4, + JAVA_FLOAT.withName("yAdvance"), // 4+4=8, + JAVA_CHAR.withName("width"), // 8+2=10, + JAVA_CHAR.withName("height"), // 10+2=12 + JAVA_CHAR.withName("rowBytes"), // 12+2=14 + JAVA_BYTE.withName("managed"), // 14+1=15 + MemoryLayout.paddingLayout(1), // 15+1=16 + JAVA_FLOAT.withName("topLeftX"), // 16+4=20 + JAVA_FLOAT.withName("topLeftY"), // 20+4=24 + ADDRESS.withName("cellInfo"), // 24+8=32 + ADDRESS.withName("image") // 32+8=40 + ); + + private static final long GLYPHIMAGESIZE = GlyphImageLayout.byteSize(); + + private static VarHandle getVarHandle(StructLayout struct, String name) { + VarHandle h = struct.varHandle(PathElement.groupElement(name)); + /* insert 0 offset so don't need to pass arg every time */ + return MethodHandles.insertCoordinates(h, 1, 0L).withInvokeExactBehavior(); + } + + private static final VarHandle xAdvanceHandle = getVarHandle(GlyphImageLayout, "xAdvance"); + private static final VarHandle yAdvanceHandle = getVarHandle(GlyphImageLayout, "yAdvance"); + private static final VarHandle widthHandle = getVarHandle(GlyphImageLayout, "width"); + private static final VarHandle heightHandle = getVarHandle(GlyphImageLayout, "height"); + private static final VarHandle rowBytesHandle = getVarHandle(GlyphImageLayout, "rowBytes"); + private static final VarHandle managedHandle = getVarHandle(GlyphImageLayout, "managed"); + private static final VarHandle topLeftXHandle = getVarHandle(GlyphImageLayout, "topLeftX"); + private static final VarHandle topLeftYHandle = getVarHandle(GlyphImageLayout, "topLeftY"); + private static final VarHandle cellInfoHandle = getVarHandle(GlyphImageLayout, "cellInfo"); + private static final VarHandle imageHandle = getVarHandle(GlyphImageLayout, "image"); + + @SuppressWarnings("restricted") + static final float getGlyphXAdvance(long ptr) { + MemorySegment seg = MemorySegment.ofAddress(ptr); + seg = seg.reinterpret(GLYPHIMAGESIZE); + return (float)xAdvanceHandle.get(seg); + } + + @SuppressWarnings("restricted") + static final void setGlyphXAdvance(long ptr, float val) { + MemorySegment seg = MemorySegment.ofAddress(ptr); + seg = seg.reinterpret(GLYPHIMAGESIZE); + xAdvanceHandle.set(seg, val); + } + + @SuppressWarnings("restricted") + static final float getGlyphYAdvance(long ptr) { + MemorySegment seg = MemorySegment.ofAddress(ptr); + seg = seg.reinterpret(GLYPHIMAGESIZE); + return (float)yAdvanceHandle.get(seg); + } + + @SuppressWarnings("restricted") + static final char getGlyphWidth(long ptr) { + MemorySegment seg = MemorySegment.ofAddress(ptr); + seg = seg.reinterpret(GLYPHIMAGESIZE); + return (char)widthHandle.get(seg); + } + + @SuppressWarnings("restricted") + static final char getGlyphHeight(long ptr) { + MemorySegment seg = MemorySegment.ofAddress(ptr); + seg = seg.reinterpret(GLYPHIMAGESIZE); + return (char)heightHandle.get(seg); + } + + @SuppressWarnings("restricted") + static final char getGlyphRowBytes(long ptr) { + MemorySegment seg = MemorySegment.ofAddress(ptr); + seg = seg.reinterpret(GLYPHIMAGESIZE); + return (char)rowBytesHandle.get(seg); + } + + @SuppressWarnings("restricted") + static final byte getGlyphManaged(long ptr) { + MemorySegment seg = MemorySegment.ofAddress(ptr); + seg = seg.reinterpret(GLYPHIMAGESIZE); + return (byte)managedHandle.get(seg); + } + + @SuppressWarnings("restricted") + static final float getGlyphTopLeftX(long ptr) { + MemorySegment seg = MemorySegment.ofAddress(ptr); + seg = seg.reinterpret(GLYPHIMAGESIZE); + return (float)topLeftXHandle.get(seg); + } + + @SuppressWarnings("restricted") + static final float getGlyphTopLeftY(long ptr) { + MemorySegment seg = MemorySegment.ofAddress(ptr); + seg = seg.reinterpret(GLYPHIMAGESIZE); + return (float)topLeftYHandle.get(seg); + } + + @SuppressWarnings("restricted") + static final long getGlyphCellInfo(long ptr) { + MemorySegment seg = MemorySegment.ofAddress(ptr); + seg = seg.reinterpret(GLYPHIMAGESIZE); + return ((MemorySegment)cellInfoHandle.get(seg)).address(); + } + + @SuppressWarnings("restricted") + static final void setGlyphCellInfo(long ptr, long val) { + MemorySegment seg = MemorySegment.ofAddress(ptr); + seg = seg.reinterpret(GLYPHIMAGESIZE); + MemorySegment segval = MemorySegment.ofAddress(val); + cellInfoHandle.set(seg, segval); + } + + @SuppressWarnings("restricted") + static final long getGlyphImagePtr(long ptr) { + MemorySegment seg = MemorySegment.ofAddress(ptr); + seg = seg.reinterpret(GLYPHIMAGESIZE); + return ((MemorySegment)imageHandle.get(seg)).address(); + } + + @SuppressWarnings("restricted") + static final MemorySegment getGlyphPixelData(long ptr) { + MemorySegment seg = MemorySegment.ofAddress(ptr); + seg = seg.reinterpret(GLYPHIMAGESIZE); + char hgt = (char)heightHandle.get(seg); + char rb = (char)rowBytesHandle.get(seg); + MemorySegment pixelData = (MemorySegment)imageHandle.get(seg); + pixelData = pixelData.reinterpret(rb * hgt); + return pixelData; + } + + @SuppressWarnings("restricted") + static final byte[] getGlyphPixelBytes(long ptr) { + MemorySegment seg = MemorySegment.ofAddress(ptr); + seg = seg.reinterpret(GLYPHIMAGESIZE); + char hgt = (char)heightHandle.get(seg); + char rb = (char)rowBytesHandle.get(seg); + MemorySegment pixelData = (MemorySegment)imageHandle.get(seg); + int sz = rb * hgt; + pixelData = pixelData.reinterpret(sz); + return pixelData.toArray(ValueLayout.JAVA_BYTE); + } + + static final byte getPixelByte(MemorySegment pixelData, long index) { + return pixelData.getAtIndex(JAVA_BYTE, index); + } static { initStatic(); @@ -140,24 +266,6 @@ public final class StrikeCache { @SuppressWarnings("removal") private static void initStatic() { - long[] nativeInfo = new long[13]; - getGlyphCacheDescription(nativeInfo); - //Can also get address size from Unsafe class :- - //nativeAddressSize = unsafe.addressSize(); - nativeAddressSize = (int)nativeInfo[0]; - glyphInfoSize = (int)nativeInfo[1]; - xAdvanceOffset = (int)nativeInfo[2]; - yAdvanceOffset = (int)nativeInfo[3]; - widthOffset = (int)nativeInfo[4]; - heightOffset = (int)nativeInfo[5]; - rowBytesOffset = (int)nativeInfo[6]; - topLeftXOffset = (int)nativeInfo[7]; - topLeftYOffset = (int)nativeInfo[8]; - pixelDataOffset = (int)nativeInfo[9]; - invisibleGlyphPtr = nativeInfo[10]; - cacheCellOffset = (int) nativeInfo[11]; - managedOffset = (int) nativeInfo[12]; - if (nativeAddressSize < 4) { throw new InternalError("Unexpected address size for font data: " + nativeAddressSize); @@ -324,7 +432,7 @@ private static void freeCachedIntMemory(int[] glyphPtrs, long pContext) { ArrayList<Long> gids = null; for (int i = 0; i < glyphPtrs.length; i++) { - if (glyphPtrs[i] != 0 && unsafe.getByte(glyphPtrs[i] + managedOffset) == 0) { + if ((glyphPtrs[i] != 0) && getGlyphManaged(glyphPtrs[i]) == 0) { if (gids == null) { gids = new ArrayList<Long>(); @@ -350,8 +458,7 @@ private static void freeCachedLongMemory(long[] glyphPtrs, long pContext) { ArrayList<Long> gids = null; for (int i=0; i < glyphPtrs.length; i++) { - if (glyphPtrs[i] != 0 - && unsafe.getByte(glyphPtrs[i] + managedOffset) == 0) { + if ((glyphPtrs[i] != 0) && getGlyphManaged(glyphPtrs[i]) == 0) { if (gids == null) { gids = new ArrayList<Long>(); diff --git a/src/java.desktop/share/native/libfontmanager/sunFont.c b/src/java.desktop/share/native/libfontmanager/sunFont.c index b50a67e5c40b0..6029dc02d89b8 100644 --- a/src/java.desktop/share/native/libfontmanager/sunFont.c +++ b/src/java.desktop/share/native/libfontmanager/sunFont.c @@ -300,41 +300,9 @@ JNIEXPORT void JNICALL Java_sun_font_StrikeCache_freeLongMemory } } -JNIEXPORT void JNICALL -Java_sun_font_StrikeCache_getGlyphCacheDescription - (JNIEnv *env, jclass cls, jlongArray results) { - - jlong* nresults; - GlyphInfo *info; - size_t baseAddr; - - if ((*env)->GetArrayLength(env, results) < 13) { - return; - } +JNIEXPORT jlong JNICALL +Java_sun_font_StrikeCache_getInvisibleGlyphPtr(JNIEnv *env, jclass cls) { - nresults = (jlong*)(*env)->GetPrimitiveArrayCritical(env, results, NULL); - if (nresults == NULL) { - return; - } - info = (GlyphInfo*) calloc(1, sizeof(GlyphInfo)); - if (info == NULL) { - (*env)->ReleasePrimitiveArrayCritical(env, results, nresults, 0); - return; - } - baseAddr = (size_t)info; - nresults[0] = sizeof(void*); - nresults[1] = sizeof(GlyphInfo); - nresults[2] = 0; - nresults[3] = (size_t)&(info->advanceY)-baseAddr; - nresults[4] = (size_t)&(info->width)-baseAddr; - nresults[5] = (size_t)&(info->height)-baseAddr; - nresults[6] = (size_t)&(info->rowBytes)-baseAddr; - nresults[7] = (size_t)&(info->topLeftX)-baseAddr; - nresults[8] = (size_t)&(info->topLeftY)-baseAddr; - nresults[9] = (size_t)&(info->image)-baseAddr; - nresults[10] = (jlong)(uintptr_t)info; /* invisible glyph */ - nresults[11] = (size_t)&(info->cellInfo)-baseAddr; - nresults[12] = (size_t)&(info->managed)-baseAddr; - - (*env)->ReleasePrimitiveArrayCritical(env, results, nresults, 0); + GlyphInfo *info = (GlyphInfo*) calloc(1, sizeof(GlyphInfo)); + return (jlong)(uintptr_t)info; /* invisible glyph */ } diff --git a/src/java.desktop/unix/classes/sun/font/XRGlyphCacheEntry.java b/src/java.desktop/unix/classes/sun/font/XRGlyphCacheEntry.java index fff6919c464e9..cd090eab52ddd 100644 --- a/src/java.desktop/unix/classes/sun/font/XRGlyphCacheEntry.java +++ b/src/java.desktop/unix/classes/sun/font/XRGlyphCacheEntry.java @@ -69,28 +69,25 @@ public int getGlyphSet() { } public static int getGlyphID(long glyphInfoPtr) { - // We need to access the GlyphID with Unsafe.getAddress() because the + // We need to access the GlyphID as a long because the // corresponding field in the underlying C data-structure is of type // 'void*' (see field 'cellInfo' of struct 'GlyphInfo' // in src/share/native/sun/font/fontscalerdefs.h). // On 64-bit Big-endian architectures it would be wrong to access this - // field with Unsafe.getInt(). - return (int) StrikeCache.unsafe.getAddress(glyphInfoPtr + - StrikeCache.cacheCellOffset); + // field as an int. + return (int)StrikeCache.getGlyphCellInfo(glyphInfoPtr); } public static void setGlyphID(long glyphInfoPtr, int id) { - // We need to access the GlyphID with Unsafe.putAddress() because the + // We need to access the GlyphID as a long because the // corresponding field in the underlying C data-structure is of type - // 'void*' (see field 'cellInfo' of struct 'GlyphInfo' in - // src/share/native/sun/font/fontscalerdefs.h). - // On 64-bit Big-endian architectures it would be wrong to write this - // field with Unsafe.putInt() because it is also accessed from native - // code as a 'long'. + // 'void*' (see field 'cellInfo' of struct 'GlyphInfo' + // in src/share/native/sun/font/fontscalerdefs.h). + // On 64-bit Big-endian architectures it would be wrong to access this + // field as an int // See Java_sun_java2d_xr_XRBackendNative_XRAddGlyphsNative() - // in src/solaris/native/sun/java2d/x11/XRBackendNative.c - StrikeCache.unsafe.putAddress(glyphInfoPtr + - StrikeCache.cacheCellOffset, (long)id); + // in src/unix/native/sun/java2d/x11/XRBackendNative.c + StrikeCache.setGlyphCellInfo(glyphInfoPtr, (long)id); } public int getGlyphID() { @@ -102,29 +99,27 @@ public void setGlyphID(int id) { } public float getXAdvance() { - return StrikeCache.unsafe.getFloat(glyphInfoPtr + StrikeCache.xAdvanceOffset); + return StrikeCache.getGlyphXAdvance(glyphInfoPtr); } public float getYAdvance() { - return StrikeCache.unsafe.getFloat(glyphInfoPtr + StrikeCache.yAdvanceOffset); + return StrikeCache.getGlyphYAdvance(glyphInfoPtr); } public int getSourceRowBytes() { - return StrikeCache.unsafe.getShort(glyphInfoPtr + StrikeCache.rowBytesOffset); + return StrikeCache.getGlyphRowBytes(glyphInfoPtr); } public int getWidth() { - return StrikeCache.unsafe.getShort(glyphInfoPtr + StrikeCache.widthOffset); + return StrikeCache.getGlyphWidth(glyphInfoPtr); } public int getHeight() { - return StrikeCache.unsafe.getShort(glyphInfoPtr + StrikeCache.heightOffset); + return StrikeCache.getGlyphHeight(glyphInfoPtr); } public void writePixelData(ByteArrayOutputStream os, boolean uploadAsLCD) { - long pixelDataAddress = - StrikeCache.unsafe.getAddress(glyphInfoPtr + - StrikeCache.pixelDataOffset); + long pixelDataAddress = StrikeCache.getGlyphImagePtr(glyphInfoPtr); if (pixelDataAddress == 0L) { return; } @@ -134,11 +129,12 @@ public void writePixelData(ByteArrayOutputStream os, boolean uploadAsLCD) { int rowBytes = getSourceRowBytes(); int paddedWidth = getPaddedWidth(uploadAsLCD); + byte[] pixelBytes = StrikeCache.getGlyphPixelBytes(glyphInfoPtr); if (!uploadAsLCD) { for (int line = 0; line < height; line++) { for(int x = 0; x < paddedWidth; x++) { if(x < width) { - os.write(StrikeCache.unsafe.getByte(pixelDataAddress + (line * rowBytes + x))); + os.write(pixelBytes[(line * rowBytes + x)]); }else { /*pad to multiple of 4 bytes per line*/ os.write(0); @@ -151,12 +147,9 @@ public void writePixelData(ByteArrayOutputStream os, boolean uploadAsLCD) { int rowBytesWidth = width * 3; int srcpix = 0; while (srcpix < rowBytesWidth) { - os.write(StrikeCache.unsafe.getByte - (pixelDataAddress + (rowStart + srcpix + 2))); - os.write(StrikeCache.unsafe.getByte - (pixelDataAddress + (rowStart + srcpix + 1))); - os.write(StrikeCache.unsafe.getByte - (pixelDataAddress + (rowStart + srcpix + 0))); + os.write(pixelBytes[rowStart + srcpix + 2]); + os.write(pixelBytes[rowStart + srcpix + 1]); + os.write(pixelBytes[rowStart + srcpix + 0]); os.write(255); srcpix += 3; } @@ -165,11 +158,11 @@ public void writePixelData(ByteArrayOutputStream os, boolean uploadAsLCD) { } public float getTopLeftXOffset() { - return StrikeCache.unsafe.getFloat(glyphInfoPtr + StrikeCache.topLeftXOffset); + return StrikeCache.getGlyphTopLeftX(glyphInfoPtr); } public float getTopLeftYOffset() { - return StrikeCache.unsafe.getFloat(glyphInfoPtr + StrikeCache.topLeftYOffset); + return StrikeCache.getGlyphTopLeftY(glyphInfoPtr); } public long getGlyphInfoPtr() {