mirror of
https://github.com/openjdk/jdk.git
synced 2026-07-30 12:50:11 +00:00
8334495: Use FFM instead of jdk.internal.misc.Unsafe in java.desktop font implementation
Reviewed-by: jdv, dnguyen, achung
This commit is contained in:
parent
bbc79a5e01
commit
02be7b8ddc
@ -315,8 +315,7 @@ public class FileFontStrike extends PhysicalStrike {
|
||||
* 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 @@ public class FileFontStrike extends PhysicalStrike {
|
||||
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 @@ public class FileFontStrike extends PhysicalStrike {
|
||||
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 @@ public class FileFontStrike extends PhysicalStrike {
|
||||
|
||||
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 @@ public class FileFontStrike extends PhysicalStrike {
|
||||
}
|
||||
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. */
|
||||
|
||||
@ -319,10 +319,9 @@ public final class GlyphList {
|
||||
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 final class GlyphList {
|
||||
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 final class GlyphList {
|
||||
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 final class GlyphList {
|
||||
* 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 @@ public final class GlyphList {
|
||||
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 @@ public final class GlyphList {
|
||||
} 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 final class GlyphList {
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@ -27,6 +27,16 @@ package sun.font;
|
||||
|
||||
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.Disposer;
|
||||
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 @@ free native memory resources.
|
||||
|
||||
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;
|
||||
static final int nativeAddressSize = (int)ValueLayout.ADDRESS.byteSize();
|
||||
static final long invisibleGlyphPtr = getInvisibleGlyphPtr(); // a singleton.
|
||||
|
||||
/* 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 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 @@ public final class StrikeCache {
|
||||
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 @@ public final class StrikeCache {
|
||||
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>();
|
||||
|
||||
@ -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) {
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_sun_font_StrikeCache_getInvisibleGlyphPtr(JNIEnv *env, jclass cls) {
|
||||
|
||||
jlong* nresults;
|
||||
GlyphInfo *info;
|
||||
size_t baseAddr;
|
||||
|
||||
if ((*env)->GetArrayLength(env, results) < 13) {
|
||||
return;
|
||||
}
|
||||
|
||||
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 */
|
||||
}
|
||||
|
||||
@ -69,28 +69,25 @@ public class XRGlyphCacheEntry {
|
||||
}
|
||||
|
||||
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 class XRGlyphCacheEntry {
|
||||
}
|
||||
|
||||
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 class XRGlyphCacheEntry {
|
||||
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 class XRGlyphCacheEntry {
|
||||
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 class XRGlyphCacheEntry {
|
||||
}
|
||||
|
||||
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() {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user