shared/java/Surface.java (453 lines of code) (raw):
package org.jetbrains.skija;
import java.lang.ref.*;
import org.jetbrains.annotations.*;
import org.jetbrains.skija.impl.*;
public class Surface extends RefCnt {
static {
Library.staticLoad();
}
@ApiStatus.Internal public final DirectContext _context;
@ApiStatus.Internal public final BackendRenderTarget _renderTarget;
@NotNull @Contract("_ -> new")
public static Surface makeRasterDirect(@NotNull Pixmap pixmap) {
return makeRasterDirect(pixmap, null);
}
/**
* <p>Allocates raster Surface. Canvas returned by Surface draws directly into pixels.</p>
*
* <p>Surface is returned if all parameters are valid. Valid parameters include:</p>
*
* <ul><li>info dimensions are greater than zero;</li>
* <li>info contains ColorType and AlphaType supported by raster surface;</li>
* <li>pixelsPtr is not 0;</li>
* <li>rowBytes is large enough to contain info width pixels of ColorType.</li></ul>
*
* <p>Pixel buffer size should be info height times computed rowBytes.</p>
*
* <p>Pixels are not initialized.</p>
*
* <p>To access pixels after drawing, peekPixels() or readPixels().</p>
*
* @param imageInfo width, height, ColorType, AlphaType, ColorSpace,
* of raster surface; width and height must be greater than zero
* @param pixelsPtr pointer to destination pixels buffer
* @param rowBytes memory address of destination native pixels buffer
* @return created Surface
*/
@NotNull @Contract("_, _, _ -> new")
public static Surface makeRasterDirect(@NotNull ImageInfo imageInfo,
long pixelsPtr,
long rowBytes) {
return makeRasterDirect(imageInfo, pixelsPtr, rowBytes, null);
}
@NotNull @Contract("_, _ -> new")
public static Surface makeRasterDirect(@NotNull Pixmap pixmap,
@Nullable SurfaceProps surfaceProps) {
try {
assert pixmap != null : "Can’t makeRasterDirect with pixmap == null";
Stats.onNativeCall();
long ptr = _nMakeRasterDirectWithPixmap(
Native.getPtr(pixmap), surfaceProps
);
if (ptr == 0)
throw new IllegalArgumentException(String.format("Failed Surface.makeRasterDirect(%s, %s)", pixmap, surfaceProps));
return new Surface(ptr);
} finally {
Reference.reachabilityFence(pixmap);
}
}
/**
* <p>Allocates raster Surface. Canvas returned by Surface draws directly into pixels.</p>
*
* <p>Surface is returned if all parameters are valid. Valid parameters include:</p>
*
* <ul><li>info dimensions are greater than zero;</li>
* <li>info contains ColorType and AlphaType supported by raster surface;</li>
* <li>pixelsPtr is not 0;</li>
* <li>rowBytes is large enough to contain info width pixels of ColorType.</li></ul>
*
* <p>Pixel buffer size should be info height times computed rowBytes.</p>
*
* <p>Pixels are not initialized.</p>
*
* <p>To access pixels after drawing, peekPixels() or readPixels().</p>
*
* @param imageInfo width, height, ColorType, AlphaType, ColorSpace,
* of raster surface; width and height must be greater than zero
* @param pixelsPtr pointer to destination pixels buffer
* @param rowBytes memory address of destination native pixels buffer
* @param surfaceProps LCD striping orientation and setting for device independent fonts;
* may be null
* @return created Surface
*/
@NotNull @Contract("_, _, _, _ -> new")
public static Surface makeRasterDirect(@NotNull ImageInfo imageInfo,
long pixelsPtr,
long rowBytes,
@Nullable SurfaceProps surfaceProps) {
try {
assert imageInfo != null : "Can’t makeRasterDirect with imageInfo == null";
Stats.onNativeCall();
long ptr = _nMakeRasterDirect(
imageInfo._width,
imageInfo._height,
imageInfo._colorInfo._colorType.ordinal(),
imageInfo._colorInfo._alphaType.ordinal(),
Native.getPtr(imageInfo._colorInfo._colorSpace),
pixelsPtr,
rowBytes,
surfaceProps);
if (ptr == 0)
throw new IllegalArgumentException(String.format("Failed Surface.makeRasterDirect(%s, %d, %d, %s)", imageInfo, pixelsPtr, rowBytes, surfaceProps));
return new Surface(ptr);
} finally {
Reference.reachabilityFence(imageInfo._colorInfo._colorSpace);
}
}
/**
* <p>Allocates raster Surface. Canvas returned by Surface draws directly into pixels.
* Allocates and zeroes pixel memory. Pixel memory size is imageInfo.height() times imageInfo.minRowBytes().
* Pixel memory is deleted when Surface is deleted.</p>
*
* <p>Surface is returned if all parameters are valid. Valid parameters include:</p>
*
* <ul><li>info dimensions are greater than zero;</li>
* <li>info contains ColorType and AlphaType supported by raster surface;</li></ul>
*
* @param imageInfo width, height, ColorType, AlphaType, ColorSpace,
* of raster surface; width and height must be greater than zero
* @return new Surface
*/
@NotNull @Contract("_, _, _ -> new")
public static Surface makeRaster(@NotNull ImageInfo imageInfo) {
return makeRaster(imageInfo, 0, null);
}
/**
* <p>Allocates raster Surface. Canvas returned by Surface draws directly into pixels.
* Allocates and zeroes pixel memory. Pixel memory size is imageInfo.height() times
* rowBytes, or times imageInfo.minRowBytes() if rowBytes is zero.
* Pixel memory is deleted when Surface is deleted.</p>
*
* <p>Surface is returned if all parameters are valid. Valid parameters include:</p>
*
* <ul><li>info dimensions are greater than zero;</li>
* <li>info contains ColorType and AlphaType supported by raster surface;</li>
* <li>rowBytes is large enough to contain info width pixels of ColorType, or is zero.</li></ul>
*
* <p>If rowBytes is zero, a suitable value will be chosen internally.</p>
*
* @param imageInfo width, height, ColorType, AlphaType, ColorSpace,
* of raster surface; width and height must be greater than zero
* @param rowBytes interval from one Surface row to the next; may be zero
* @return new Surface
*/
@NotNull @Contract("_, _, _ -> new")
public static Surface makeRaster(@NotNull ImageInfo imageInfo,
long rowBytes) {
return makeRaster(imageInfo, rowBytes, null);
}
/**
* <p>Allocates raster Surface. Canvas returned by Surface draws directly into pixels.
* Allocates and zeroes pixel memory. Pixel memory size is imageInfo.height() times
* rowBytes, or times imageInfo.minRowBytes() if rowBytes is zero.
* Pixel memory is deleted when Surface is deleted.</p>
*
* <p>Surface is returned if all parameters are valid. Valid parameters include:</p>
*
* <ul><li>info dimensions are greater than zero;</li>
* <li>info contains ColorType and AlphaType supported by raster surface;</li>
* <li>rowBytes is large enough to contain info width pixels of ColorType, or is zero.</li></ul>
*
* <p>If rowBytes is zero, a suitable value will be chosen internally.</p>
*
* @param imageInfo width, height, ColorType, AlphaType, ColorSpace,
* of raster surface; width and height must be greater than zero
* @param rowBytes interval from one Surface row to the next; may be zero
* @param surfaceProps LCD striping orientation and setting for device independent fonts;
* may be null
* @return new Surface
*/
@NotNull @Contract("_, _, _ -> new")
public static Surface makeRaster(@NotNull ImageInfo imageInfo,
long rowBytes,
@Nullable SurfaceProps surfaceProps) {
try {
assert imageInfo != null : "Can’t makeRaster with imageInfo == null";
Stats.onNativeCall();
long ptr = _nMakeRaster(
imageInfo._width,
imageInfo._height,
imageInfo._colorInfo._colorType.ordinal(),
imageInfo._colorInfo._alphaType.ordinal(),
Native.getPtr(imageInfo._colorInfo._colorSpace),
rowBytes,
surfaceProps);
if (ptr == 0)
throw new IllegalArgumentException(String.format("Failed Surface.makeRaster(%s, %d, %s)", imageInfo, rowBytes, surfaceProps));
return new Surface(ptr);
} finally {
Reference.reachabilityFence(imageInfo._colorInfo._colorSpace);
}
}
/**
* <p>Wraps a GPU-backed buffer into {@link Surface}.</p>
*
* <p>Caller must ensure backendRenderTarget is valid for the lifetime of returned {@link Surface}.</p>
*
* <p>{@link Surface} is returned if all parameters are valid. backendRenderTarget is valid if its pixel
* configuration agrees with colorSpace and context;
* for instance, if backendRenderTarget has an sRGB configuration, then context must support sRGB,
* and colorSpace must be present. Further, backendRenderTarget width and height must not exceed
* context capabilities, and the context must be able to support back-end render targets.</p>
*
* @param context GPU context
* @param rt texture residing on GPU
* @param origin surfaceOrigin pins either the top-left or the bottom-left corner to the origin.
* @param colorFormat color format
* @param colorSpace range of colors; may be null
* @return Surface if all parameters are valid; otherwise, null
* @see <a href="https://fiddle.skia.org/c/@Surface_MakeFromBackendTexture">https://fiddle.skia.org/c/@Surface_MakeFromBackendTexture</a>
*/
@NotNull
public static Surface makeFromBackendRenderTarget(@NotNull DirectContext context,
@NotNull BackendRenderTarget rt,
@NotNull SurfaceOrigin origin,
@NotNull SurfaceColorFormat colorFormat,
@Nullable ColorSpace colorSpace) {
return makeFromBackendRenderTarget(context, rt, origin, colorFormat, colorSpace, null);
}
/**
* <p>Wraps a GPU-backed buffer into {@link Surface}.</p>
*
* <p>Caller must ensure backendRenderTarget is valid for the lifetime of returned {@link Surface}.</p>
*
* <p>{@link Surface} is returned if all parameters are valid. backendRenderTarget is valid if its pixel
* configuration agrees with colorSpace and context;
* for instance, if backendRenderTarget has an sRGB configuration, then context must support sRGB,
* and colorSpace must be present. Further, backendRenderTarget width and height must not exceed
* context capabilities, and the context must be able to support back-end render targets.</p>
*
* @param context GPU context
* @param rt texture residing on GPU
* @param origin surfaceOrigin pins either the top-left or the bottom-left corner to the origin.
* @param colorFormat color format
* @param colorSpace range of colors; may be null
* @param surfaceProps LCD striping orientation and setting for device independent fonts; may be null
* @return Surface if all parameters are valid; otherwise, null
* @see <a href="https://fiddle.skia.org/c/@Surface_MakeFromBackendTexture">https://fiddle.skia.org/c/@Surface_MakeFromBackendTexture</a>
*/
@NotNull
public static Surface makeFromBackendRenderTarget(@NotNull DirectContext context,
@NotNull BackendRenderTarget rt,
@NotNull SurfaceOrigin origin,
@NotNull SurfaceColorFormat colorFormat,
@Nullable ColorSpace colorSpace,
@Nullable SurfaceProps surfaceProps) {
try {
assert context != null : "Can’t makeFromBackendRenderTarget with context == null";
assert rt != null : "Can’t makeFromBackendRenderTarget with rt == null";
assert origin != null : "Can’t makeFromBackendRenderTarget with origin == null";
assert colorFormat != null : "Can’t makeFromBackendRenderTarget with colorFormat == null";
Stats.onNativeCall();
long ptr = _nMakeFromBackendRenderTarget(Native.getPtr(context), Native.getPtr(rt), origin.ordinal(), colorFormat.ordinal(), Native.getPtr(colorSpace), surfaceProps);
if (ptr == 0)
throw new IllegalArgumentException(String.format("Failed Surface.makeFromBackendRenderTarget(%s, %s, %s, %s, %s)", context, rt, origin, colorFormat, colorSpace));
return new Surface(ptr, context, rt);
} finally {
Reference.reachabilityFence(context);
Reference.reachabilityFence(rt);
Reference.reachabilityFence(colorSpace);
}
}
@NotNull
public static Surface makeFromMTKView(@NotNull DirectContext context,
long mtkViewPtr,
@NotNull SurfaceOrigin origin,
int sampleCount,
@NotNull SurfaceColorFormat colorFormat,
@Nullable ColorSpace colorSpace,
@Nullable SurfaceProps surfaceProps) {
try {
assert context != null : "Can’t makeFromBackendRenderTarget with context == null";
assert origin != null : "Can’t makeFromBackendRenderTarget with origin == null";
assert colorFormat != null : "Can’t makeFromBackendRenderTarget with colorFormat == null";
Stats.onNativeCall();
long ptr = _nMakeFromMTKView(Native.getPtr(context), mtkViewPtr, origin.ordinal(), sampleCount, colorFormat.ordinal(), Native.getPtr(colorSpace), surfaceProps);
if (ptr == 0)
throw new IllegalArgumentException(String.format("Failed Surface.makeFromMTKView(%s, %s, %s, %s, %s, %s)", context, mtkViewPtr, origin, colorFormat, colorSpace, surfaceProps));
return new Surface(ptr, context);
} finally {
Reference.reachabilityFence(context);
Reference.reachabilityFence(colorSpace);
}
}
/**
* <p>Allocates raster {@link Surface}.</p>
*
* <p>Canvas returned by Surface draws directly into pixels. Allocates and zeroes pixel memory.
* Pixel memory size is height times width times four. Pixel memory is deleted when Surface is deleted.</p>
*
* <p>Internally, sets ImageInfo to width, height, native color type, and ColorAlphaType.PREMUL.</p>
*
* <p>Surface is returned if width and height are greater than zero.</p>
*
* <p>Use to create Surface that matches PMColor, the native pixel arrangement on the platform.
* Surface drawn to output device skips converting its pixel format.</p>
*
* @param width pixel column count; must be greater than zero
* @param height pixel row count; must be greater than zero
* @return Surface if all parameters are valid; otherwise, null
* @see <a href="https://fiddle.skia.org/c/@Surface_MakeRasterN32Premul">https://fiddle.skia.org/c/@Surface_MakeRasterN32Premul</a>
*/
@NotNull
public static Surface makeRasterN32Premul(int width, int height) {
Stats.onNativeCall();
long ptr = _nMakeRasterN32Premul(width, height);
if (ptr == 0)
throw new IllegalArgumentException(String.format("Failed Surface.makeRasterN32Premul(%d, %d)", width, height));
return new Surface(ptr);
}
/**
* <p>Returns Surface on GPU indicated by context. Allocates memory for
* pixels, based on the width, height, and ColorType in ImageInfo.
* describes the pixel format in ColorType, and transparency in
* AlphaType, and color matching in ColorSpace.</p>
*
* @param context GPU context
* @param budgeted selects whether allocation for pixels is tracked by context
* @param imageInfo width, height, ColorType, AlphaType, ColorSpace;
* width, or height, or both, may be zero
* @return new SkSurface
*/
@NotNull @Contract("_, _, _ -> new")
public static Surface makeRenderTarget(@NotNull DirectContext context,
boolean budgeted,
@NotNull ImageInfo imageInfo) {
return makeRenderTarget(context, budgeted, imageInfo, 0, SurfaceOrigin.BOTTOM_LEFT, null, false);
}
/**
* <p>Returns Surface on GPU indicated by context. Allocates memory for
* pixels, based on the width, height, and ColorType in ImageInfo.
* describes the pixel format in ColorType, and transparency in
* AlphaType, and color matching in ColorSpace.</p>
*
* <p>sampleCount requests the number of samples per pixel.
* Pass zero to disable multi-sample anti-aliasing. The request is rounded
* up to the next supported count, or rounded down if it is larger than the
* maximum supported count.</p>
*
* @param context GPU context
* @param budgeted selects whether allocation for pixels is tracked by context
* @param imageInfo width, height, ColorType, AlphaType, ColorSpace;
* width, or height, or both, may be zero
* @param sampleCount samples per pixel, or 0 to disable full scene anti-aliasing
* @param surfaceProps LCD striping orientation and setting for device independent
* fonts; may be null
* @return new SkSurface
*/
@NotNull @Contract("_, _, _, _, _ -> new")
public static Surface makeRenderTarget(@NotNull DirectContext context,
boolean budgeted,
@NotNull ImageInfo imageInfo,
int sampleCount,
@Nullable SurfaceProps surfaceProps) {
return makeRenderTarget(context, budgeted, imageInfo, sampleCount, SurfaceOrigin.BOTTOM_LEFT, surfaceProps, false);
}
/**
* <p>Returns Surface on GPU indicated by context. Allocates memory for
* pixels, based on the width, height, and ColorType in ImageInfo.
* describes the pixel format in ColorType, and transparency in
* AlphaType, and color matching in ColorSpace.</p>
*
* <p>sampleCount requests the number of samples per pixel.
* Pass zero to disable multi-sample anti-aliasing. The request is rounded
* up to the next supported count, or rounded down if it is larger than the
* maximum supported count.</p>
*
* @param context GPU context
* @param budgeted selects whether allocation for pixels is tracked by context
* @param imageInfo width, height, ColorType, AlphaType, ColorSpace;
* width, or height, or both, may be zero
* @param sampleCount samples per pixel, or 0 to disable full scene anti-aliasing
* @param origin pins either the top-left or the bottom-left corner to the origin.
* @param surfaceProps LCD striping orientation and setting for device independent
* fonts; may be null
* @return new SkSurface
*/
@NotNull @Contract("_, _, _, _, _, _ -> new")
public static Surface makeRenderTarget(@NotNull DirectContext context,
boolean budgeted,
@NotNull ImageInfo imageInfo,
int sampleCount,
@NotNull SurfaceOrigin origin,
@Nullable SurfaceProps surfaceProps) {
return makeRenderTarget(context, budgeted, imageInfo, sampleCount, origin, surfaceProps, false);
}
/**
* <p>Returns Surface on GPU indicated by context. Allocates memory for
* pixels, based on the width, height, and ColorType in ImageInfo.
* describes the pixel format in ColorType, and transparency in
* AlphaType, and color matching in ColorSpace.</p>
*
* <p>sampleCount requests the number of samples per pixel.
* Pass zero to disable multi-sample anti-aliasing. The request is rounded
* up to the next supported count, or rounded down if it is larger than the
* maximum supported count.</p>
*
* <p>shouldCreateWithMips hints that Image returned by {@link #makeImageSnapshot()} is mip map.</p>
*
* @param context GPU context
* @param budgeted selects whether allocation for pixels is tracked by context
* @param imageInfo width, height, ColorType, AlphaType, ColorSpace;
* width, or height, or both, may be zero
* @param sampleCount samples per pixel, or 0 to disable full scene anti-aliasing
* @param origin pins either the top-left or the bottom-left corner to the origin.
* @param surfaceProps LCD striping orientation and setting for device independent
* fonts; may be null
* @param shouldCreateWithMips hint that SkSurface will host mip map images
* @return new SkSurface
*/
@NotNull @Contract("_, _, _, _, _, _, _ -> new")
public static Surface makeRenderTarget(@NotNull DirectContext context,
boolean budgeted,
@NotNull ImageInfo imageInfo,
int sampleCount,
@NotNull SurfaceOrigin origin,
@Nullable SurfaceProps surfaceProps,
boolean shouldCreateWithMips) {
try {
assert context != null : "Can’t makeFromBackendRenderTarget with context == null";
assert imageInfo != null : "Can’t makeFromBackendRenderTarget with imageInfo == null";
assert origin != null : "Can’t makeFromBackendRenderTarget with origin == null";
Stats.onNativeCall();
long ptr = _nMakeRenderTarget(
Native.getPtr(context),
budgeted,
imageInfo._width,
imageInfo._height,
imageInfo._colorInfo._colorType.ordinal(),
imageInfo._colorInfo._alphaType.ordinal(),
Native.getPtr(imageInfo._colorInfo._colorSpace),
sampleCount,
origin.ordinal(),
surfaceProps,
shouldCreateWithMips);
if (ptr == 0)
throw new IllegalArgumentException(String.format("Failed Surface.makeRenderTarget(%s, %b, %s, %d, %s, %s, %b)", context, budgeted, imageInfo, sampleCount, origin, surfaceProps, shouldCreateWithMips));
return new Surface(ptr, context);
} finally {
Reference.reachabilityFence(context);
Reference.reachabilityFence(imageInfo._colorInfo._colorSpace);
}
}
/**
* Returns Surface without backing pixels. Drawing to Canvas returned from Surface
* has no effect. Calling makeImageSnapshot() on returned Surface returns null.
*
* @param width one or greater
* @param height one or greater
* @return Surface if width and height are positive
*
* @see <a href="https://fiddle.skia.org/c/@Surface_MakeNull">https://fiddle.skia.org/c/@Surface_MakeNull</a>
*/
@NotNull @Contract("_, _ -> new")
public static Surface makeNull(int width, int height) {
Stats.onNativeCall();
long ptr = _nMakeNull(width, height);
if (ptr == 0)
throw new IllegalArgumentException(String.format("Failed Surface.makeNull(%d, %d)", width, height));
return new Surface(ptr);
}
/**
* <p>Returns pixel count in each row; may be zero or greater.</p>
*
* @return number of pixel columns
* @see <a href="https://fiddle.skia.org/c/@Surface_width">https://fiddle.skia.org/c/@Surface_width</a>
*/
public int getWidth() {
try {
Stats.onNativeCall();
return _nGetWidth(_ptr);
} finally {
Reference.reachabilityFence(this);
}
}
/**
* <p>Returns pixel row count; may be zero or greater.</p>
*
* @return number of pixel rows
* @see <a href="https://fiddle.skia.org/c/@Surface_height">https://fiddle.skia.org/c/@Surface_height</a>
*/
public int getHeight() {
try {
Stats.onNativeCall();
return _nGetHeight(_ptr);
} finally {
Reference.reachabilityFence(this);
}
}
/**
* <p>Returns an ImageInfo describing the surface.</p>
*
* @return ImageInfo describing the surface.
*/
@NotNull
public ImageInfo getImageInfo() {
try {
Stats.onNativeCall();
return _nGetImageInfo(_ptr);
} finally {
Reference.reachabilityFence(this);
}
}
/**
* <p>Returns unique value identifying the content of Surface.</p>
*
* <p>Returned value changes each time the content changes.
* Content is changed by drawing, or by calling notifyContentWillChange().</p>
*
* @return unique content identifier
*/
public int getGenerationId() {
try {
Stats.onNativeCall();
return _nGenerationId(_ptr);
} finally {
Reference.reachabilityFence(this);
}
}
/**
* <p>Notifies that Surface contents will be changed by code outside of Skia.</p>
*
* <p>Subsequent calls to generationID() return a different value.</p>
*
* @see <a href="https://fiddle.skia.org/c/@Surface_notifyContentWillChange">https://fiddle.skia.org/c/@Surface_notifyContentWillChange</a>
*/
public void notifyContentWillChange(ContentChangeMode mode) {
try {
Stats.onNativeCall();
_nNotifyContentWillChange(_ptr, mode.ordinal());
} finally {
Reference.reachabilityFence(this);
}
}
/**
* <p>Returns the recording context being used by the Surface.</p>
*
* @return the recording context, if available; null otherwise
*/
@Nullable
public DirectContext getRecordingContext() {
try {
Stats.onNativeCall();
long ptr = _nGetRecordingContext(_ptr);
return ptr == 0 ? null : new DirectContext(ptr);
} finally {
Reference.reachabilityFence(this);
}
}
/**
* <p>Returns Canvas that draws into Surface.</p>
*
* <p>Subsequent calls return the same Canvas.
* Canvas returned is managed and owned by Surface, and is deleted when Surface is deleted.</p>
*
* @return Canvas for Surface
*/
@NotNull
public Canvas getCanvas() {
try {
Stats.onNativeCall();
long ptr = _nGetCanvas(_ptr);
return ptr == 0 ? null : new Canvas(ptr, false, this);
} finally {
Reference.reachabilityFence(this);
}
}
/**
* <p>Returns a compatible Surface, or null.</p>
*
* <p>Returned Surface contains the same raster, GPU, or null properties as the original.
* Returned Surface does not share the same pixels.</p>
*
* <p>Returns null if imageInfo width or height are zero, or if imageInfo is incompatible with Surface.</p>
*
* @param imageInfo contains width, height, AlphaType, ColorType, ColorSpace
* @return compatible SkSurface or null
* @see <a href="https://fiddle.skia.org/c/@Surface_makeSurface">https://fiddle.skia.org/c/@Surface_makeSurface</a>
*/
@Nullable
public Surface makeSurface(ImageInfo imageInfo) {
try {
Stats.onNativeCall();
long ptr = _nMakeSurfaceI(_ptr,
imageInfo._width,
imageInfo._height,
imageInfo._colorInfo._colorType.ordinal(),
imageInfo._colorInfo._alphaType.ordinal(),
Native.getPtr(imageInfo._colorInfo._colorSpace));
return new Surface(ptr);
} finally {
Reference.reachabilityFence(this);
}
}
/**
* <p>Calls makeSurface(ImageInfo) with the same ImageInfo as this surface,
* but with the specified width and height.</p>
*
* <p>Returned Surface contains the same raster, GPU, or null properties as the original.
* Returned Surface does not share the same pixels.</p>
*
* <p>Returns null if imageInfo width or height are zero, or if imageInfo is incompatible with Surface.</p>
*
* @param width pixel column count; must be greater than zero
* @param height pixel row count; must be greater than zero
* @return compatible SkSurface or null
*/
@Nullable
public Surface makeSurface(int width, int height) {
try {
Stats.onNativeCall();
long ptr = _nMakeSurface(_ptr, width, height);
return new Surface(ptr);
} finally {
Reference.reachabilityFence(this);
}
}
/**
* <p>Returns Image capturing Surface contents.</p>
*
* <p>Subsequent drawing to Surface contents are not captured.
* Image allocation is accounted for if Surface was created with SkBudgeted::kYes.</p>
*
* @return Image initialized with Surface contents
* @see <a href="https://fiddle.skia.org/c/@Surface_makeImageSnapshot">https://fiddle.skia.org/c/@Surface_makeImageSnapshot</a>
*/
public Image makeImageSnapshot() {
try {
Stats.onNativeCall();
return new Image(_nMakeImageSnapshot(_ptr));
} finally {
Reference.reachabilityFence(this);
}
}
/**
* <p>Like the no-parameter version, this returns an image of the current surface contents.</p>
*
* <p>This variant takes a rectangle specifying the subset of the surface that is of interest.
* These bounds will be sanitized before being used.</p>
*
* <ul>
* <li>If bounds extends beyond the surface, it will be trimmed to just the intersection of it and the surface.</li>
* <li>If bounds does not intersect the surface, then this returns null.</li>
* <li>If bounds == the surface, then this is the same as calling the no-parameter variant.</li>
* </ul>
*
* @return Image initialized with Surface contents or null
* @see <a href="https://fiddle.skia.org/c/@Surface_makeImageSnapshot_2">https://fiddle.skia.org/c/@Surface_makeImageSnapshot_2</a>
*/
@Nullable
public Image makeImageSnapshot(IRect area) {
try {
Stats.onNativeCall();
return new Image(_nMakeImageSnapshotR(_ptr, area._left, area._top, area._right, area._bottom));
} finally {
Reference.reachabilityFence(this);
}
}
/**
* <p>Draws Surface contents to canvas, with its top-left corner at (x, y).</p>
*
* <p>If Paint paint is not null, apply ColorFilter, alpha, ImageFilter, and BlendMode.</p>
*
* @param canvas Canvas drawn into
* @param x horizontal offset in Canvas
* @param y vertical offset in Canvas
* @param paint Paint containing BlendMode, ColorFilter, ImageFilter, and so on; or null
* @see <a href="https://fiddle.skia.org/c/@Surface_draw">https://fiddle.skia.org/c/@Surface_draw</a>
*/
public void draw(Canvas canvas, int x, int y, Paint paint) {
try {
Stats.onNativeCall();
_nDraw(_ptr, Native.getPtr(canvas), x, y, Native.getPtr(paint));
} finally {
Reference.reachabilityFence(this);
Reference.reachabilityFence(canvas);
Reference.reachabilityFence(paint);
}
}
public boolean peekPixels(@NotNull Pixmap pixmap) {
try {
Stats.onNativeCall();
return _nPeekPixels(_ptr, Native.getPtr(pixmap));
} finally {
Reference.reachabilityFence(this);
Reference.reachabilityFence(pixmap);
}
}
public boolean readPixels(Pixmap pixmap, int srcX, int srcY) {
try {
Stats.onNativeCall();
return _nReadPixelsToPixmap(_ptr, Native.getPtr(pixmap), srcX, srcY);
} finally {
Reference.reachabilityFence(this);
Reference.reachabilityFence(pixmap);
}
}
/**
* <p>Copies Rect of pixels from Surface into bitmap.</p>
*
* <p>Source Rect corners are (srcX, srcY) and Surface (width(), height()).
* Destination Rect corners are (0, 0) and (bitmap.width(), bitmap.height()).
* Copies each readable pixel intersecting both rectangles, without scaling,
* converting to bitmap.colorType() and bitmap.alphaType() if required.</p>
*
* <p>Pixels are readable when Surface is raster, or backed by a GPU.</p>
*
* <p>The destination pixel storage must be allocated by the caller.</p>
*
* <p>Pixel values are converted only if ColorType and AlphaType do not match.
* Only pixels within both source and destination rectangles are copied.
* dst contents outside Rect intersection are unchanged.</p>
*
* <p>Pass negative values for srcX or srcY to offset pixels across or down destination.</p>
*
* <p>Does not copy, and returns false if:</p>
*
* <ul>
* <li>Source and destination rectangles do not intersect.</li>
* <li>Surface pixels could not be converted to dst.colorType() or dst.alphaType().</li>
* <li>dst pixels could not be allocated.</li>
* <li>dst.rowBytes() is too small to contain one row of pixels.</li>
* </ul>
*
* @param bitmap storage for pixels copied from SkSurface
* @param srcX offset into readable pixels on x-axis; may be negative
* @param srcY offset into readable pixels on y-axis; may be negative
* @return true if pixels were copied
* @see <a href="https://fiddle.skia.org/c/@Surface_readPixels_3">https://fiddle.skia.org/c/@Surface_readPixels_3</a>
*/
public boolean readPixels(Bitmap bitmap, int srcX, int srcY) {
try {
Stats.onNativeCall();
return _nReadPixels(_ptr, Native.getPtr(bitmap), srcX, srcY);
} finally {
Reference.reachabilityFence(this);
Reference.reachabilityFence(bitmap);
}
}
public void writePixels(Pixmap pixmap, int x, int y) {
try {
Stats.onNativeCall();
_nWritePixelsFromPixmap(_ptr, Native.getPtr(pixmap), x, y);
} finally {
Reference.reachabilityFence(this);
Reference.reachabilityFence(pixmap);
}
}
/**
* <p>Copies Rect of pixels from the src Bitmap to the Surface.</p>
*
* <p>Source Rect corners are (0, 0) and (src.width(), src.height()).
* Destination Rect corners are (dstX, dstY) and (dstX + Surface width(), dstY + Surface height()).</p>
*
* <p>Copies each readable pixel intersecting both rectangles, without scaling,
* converting to Surface colorType() and Surface alphaType() if required.</p>
*
* @param bitmap storage for pixels to copy to Surface
* @param x x-axis position relative to Surface to begin copy; may be negative
* @param y y-axis position relative to Surface to begin copy; may be negative
* @see <a href="https://fiddle.skia.org/c/@Surface_writePixels_2">https://fiddle.skia.org/c/@Surface_writePixels_2</a>
*/
public void writePixels(Bitmap bitmap, int x, int y) {
try {
Stats.onNativeCall();
_nWritePixels(_ptr, Native.getPtr(bitmap), x, y);
} finally {
Reference.reachabilityFence(this);
Reference.reachabilityFence(bitmap);
}
}
/**
* <p>Call to ensure all reads/writes of the surface have been issued to the underlying 3D API.</p>
*
* <p>Skia will correctly order its own draws and pixel operations.
* This must to be used to ensure correct ordering when the surface backing store is accessed
* outside Skia (e.g. direct use of the 3D API or a windowing system).
* DirectContext has additional flush and submit methods that apply to all surfaces and images created from
* a DirectContext.
*/
public void flushAndSubmit() {
try {
Stats.onNativeCall();
_nFlushAndSubmit(_ptr, false);
} finally {
Reference.reachabilityFence(this);
}
}
/**
* <p>Call to ensure all reads/writes of the surface have been issued to the underlying 3D API.</p>
*
* <p>Skia will correctly order its own draws and pixel operations.
* This must to be used to ensure correct ordering when the surface backing store is accessed
* outside Skia (e.g. direct use of the 3D API or a windowing system).
* DirectContext has additional flush and submit methods that apply to all surfaces and images created from
* a DirectContext.
*
* @param syncCpu a flag determining if cpu should be synced
*/
public void flushAndSubmit(boolean syncCpu) {
try {
Stats.onNativeCall();
_nFlushAndSubmit(_ptr, syncCpu);
} finally {
Reference.reachabilityFence(this);
}
}
public void flush() {
try {
Stats.onNativeCall();
_nFlush(_ptr);
} finally {
Reference.reachabilityFence(this);
}
}
/**
* <p>May return true if the caller is the only owner.</p>
*
* <p>Ensures that all previous owner's actions are complete.</p>
*/
public boolean isUnique() {
try {
Stats.onNativeCall();
return _nUnique(_ptr);
} finally {
Reference.reachabilityFence(this);
}
}
@ApiStatus.Internal
public Surface(long ptr) {
super(ptr);
_context = null;
_renderTarget = null;
}
@ApiStatus.Internal
public Surface(long ptr, DirectContext context) {
super(ptr);
_context = context;
_renderTarget = null;
}
@ApiStatus.Internal
public Surface(long ptr, DirectContext context, BackendRenderTarget renderTarget) {
super(ptr);
_context = context;
_renderTarget = renderTarget;
}
public static native long _nMakeRasterDirect(int width, int height, int colorType, int alphaType, long colorSpacePtr, long pixelsPtr, long rowBytes, SurfaceProps surfaceProps);
public static native long _nMakeRasterDirectWithPixmap(long pixmapPtr, SurfaceProps surfaceProps);
public static native long _nMakeRaster(int width, int height, int colorType, int alphaType, long colorSpacePtr, long rowBytes, SurfaceProps surfaceProps);
public static native long _nMakeRasterN32Premul(int width, int height);
public static native long _nMakeFromBackendRenderTarget(long pContext, long pBackendRenderTarget, int surfaceOrigin, int colorType, long colorSpacePtr, SurfaceProps surfaceProps);
public static native long _nMakeFromMTKView(long contextPtr, long mtkViewPtr, int surfaceOrigin, int sampleCount, int colorType, long colorSpacePtr, SurfaceProps surfaceProps);
public static native long _nMakeRenderTarget(long contextPtr, boolean budgeted, int width, int height, int colorType, int alphaType, long colorSpacePtr, int sampleCount, int surfaceOrigin, SurfaceProps surfaceProps, boolean shouldCreateWithMips);
public static native long _nMakeNull(int width, int height);
public static native int _nGetWidth(long ptr);
public static native int _nGetHeight(long ptr);
public static native ImageInfo _nGetImageInfo(long ptr);
public static native int _nGenerationId(long ptr);
public static native void _nNotifyContentWillChange(long ptr, int mode);
public static native long _nGetRecordingContext(long ptr);
public static native long _nGetCanvas(long ptr);
public static native long _nMakeSurfaceI(long ptr, int width, int height, int colorType, int alphaType, long colorSpacePtr);
public static native long _nMakeSurface(long ptr, int width, int height);
public static native long _nMakeImageSnapshot(long ptr);
public static native long _nMakeImageSnapshotR(long ptr, int left, int top, int right, int bottom);
public static native void _nDraw(long ptr, long canvasPtr, float x, float y, long paintPtr);
public static native boolean _nPeekPixels(long ptr, long pixmapPtr);
public static native boolean _nReadPixelsToPixmap(long ptr, long pixmapPtr, int srcX, int srcY);
public static native boolean _nReadPixels(long ptr, long bitmapPtr, int srcX, int srcY);
public static native void _nWritePixelsFromPixmap(long ptr, long pixmapPtr, int x, int y);
public static native void _nWritePixels(long ptr, long bitmapPtr, int x, int y);
public static native void _nFlushAndSubmit(long ptr, boolean syncCpu);
public static native void _nFlush(long ptr);
public static native boolean _nUnique(long ptr);
}