improve kitty image data handling
This commit is contained in:
@@ -30,6 +30,14 @@ public final class KittyGraphics {
|
|||||||
return placements(KittyPlacementLayer.ALL);
|
return placements(KittyPlacementLayer.ALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Whether any placement exists, without materializing the placement list or its per-image
|
||||||
|
// render info. Cheap enough to call every frame to decide the render path.
|
||||||
|
public boolean isEmpty() {
|
||||||
|
try (KittyPlacementIterator iterator = KittyPlacementIterator.open(library, graphics, KittyPlacementLayer.ALL)) {
|
||||||
|
return !iterator.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public List<KittyPlacement> placements(KittyPlacementLayer layer) {
|
public List<KittyPlacement> placements(KittyPlacementLayer layer) {
|
||||||
try (KittyPlacementIterator iterator = KittyPlacementIterator.open(library, graphics, layer)) {
|
try (KittyPlacementIterator iterator = KittyPlacementIterator.open(library, graphics, layer)) {
|
||||||
List<KittyPlacement> placements = new ArrayList<>();
|
List<KittyPlacement> placements = new ArrayList<>();
|
||||||
@@ -53,7 +61,7 @@ public final class KittyGraphics {
|
|||||||
iterator.getU32(GhosttyLibrary.KITTY_GRAPHICS_PLACEMENT_DATA_COLUMNS),
|
iterator.getU32(GhosttyLibrary.KITTY_GRAPHICS_PLACEMENT_DATA_COLUMNS),
|
||||||
iterator.getU32(GhosttyLibrary.KITTY_GRAPHICS_PLACEMENT_DATA_ROWS),
|
iterator.getU32(GhosttyLibrary.KITTY_GRAPHICS_PLACEMENT_DATA_ROWS),
|
||||||
iterator.getI32(GhosttyLibrary.KITTY_GRAPHICS_PLACEMENT_DATA_Z),
|
iterator.getI32(GhosttyLibrary.KITTY_GRAPHICS_PLACEMENT_DATA_Z),
|
||||||
image.map(KittyImage::snapshot),
|
image,
|
||||||
Optional.ofNullable(renderInfo)
|
Optional.ofNullable(renderInfo)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,16 +13,46 @@ public final class KittyImage {
|
|||||||
this.handle = handle;
|
this.handle = handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cheap metadata accessors: a single native field read each, no pixel-buffer copy. Use these
|
||||||
|
// to build cache keys; only call data() once you've decided you actually need the bytes.
|
||||||
|
|
||||||
|
public long id() {
|
||||||
|
return library.kittyImageGetU32(handle, GhosttyLibrary.KITTY_IMAGE_DATA_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long number() {
|
||||||
|
return library.kittyImageGetU32(handle, GhosttyLibrary.KITTY_IMAGE_DATA_NUMBER);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long width() {
|
||||||
|
return library.kittyImageGetU32(handle, GhosttyLibrary.KITTY_IMAGE_DATA_WIDTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long height() {
|
||||||
|
return library.kittyImageGetU32(handle, GhosttyLibrary.KITTY_IMAGE_DATA_HEIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public KittyImageFormat format() {
|
||||||
|
return KittyImageFormat.fromNative(library.kittyImageGetI32(handle, GhosttyLibrary.KITTY_IMAGE_DATA_FORMAT));
|
||||||
|
}
|
||||||
|
|
||||||
|
public KittyImageCompression compression() {
|
||||||
|
return KittyImageCompression.fromNative(library.kittyImageGetI32(handle, GhosttyLibrary.KITTY_IMAGE_DATA_COMPRESSION));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Byte length of the pixel buffer, read without copying it.
|
||||||
|
public long dataLength() {
|
||||||
|
return library.kittyImageDataLength(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copies the pixel buffer out of native memory. Expensive for large images; call only when
|
||||||
|
// the decoded image isn't already cached.
|
||||||
|
public byte[] data() {
|
||||||
|
return library.kittyImageData(handle);
|
||||||
|
}
|
||||||
|
|
||||||
public KittyImageSnapshot snapshot() {
|
public KittyImageSnapshot snapshot() {
|
||||||
return new KittyImageSnapshot(
|
return new KittyImageSnapshot(id(), number(), width(), height(), format(), compression(), data());
|
||||||
library.kittyImageGetU32(handle, GhosttyLibrary.KITTY_IMAGE_DATA_ID),
|
|
||||||
library.kittyImageGetU32(handle, GhosttyLibrary.KITTY_IMAGE_DATA_NUMBER),
|
|
||||||
library.kittyImageGetU32(handle, GhosttyLibrary.KITTY_IMAGE_DATA_WIDTH),
|
|
||||||
library.kittyImageGetU32(handle, GhosttyLibrary.KITTY_IMAGE_DATA_HEIGHT),
|
|
||||||
KittyImageFormat.fromNative(library.kittyImageGetI32(handle, GhosttyLibrary.KITTY_IMAGE_DATA_FORMAT)),
|
|
||||||
KittyImageCompression.fromNative(library.kittyImageGetI32(handle, GhosttyLibrary.KITTY_IMAGE_DATA_COMPRESSION)),
|
|
||||||
library.kittyImageData(handle)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MemorySegment handle() {
|
MemorySegment handle() {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public record KittyPlacement(
|
|||||||
long columns,
|
long columns,
|
||||||
long rows,
|
long rows,
|
||||||
int z,
|
int z,
|
||||||
Optional<KittyImageSnapshot> image,
|
Optional<KittyImage> image,
|
||||||
Optional<KittyRenderInfo> renderInfo
|
Optional<KittyRenderInfo> renderInfo
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1434,6 +1434,19 @@ public final class GhosttyLibrary {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Length of the image's pixel buffer without copying it out of native memory. Lets callers
|
||||||
|
// build a cache key cheaply and only pull the bytes (kittyImageData) on a cache miss.
|
||||||
|
public long kittyImageDataLength(MemorySegment image) {
|
||||||
|
try (Arena arena = Arena.ofConfined()) {
|
||||||
|
MemorySegment outLen = arena.allocate(C_SIZE_T);
|
||||||
|
int result = (int) kittyGraphicsImageGet.invoke(image, KITTY_IMAGE_DATA_DATA_LEN, outLen);
|
||||||
|
checkResult("ghostty_kitty_graphics_image_get", result);
|
||||||
|
return outLen.get(C_SIZE_T, 0);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
return rethrow(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public MemorySegment kittyPlacementIteratorNew() {
|
public MemorySegment kittyPlacementIteratorNew() {
|
||||||
try (Arena arena = Arena.ofConfined()) {
|
try (Arena arena = Arena.ofConfined()) {
|
||||||
MemorySegment out = arena.allocate(C_POINTER);
|
MemorySegment out = arena.allocate(C_POINTER);
|
||||||
|
|||||||
Reference in New Issue
Block a user