Unverified Commit 8ea278fd authored by Ivan Matkov's avatar Ivan Matkov Committed by GitHub

Update skia to m144 (#1154)

Fixes [SKIKO-1094](https://youtrack.jetbrains.com/issue/SKIKO-1094)
Update skia to m144
parent 26b421ed
......@@ -90,6 +90,7 @@ runs:
docker run --rm \
-v "${{ github.workspace }}":/workspace \
-v "${HOME}/.gradle":/gradle-cache \
-v "${HOME}/.m2":/root/.m2 \
-e GRADLE_USER_HOME=/gradle-cache \
-w /workspace/${{ inputs.working_directory }} \
"ghcr.io/${{ steps.vars.outputs.image_namespace }}/${{ inputs.image_name }}:${{ steps.vars.outputs.tag }}" \
......
......@@ -376,8 +376,8 @@ jobs:
git clone https://github.com/emscripten-core/emsdk.git
cd ./emsdk
fi
./emsdk install 3.1.50
./emsdk activate 3.1.50
./emsdk install 4.0.7
./emsdk activate 4.0.7
- shell: bash
name: 'Run WASM Tests'
......
......@@ -89,11 +89,14 @@ open class ClocksAwt(
val y = ypos.toFloat()
canvas.drawString(text, x, y, font, paint)
val style = ParagraphStyle().apply {
fontRastrSettings = FontRastrSettings(FontEdging.SUBPIXEL_ANTI_ALIAS, FontHinting.SLIGHT, true)
}
val style = ParagraphStyle()
val paragraph = ParagraphBuilder(style, fontCollection)
.pushStyle(TextStyle().setColor(0xFF000000.toInt()))
.pushStyle(TextStyle().apply {
color = 0xFF000000.toInt()
fontEdging = FontEdging.SUBPIXEL_ANTI_ALIAS
fontHinting = FontHinting.SLIGHT
subpixel = true
})
.addText("Graphic API: ${renderProvider()}, JRE: ${System.getProperty("java.vendor")}, ${System.getProperty("java.runtime.version")} $currentSystemTheme")
.popStyle()
.build()
......@@ -123,4 +126,4 @@ open class ClocksAwt(
xpos = e.x
ypos = e.y
}
}
\ No newline at end of file
}
......@@ -10,7 +10,7 @@ enum class OS(
Linux("linux", arrayOf()),
Android("android", arrayOf()),
Windows("windows", arrayOf()),
MacOS("macos", arrayOf("-mmacosx-version-min=10.15")),
MacOS("macos", arrayOf("-mmacosx-version-min=11.0")),
Wasm("wasm", arrayOf()),
IOS("ios", arrayOf()),
TVOS("tvos", arrayOf())
......
......@@ -65,8 +65,8 @@ fun skiaPreprocessorFlags(os: OS, buildType: SkiaBuildType): Array<String> {
"-DSK_SHAPER_UNICODE_AVAILABLE",
"-DSK_SUPPORT_OPENCL=0",
"-DSK_UNICODE_AVAILABLE",
"-DU_DISABLE_RENAMING",
"-DSK_USING_THIRD_PARTY_ICU",
"-DSK_HIDE_PATH_EDIT_METHODS", // Temporary (m144) skia flag for migration to SkPathBuilder
// For ICU symbols renaming:
"-DU_DISABLE_RENAMING=0",
"-DU_DISABLE_VERSION_SUFFIX=1",
......@@ -355,4 +355,4 @@ fun KotlinTarget.generateVersion(
(this as KotlinCompileTool).source(generatedDir.get().asFile)
}
}
}
\ No newline at end of file
}
......@@ -10,7 +10,7 @@ RUN apt update -y && \
# Install emscripten
ENV EMSDK_DIR=/usr/emsdk
ENV EMSDK_VER=3.1.50
ENV EMSDK_VER=4.0.7
ENV PATH=$EMSDK_DIR/upstream/emscripten:$PATH
RUN git clone https://github.com/emscripten-core/emsdk.git $EMSDK_DIR && \
$EMSDK_DIR/emsdk install $EMSDK_VER && \
......
......@@ -7,7 +7,7 @@ kotlin.mpp.enableCInteropCommonization=true
deploy.version=0.0.0
# a tag from https://github.com/JetBrains/skia-pack
dependencies.skia=m138-80d088a-2
dependencies.skia=m144-e2e6623374-2
# a tag from https://github.com/JetBrains/angle-pack
dependencies.angle=ec4d8f8e4d
......
......@@ -11,10 +11,12 @@
#if (defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_LINUX)) && !defined(SKIKO_WASM)
#include "ports/SkFontMgr_fontconfig.h"
#include "ports/SkFontScanner_FreeType.h"
#endif
#ifdef SK_BUILD_FOR_ANDROID
#include "ports/SkFontMgr_android.h"
#include "ports/SkFontScanner_FreeType.h"
#endif
#ifdef SKIKO_WASM
......@@ -36,11 +38,11 @@ sk_sp<SkFontMgr> SkFontMgrSkikoDefault() {
#endif
#if (defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_LINUX)) && !defined(SKIKO_WASM)
return SkFontMgr_New_FontConfig(nullptr);
return SkFontMgr_New_FontConfig(nullptr, SkFontScanner_Make_FreeType());
#endif
#ifdef SK_BUILD_FOR_ANDROID
return SkFontMgr_New_Android(nullptr);
return SkFontMgr_New_Android(nullptr, SkFontScanner_Make_FreeType());
#endif
#ifdef SKIKO_WASM
......
......@@ -49,7 +49,7 @@ namespace skikoMpp {
if (run.fGlyphCount > 1 && SkScalarNearlyEqual(posBuffer[(run.fGlyphCount - 2) * 2], lastLeft))
lastWidth = 0;
else
font.getWidths(&run.fGlyphIndices[run.fGlyphCount - 1], 1, &lastWidth);
font.getWidths({&run.fGlyphIndices[run.fGlyphCount - 1], 1}, {&lastWidth, 1});
auto runBounds = SkRect::MakeLTRB(posBuffer[0], posBuffer[1] + metrics.fAscent, lastLeft + lastWidth, posBuffer[1] + metrics.fDescent);
bounds->join(runBounds);
......
#include <SkNWayCanvas.h>
#include <SkPathBuilder.h>
#include <SkPicture.h>
#include <SkShadowUtils.h>
#include "node/RenderNode.h"
......@@ -306,9 +307,9 @@ void RenderNode::updateMatrix() {
void RenderNode::drawShadow(SkCanvas *canvas, const LightGeometry& lightGeometry, const LightInfo& lightInfo) {
SkPath tmpPath, *path = &tmpPath;
if (this->clipRect) {
tmpPath.addRect(*this->clipRect);
tmpPath = SkPathBuilder().addRect(*this->clipRect).detach();
} else if (this->clipRRect) {
tmpPath.addRRect(*this->clipRRect);
tmpPath = SkPathBuilder().addRRect(*this->clipRRect).detach();
} else if (this->clipPath) {
path = &*this->clipPath;
} else {
......
......@@ -5,28 +5,23 @@ import org.jetbrains.skia.impl.Library.Companion.staticLoad
import kotlin.math.min
/**
*
* Path contain geometry. Path may be empty, or contain one or more verbs that
* outline a figure. Path always starts with a move verb to a Cartesian coordinate,
* and may be followed by additional verbs that add lines or curves.
*
*
* Adding a close verb makes the geometry into a continuous loop, a closed contour.
* Path may contain any number of contours, each beginning with a move verb.
*
*
* Path contours may contain only a move verb, or may also contain lines,
* quadratic beziers, conics, and cubic beziers. Path contours may be open or
* closed.
*
*
* When used to draw a filled area, Path describes whether the fill is inside or
* outside the geometry. Path also describes the winding rule used to fill
* overlapping contours.
*
*
* Internally, Path lazily computes metrics likes bounds and convexity. Call
* [.updateBoundsCache] to make Path thread safe.
* [updateBoundsCache] to make Path thread safe.
*/
class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHolder.PTR), Iterable<PathSegment?> {
companion object {
......@@ -43,6 +38,200 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol
}
}
/**
* Creates a new path with the specified spans.
*
* The points and weights arrays are read in order, based on the sequence of verbs.
*
* - Move 1 point
* - Line 1 point
* - Quad 2 points
* - Conic 2 points and 1 weight
* - Cubic 3 points
* - Close 0 points
*
* If an illegal sequence of verbs is encountered, or the specified number of points
* or weights is not sufficient given the verbs, an empty Path is returned.
*
* A legal sequence of verbs consists of any number of Contours. A contour always begins
* with a Move verb, followed by 0 or more segments: Line, Quad, Conic, Cubic, followed
* by an optional Close.
*
* @param pts array of points
* @param verbs array of path verbs
* @param conicWeights array of conic weights
* @param fillType fill type for the path
* @param isVolatile whether the path is volatile
* @return new Path constructed from the provided data
*/
fun Raw(
pts: Array<Point>,
verbs: Array<PathVerb>,
conicWeights: FloatArray = FloatArray(0),
fillType: PathFillMode = PathFillMode.WINDING,
isVolatile: Boolean = false
): Path {
Stats.onNativeCall()
val ptsFlat = FloatArray(pts.size * 2)
for (i in pts.indices) {
ptsFlat[i * 2] = pts[i].x
ptsFlat[i * 2 + 1] = pts[i].y
}
val verbsBytes = ByteArray(verbs.size) { verbs[it].ordinal.toByte() }
return interopScope {
val result = _nMakeFromRaw(
toInterop(ptsFlat), pts.size,
toInterop(verbsBytes), verbs.size,
toInterop(conicWeights), conicWeights.size,
fillType.ordinal, isVolatile
)
require(result != NullPointer) { "Failed to create Path from raw data" }
Path(result)
}
}
/**
* Creates a rectangular path.
*
* @param rect rectangle bounds
* @param fillType fill type for the path
* @param direction direction to wind the rectangle
* @param startIndex starting corner index (0-3)
* @return new rectangular Path
*/
fun Rect(
rect: Rect,
fillType: PathFillMode = PathFillMode.WINDING,
direction: PathDirection = PathDirection.CLOCKWISE,
startIndex: Int = 0
): Path {
Stats.onNativeCall()
val result = _nMakeFromRect(rect.left, rect.top, rect.right, rect.bottom, fillType.ordinal, direction.ordinal, startIndex)
require(result != NullPointer) { "Failed to create Path from rectangle" }
return Path(result)
}
/**
* Creates an oval path.
*
* @param rect oval bounds
* @param direction direction to wind the oval
* @param startIndex starting point index
* @return new oval Path
*/
fun Oval(
rect: Rect,
direction: PathDirection = PathDirection.CLOCKWISE,
startIndex: Int = 1
): Path {
Stats.onNativeCall()
val result = _nMakeFromOval(rect.left, rect.top, rect.right, rect.bottom, direction.ordinal, startIndex)
require(result != NullPointer) { "Failed to create Path from oval" }
return Path(result)
}
/**
* Creates a circular path.
*
* @param centerX x-coordinate of circle center
* @param centerY y-coordinate of circle center
* @param radius circle radius
* @param direction direction to wind the circle
* @return new circular Path
*/
fun Circle(
centerX: Float,
centerY: Float,
radius: Float,
direction: PathDirection = PathDirection.CLOCKWISE
): Path {
Stats.onNativeCall()
val result = _nMakeFromCircle(centerX, centerY, radius, direction.ordinal)
require(result != NullPointer) { "Failed to create Path from circle" }
return Path(result)
}
/**
* Creates a rounded rectangle path.
*
* @param rrect rounded rectangle
* @param direction direction to wind the rounded rectangle
* @param startIndex starting point index
* @return new rounded rectangle Path
*/
fun RRect(
rrect: RRect,
direction: PathDirection = PathDirection.CLOCKWISE,
startIndex: Int = if (direction == PathDirection.CLOCKWISE) 6 else 7
): Path {
Stats.onNativeCall()
return interopScope {
val result = _nMakeFromRRect(toInterop(rrect.radii), rrect.left, rrect.top, rrect.right, rrect.bottom, direction.ordinal, startIndex)
require(result != NullPointer) { "Failed to create Path from rounded rectangle" }
Path(result)
}
}
/**
* Creates a rounded rectangle path from bounds and corner radii.
*
* @param bounds rectangle bounds
* @param rx x-axis radius of corners
* @param ry y-axis radius of corners
* @param direction direction to wind the rounded rectangle
* @return new rounded rectangle Path
*/
fun RRect(
bounds: Rect,
rx: Float,
ry: Float,
direction: PathDirection = PathDirection.CLOCKWISE
): Path {
Stats.onNativeCall()
val result = _nMakeFromRRectXY(bounds.left, bounds.top, bounds.right, bounds.bottom, rx, ry, direction.ordinal)
require(result != NullPointer) { "Failed to create Path from rounded rectangle" }
return Path(result)
}
/**
* Creates a polygon path from an array of points.
*
* @param pts array of polygon vertices
* @param isClosed whether to close the polygon
* @param fillType fill type for the path
* @param isVolatile whether the path is volatile
* @return new polygon Path
*/
fun Polygon(
pts: Array<Point>,
isClosed: Boolean,
fillType: PathFillMode = PathFillMode.WINDING,
isVolatile: Boolean = false
): Path {
Stats.onNativeCall()
val ptsFlat = FloatArray(pts.size * 2)
for (i in pts.indices) {
ptsFlat[i * 2] = pts[i].x
ptsFlat[i * 2 + 1] = pts[i].y
}
return interopScope {
val result = _nMakeFromPolygon(toInterop(ptsFlat), pts.size, isClosed, fillType.ordinal, isVolatile)
require(result != NullPointer) { "Failed to create Path from polygon" }
Path(result)
}
}
/**
* Creates a simple line path between two points.
*
* @param p0 start point
* @param p1 end point
* @return new line Path
*/
fun Line(p0: Point, p1: Point): Path {
return Polygon(arrayOf(p0, p1), false)
}
/**
*
* Tests if line between Point pair is degenerate.
......@@ -185,16 +374,13 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol
}
/**
*
* Initializes Path from byte buffer. Returns null if the buffer is
* Initializes Path from byte buffer. Throws exception if the buffer
* data is inconsistent, or the length is too small.
*
*
* Reads [PathFillMode], verb array, Point array, conic weight, and
* additionally reads computed information like path convexity and bounds.
*
*
* Used only in concert with [];
* Used only in concert with [serializeToBytes];
* the format used for Path in memory is not guaranteed.
*
* @param data storage for Path
......@@ -249,14 +435,12 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol
}
/**
*
* Returns true if Path contain equal verbs and equal weights.
* If Path contain one or more conics, the weights must match.
*
*
* [.conicTo] may add different verbs
* depending on conic weight, so it is not trivial to interpolate a pair of Path
* containing conics with different conic weight values.
* conicTo may add different verbs depending on conic weight, so it is not
* trivial to interpolate a pair of Path containing conics with different
* conic weight values.
*
* @param compare Path to compare
* @return true if Path verb array and weights are equivalent
......@@ -317,6 +501,12 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol
}
}
/**
* Returns the path's fill type. This defines how "inside" is computed.
* The default value is [PathFillMode.WINDING].
*
* @return this path's [PathFillMode]
*/
var fillMode: PathFillMode
get() = try {
Stats.onNativeCall()
......@@ -360,65 +550,41 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol
}
/**
* Returns [RRect] if this path is recognized as an oval, circle or RRect.
* Returns rect bounds if this path is recognized as a rectangle.
*
* @return bounds is recognized as an oval, circle or RRect, null otherwise
* @return bounds if recognized as a rectangle, null otherwise
*
* @see [https://fiddle.skia.org/c/@Path_isRRect](https://fiddle.skia.org/c/@Path_isRRect)
* @see [https://fiddle.skia.org/c/@Path_isRect](https://fiddle.skia.org/c/@Path_isRect)
*/
val isRRect: RRect?
val isRect: Rect?
get() = try {
Stats.onNativeCall()
RRect.fromInteropPointerNullable { _nIsRRect(_ptr, it) }
Rect.fromInteropPointerNullable { _nIsRect(_ptr, it) }
} finally {
reachabilityBarrier(this)
}
/**
* Returns [RRect] if this path is recognized as an oval, circle or RRect.
*
* Sets Path to its initial state.
*
*
* Removes verb array, Point array, and weights, and sets FillMode to [PathFillMode.WINDING].
* Internal storage associated with Path is released.
*
* @return this
* @return bounds is recognized as an oval, circle or RRect, null otherwise
*
* @see [https://fiddle.skia.org/c/@Path_reset](https://fiddle.skia.org/c/@Path_reset)
* @see [https://fiddle.skia.org/c/@Path_isRRect](https://fiddle.skia.org/c/@Path_isRRect)
*/
fun reset(): Path {
Stats.onNativeCall()
Path_nReset(_ptr)
return this
}
val isRRect: RRect?
get() = try {
Stats.onNativeCall()
RRect.fromInteropPointerNullable { _nIsRRect(_ptr, it) }
} finally {
reachabilityBarrier(this)
}
/**
*
* Sets Path to its initial state, preserving internal storage.
* Removes verb array, Point array, and weights, and sets FillMode to kWinding.
* Internal storage associated with Path is retained.
*
*
* Use [.rewind] instead of [.reset] if Path storage will be reused and performance
* is critical.
*
* @return this
*
* @see [https://fiddle.skia.org/c/@Path_rewind](https://fiddle.skia.org/c/@Path_rewind)
*/
fun rewind(): Path {
Stats.onNativeCall()
_nRewind(_ptr)
return this
}
/**
*
* Returns if Path is empty.
*
*
* Empty Path may have FillMode but has no [Point], [PathVerb], or conic weight.
* [] constructs empty Path; [.reset] and [.rewind] make Path empty.
* [Path] constructor constructs empty Path.
*
* @return true if the path contains no Verb array
*/
......@@ -431,11 +597,9 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol
}
/**
*
* Returns if contour is closed.
*
*
* Contour is closed if Path Verb array was last modified by [.closePath]. When stroked,
* Contour is closed if Path Verb array was last modified by close verb. When stroked,
* closed contour draws [PaintStrokeJoin] instead of [PaintStrokeCap] at first and last Point.
*
* @return true if the last contour ends with a [PathVerb.CLOSE]
......@@ -643,6 +807,21 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol
}
}
/**
* Returns last point on Path in lastPt. Returns null if Point array is empty.
*
* @return point if Point array contains one or more Point, null otherwise
*
* @see [https://fiddle.skia.org/c/@Path_getLastPt](https://fiddle.skia.org/c/@Path_getLastPt)
*/
val lastPt: Point?
get() = try {
Stats.onNativeCall()
Point.fromNullableInteropPointer { _nGetLastPt(_ptr, it) }
} finally {
reachabilityBarrier(this)
}
/**
* Returns the number of verbs: [PathVerb.MOVE], [PathVerb.LINE], [PathVerb.QUAD], [PathVerb.CONIC],
* [PathVerb.CUBIC], and [PathVerb.CLOSE]; added to Path.
......@@ -658,6 +837,13 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol
} finally {
reachabilityBarrier(this)
}
/**
* Returns all verbs in Path.
*
* @return Array containing all Path verbs
*
* @see [https://fiddle.skia.org/c/@Path_getVerbs](https://fiddle.skia.org/c/@Path_getVerbs)
*/
val verbs: Array<PathVerb?>
get() {
val res = arrayOfNulls<PathVerb>(verbsCount)
......@@ -695,9 +881,9 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol
/**
* Returns the approximate byte size of the Path in memory.
*
* @return approximate size
* @return approximate size in bytes
*/
val approximateBytesUsed: NativePointer
val approximateBytesUsed: Int
get() = try {
Stats.onNativeCall()
_nApproximateBytesUsed(_ptr)
......@@ -750,13 +936,10 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol
}
/**
* Updates internal bounds so that subsequent calls to [bounds] are instantaneous.
* Unaltered copies of Path may also access cached bounds through [bounds].
*
* Updates internal bounds so that subsequent calls to [.getBounds] are instantaneous.
* Unaltered copies of Path may also access cached bounds through [.getBounds].
*
*
* For now, identical to calling [.getBounds] and ignoring the returned value.
*
* For now, identical to calling [bounds] and ignoring the returned value.
*
* Call to prepare Path subsequently drawn from multiple threads,
* to avoid a race condition where each draw separately computes the bounds.
......@@ -770,20 +953,18 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol
}
/**
*
* Returns minimum and maximum axes values of the lines and curves in Path.
* Returns (0, 0, 0, 0) if Path contains no points.
* Returned bounds width and height may be larger or smaller than area affected
* when Path is drawn.
*
*
* Includes Point associated with [PathVerb.MOVE] that define empty
* contours.
*
* Behaves identically to [.getBounds] when Path contains
* Behaves identically to [bounds] when Path contains
* only lines. If Path contains curves, computed bounds includes
* the maximum extent of the quad, conic, or cubic; is slower than [.getBounds];
* and unlike [.getBounds], does not cache the result.
* the maximum extent of the quad, conic, or cubic; is slower than [bounds];
* and unlike [bounds], does not cache the result.
*
* @return tight bounds of curves in Path
*
......@@ -831,1388 +1012,150 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol
/**
*
* Grows Path verb array and Point array to contain extraPtCount additional Point.
* May improve performance and use less memory by
* reducing the number and size of allocations when creating Path.
*
* @param extraPtCount number of additional Point to allocate
* @return this
* Returns a mask, where each set bit corresponds to a SegmentMask constant
* if Path contains one or more verbs of that type.
*
* @see [https://fiddle.skia.org/c/@Path_incReserve](https://fiddle.skia.org/c/@Path_incReserve)
*/
fun incReserve(extraPtCount: Int): Path {
Stats.onNativeCall()
_nIncReserve(_ptr, extraPtCount)
return this
}
/**
* Adds beginning of contour at Point (x, y).
*
* @param x x-axis value of contour start
* @param y y-axis value of contour start
* @return reference to Path
* Returns zero if Path contains no lines, or curves: quads, conics, or cubics.
*
* @see [https://fiddle.skia.org/c/@Path_moveTo](https://fiddle.skia.org/c/@Path_moveTo)
*/
fun moveTo(x: Float, y: Float): Path {
Stats.onNativeCall()
_nMoveTo(_ptr, x, y)
return this
}
/**
* Adds beginning of contour at Point p.
*
* @param p contour start
* @return this
*/
fun moveTo(p: Point): Path {
return moveTo(p.x, p.y)
}
/**
* getSegmentMasks() returns a cached result; it is very fast.
*
* Adds beginning of contour relative to last point.
* @return SegmentMask bits or zero
*
* @see PathSegmentMask.LINE
*
* If Path is empty, starts contour at (dx, dy).
* Otherwise, start contour at last point offset by (dx, dy).
* Function name stands for "relative move to".
* @see PathSegmentMask.QUAD
*
* @param dx offset from last point to contour start on x-axis
* @param dy offset from last point to contour start on y-axis
* @return reference to Path
* @see PathSegmentMask.CONIC
*
* @see [https://fiddle.skia.org/c/@Path_rMoveTo](https://fiddle.skia.org/c/@Path_rMoveTo)
* @see PathSegmentMask.CUBIC
*/
fun rMoveTo(dx: Float, dy: Float): Path {
Stats.onNativeCall()
_nRMoveTo(_ptr, dx, dy)
return this
val segmentMasks: Int
get() = try {
Stats.onNativeCall()
_nGetSegmentMasks(_ptr)
} finally {
reachabilityBarrier(this)
}
override fun iterator(): PathSegmentIterator {
return iterator(false)
}
fun iterator(forceClose: Boolean): PathSegmentIterator {
return PathSegmentIterator.make(this, forceClose)
}
/**
* Returns true if the point (x, y) is contained by Path, taking into
* account [PathFillMode].
*
* Adds line from last point to (x, y). If Path is empty, or last Verb is
* [PathVerb.CLOSE], last point is set to (0, 0) before adding line.
*
*
* lineTo() appends [PathVerb.MOVE] to verb array and (0, 0) to Point array, if needed.
* lineTo() then appends [PathVerb.LINE] to verb array and (x, y) to Point array.
*
* @param x end of added line on x-axis
* @param y end of added line on y-axis
* @return this
* @param x x-axis value of containment test
* @param y y-axis value of containment test
* @return true if Point is in Path
*
* @see [https://fiddle.skia.org/c/@Path_lineTo](https://fiddle.skia.org/c/@Path_lineTo)
* @see [https://fiddle.skia.org/c/@Path_contains](https://fiddle.skia.org/c/@Path_contains)
*/
fun lineTo(x: Float, y: Float): Path {
Stats.onNativeCall()
_nLineTo(_ptr, x, y)
return this
fun contains(x: Float, y: Float): Boolean {
return try {
Stats.onNativeCall()
_nContains(_ptr, x, y)
} finally {
reachabilityBarrier(this)
}
}
/**
* Returns true if the point is contained by Path, taking into
* account [PathFillMode].
*
* Adds line from last point to Point p. If Path is empty, or last [PathVerb] is
* [PathVerb.CLOSE], last point is set to (0, 0) before adding line.
*
*
* lineTo() first appends [PathVerb.MOVE] to verb array and (0, 0) to Point array, if needed.
* lineTo() then appends [PathVerb.LINE] to verb array and Point p to Point array.
* @param p point of containment test
* @return true if Point is in Path
*
* @param p end Point of added line
* @return reference to Path
* @see [https://fiddle.skia.org/c/@Path_contains](https://fiddle.skia.org/c/@Path_contains)
*/
fun lineTo(p: Point): Path {
return lineTo(p.x, p.y)
operator fun contains(p: Point): Boolean {
return contains(p.x, p.y)
}
/**
* Writes text representation of Path to standard output. The representation may be
* directly compiled as C++ code. Floating point values are written
* with limited precision; it may not be possible to reconstruct original Path
* from output.
*
* Adds line from last point to vector (dx, dy). If Path is empty, or last [PathVerb] is
* [PathVerb.CLOSE], last point is set to (0, 0) before adding line.
*
*
* Appends [PathVerb.MOVE] to verb array and (0, 0) to Point array, if needed;
* then appends [PathVerb.LINE] to verb array and line end to Point array.
*
*
* Line end is last point plus vector (dx, dy).
*
*
* Function name stands for "relative line to".
*
* @param dx offset from last point to line end on x-axis
* @param dy offset from last point to line end on y-axis
* @return reference to Path
*
* @see [https://fiddle.skia.org/c/@Path_rLineTo](https://fiddle.skia.org/c/@Path_rLineTo)
*
* @see [https://fiddle.skia.org/c/@Quad_a](https://fiddle.skia.org/c/@Quad_a)
* @return this
*
* @see [https://fiddle.skia.org/c/@Quad_b](https://fiddle.skia.org/c/@Quad_b)
* @see [https://fiddle.skia.org/c/@Path_dump_2](https://fiddle.skia.org/c/@Path_dump_2)
*/
fun rLineTo(dx: Float, dy: Float): Path {
fun dump(): Path {
Stats.onNativeCall()
_nRLineTo(_ptr, dx, dy)
_nDump(_ptr)
return this
}
/**
* Adds quad from last point towards (x1, y1), to (x2, y2).
* If Path is empty, or last [PathVerb] is [PathVerb.CLOSE], last point is set to (0, 0)
* before adding quad.
* Writes text representation of Path to standard output. The representation may be
* directly compiled as C++ code. Floating point values are written
* in hexadecimal to preserve their exact bit pattern. The output reconstructs the
* original Path.
*
* Appends [PathVerb.MOVE] to verb array and (0, 0) to Point array, if needed;
* then appends [PathVerb.QUAD] to verb array; and (x1, y1), (x2, y2)
* to Point array.
* Use instead of [dump] when precision is important.
*
* @param x1 control Point of quad on x-axis
* @param y1 control Point of quad on y-axis
* @param x2 end Point of quad on x-axis
* @param y2 end Point of quad on y-axis
* @return reference to Path
* @return this
*
* @see [https://fiddle.skia.org/c/@Path_quadTo](https://fiddle.skia.org/c/@Path_quadTo)
* @see [https://fiddle.skia.org/c/@Path_dumpHex](https://fiddle.skia.org/c/@Path_dumpHex)
*/
fun quadTo(x1: Float, y1: Float, x2: Float, y2: Float): Path {
fun dumpHex(): Path {
Stats.onNativeCall()
_nQuadTo(_ptr, x1, y1, x2, y2)
_nDumpHex(_ptr)
return this
}
/**
* Writes Path to byte buffer.
*
* Adds quad from last point towards Point p1, to Point p2.
*
*
* If Path is empty, or last [PathVerb] is [PathVerb.CLOSE], last point is set to (0, 0)
* before adding quad.
* Writes [PathFillMode], verb array, Point array, conic weight, and
* additionally writes computed information like path convexity and bounds.
*
* Use only in concert with [makeFromBytes];
* the format used for Path in memory is not guaranteed.
*
* Appends [PathVerb.MOVE] to verb array and (0, 0) to Point array, if needed;
* then appends [PathVerb.QUAD] to verb array; and Point p1, p2
* to Point array.
* @return serialized Path; length always a multiple of 4
*
* @param p1 control Point of added quad
* @param p2 end Point of added quad
* @return reference to Path
* @see [https://fiddle.skia.org/c/@Path_writeToMemory](https://fiddle.skia.org/c/@Path_writeToMemory)
*/
fun quadTo(p1: Point, p2: Point): Path {
return quadTo(p1.x, p1.y, p2.x, p2.y)
fun serializeToBytes(): ByteArray {
return try {
Stats.onNativeCall()
val size = interopScope { _nSerializeToBytes(_ptr, toInterop(null as ByteArray?)) }
if (size == -1) {
throw Error("Path is too big")
}
withResult(ByteArray(size)) {
_nSerializeToBytes(_ptr, it)
}
} finally {
reachabilityBarrier(this)
}
}
/**
*
* Adds quad from last point towards vector (dx1, dy1), to vector (dx2, dy2).
* If Path is empty, or last [PathVerb]
* is [PathVerb.CLOSE], last point is set to (0, 0) before adding quad.
*
* Returns a non-zero, globally unique value. A different value is returned
* if verb array, Point array, or conic weight changes.
*
* Appends [PathVerb.MOVE] to verb array and (0, 0) to Point array,
* if needed; then appends [PathVerb.QUAD] to verb array; and appends quad
* control and quad end to Point array.
*
* Setting [PathFillMode] does not change generation identifier.
*
* Quad control is last point plus vector (dx1, dy1).
*
* Each time the path is modified, a different generation identifier will be returned.
* [PathFillMode] does affect generation identifier on Android framework.
*
* Quad end is last point plus vector (dx2, dy2).
* @return non-zero, globally unique value
*
*
* Function name stands for "relative quad to".
*
* @param dx1 offset from last point to quad control on x-axis
* @param dy1 offset from last point to quad control on y-axis
* @param dx2 offset from last point to quad end on x-axis
* @param dy2 offset from last point to quad end on y-axis
* @return reference to Path
*
* @see [https://fiddle.skia.org/c/@Conic_Weight_a](https://fiddle.skia.org/c/@Conic_Weight_a)
*
* @see [https://fiddle.skia.org/c/@Conic_Weight_b](https://fiddle.skia.org/c/@Conic_Weight_b)
*
* @see [https://fiddle.skia.org/c/@Conic_Weight_c](https://fiddle.skia.org/c/@Conic_Weight_c)
*
* @see [https://fiddle.skia.org/c/@Path_rQuadTo](https://fiddle.skia.org/c/@Path_rQuadTo)
*/
fun rQuadTo(dx1: Float, dy1: Float, dx2: Float, dy2: Float): Path {
Stats.onNativeCall()
_nRQuadTo(_ptr, dx1, dy1, dx2, dy2)
return this
}
/**
*
* Adds conic from last point towards (x1, y1), to (x2, y2), weighted by w.
*
*
* If Path is empty, or last [PathVerb] is [PathVerb.CLOSE], last point is set to (0, 0)
* before adding conic.
*
*
* Appends [PathVerb.MOVE] to verb array and (0, 0) to Point array, if needed.
*
*
* If w is finite and not one, appends [PathVerb.CONIC] to verb array;
* and (x1, y1), (x2, y2) to Point array; and w to conic weights.
*
*
* If w is one, appends [PathVerb.QUAD] to verb array, and
* (x1, y1), (x2, y2) to Point array.
*
*
* If w is not finite, appends [PathVerb.LINE] twice to verb array, and
* (x1, y1), (x2, y2) to Point array.
*
* @param x1 control Point of conic on x-axis
* @param y1 control Point of conic on y-axis
* @param x2 end Point of conic on x-axis
* @param y2 end Point of conic on y-axis
* @param w weight of added conic
* @return reference to Path
*/
fun conicTo(x1: Float, y1: Float, x2: Float, y2: Float, w: Float): Path {
Stats.onNativeCall()
_nConicTo(_ptr, x1, y1, x2, y2, w)
return this
}
/**
*
* Adds conic from last point towards Point p1, to Point p2, weighted by w.
*
*
* If Path is empty, or last [PathVerb] is [PathVerb.CLOSE], last point is set to (0, 0)
* before adding conic.
*
*
* Appends [PathVerb.MOVE] to verb array and (0, 0) to Point array, if needed.
*
*
* If w is finite and not one, appends [PathVerb.CONIC] to verb array;
* and Point p1, p2 to Point array; and w to conic weights.
*
*
* If w is one, appends [PathVerb.QUAD] to verb array, and Point p1, p2
* to Point array.
*
*
* If w is not finite, appends [PathVerb.LINE] twice to verb array, and
* Point p1, p2 to Point array.
*
* @param p1 control Point of added conic
* @param p2 end Point of added conic
* @param w weight of added conic
* @return reference to Path
*/
fun conicTo(p1: Point, p2: Point, w: Float): Path {
return conicTo(p1.x, p1.y, p2.x, p2.y, w)
}
/**
*
* Adds conic from last point towards vector (dx1, dy1), to vector (dx2, dy2),
* weighted by w. If Path is empty, or last [PathVerb]
* is [PathVerb.CLOSE], last point is set to (0, 0) before adding conic.
*
*
* Appends [PathVerb.MOVE] to verb array and (0, 0) to Point array,
* if needed.
*
*
* If w is finite and not one, next appends [PathVerb.CONIC] to verb array,
* and w is recorded as conic weight; otherwise, if w is one, appends
* [PathVerb.QUAD] to verb array; or if w is not finite, appends [PathVerb.LINE]
* twice to verb array.
*
*
* In all cases appends Point control and end to Point array.
* control is last point plus vector (dx1, dy1).
* end is last point plus vector (dx2, dy2).
*
*
* Function name stands for "relative conic to".
*
* @param dx1 offset from last point to conic control on x-axis
* @param dy1 offset from last point to conic control on y-axis
* @param dx2 offset from last point to conic end on x-axis
* @param dy2 offset from last point to conic end on y-axis
* @param w weight of added conic
* @return reference to Path
*/
fun rConicTo(dx1: Float, dy1: Float, dx2: Float, dy2: Float, w: Float): Path {
Stats.onNativeCall()
_nRConicTo(_ptr, dx1, dy1, dx2, dy2, w)
return this
}
/**
*
* Adds cubic from last point towards (x1, y1), then towards (x2, y2), ending at
* (x3, y3). If Path is empty, or last [PathVerb] is [PathVerb.CLOSE], last point is set to
* (0, 0) before adding cubic.
*
*
* Appends [PathVerb.MOVE] to verb array and (0, 0) to Point array, if needed;
* then appends [PathVerb.CUBIC] to verb array; and (x1, y1), (x2, y2), (x3, y3)
* to Point array.
*
* @param x1 first control Point of cubic on x-axis
* @param y1 first control Point of cubic on y-axis
* @param x2 second control Point of cubic on x-axis
* @param y2 second control Point of cubic on y-axis
* @param x3 end Point of cubic on x-axis
* @param y3 end Point of cubic on y-axis
* @return reference to Path
*/
fun cubicTo(x1: Float, y1: Float, x2: Float, y2: Float, x3: Float, y3: Float): Path {
Stats.onNativeCall()
_nCubicTo(_ptr, x1, y1, x2, y2, x3, y3)
return this
}
/**
*
* Adds cubic from last point towards Point p1, then towards Point p2, ending at
* Point p3. If Path is empty, or last [PathVerb] is [PathVerb.CLOSE], last point is set to
* (0, 0) before adding cubic.
*
*
* Appends [PathVerb.MOVE] to verb array and (0, 0) to Point array, if needed;
* then appends [PathVerb.CUBIC] to verb array; and Point p1, p2, p3
* to Point array.
*
* @param p1 first control Point of cubic
* @param p2 second control Point of cubic
* @param p3 end Point of cubic
* @return reference to Path
*/
fun cubicTo(p1: Point, p2: Point, p3: Point): Path {
return cubicTo(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y)
}
/**
*
* Adds cubic from last point towards vector (dx1, dy1), then towards
* vector (dx2, dy2), to vector (dx3, dy3).
* If Path is empty, or last [PathVerb]
* is [PathVerb.CLOSE], last point is set to (0, 0) before adding cubic.
*
*
* Appends [PathVerb.MOVE] to verb array and (0, 0) to Point array,
* if needed; then appends [PathVerb.CUBIC] to verb array; and appends cubic
* control and cubic end to Point array.
*
*
* Cubic control is last point plus vector (dx1, dy1).
*
*
* Cubic end is last point plus vector (dx2, dy2).
*
*
* Function name stands for "relative cubic to".
*
* @param dx1 offset from last point to first cubic control on x-axis
* @param dy1 offset from last point to first cubic control on y-axis
* @param dx2 offset from last point to second cubic control on x-axis
* @param dy2 offset from last point to second cubic control on y-axis
* @param dx3 offset from last point to cubic end on x-axis
* @param dy3 offset from last point to cubic end on y-axis
* @return reference to Path
*/
fun rCubicTo(dx1: Float, dy1: Float, dx2: Float, dy2: Float, dx3: Float, dy3: Float): Path {
Stats.onNativeCall()
_nRCubicTo(_ptr, dx1, dy1, dx2, dy2, dx3, dy3)
return this
}
/**
*
* Appends arc to Path. Arc added is part of ellipse
* bounded by oval, from startAngle through sweepAngle. Both startAngle and
* sweepAngle are measured in degrees, where zero degrees is aligned with the
* positive x-axis, and positive sweeps extends arc clockwise.
*
*
* arcTo() adds line connecting Path last Point to initial arc Point if forceMoveTo
* is false and Path is not empty. Otherwise, added contour begins with first point
* of arc. Angles greater than -360 and less than 360 are treated modulo 360.
*
* @param oval bounds of ellipse containing arc
* @param startAngle starting angle of arc in degrees
* @param sweepAngle sweep, in degrees. Positive is clockwise; treated modulo 360
* @param forceMoveTo true to start a new contour with arc
* @return reference to Path
*
* @see [https://fiddle.skia.org/c/@Path_arcTo](https://fiddle.skia.org/c/@Path_arcTo)
*/
fun arcTo(oval: Rect, startAngle: Float, sweepAngle: Float, forceMoveTo: Boolean): Path {
return arcTo(oval.left, oval.top, oval.right, oval.bottom, startAngle, sweepAngle, forceMoveTo)
}
/**
*
* Appends arc to Path. Arc added is part of ellipse
* bounded by oval, from startAngle through sweepAngle. Both startAngle and
* sweepAngle are measured in degrees, where zero degrees is aligned with the
* positive x-axis, and positive sweeps extends arc clockwise.
*
*
* arcTo() adds line connecting Path last Point to initial arc Point if forceMoveTo
* is false and Path is not empty. Otherwise, added contour begins with first point
* of arc. Angles greater than -360 and less than 360 are treated modulo 360.
*
* @param left left edge of oval bounding ellipse
* @param top top edge of oval bounding ellipse
* @param right right edge of oval bounding ellipse
* @param bottom bottom edge of oval bounding ellipse
* @param startAngle starting angle of arc in degrees
* @param sweepAngle sweep, in degrees. Positive is clockwise; treated modulo 360
* @param forceMoveTo true to start a new contour with arc
* @return reference to Path
*
* @see [https://fiddle.skia.org/c/@Path_arcTo](https://fiddle.skia.org/c/@Path_arcTo)
*/
fun arcTo(left: Float, top: Float, right: Float, bottom: Float, startAngle: Float, sweepAngle: Float, forceMoveTo: Boolean): Path {
Stats.onNativeCall()
_nArcTo(_ptr, left, top, right, bottom, startAngle, sweepAngle, forceMoveTo)
return this
}
/**
*
* Appends arc to Path, after appending line if needed. Arc is implemented by conic
* weighted to describe part of circle. Arc is contained by tangent from
* last Path point to (x1, y1), and tangent from (x1, y1) to (x2, y2). Arc
* is part of circle sized to radius, positioned so it touches both tangent lines.
*
*
* If last Path Point does not start Arc, tangentArcTo appends connecting Line to Path.
* The length of Vector from (x1, y1) to (x2, y2) does not affect Arc.
*
*
* Arc sweep is always less than 180 degrees. If radius is zero, or if
* tangents are nearly parallel, tangentArcTo appends Line from last Path Point to (x1, y1).
*
*
* tangentArcTo appends at most one Line and one conic.
*
*
* tangentArcTo implements the functionality of PostScript arct and HTML Canvas tangentArcTo.
*
* @param x1 x-axis value common to pair of tangents
* @param y1 y-axis value common to pair of tangents
* @param x2 x-axis value end of second tangent
* @param y2 y-axis value end of second tangent
* @param radius distance from arc to circle center
* @return reference to Path
*
* @see [https://fiddle.skia.org/c/@Path_arcTo_2_a](https://fiddle.skia.org/c/@Path_arcTo_2_a)
*
* @see [https://fiddle.skia.org/c/@Path_arcTo_2_b](https://fiddle.skia.org/c/@Path_arcTo_2_b)
*
* @see [https://fiddle.skia.org/c/@Path_arcTo_2_c](https://fiddle.skia.org/c/@Path_arcTo_2_c)
*/
fun tangentArcTo(x1: Float, y1: Float, x2: Float, y2: Float, radius: Float): Path {
Stats.onNativeCall()
_nTangentArcTo(_ptr, x1, y1, x2, y2, radius)
return this
}
/**
*
* Appends arc to Path, after appending line if needed. Arc is implemented by conic
* weighted to describe part of circle. Arc is contained by tangent from
* last Path point to p1, and tangent from p1 to p2. Arc
* is part of circle sized to radius, positioned so it touches both tangent lines.
*
*
* If last Path Point does not start arc, tangentArcTo() appends connecting line to Path.
* The length of vector from p1 to p2 does not affect arc.
*
*
* Arc sweep is always less than 180 degrees. If radius is zero, or if
* tangents are nearly parallel, tangentArcTo() appends line from last Path Point to p1.
*
*
* tangentArcTo() appends at most one line and one conic.
*
*
* tangentArcTo() implements the functionality of PostScript arct and HTML Canvas tangentArcTo.
*
* @param p1 Point common to pair of tangents
* @param p2 end of second tangent
* @param radius distance from arc to circle center
* @return reference to Path
*/
fun tangentArcTo(p1: Point, p2: Point, radius: Float): Path {
return tangentArcTo(p1.x, p1.y, p2.x, p2.y, radius)
}
/**
*
*Appends arc to Path. Arc is implemented by one or more conics weighted to
* describe part of oval with radii (rx, ry) rotated by xAxisRotate degrees. Arc
* curves from last Path Point to (x, y), choosing one of four possible routes:
* clockwise or counterclockwise, and smaller or larger.
*
*
* Arc sweep is always less than 360 degrees. ellipticalArcTo() appends line to (x, y) if
* either radii are zero, or if last Path Point equals (x, y). ellipticalArcTo() scales radii
* (rx, ry) to fit last Path Point and (x, y) if both are greater than zero but
* too small.
*
*
* ellipticalArcTo() appends up to four conic curves.
*
*
* ellipticalArcTo() implements the functionality of SVG arc, although SVG sweep-flag value
* is opposite the integer value of sweep; SVG sweep-flag uses 1 for clockwise,
* while [PathDirection.CLOCKWISE] cast to int is zero.
*
* @param rx radius on x-axis before x-axis rotation
* @param ry radius on y-axis before x-axis rotation
* @param xAxisRotate x-axis rotation in degrees; positive values are clockwise
* @param arc chooses smaller or larger arc
* @param direction chooses clockwise or counterclockwise arc
* @param x end of arc
* @param y end of arc
* @return reference to Path
*/
fun ellipticalArcTo(
rx: Float,
ry: Float,
xAxisRotate: Float,
arc: PathEllipseArc,
direction: PathDirection,
x: Float,
y: Float
): Path {
Stats.onNativeCall()
_nEllipticalArcTo(_ptr, rx, ry, xAxisRotate, arc.ordinal, direction.ordinal, x, y)
return this
}
/**
*
* Appends arc to Path. Arc is implemented by one or more conic weighted to describe
* part of oval with radii (r.fX, r.fY) rotated by xAxisRotate degrees. Arc curves
* from last Path Point to (xy.fX, xy.fY), choosing one of four possible routes:
* clockwise or counterclockwise, and smaller or larger.
*
*
* Arc sweep is always less than 360 degrees. ellipticalArcTo() appends line to xy if either
* radii are zero, or if last Path Point equals (xy.fX, xy.fY). ellipticalArcTo() scales radii r to
* fit last Path Point and xy if both are greater than zero but too small to describe
* an arc.
*
*
* ellipticalArcTo() appends up to four conic curves.
*
*
* ellipticalArcTo() implements the functionality of SVG arc, although SVG sweep-flag value is
* opposite the integer value of sweep; SVG sweep-flag uses 1 for clockwise, while
* [PathDirection.CLOCKWISE] cast to int is zero.
*
* @param r radii on axes before x-axis rotation
* @param xAxisRotate x-axis rotation in degrees; positive values are clockwise
* @param arc chooses smaller or larger arc
* @param direction chooses clockwise or counterclockwise arc
* @param xy end of arc
* @return reference to Path
*/
fun ellipticalArcTo(r: Point, xAxisRotate: Float, arc: PathEllipseArc, direction: PathDirection, xy: Point): Path {
return ellipticalArcTo(r.x, r.y, xAxisRotate, arc, direction, xy.x, xy.y)
}
/**
*
* Appends arc to Path, relative to last Path Point. Arc is implemented by one or
* more conic, weighted to describe part of oval with radii (rx, ry) rotated by
* xAxisRotate degrees. Arc curves from last Path Point to relative end Point:
* (dx, dy), choosing one of four possible routes: clockwise or
* counterclockwise, and smaller or larger. If Path is empty, the start arc Point
* is (0, 0).
*
*
* Arc sweep is always less than 360 degrees. rEllipticalArcTo() appends line to end Point
* if either radii are zero, or if last Path Point equals end Point.
* rEllipticalArcTo() scales radii (rx, ry) to fit last Path Point and end Point if both are
* greater than zero but too small to describe an arc.
*
*
* rEllipticalArcTo() appends up to four conic curves.
*
*
* rEllipticalArcTo() implements the functionality of svg arc, although SVG "sweep-flag" value is
* opposite the integer value of sweep; SVG "sweep-flag" uses 1 for clockwise, while
* [PathDirection.CLOCKWISE] cast to int is zero.
*
* @param rx radius before x-axis rotation
* @param ry radius before x-axis rotation
* @param xAxisRotate x-axis rotation in degrees; positive values are clockwise
* @param arc chooses smaller or larger arc
* @param direction chooses clockwise or counterclockwise arc
* @param dx x-axis offset end of arc from last Path Point
* @param dy y-axis offset end of arc from last Path Point
* @return reference to Path
*/
fun rEllipticalArcTo(
rx: Float,
ry: Float,
xAxisRotate: Float,
arc: PathEllipseArc,
direction: PathDirection,
dx: Float,
dy: Float
): Path {
Stats.onNativeCall()
_nREllipticalArcTo(_ptr, rx, ry, xAxisRotate, arc.ordinal, direction.ordinal, dx, dy)
return this
}
/**
*
* Appends [PathVerb.CLOSE] to Path. A closed contour connects the first and last Point
* with line, forming a continuous loop. Open and closed contour draw the same
* with [PaintMode.FILL]. With [PaintMode.STROKE], open contour draws
* [PaintStrokeCap] at contour start and end; closed contour draws
* [PaintStrokeJoin] at contour start and end.
*
*
* closePath() has no effect if Path is empty or last Path [PathVerb] is [PathVerb.CLOSE].
*
* @return reference to Path
*
* @see [https://fiddle.skia.org/c/@Path_close](https://fiddle.skia.org/c/@Path_close)
*/
fun closePath(): Path {
Stats.onNativeCall()
_nClosePath(_ptr)
return this
}
/**
*
* Returns Rect if Path is equivalent to Rect when filled.
*
* rect may be smaller than the Path bounds. Path bounds may include [PathVerb.MOVE] points
* that do not alter the area drawn by the returned rect.
*
* @return bounds if Path contains Rect, null otherwise
*
* @see [https://fiddle.skia.org/c/@Path_isRect](https://fiddle.skia.org/c/@Path_isRect)
*/
val isRect: Rect?
get() = try {
Stats.onNativeCall()
Rect.fromInteropPointerNullable { _nIsRect(_ptr, it) }
} finally {
reachabilityBarrier(this)
}
/**
* Adds Rect to Path, appending [PathVerb.MOVE], three [PathVerb.LINE], and [PathVerb.CLOSE].
* If dir is [PathDirection.CLOCKWISE], Rect corners are added clockwise; if dir is
* [PathDirection.COUNTER_CLOCKWISE], Rect corners are added counterclockwise.
* start determines the first corner added.
*
* @param rect Rect to add as a closed contour
* @param dir Direction to wind added contour
* @param start initial corner of Rect to add. 0 for top left, 1 for top right, 2 for lower right, 3 for lower left
* @return reference to Path
*
* @see [https://fiddle.skia.org/c/@Path_addRect_2](https://fiddle.skia.org/c/@Path_addRect_2)
*/
/**
* Adds Rect to Path, appending [PathVerb.MOVE], three [PathVerb.LINE], and [PathVerb.CLOSE],
* starting with top-left corner of Rect; followed by top-right, bottom-right,
* and bottom-left if dir is [PathDirection.CLOCKWISE]; or followed by bottom-left,
* bottom-right, and top-right if dir is [PathDirection.COUNTER_CLOCKWISE].
*
* @param rect Rect to add as a closed contour
* @param dir Direction to wind added contour
* @return reference to Path
*
* @see [https://fiddle.skia.org/c/@Path_addRect](https://fiddle.skia.org/c/@Path_addRect)
*/
fun addRect(rect: Rect, dir: PathDirection = PathDirection.CLOCKWISE, start: Int = 0): Path {
return addRect(rect.left, rect.top, rect.right, rect.bottom, dir, start)
}
/**
* Adds Rect to Path, appending [PathVerb.MOVE], three [PathVerb.LINE], and [PathVerb.CLOSE],
* starting with top-left corner of Rect; followed by top-right, bottom-right,
* and bottom-left if dir is [PathDirection.CLOCKWISE]; or followed by bottom-left,
* bottom-right, and top-right if dir is [PathDirection.COUNTER_CLOCKWISE].
*
* @param left left edge of Rect to add as a closed contour
* @param top top edge of Rect to add as a closed contour
* @param right right edge of Rect to add as a closed contour
* @param bottom bottom edge of Rect to add as a closed contour
* @param dir Direction to wind added contour
* @return reference to Path
*
* @see [https://fiddle.skia.org/c/@Path_addRect](https://fiddle.skia.org/c/@Path_addRect)
*/
fun addRect(left: Float, top: Float, right: Float, bottom: Float, dir: PathDirection = PathDirection.CLOCKWISE, start: Int = 0): Path {
Stats.onNativeCall()
_nAddRect(_ptr, left, top, right, bottom, dir.ordinal, start)
return this
}
/**
* Adds oval to Path, appending [PathVerb.MOVE], four [PathVerb.CONIC], and [PathVerb.CLOSE].
* Oval is upright ellipse bounded by Rect oval with radii equal to half oval width
* and half oval height. Oval begins at start and continues
* clockwise if dir is [PathDirection.CLOCKWISE], counterclockwise if dir is [PathDirection.COUNTER_CLOCKWISE].
*
* @param oval bounds of ellipse added
* @param dir Direction to wind ellipse
* @param start index of initial point of ellipse. 0 for top, 1 for right, 2 for bottom, 3 for left
* @return reference to Path
*
* @see [https://fiddle.skia.org/c/@Path_addOval_2](https://fiddle.skia.org/c/@Path_addOval_2)
*/
/**
*
* Adds oval to path, appending [PathVerb.MOVE], four [PathVerb.CONIC], and [PathVerb.CLOSE].
*
*
* Oval is upright ellipse bounded by Rect oval with radii equal to half oval width
* and half oval height. Oval begins at (oval.fRight, oval.centerY()) and continues
* clockwise if dir is [PathDirection.CLOCKWISE], counterclockwise if dir is [PathDirection.COUNTER_CLOCKWISE].
*
* @param oval bounds of ellipse added
* @param dir Direction to wind ellipse
* @return reference to Path
*
* @see [https://fiddle.skia.org/c/@Path_addOval](https://fiddle.skia.org/c/@Path_addOval)
*/
fun addOval(oval: Rect, dir: PathDirection = PathDirection.CLOCKWISE, start: Int = 1): Path {
return addOval(oval.left, oval.top, oval.right, oval.bottom, dir, start)
}
/**
*
* Adds oval to path, appending [PathVerb.MOVE], four [PathVerb.CONIC], and [PathVerb.CLOSE].
*
*
* Oval is upright ellipse bounded by Rect oval with radii equal to half oval width
* and half oval height. Oval begins at (oval.fRight, oval.centerY()) and continues
* clockwise if dir is [PathDirection.CLOCKWISE], counterclockwise if dir is [PathDirection.COUNTER_CLOCKWISE].
*
* @param left left edge of oval bounding ellipse
* @param top top edge of oval bounding ellipse
* @param right right edge of oval bounding ellipse
* @param bottom bottom edge of oval bounding ellipse
* @param dir Direction to wind ellipse
* @return reference to Path
*
* @see [https://fiddle.skia.org/c/@Path_addOval](https://fiddle.skia.org/c/@Path_addOval)
*/
fun addOval(left: Float, top: Float, right: Float, bottom: Float, dir: PathDirection = PathDirection.CLOCKWISE, start: Int = 1): Path {
Stats.onNativeCall()
_nAddOval(_ptr, left, top, right, bottom, dir.ordinal, start)
return this
}
/**
*
* Adds circle centered at (x, y) of size radius to Path, appending [PathVerb.MOVE],
* four [PathVerb.CONIC], and [PathVerb.CLOSE]. Circle begins at: (x + radius, y), continuing
* clockwise if dir is [PathDirection.CLOCKWISE], and counterclockwise if dir is [PathDirection.COUNTER_CLOCKWISE].
*
*
* Has no effect if radius is zero or negative.
*
* @param x center of circle
* @param y center of circle
* @param radius distance from center to edge
* @param dir Direction to wind circle
* @return reference to Path
*/
/**
*
* Adds circle centered at (x, y) of size radius to Path, appending [PathVerb.MOVE],
* four [PathVerb.CONIC], and [PathVerb.CLOSE]. Circle begins at: (x + radius, y)
*
*
* Has no effect if radius is zero or negative.
*
* @param x center of circle
* @param y center of circle
* @param radius distance from center to edge
* @return reference to Path
*/
fun addCircle(x: Float, y: Float, radius: Float, dir: PathDirection = PathDirection.CLOCKWISE): Path {
Stats.onNativeCall()
_nAddCircle(_ptr, x, y, radius, dir.ordinal)
return this
}
/**
*
* Appends arc to Path, as the start of new contour. Arc added is part of ellipse
* bounded by oval, from startAngle through sweepAngle. Both startAngle and
* sweepAngle are measured in degrees, where zero degrees is aligned with the
* positive x-axis, and positive sweeps extends arc clockwise.
*
*
* If sweepAngle -360, or sweepAngle 360; and startAngle modulo 90 is nearly
* zero, append oval instead of arc. Otherwise, sweepAngle values are treated
* modulo 360, and arc may or may not draw depending on numeric rounding.
*
* @param oval bounds of ellipse containing arc
* @param startAngle starting angle of arc in degrees
* @param sweepAngle sweep, in degrees. Positive is clockwise; treated modulo 360
* @return reference to Path
*
* @see [https://fiddle.skia.org/c/@Path_addArc](https://fiddle.skia.org/c/@Path_addArc)
*/
fun addArc(oval: Rect, startAngle: Float, sweepAngle: Float): Path {
return addArc(oval.left, oval.top, oval.right, oval.bottom, startAngle, sweepAngle)
}
/**
*
* Adds rrect to Path, creating a new closed contour. If dir is [PathDirection.CLOCKWISE], rrect
* winds clockwise; if dir is [PathDirection.COUNTER_CLOCKWISE], rrect winds counterclockwise.
* start determines the first point of rrect to add.
*
* @param left left edge of rounded rectangle
* @param top top edge of rounded rectangle
* @param right right edge of rounded rectangle
* @param bottom bottom edge of rounded rectangle
* @param dir Direction to wind RRect
* @param start index of initial point of RRect. 0 for top-right end of the arc at top left,
* 1 for top-left end of the arc at top right, 2 for bottom-right end of top right arc, etc.
* @return reference to Path
*
* @see [https://fiddle.skia.org/c/@Path_addRRect_2](https://fiddle.skia.org/c/@Path_addRRect_2)
*/
fun addArc(left: Float, top: Float, right: Float, bottom: Float, startAngle: Float, sweepAngle: Float): Path {
Stats.onNativeCall()
_nAddArc(_ptr, left, top, right, bottom, startAngle, sweepAngle)
return this
}
/**
*
* Adds rrect to Path, creating a new closed contour. RRect starts at top-left of the lower-left corner and
* winds clockwise.
*
*
* After appending, Path may be empty, or may contain: Rect, Oval, or RRect.
*
* @param rrect bounds and radii of rounded rectangle
* @return reference to Path
*
* @see [https://fiddle.skia.org/c/@Path_addRRect](https://fiddle.skia.org/c/@Path_addRRect)
*/
fun addRRect(rrect: RRect, dir: PathDirection = PathDirection.CLOCKWISE, start: Int = 6): Path {
return addRRect(rrect.left, rrect.top, rrect.right, rrect.bottom, rrect.radii, dir, start)
}
/**
*
* Adds rrect to Path, creating a new closed contour. RRect starts at top-left of the lower-left corner and
* winds clockwise.
*
*
* After appending, Path may be empty, or may contain: Rect, Oval, or RRect.
*
* @param left left edge of rounded rectangle
* @param top top edge of rounded rectangle
* @param right right edge of rounded rectangle
* @param bottom bottom edge of rounded rectangle
* @param radii array of 8 radius values, 2 for each corner
* @param dir Direction to wind rounded rectangle
* @return reference to Path
*
* @see [https://fiddle.skia.org/c/@Path_addRRect](https://fiddle.skia.org/c/@Path_addRRect)
*/
fun addRRect(left: Float, top: Float, right: Float, bottom: Float, radii: FloatArray, dir: PathDirection = PathDirection.CLOCKWISE, start: Int = 6): Path {
Stats.onNativeCall()
interopScope {
_nAddRRect(_ptr, left, top, right, bottom, toInterop(radii), radii.size, dir.ordinal, start)
}
return this
}
/**
*
* Adds contour created from line array, adding (pts.length - 1) line segments.
* Contour added starts at pts[0], then adds a line for every additional Point
* in pts array. If close is true, appends [PathVerb.CLOSE] to Path, connecting
* pts[pts.length - 1] and pts[0].
*
*
* If pts is empty, append [PathVerb.MOVE] to path.
*
* @param pts array of line sharing end and start Point
* @param close true to add line connecting contour end and start
* @return reference to Path
*
* @see [https://fiddle.skia.org/c/@Path_addPoly](https://fiddle.skia.org/c/@Path_addPoly)
*/
fun addPoly(pts: Array<Point>, close: Boolean): Path {
val flat = FloatArray(pts.size * 2)
for (i in pts.indices) {
flat[i * 2] = pts[i].x
flat[i * 2 + 1] = pts[i].y
}
return addPoly(flat, close)
}
/**
*
* Adds contour created from line array, adding (pts.length / 2 - 1) line segments.
* Contour added starts at (pts[0], pts[1]), then adds a line for every additional pair of floats
* in pts array. If close is true, appends [PathVerb.CLOSE] to Path, connecting
* (pts[count - 2], pts[count - 1]) and (pts[0], pts[1]).
*
*
* If pts is empty, append [PathVerb.MOVE] to path.
*
* @param pts flat array of line sharing end and start Point
* @param close true to add line connecting contour end and start
* @return reference to Path
*
* @see [https://fiddle.skia.org/c/@Path_addPoly](https://fiddle.skia.org/c/@Path_addPoly)
*/
fun addPoly(pts: FloatArray, close: Boolean): Path {
require(pts.size % 2 == 0) { "Expected even amount of pts, got " + pts.size }
Stats.onNativeCall()
interopScope {
_nAddPoly(_ptr, toInterop(pts), pts.size / 2, close)
}
return this
}
/**
*
* Appends src to Path.
*
*
* If extend is false, src verb array, Point array, and conic weights are
* added unaltered. If extend is true, add line before appending
* verbs, Point, and conic weights.
*
* @param src Path verbs, Point, and conic weights to add
* @param extend if should add a line before appending verbs
* @return reference to Path
*/
/**
*
* Appends src to Path.
*
*
* src verb array, Point array, and conic weights are
* added unaltered.
*
* @param src Path verbs, Point, and conic weights to add
* @return reference to Path
*/
fun addPath(src: Path?, extend: Boolean = false): Path {
return try {
Stats.onNativeCall()
_nAddPath(
_ptr,
getPtr(src),
extend
)
this
} finally {
reachabilityBarrier(this)
reachabilityBarrier(src)
}
}
/**
*
* Appends src to Path, offset by (dx, dy).
*
*
* If extend is false, src verb array, Point array, and conic weights are
* added unaltered. If extend is true, add line before appending
* verbs, Point, and conic weights.
*
* @param src Path verbs, Point, and conic weights to add
* @param dx offset added to src Point array x-axis coordinates
* @param dy offset added to src Point array y-axis coordinates
* @param extend if should add a line before appending verbs
* @return reference to Path
*/
/**
*
* Appends src to Path, offset by (dx, dy).
*
*
* Src verb array, Point array, and conic weights are
* added unaltered.
*
* @param src Path verbs, Point, and conic weights to add
* @param dx offset added to src Point array x-axis coordinates
* @param dy offset added to src Point array y-axis coordinates
* @return reference to Path
*/
fun addPath(src: Path?, dx: Float, dy: Float, extend: Boolean = false): Path {
return try {
Stats.onNativeCall()
_nAddPathOffset(
_ptr,
getPtr(src),
dx,
dy,
extend
)
this
} finally {
reachabilityBarrier(this)
reachabilityBarrier(src)
}
}
/**
*
* Appends src to Path, transformed by matrix. Transformed curves may have different
* verbs, Point, and conic weights.
*
*
* If extend is false, src verb array, Point array, and conic weights are
* added unaltered. If extend is true, add line before appending
* verbs, Point, and conic weights.
*
* @param src Path verbs, Point, and conic weights to add
* @param matrix transform applied to src
* @param extend if should add a line before appending verbs
* @return reference to Path
*/
/**
*
* Appends src to Path, transformed by matrix. Transformed curves may have different
* verbs, Point, and conic weights.
*
*
* Src verb array, Point array, and conic weights are
* added unaltered.
*
* @param src Path verbs, Point, and conic weights to add
* @param matrix transform applied to src
* @return reference to Path
*/
fun addPath(src: Path?, matrix: Matrix33, extend: Boolean = false): Path {
return try {
Stats.onNativeCall()
interopScope {
_nAddPathTransform(
_ptr,
getPtr(src),
toInterop(matrix.mat),
extend
)
}
this
} finally {
reachabilityBarrier(this)
reachabilityBarrier(src)
}
}
/**
* Appends src to Path, from back to front.
* Reversed src always appends a new contour to Path.
*
* @param src Path verbs, Point, and conic weights to add
* @return reference to Path
*
* @see [https://fiddle.skia.org/c/@Path_reverseAddPath](https://fiddle.skia.org/c/@Path_reverseAddPath)
*/
fun reverseAddPath(src: Path?): Path {
return try {
Stats.onNativeCall()
_nReverseAddPath(_ptr, getPtr(src))
this
} finally {
reachabilityBarrier(this)
reachabilityBarrier(src)
}
}
/**
* Offsets Point array by (dx, dy). Offset Path replaces dst.
* If dst is null, Path is replaced by offset data.
*
* @param dx offset added to Point array x-axis coordinates
* @param dy offset added to Point array y-axis coordinates
* @param dst overwritten, translated copy of Path; may be null
* @return this
*
* @see [https://fiddle.skia.org/c/@Path_offset](https://fiddle.skia.org/c/@Path_offset)
*/
/**
* Offsets Point array by (dx, dy). Path is replaced by offset data.
*
* @param dx offset added to Point array x-axis coordinates
* @param dy offset added to Point array y-axis coordinates
* @return this
*/
fun offset(dx: Float, dy: Float, dst: Path? = null): Path {
return try {
Stats.onNativeCall()
_nOffset(_ptr, dx, dy, getPtr(dst))
this
} finally {
reachabilityBarrier(this)
reachabilityBarrier(dst)
}
}
/**
* Transforms verb array, Point array, and weight by matrix.
* transform may change verbs and increase their number.
* Path is replaced by transformed data.
*
* @param matrix matrix to apply to Path
* @param applyPerspectiveClip whether to apply perspective clipping
* @return this
*/
fun transform(matrix: Matrix33, applyPerspectiveClip: Boolean): Path {
return transform(matrix, null, applyPerspectiveClip)
}
/**
* Transforms verb array, Point array, and weight by matrix.
* transform may change verbs and increase their number.
* Transformed Path replaces dst; if dst is null, original data
* is replaced.
*
* @param matrix matrix to apply to Path
* @param dst overwritten, transformed copy of Path; may be null
* @param applyPerspectiveClip whether to apply perspective clipping
* @return this
*
* @see [https://fiddle.skia.org/c/@Path_transform](https://fiddle.skia.org/c/@Path_transform)
*/
/**
* Transforms verb array, Point array, and weight by matrix.
* transform may change verbs and increase their number.
* Path is replaced by transformed data.
*
* @param matrix matrix to apply to Path
* @return this
*/
/**
* Transforms verb array, Point array, and weight by matrix.
* transform may change verbs and increase their number.
* Transformed Path replaces dst; if dst is null, original data
* is replaced.
*
* @param matrix matrix to apply to Path
* @param dst overwritten, transformed copy of Path; may be null
* @return this
*
* @see [https://fiddle.skia.org/c/@Path_transform](https://fiddle.skia.org/c/@Path_transform)
*/
fun transform(matrix: Matrix33, dst: Path? = null, applyPerspectiveClip: Boolean = true): Path {
return try {
Stats.onNativeCall()
interopScope {
_nTransform(
_ptr,
toInterop(matrix.mat),
getPtr(dst),
applyPerspectiveClip
)
}
this
} finally {
reachabilityBarrier(this)
reachabilityBarrier(dst)
}
}
/**
* Returns last point on Path in lastPt. Returns null if Point array is empty.
*
* @return point if Point array contains one or more Point, null otherwise
*
* @see [https://fiddle.skia.org/c/@Path_getLastPt](https://fiddle.skia.org/c/@Path_getLastPt)
*/
var lastPt: Point
get() = try {
Stats.onNativeCall()
Point.fromInteropPointer { _nGetLastPt(_ptr, it) }
} finally {
reachabilityBarrier(this)
}
set(value) {
setLastPt(value.x, value.y)
}
/**
* Sets last point to (x, y). If Point array is empty, append [PathVerb.MOVE] to
* verb array and append (x, y) to Point array.
*
* @param x set x-axis value of last point
* @param y set y-axis value of last point
* @return this
*
* @see [https://fiddle.skia.org/c/@Path_setLastPt](https://fiddle.skia.org/c/@Path_setLastPt)
*/
fun setLastPt(x: Float, y: Float): Path {
Stats.onNativeCall()
_nSetLastPt(_ptr, x, y)
return this
}
/**
*
* Returns a mask, where each set bit corresponds to a SegmentMask constant
* if Path contains one or more verbs of that type.
*
*
* Returns zero if Path contains no lines, or curves: quads, conics, or cubics.
*
*
* getSegmentMasks() returns a cached result; it is very fast.
*
* @return SegmentMask bits or zero
*
* @see PathSegmentMask.LINE
*
* @see PathSegmentMask.QUAD
*
* @see PathSegmentMask.CONIC
*
* @see PathSegmentMask.CUBIC
*/
val segmentMasks: Int
get() = try {
Stats.onNativeCall()
_nGetSegmentMasks(_ptr)
} finally {
reachabilityBarrier(this)
}
override fun iterator(): PathSegmentIterator {
return iterator(false)
}
fun iterator(forceClose: Boolean): PathSegmentIterator {
return PathSegmentIterator.make(this, forceClose)
}
/**
* Returns true if the point (x, y) is contained by Path, taking into
* account [PathFillMode].
*
* @param x x-axis value of containment test
* @param y y-axis value of containment test
* @return true if Point is in Path
*
* @see [https://fiddle.skia.org/c/@Path_contains](https://fiddle.skia.org/c/@Path_contains)
*/
fun contains(x: Float, y: Float): Boolean {
return try {
Stats.onNativeCall()
_nContains(_ptr, x, y)
} finally {
reachabilityBarrier(this)
}
}
/**
* Returns true if the point is contained by Path, taking into
* account [PathFillMode].
*
* @param p point of containment test
* @return true if Point is in Path
*
* @see [https://fiddle.skia.org/c/@Path_contains](https://fiddle.skia.org/c/@Path_contains)
*/
operator fun contains(p: Point): Boolean {
return contains(p.x, p.y)
}
/**
* Writes text representation of Path to standard output. The representation may be
* directly compiled as C++ code. Floating point values are written
* with limited precision; it may not be possible to reconstruct original Path
* from output.
*
* @return this
*
* @see [https://fiddle.skia.org/c/@Path_dump_2](https://fiddle.skia.org/c/@Path_dump_2)
*/
fun dump(): Path {
Stats.onNativeCall()
_nDump(_ptr)
return this
}
/**
*
* Writes text representation of Path to standard output. The representation may be
* directly compiled as C++ code. Floating point values are written
* in hexadecimal to preserve their exact bit pattern. The output reconstructs the
* original Path.
*
*
* Use instead of [] when submitting
*
* @return this
*
* @see [https://fiddle.skia.org/c/@Path_dumpHex](https://fiddle.skia.org/c/@Path_dumpHex)
*/
fun dumpHex(): Path {
Stats.onNativeCall()
_nDumpHex(_ptr)
return this
}
/**
*
* Writes Path to byte buffer.
*
*
* Writes [PathFillMode], verb array, Point array, conic weight, and
* additionally writes computed information like path convexity and bounds.
*
*
* Use only be used in concert with [];
* the format used for Path in memory is not guaranteed.
*
* @return serialized Path; length always a multiple of 4
*
* @see [https://fiddle.skia.org/c/@Path_writeToMemory](https://fiddle.skia.org/c/@Path_writeToMemory)
*/
fun serializeToBytes(): ByteArray {
return try {
Stats.onNativeCall()
val size = interopScope { _nSerializeToBytes(_ptr, toInterop(null as ByteArray?)) }
if (size == -1) {
throw Error("Path is too big")
}
withResult(ByteArray(size)) {
_nSerializeToBytes(_ptr, it)
}
} finally {
reachabilityBarrier(this)
}
}
/**
*
* Returns a non-zero, globally unique value. A different value is returned
* if verb array, Point array, or conic weight changes.
*
*
* Setting [PathFillMode] does not change generation identifier.
*
*
* Each time the path is modified, a different generation identifier will be returned.
* [PathFillMode] does affect generation identifier on Android framework.
*
* @return non-zero, globally unique value
*
* @see [https://fiddle.skia.org/c/@Path_getGenerationID](https://fiddle.skia.org/c/@Path_getGenerationID)
* @see [https://fiddle.skia.org/c/@Path_getGenerationID](https://fiddle.skia.org/c/@Path_getGenerationID)
*
* @see [https://bugs.chromium.org/p/skia/issues/detail?id=1762](https://bugs.chromium.org/p/skia/issues/detail?id=1762)
*/
......@@ -2240,7 +1183,6 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol
}
}
@ExternalSymbolName("org_jetbrains_skia_Path__1nGetFinalizer")
internal external fun Path_nGetFinalizer(): NativePointer
......@@ -2250,9 +1192,6 @@ private external fun Path_nMake(): NativePointer
@ExternalSymbolName("org_jetbrains_skia_Path__1nEquals")
private external fun Path_nEquals(aPtr: NativePointer, bPtr: NativePointer): Boolean
@ExternalSymbolName("org_jetbrains_skia_Path__1nReset")
private external fun Path_nReset(ptr: NativePointer)
@ExternalSymbolName("org_jetbrains_skia_Path__1nIsVolatile")
private external fun Path_nIsVolatile(ptr: NativePointer): Boolean
......@@ -2265,6 +1204,50 @@ private external fun Path_nSwap(ptr: NativePointer, otherPtr: NativePointer)
@ExternalSymbolName("org_jetbrains_skia_Path__1nGetGenerationId")
private external fun Path_nGetGenerationId(ptr: NativePointer): Int
@ExternalSymbolName("org_jetbrains_skia_Path__1nMakeFromRaw")
private external fun _nMakeFromRaw(
pts: InteropPointer, ptsCount: Int,
verbs: InteropPointer, verbsCount: Int,
conicWeights: InteropPointer, conicWeightsCount: Int,
fillType: Int, isVolatile: Boolean
): NativePointer
@ExternalSymbolName("org_jetbrains_skia_Path__1nMakeFromRect")
private external fun _nMakeFromRect(
left: Float, top: Float, right: Float, bottom: Float,
fillType: Int, direction: Int, startIndex: Int
): NativePointer
@ExternalSymbolName("org_jetbrains_skia_Path__1nMakeFromOval")
private external fun _nMakeFromOval(
left: Float, top: Float, right: Float, bottom: Float,
direction: Int, startIndex: Int
): NativePointer
@ExternalSymbolName("org_jetbrains_skia_Path__1nMakeFromCircle")
private external fun _nMakeFromCircle(
centerX: Float, centerY: Float, radius: Float, direction: Int
): NativePointer
@ExternalSymbolName("org_jetbrains_skia_Path__1nMakeFromRRect")
private external fun _nMakeFromRRect(
radii: InteropPointer,
left: Float, top: Float, right: Float, bottom: Float,
direction: Int, startIndex: Int
): NativePointer
@ExternalSymbolName("org_jetbrains_skia_Path__1nMakeFromRRectXY")
private external fun _nMakeFromRRectXY(
left: Float, top: Float, right: Float, bottom: Float,
rx: Float, ry: Float, direction: Int
): NativePointer
@ExternalSymbolName("org_jetbrains_skia_Path__1nMakeFromPolygon")
private external fun _nMakeFromPolygon(
pts: InteropPointer, ptsCount: Int,
isClosed: Boolean, fillType: Int, isVolatile: Boolean
): NativePointer
@ExternalSymbolName("org_jetbrains_skia_Path__1nMakeFromSVGString")
private external fun _nMakeFromSVGString(svg: InteropPointer): NativePointer
......@@ -2286,12 +1269,12 @@ private external fun _nIsConvex(ptr: NativePointer): Boolean
@ExternalSymbolName("org_jetbrains_skia_Path__1nIsOval")
private external fun _nIsOval(ptr: NativePointer, rect: InteropPointer): Boolean
@ExternalSymbolName("org_jetbrains_skia_Path__1nIsRect")
private external fun _nIsRect(ptr: NativePointer, rect: InteropPointer): Boolean
@ExternalSymbolName("org_jetbrains_skia_Path__1nIsRRect")
private external fun _nIsRRect(ptr: NativePointer, rrect: InteropPointer): Boolean
@ExternalSymbolName("org_jetbrains_skia_Path__1nRewind")
private external fun _nRewind(ptr: NativePointer)
@ExternalSymbolName("org_jetbrains_skia_Path__1nIsEmpty")
private external fun _nIsEmpty(ptr: NativePointer): Boolean
......@@ -2315,7 +1298,6 @@ private external fun _nIsQuadDegenerate(
exact: Boolean
): Boolean
@ExternalSymbolName("org_jetbrains_skia_Path__1nIsCubicDegenerate")
private external fun _nIsCubicDegenerate(
x0: Float,
......@@ -2329,7 +1311,6 @@ private external fun _nIsCubicDegenerate(
exact: Boolean
): Boolean
@ExternalSymbolName("org_jetbrains_skia_Path__1nMaybeGetAsLine")
private external fun _nMaybeGetAsLine(ptr: NativePointer, rectBuffer: InteropPointer): Boolean
......@@ -2349,7 +1330,7 @@ private external fun _nCountVerbs(ptr: NativePointer): Int
private external fun _nGetVerbs(ptr: NativePointer, verbs: InteropPointer, max: Int): Int
@ExternalSymbolName("org_jetbrains_skia_Path__1nApproximateBytesUsed")
private external fun _nApproximateBytesUsed(ptr: NativePointer): NativePointer
private external fun _nApproximateBytesUsed(ptr: NativePointer): Int
@ExternalSymbolName("org_jetbrains_skia_Path__1nGetBounds")
private external fun _nGetBounds(ptr: NativePointer, rect: InteropPointer)
......@@ -2363,84 +1344,6 @@ private external fun _nComputeTightBounds(ptr: NativePointer, rect: InteropPoint
@ExternalSymbolName("org_jetbrains_skia_Path__1nConservativelyContainsRect")
private external fun _nConservativelyContainsRect(ptr: NativePointer, l: Float, t: Float, r: Float, b: Float): Boolean
@ExternalSymbolName("org_jetbrains_skia_Path__1nIncReserve")
private external fun _nIncReserve(ptr: NativePointer, extraPtCount: Int)
@ExternalSymbolName("org_jetbrains_skia_Path__1nMoveTo")
private external fun _nMoveTo(ptr: NativePointer, x: Float, y: Float)
@ExternalSymbolName("org_jetbrains_skia_Path__1nRMoveTo")
private external fun _nRMoveTo(ptr: NativePointer, dx: Float, dy: Float)
@ExternalSymbolName("org_jetbrains_skia_Path__1nLineTo")
private external fun _nLineTo(ptr: NativePointer, x: Float, y: Float)
@ExternalSymbolName("org_jetbrains_skia_Path__1nRLineTo")
private external fun _nRLineTo(ptr: NativePointer, dx: Float, dy: Float)
@ExternalSymbolName("org_jetbrains_skia_Path__1nQuadTo")
private external fun _nQuadTo(ptr: NativePointer, x1: Float, y1: Float, x2: Float, y2: Float)
@ExternalSymbolName("org_jetbrains_skia_Path__1nRQuadTo")
private external fun _nRQuadTo(ptr: NativePointer, dx1: Float, dy1: Float, dx2: Float, dy2: Float)
@ExternalSymbolName("org_jetbrains_skia_Path__1nConicTo")
private external fun _nConicTo(ptr: NativePointer, x1: Float, y1: Float, x2: Float, y2: Float, w: Float)
@ExternalSymbolName("org_jetbrains_skia_Path__1nRConicTo")
private external fun _nRConicTo(ptr: NativePointer, dx1: Float, dy1: Float, dx2: Float, dy2: Float, w: Float)
@ExternalSymbolName("org_jetbrains_skia_Path__1nCubicTo")
private external fun _nCubicTo(ptr: NativePointer, x1: Float, y1: Float, x2: Float, y2: Float, x3: Float, y3: Float)
@ExternalSymbolName("org_jetbrains_skia_Path__1nRCubicTo")
private external fun _nRCubicTo(ptr: NativePointer, dx1: Float, dy1: Float, dx2: Float, dy2: Float, dx3: Float, dy3: Float)
@ExternalSymbolName("org_jetbrains_skia_Path__1nArcTo")
private external fun _nArcTo(
ptr: NativePointer,
left: Float,
top: Float,
right: Float,
bottom: Float,
startAngle: Float,
sweepAngle: Float,
forceMoveTo: Boolean
)
@ExternalSymbolName("org_jetbrains_skia_Path__1nTangentArcTo")
private external fun _nTangentArcTo(ptr: NativePointer, x1: Float, y1: Float, x2: Float, y2: Float, radius: Float)
@ExternalSymbolName("org_jetbrains_skia_Path__1nEllipticalArcTo")
private external fun _nEllipticalArcTo(
ptr: NativePointer,
rx: Float,
ry: Float,
xAxisRotate: Float,
size: Int,
direction: Int,
x: Float,
y: Float
)
@ExternalSymbolName("org_jetbrains_skia_Path__1nREllipticalArcTo")
private external fun _nREllipticalArcTo(
ptr: NativePointer,
rx: Float,
ry: Float,
xAxisRotate: Float,
size: Int,
direction: Int,
dx: Float,
dy: Float
)
@ExternalSymbolName("org_jetbrains_skia_Path__1nClosePath")
private external fun _nClosePath(ptr: NativePointer)
@ExternalSymbolName("org_jetbrains_skia_Path__1nConvertConicToQuads")
private external fun _nConvertConicToQuads(
x0: Float,
......@@ -2454,63 +1357,9 @@ private external fun _nConvertConicToQuads(
result: InteropPointer
): Int
@ExternalSymbolName("org_jetbrains_skia_Path__1nIsRect")
private external fun _nIsRect(ptr: NativePointer, rect: InteropPointer): Boolean
@ExternalSymbolName("org_jetbrains_skia_Path__1nAddRect")
private external fun _nAddRect(ptr: NativePointer, l: Float, t: Float, r: Float, b: Float, dir: Int, start: Int)
@ExternalSymbolName("org_jetbrains_skia_Path__1nAddOval")
private external fun _nAddOval(ptr: NativePointer, l: Float, t: Float, r: Float, b: Float, dir: Int, start: Int)
@ExternalSymbolName("org_jetbrains_skia_Path__1nAddCircle")
private external fun _nAddCircle(ptr: NativePointer, x: Float, y: Float, r: Float, dir: Int)
@ExternalSymbolName("org_jetbrains_skia_Path__1nAddArc")
private external fun _nAddArc(ptr: NativePointer, l: Float, t: Float, r: Float, b: Float, startAngle: Float, sweepAngle: Float)
@ExternalSymbolName("org_jetbrains_skia_Path__1nAddRRect")
private external fun _nAddRRect(
ptr: NativePointer,
l: Float,
t: Float,
r: Float,
b: Float,
radii: InteropPointer,
size: Int,
dir: Int,
start: Int
)
@ExternalSymbolName("org_jetbrains_skia_Path__1nAddPoly")
private external fun _nAddPoly(ptr: NativePointer, coords: InteropPointer, count: Int, close: Boolean)
@ExternalSymbolName("org_jetbrains_skia_Path__1nAddPath")
private external fun _nAddPath(ptr: NativePointer, srcPtr: NativePointer, extend: Boolean)
@ExternalSymbolName("org_jetbrains_skia_Path__1nAddPathOffset")
private external fun _nAddPathOffset(ptr: NativePointer, srcPtr: NativePointer, dx: Float, dy: Float, extend: Boolean)
@ExternalSymbolName("org_jetbrains_skia_Path__1nAddPathTransform")
private external fun _nAddPathTransform(ptr: NativePointer, srcPtr: NativePointer, matrix: InteropPointer, extend: Boolean)
@ExternalSymbolName("org_jetbrains_skia_Path__1nReverseAddPath")
private external fun _nReverseAddPath(ptr: NativePointer, srcPtr: NativePointer)
@ExternalSymbolName("org_jetbrains_skia_Path__1nOffset")
private external fun _nOffset(ptr: NativePointer, dx: Float, dy: Float, dst: NativePointer)
@ExternalSymbolName("org_jetbrains_skia_Path__1nTransform")
private external fun _nTransform(ptr: NativePointer, matrix: InteropPointer, dst: NativePointer, applyPerspectiveClip: Boolean)
@ExternalSymbolName("org_jetbrains_skia_Path__1nGetLastPt")
private external fun _nGetLastPt(ptr: NativePointer, result: InteropPointer): Boolean
@ExternalSymbolName("org_jetbrains_skia_Path__1nSetLastPt")
private external fun _nSetLastPt(ptr: NativePointer, x: Float, y: Float)
@ExternalSymbolName("org_jetbrains_skia_Path__1nGetSegmentMasks")
private external fun _nGetSegmentMasks(ptr: NativePointer): Int
......@@ -2533,4 +1382,4 @@ private external fun _nMakeCombining(onePtr: NativePointer, twoPtr: NativePointe
private external fun _nMakeFromBytes(data: InteropPointer, size: Int): NativePointer
@ExternalSymbolName("org_jetbrains_skia_Path__1nIsValid")
private external fun _nIsValid(ptr: NativePointer): Boolean
\ No newline at end of file
private external fun _nIsValid(ptr: NativePointer): Boolean
package org.jetbrains.skia
/**
* PathAddMode chooses how addPath() appends paths.
* Adding one Path to another can extend the last contour or start a new contour.
*/
enum class PathAddMode {
/**
* Contours are appended to the destination path as new contours.
*/
APPEND,
/**
* Extends the last contour of the destination path with the first contour
* of the source path, connecting them with a line.
*/
EXTEND
}
package org.jetbrains.skia
/**
* Enum for choosing smaller or larger arc when adding arcs to paths.
*/
enum class PathArcSize {
/** Smaller of arc pair */
SMALL,
/** Larger of arc pair */
LARGE
}
package org.jetbrains.skia
import org.jetbrains.skia.impl.*
import org.jetbrains.skia.impl.Library.Companion.staticLoad
/**
* PathBuilder is used to create immutable Path objects.
*
* PathBuilder follows the builder pattern - all mutation methods return the builder instance
* for method chaining. Once path construction is complete, call [detach] to get an immutable
* Path object, or [snapshot] to get a copy while keeping the builder usable.
*
* This class contains all path construction methods that were previously mutation methods
* on the Path class. Path objects created from PathBuilder are immutable.
*/
class PathBuilder internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHolder.PTR) {
companion object {
init {
staticLoad()
}
}
private object _FinalizerHolder {
val PTR = PathBuilder_nGetFinalizer()
}
/**
* Constructs an empty PathBuilder with WINDING fill type.
*/
constructor() : this(PathBuilder_nMake())
/**
* Constructs a PathBuilder with the specified fill type.
*
* @param fillType the fill type for paths created from this builder
*/
constructor(fillType: PathFillMode) : this(PathBuilder_nMakeWithFillType(fillType.ordinal))
/**
* Constructs a PathBuilder by copying an existing Path.
*
* @param path the path to copy into this builder
*/
constructor(path: Path) : this(
PathBuilder_nMakeFromPath(getPtr(path)).also {
reachabilityBarrier(path)
}
)
/**
* Returns an immutable Path representing the current state of this builder.
* The builder remains valid and can continue to be used.
*
* @return a new immutable Path
*/
fun snapshot(): Path {
return try {
Stats.onNativeCall()
Path(PathBuilder_nSnapshot(_ptr))
} finally {
reachabilityBarrier(this)
}
}
/**
* Returns an immutable Path representing the current state of this builder.
* The builder is reset to empty after this call.
*
* @return a new immutable Path
*/
fun detach(): Path {
return try {
Stats.onNativeCall()
Path(PathBuilder_nDetach(_ptr))
} finally {
reachabilityBarrier(this)
}
}
/**
* Sets the fill type for paths created from this builder.
*
* @param fillType the fill type to set
* @return this builder for chaining
*/
fun setFillType(fillType: PathFillMode): PathBuilder {
return try {
Stats.onNativeCall()
PathBuilder_nSetFillType(_ptr, fillType.ordinal)
this
} finally {
reachabilityBarrier(this)
}
}
/**
* Resets the builder to empty, removing all verbs, points, and weights.
* Fill type is reset to WINDING.
*
* @return this builder for chaining
*/
fun reset(): PathBuilder {
return try {
Stats.onNativeCall()
PathBuilder_nReset(_ptr)
this
} finally {
reachabilityBarrier(this)
}
}
/**
* Hints to reserve additional space for approximately [extraPtCount] points and verbs.
* May improve performance by reducing allocations.
*
* @param extraPtCount number of additional points to reserve
* @return this builder for chaining
*/
fun incReserve(extraPtCount: Int): PathBuilder {
return try {
Stats.onNativeCall()
PathBuilder_nIncReserve(_ptr, extraPtCount)
this
} finally {
reachabilityBarrier(this)
}
}
/**
* Adds beginning of contour at point (x, y).
*
* @param x x-axis value of contour start
* @param y y-axis value of contour start
* @return this builder for chaining
*/
fun moveTo(x: Float, y: Float): PathBuilder {
return try {
Stats.onNativeCall()
PathBuilder_nMoveTo(_ptr, x, y)
this
} finally {
reachabilityBarrier(this)
}
}
/**
* Adds beginning of contour at point p.
*
* @param p contour start
* @return this builder for chaining
*/
fun moveTo(p: Point): PathBuilder {
return moveTo(p.x, p.y)
}
/**
* Adds beginning of contour relative to last point.
* If PathBuilder is empty, starts contour at (dx, dy).
* Otherwise, start contour at last point offset by (dx, dy).
*
* @param dx offset from last point to contour start on x-axis
* @param dy offset from last point to contour start on y-axis
* @return this builder for chaining
*/
fun rMoveTo(dx: Float, dy: Float): PathBuilder {
return try {
Stats.onNativeCall()
PathBuilder_nRMoveTo(_ptr, dx, dy)
this
} finally {
reachabilityBarrier(this)
}
}
/**
* Adds line from last point to (x, y). If PathBuilder is empty, or last verb is
* CLOSE, last point is set to (0, 0) before adding line.
*
* @param x end of added line on x-axis
* @param y end of added line on y-axis
* @return this builder for chaining
*/
fun lineTo(x: Float, y: Float): PathBuilder {
return try {
Stats.onNativeCall()
PathBuilder_nLineTo(_ptr, x, y)
this
} finally {
reachabilityBarrier(this)
}
}
/**
* Adds line from last point to point p.
*
* @param p end point of added line
* @return this builder for chaining
*/
fun lineTo(p: Point): PathBuilder {
return lineTo(p.x, p.y)
}
/**
* Adds line from last point to vector (dx, dy). If PathBuilder is empty, or last verb is
* CLOSE, last point is set to (0, 0) before adding line.
* Line end is last point plus vector (dx, dy).
*
* @param dx offset from last point to line end on x-axis
* @param dy offset from last point to line end on y-axis
* @return this builder for chaining
*/
fun rLineTo(dx: Float, dy: Float): PathBuilder {
return try {
Stats.onNativeCall()
PathBuilder_nRLineTo(_ptr, dx, dy)
this
} finally {
reachabilityBarrier(this)
}
}
/**
* Adds quad from last point towards (x1, y1), to (x2, y2).
*
* @param x1 control point of quad on x-axis
* @param y1 control point of quad on y-axis
* @param x2 end point of quad on x-axis
* @param y2 end point of quad on y-axis
* @return this builder for chaining
*/
fun quadTo(x1: Float, y1: Float, x2: Float, y2: Float): PathBuilder {
return try {
Stats.onNativeCall()
PathBuilder_nQuadTo(_ptr, x1, y1, x2, y2)
this
} finally {
reachabilityBarrier(this)
}
}
/**
* Adds quad from last point towards point p1, to point p2.
*
* @param p1 control point of added quad
* @param p2 end point of added quad
* @return this builder for chaining
*/
fun quadTo(p1: Point, p2: Point): PathBuilder {
return quadTo(p1.x, p1.y, p2.x, p2.y)
}
/**
* Adds quad from last point towards vector (dx1, dy1), to vector (dx2, dy2).
* Quad control is last point plus vector (dx1, dy1).
* Quad end is last point plus vector (dx2, dy2).
*
* @param dx1 offset from last point to quad control on x-axis
* @param dy1 offset from last point to quad control on y-axis
* @param dx2 offset from last point to quad end on x-axis
* @param dy2 offset from last point to quad end on y-axis
* @return this builder for chaining
*/
fun rQuadTo(dx1: Float, dy1: Float, dx2: Float, dy2: Float): PathBuilder {
return try {
Stats.onNativeCall()
PathBuilder_nRQuadTo(_ptr, dx1, dy1, dx2, dy2)
this
} finally {
reachabilityBarrier(this)
}
}
/**
* Adds conic from last point towards (x1, y1), to (x2, y2), weighted by w.
*
* @param x1 control point of conic on x-axis
* @param y1 control point of conic on y-axis
* @param x2 end point of conic on x-axis
* @param y2 end point of conic on y-axis
* @param w weight of added conic
* @return this builder for chaining
*/
fun conicTo(x1: Float, y1: Float, x2: Float, y2: Float, w: Float): PathBuilder {
return try {
Stats.onNativeCall()
PathBuilder_nConicTo(_ptr, x1, y1, x2, y2, w)
this
} finally {
reachabilityBarrier(this)
}
}
/**
* Adds conic from last point towards point p1, to point p2, weighted by w.
*
* @param p1 control point of added conic
* @param p2 end point of added conic
* @param w weight of added conic
* @return this builder for chaining
*/
fun conicTo(p1: Point, p2: Point, w: Float): PathBuilder {
return conicTo(p1.x, p1.y, p2.x, p2.y, w)
}
/**
* Adds conic from last point towards vector (dx1, dy1), to vector (dx2, dy2), weighted by w.
* Control is last point plus vector (dx1, dy1).
* End is last point plus vector (dx2, dy2).
*
* @param dx1 offset from last point to conic control on x-axis
* @param dy1 offset from last point to conic control on y-axis
* @param dx2 offset from last point to conic end on x-axis
* @param dy2 offset from last point to conic end on y-axis
* @param w weight of added conic
* @return this builder for chaining
*/
fun rConicTo(dx1: Float, dy1: Float, dx2: Float, dy2: Float, w: Float): PathBuilder {
return try {
Stats.onNativeCall()
PathBuilder_nRConicTo(_ptr, dx1, dy1, dx2, dy2, w)
this
} finally {
reachabilityBarrier(this)
}
}
/**
* Adds cubic from last point towards (x1, y1), then towards (x2, y2), ending at (x3, y3).
*
* @param x1 first control point of cubic on x-axis
* @param y1 first control point of cubic on y-axis
* @param x2 second control point of cubic on x-axis
* @param y2 second control point of cubic on y-axis
* @param x3 end point of cubic on x-axis
* @param y3 end point of cubic on y-axis
* @return this builder for chaining
*/
fun cubicTo(x1: Float, y1: Float, x2: Float, y2: Float, x3: Float, y3: Float): PathBuilder {
return try {
Stats.onNativeCall()
PathBuilder_nCubicTo(_ptr, x1, y1, x2, y2, x3, y3)
this
} finally {
reachabilityBarrier(this)
}
}
/**
* Adds cubic from last point towards point p1, then towards point p2, ending at point p3.
*
* @param p1 first control point of cubic
* @param p2 second control point of cubic
* @param p3 end point of cubic
* @return this builder for chaining
*/
fun cubicTo(p1: Point, p2: Point, p3: Point): PathBuilder {
return cubicTo(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y)
}
/**
* Adds cubic from last point towards vector (dx1, dy1), then towards (dx2, dy2), to (dx3, dy3).
*
* @param dx1 offset from last point to first cubic control on x-axis
* @param dy1 offset from last point to first cubic control on y-axis
* @param dx2 offset from last point to second cubic control on x-axis
* @param dy2 offset from last point to second cubic control on y-axis
* @param dx3 offset from last point to cubic end on x-axis
* @param dy3 offset from last point to cubic end on y-axis
* @return this builder for chaining
*/
fun rCubicTo(dx1: Float, dy1: Float, dx2: Float, dy2: Float, dx3: Float, dy3: Float): PathBuilder {
return try {
Stats.onNativeCall()
PathBuilder_nRCubicTo(_ptr, dx1, dy1, dx2, dy2, dx3, dy3)
this
} finally {
reachabilityBarrier(this)
}
}
/**
* Appends arc to path. Arc is part of ellipse bounded by oval, from startAngle through sweepAngle.
*
* @param oval bounds of ellipse containing arc
* @param startAngle starting angle of arc in degrees
* @param sweepAngle sweep, in degrees. Positive is clockwise
* @param forceMoveTo true to start a new contour with arc
* @return this builder for chaining
*/
fun arcTo(oval: Rect, startAngle: Float, sweepAngle: Float, forceMoveTo: Boolean): PathBuilder {
return arcTo(oval.left, oval.top, oval.right, oval.bottom, startAngle, sweepAngle, forceMoveTo)
}
/**
* Appends arc to path. Arc is part of ellipse bounded by rectangle.
*
* @param left left edge of oval bounding ellipse
* @param top top edge of oval bounding ellipse
* @param right right edge of oval bounding ellipse
* @param bottom bottom edge of oval bounding ellipse
* @param startAngle starting angle of arc in degrees
* @param sweepAngle sweep, in degrees. Positive is clockwise
* @param forceMoveTo true to start a new contour with arc
* @return this builder for chaining
*/
fun arcTo(left: Float, top: Float, right: Float, bottom: Float, startAngle: Float, sweepAngle: Float, forceMoveTo: Boolean): PathBuilder {
return try {
Stats.onNativeCall()
PathBuilder_nArcTo(_ptr, left, top, right, bottom, startAngle, sweepAngle, forceMoveTo)
this
} finally {
reachabilityBarrier(this)
}
}
/**
* Appends arc to path, after appending line if needed. Arc is contained by tangent from
* last point to (x1, y1), and tangent from (x1, y1) to (x2, y2).
*
* @param x1 x-axis value common to pair of tangents
* @param y1 y-axis value common to pair of tangents
* @param x2 x-axis value end of second tangent
* @param y2 y-axis value end of second tangent
* @param radius distance from arc to circle center
* @return this builder for chaining
*/
fun tangentArcTo(x1: Float, y1: Float, x2: Float, y2: Float, radius: Float): PathBuilder {
return try {
Stats.onNativeCall()
PathBuilder_nTangentArcTo(_ptr, x1, y1, x2, y2, radius)
this
} finally {
reachabilityBarrier(this)
}
}
/**
* Appends arc to path, after appending line if needed.
*
* @param p1 point common to pair of tangents
* @param p2 end of second tangent
* @param radius distance from arc to circle center
* @return this builder for chaining
*/
fun tangentArcTo(p1: Point, p2: Point, radius: Float): PathBuilder {
return tangentArcTo(p1.x, p1.y, p2.x, p2.y, radius)
}
/**
* Appends arc to path. Arc is implemented by one or more conics weighted to describe
* part of oval with radii (rx, ry) rotated by xAxisRotate degrees.
*
* @param rx radius on x-axis before x-axis rotation
* @param ry radius on y-axis before x-axis rotation
* @param xAxisRotate x-axis rotation in degrees; positive values are clockwise
* @param arc chooses smaller or larger arc
* @param direction chooses clockwise or counterclockwise arc
* @param x end of arc on x-axis
* @param y end of arc on y-axis
* @return this builder for chaining
*/
fun ellipticalArcTo(
rx: Float,
ry: Float,
xAxisRotate: Float,
arc: PathEllipseArc,
direction: PathDirection,
x: Float,
y: Float
): PathBuilder {
return try {
Stats.onNativeCall()
PathBuilder_nEllipticalArcTo(_ptr, rx, ry, xAxisRotate, arc.ordinal, direction.ordinal, x, y)
this
} finally {
reachabilityBarrier(this)
}
}
/**
* Appends arc to path using point parameters.
*
* @param r radii on axes before x-axis rotation
* @param xAxisRotate x-axis rotation in degrees
* @param arc chooses smaller or larger arc
* @param direction chooses clockwise or counterclockwise arc
* @param xy end of arc
* @return this builder for chaining
*/
fun ellipticalArcTo(r: Point, xAxisRotate: Float, arc: PathEllipseArc, direction: PathDirection, xy: Point): PathBuilder {
return ellipticalArcTo(r.x, r.y, xAxisRotate, arc, direction, xy.x, xy.y)
}
/**
* Appends arc to path, relative to last point.
*
* @param rx radius before x-axis rotation
* @param ry radius before x-axis rotation
* @param xAxisRotate x-axis rotation in degrees
* @param arc chooses smaller or larger arc
* @param direction chooses clockwise or counterclockwise arc
* @param dx x-axis offset end of arc from last point
* @param dy y-axis offset end of arc from last point
* @return this builder for chaining
*/
fun rEllipticalArcTo(
rx: Float,
ry: Float,
xAxisRotate: Float,
arc: PathEllipseArc,
direction: PathDirection,
dx: Float,
dy: Float
): PathBuilder {
return try {
Stats.onNativeCall()
PathBuilder_nREllipticalArcTo(_ptr, rx, ry, xAxisRotate, arc.ordinal, direction.ordinal, dx, dy)
this
} finally {
reachabilityBarrier(this)
}
}
/**
* Appends CLOSE verb to path. A closed contour connects the first and last point with line.
*
* @return this builder for chaining
*/
fun closePath(): PathBuilder {
return try {
Stats.onNativeCall()
PathBuilder_nClosePath(_ptr)
this
} finally {
reachabilityBarrier(this)
}
}
/**
* Adds rectangle to path, appending MOVE, three LINE, and CLOSE verbs.
*
* @param rect rectangle to add as a closed contour
* @param dir direction to wind added contour
* @param start initial corner: 0=top-left, 1=top-right, 2=bottom-right, 3=bottom-left
* @return this builder for chaining
*/
fun addRect(rect: Rect, dir: PathDirection = PathDirection.CLOCKWISE, start: Int = 0): PathBuilder {
return addRect(rect.left, rect.top, rect.right, rect.bottom, dir, start)
}
/**
* Adds rectangle to path, appending MOVE, three LINE, and CLOSE verbs.
*
* @param left left edge of rectangle
* @param top top edge of rectangle
* @param right right edge of rectangle
* @param bottom bottom edge of rectangle
* @param dir direction to wind added contour
* @param start initial corner: 0=top-left, 1=top-right, 2=bottom-right, 3=bottom-left
* @return this builder for chaining
*/
fun addRect(left: Float, top: Float, right: Float, bottom: Float, dir: PathDirection = PathDirection.CLOCKWISE, start: Int = 0): PathBuilder {
return try {
Stats.onNativeCall()
PathBuilder_nAddRect(_ptr, left, top, right, bottom, dir.ordinal, start)
this
} finally {
reachabilityBarrier(this)
}
}
/**
* Adds oval to path, appending MOVE, four CONIC, and CLOSE verbs.
*
* @param oval bounds of ellipse
* @param dir direction to wind ellipse
* @param start index of initial point: 0=top, 1=right, 2=bottom, 3=left
* @return this builder for chaining
*/
fun addOval(oval: Rect, dir: PathDirection = PathDirection.CLOCKWISE, start: Int = 1): PathBuilder {
return addOval(oval.left, oval.top, oval.right, oval.bottom, dir, start)
}
/**
* Adds oval to path, appending MOVE, four CONIC, and CLOSE verbs.
*
* @param left left edge of oval
* @param top top edge of oval
* @param right right edge of oval
* @param bottom bottom edge of oval
* @param dir direction to wind ellipse
* @param start index of initial point: 0=top, 1=right, 2=bottom, 3=left
* @return this builder for chaining
*/
fun addOval(left: Float, top: Float, right: Float, bottom: Float, dir: PathDirection = PathDirection.CLOCKWISE, start: Int = 1): PathBuilder {
return try {
Stats.onNativeCall()
PathBuilder_nAddOval(_ptr, left, top, right, bottom, dir.ordinal, start)
this
} finally {
reachabilityBarrier(this)
}
}
/**
* Adds circle centered at (x, y) of size radius to path.
*
* @param x center of circle on x-axis
* @param y center of circle on y-axis
* @param radius distance from center to edge
* @param dir direction to wind circle
* @return this builder for chaining
*/
fun addCircle(x: Float, y: Float, radius: Float, dir: PathDirection = PathDirection.CLOCKWISE): PathBuilder {
return try {
Stats.onNativeCall()
PathBuilder_nAddCircle(_ptr, x, y, radius, dir.ordinal)
this
} finally {
reachabilityBarrier(this)
}
}
/**
* Appends arc to path, as the start of new contour.
*
* @param oval bounds of ellipse containing arc
* @param startAngle starting angle of arc in degrees
* @param sweepAngle sweep, in degrees. Positive is clockwise
* @return this builder for chaining
*/
fun addArc(oval: Rect, startAngle: Float, sweepAngle: Float): PathBuilder {
return addArc(oval.left, oval.top, oval.right, oval.bottom, startAngle, sweepAngle)
}
/**
* Appends arc to path, as the start of new contour.
*
* @param left left edge of oval bounding ellipse
* @param top top edge of oval bounding ellipse
* @param right right edge of oval bounding ellipse
* @param bottom bottom edge of oval bounding ellipse
* @param startAngle starting angle of arc in degrees
* @param sweepAngle sweep, in degrees. Positive is clockwise
* @return this builder for chaining
*/
fun addArc(left: Float, top: Float, right: Float, bottom: Float, startAngle: Float, sweepAngle: Float): PathBuilder {
return try {
Stats.onNativeCall()
PathBuilder_nAddArc(_ptr, left, top, right, bottom, startAngle, sweepAngle)
this
} finally {
reachabilityBarrier(this)
}
}
/**
* Adds rounded rectangle to path, creating a new closed contour.
*
* @param rrect bounds and radii of rounded rectangle
* @param dir direction to wind rounded rectangle
* @param start index of initial point
* @return this builder for chaining
*/
fun addRRect(rrect: RRect, dir: PathDirection = PathDirection.CLOCKWISE, start: Int = 6): PathBuilder {
return addRRect(rrect.left, rrect.top, rrect.right, rrect.bottom, rrect.radii, dir, start)
}
/**
* Adds rounded rectangle to path, creating a new closed contour.
*
* @param left left edge of rounded rectangle
* @param top top edge of rounded rectangle
* @param right right edge of rounded rectangle
* @param bottom bottom edge of rounded rectangle
* @param radii array of 8 radius values, 2 for each corner
* @param dir direction to wind rounded rectangle
* @param start index of initial point
* @return this builder for chaining
*/
fun addRRect(left: Float, top: Float, right: Float, bottom: Float, radii: FloatArray, dir: PathDirection = PathDirection.CLOCKWISE, start: Int = 6): PathBuilder {
return try {
Stats.onNativeCall()
interopScope {
PathBuilder_nAddRRect(_ptr, left, top, right, bottom, toInterop(radii), radii.size, dir.ordinal, start)
}
this
} finally {
reachabilityBarrier(this)
}
}
/**
* Adds contour created from line array.
*
* @param pts array of points
* @param close true to add line connecting contour end and start
* @return this builder for chaining
*/
fun addPoly(pts: Array<Point>, close: Boolean): PathBuilder {
val flat = FloatArray(pts.size * 2)
for (i in pts.indices) {
flat[i * 2] = pts[i].x
flat[i * 2 + 1] = pts[i].y
}
return addPoly(flat, close)
}
/**
* Adds contour created from line array.
*
* @param coords flat array of point coordinates (x, y pairs)
* @param close true to add line connecting contour end and start
* @return this builder for chaining
*/
fun addPoly(coords: FloatArray, close: Boolean): PathBuilder {
return try {
Stats.onNativeCall()
interopScope {
PathBuilder_nAddPoly(_ptr, toInterop(coords), coords.size / 2, close)
}
this
} finally {
reachabilityBarrier(this)
}
}
/**
* Appends src path to this builder.
*
* @param src path to add
* @param mode how to append the path (APPEND or EXTEND)
* @return this builder for chaining
*/
fun addPath(src: Path, mode: PathAddMode = PathAddMode.APPEND): PathBuilder {
return try {
Stats.onNativeCall()
PathBuilder_nAddPath(_ptr, getPtr(src), mode.ordinal)
this
} finally {
reachabilityBarrier(src)
}
}
/**
* Appends src path offset by (dx, dy).
*
* @param src path to add
* @param dx offset on x-axis
* @param dy offset on y-axis
* @param mode how to append the path (APPEND or EXTEND)
* @return this builder for chaining
*/
fun addPath(src: Path, dx: Float, dy: Float, mode: PathAddMode = PathAddMode.APPEND): PathBuilder {
return try {
Stats.onNativeCall()
PathBuilder_nAddPathOffset(_ptr, getPtr(src), dx, dy, mode.ordinal)
this
} finally {
reachabilityBarrier(src)
}
}
/**
* Appends src path transformed by matrix.
*
* @param src path to add
* @param matrix transform to apply
* @param mode how to append the path (APPEND or EXTEND)
* @return this builder for chaining
*/
fun addPath(src: Path, matrix: Matrix33, mode: PathAddMode = PathAddMode.APPEND): PathBuilder {
return try {
Stats.onNativeCall()
interopScope {
PathBuilder_nAddPathTransform(_ptr, getPtr(src), toInterop(matrix.mat), mode.ordinal)
}
this
} finally {
reachabilityBarrier(src)
reachabilityBarrier(matrix)
}
}
/**
* Sets last point to (x, y).
*
* @param x x-coordinate
* @param y y-coordinate
* @return this builder for chaining
*/
fun setLastPt(x: Float, y: Float): PathBuilder {
return try {
Stats.onNativeCall()
PathBuilder_nSetLastPt(_ptr, x, y)
this
} finally {
reachabilityBarrier(this)
}
}
}
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nGetFinalizer")
private external fun PathBuilder_nGetFinalizer(): NativePointer
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nMake")
private external fun PathBuilder_nMake(): NativePointer
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nMakeWithFillType")
private external fun PathBuilder_nMakeWithFillType(fillType: Int): NativePointer
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nMakeFromPath")
private external fun PathBuilder_nMakeFromPath(pathPtr: NativePointer): NativePointer
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nSnapshot")
private external fun PathBuilder_nSnapshot(ptr: NativePointer): NativePointer
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nDetach")
private external fun PathBuilder_nDetach(ptr: NativePointer): NativePointer
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nSetFillType")
private external fun PathBuilder_nSetFillType(ptr: NativePointer, fillType: Int)
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nReset")
private external fun PathBuilder_nReset(ptr: NativePointer)
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nIncReserve")
private external fun PathBuilder_nIncReserve(ptr: NativePointer, extraPtCount: Int)
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nMoveTo")
private external fun PathBuilder_nMoveTo(ptr: NativePointer, x: Float, y: Float)
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nRMoveTo")
private external fun PathBuilder_nRMoveTo(ptr: NativePointer, dx: Float, dy: Float)
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nLineTo")
private external fun PathBuilder_nLineTo(ptr: NativePointer, x: Float, y: Float)
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nRLineTo")
private external fun PathBuilder_nRLineTo(ptr: NativePointer, dx: Float, dy: Float)
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nQuadTo")
private external fun PathBuilder_nQuadTo(ptr: NativePointer, x1: Float, y1: Float, x2: Float, y2: Float)
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nRQuadTo")
private external fun PathBuilder_nRQuadTo(ptr: NativePointer, dx1: Float, dy1: Float, dx2: Float, dy2: Float)
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nConicTo")
private external fun PathBuilder_nConicTo(ptr: NativePointer, x1: Float, y1: Float, x2: Float, y2: Float, w: Float)
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nRConicTo")
private external fun PathBuilder_nRConicTo(ptr: NativePointer, dx1: Float, dy1: Float, dx2: Float, dy2: Float, w: Float)
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nCubicTo")
private external fun PathBuilder_nCubicTo(ptr: NativePointer, x1: Float, y1: Float, x2: Float, y2: Float, x3: Float, y3: Float)
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nRCubicTo")
private external fun PathBuilder_nRCubicTo(ptr: NativePointer, dx1: Float, dy1: Float, dx2: Float, dy2: Float, dx3: Float, dy3: Float)
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nArcTo")
private external fun PathBuilder_nArcTo(ptr: NativePointer, left: Float, top: Float, right: Float, bottom: Float, startAngle: Float, sweepAngle: Float, forceMoveTo: Boolean)
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nTangentArcTo")
private external fun PathBuilder_nTangentArcTo(ptr: NativePointer, x1: Float, y1: Float, x2: Float, y2: Float, radius: Float)
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nEllipticalArcTo")
private external fun PathBuilder_nEllipticalArcTo(ptr: NativePointer, rx: Float, ry: Float, xAxisRotate: Float, arc: Int, direction: Int, x: Float, y: Float)
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nREllipticalArcTo")
private external fun PathBuilder_nREllipticalArcTo(ptr: NativePointer, rx: Float, ry: Float, xAxisRotate: Float, arc: Int, direction: Int, dx: Float, dy: Float)
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nClosePath")
private external fun PathBuilder_nClosePath(ptr: NativePointer)
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nAddRect")
private external fun PathBuilder_nAddRect(ptr: NativePointer, left: Float, top: Float, right: Float, bottom: Float, dir: Int, start: Int)
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nAddOval")
private external fun PathBuilder_nAddOval(ptr: NativePointer, left: Float, top: Float, right: Float, bottom: Float, dir: Int, start: Int)
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nAddCircle")
private external fun PathBuilder_nAddCircle(ptr: NativePointer, x: Float, y: Float, radius: Float, dir: Int)
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nAddArc")
private external fun PathBuilder_nAddArc(ptr: NativePointer, left: Float, top: Float, right: Float, bottom: Float, startAngle: Float, sweepAngle: Float)
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nAddRRect")
private external fun PathBuilder_nAddRRect(ptr: NativePointer, left: Float, top: Float, right: Float, bottom: Float, radii: InteropPointer, size: Int, dir: Int, start: Int)
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nAddPoly")
private external fun PathBuilder_nAddPoly(ptr: NativePointer, coords: InteropPointer, count: Int, close: Boolean)
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nAddPath")
private external fun PathBuilder_nAddPath(ptr: NativePointer, srcPtr: NativePointer, mode: Int)
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nAddPathOffset")
private external fun PathBuilder_nAddPathOffset(ptr: NativePointer, srcPtr: NativePointer, dx: Float, dy: Float, mode: Int)
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nAddPathTransform")
private external fun PathBuilder_nAddPathTransform(ptr: NativePointer, srcPtr: NativePointer, matrix: InteropPointer, mode: Int)
@ExternalSymbolName("org_jetbrains_skia_PathBuilder__1nSetLastPt")
private external fun PathBuilder_nSetLastPt(ptr: NativePointer, x: Float, y: Float)
......@@ -182,7 +182,7 @@ class Picture internal constructor(ptr: NativePointer, managed: Boolean = true)
*
* @see [https://fiddle.skia.org/c/@Picture_approximateBytesUsed](https://fiddle.skia.org/c/@Picture_approximateBytesUsed)
*/
val approximateBytesUsed: NativePointer
val approximateBytesUsed: Int
get() = try {
Stats.onNativeCall()
_nGetApproximateBytesUsed(_ptr)
......@@ -273,7 +273,7 @@ private external fun _nMakePlaceholder(left: Float, top: Float, right: Float, bo
private external fun _nGetApproximateOpCount(ptr: NativePointer): Int
@ExternalSymbolName("org_jetbrains_skia_Picture__1nGetApproximateBytesUsed")
private external fun _nGetApproximateBytesUsed(ptr: NativePointer): NativePointer
private external fun _nGetApproximateBytesUsed(ptr: NativePointer): Int
@ExternalSymbolName("org_jetbrains_skia_Picture__1nMakeShader")
private external fun _nMakeShader(
......
......@@ -2,6 +2,7 @@ package org.jetbrains.skia
import org.jetbrains.skia.impl.InteropPointer
import org.jetbrains.skia.impl.InteropScope
import org.jetbrains.skia.impl.withNullableResult
import org.jetbrains.skia.impl.withResult
class Point(val x: Float, val y: Float) {
......@@ -68,5 +69,10 @@ class Point(val x: Float, val y: Float) {
val result = withResult(FloatArray(2), block)
return Point(result[0], result[1])
}
internal fun fromNullableInteropPointer(block: InteropScope.(InteropPointer) -> Boolean): Point? {
val result = withNullableResult(FloatArray(2), block) ?: return null
return Point(result[0], result[1])
}
}
}
\ No newline at end of file
......@@ -3,6 +3,10 @@ package org.jetbrains.skia
import org.jetbrains.skia.impl.*
import org.jetbrains.skia.impl.Library.Companion.staticLoad
/**
* Describes a set of pixels as either one integer rectangle or a run-length encoded
* set of rectangles.
*/
class Region : Managed(Region_nMake(), _FinalizerHolder.PTR) {
companion object {
init {
......@@ -10,24 +14,47 @@ class Region : Managed(Region_nMake(), _FinalizerHolder.PTR) {
}
}
/** Logical operations used to combine regions. */
enum class Op {
DIFFERENCE, INTERSECT, UNION, XOR, REVERSE_DIFFERENCE, REPLACE;
/** target minus operand */
DIFFERENCE,
/** target intersected with operand */
INTERSECT,
/** target unioned with operand */
UNION,
/** target exclusive-or with operand */
XOR,
/** operand minus target */
REVERSE_DIFFERENCE,
/** replace target with operand */
REPLACE;
companion object {
internal val _values = Op.entries.toTypedArray()
}
}
fun set(r: Region?): Boolean {
/**
* Sets this region to [src].
*
* @return true if the resulting region is not empty
*/
fun set(src: Region): Boolean {
return try {
Stats.onNativeCall()
Region_nSet(_ptr, getPtr(r))
Region_nSet(_ptr, getPtr(src))
} finally {
reachabilityBarrier(this)
reachabilityBarrier(r)
reachabilityBarrier(src)
}
}
/** Returns true if this region is empty. */
val isEmpty: Boolean
get() = try {
Stats.onNativeCall()
......@@ -35,6 +62,8 @@ class Region : Managed(Region_nMake(), _FinalizerHolder.PTR) {
} finally {
reachabilityBarrier(this)
}
/** Returns true if this region is one non-empty rectangle. */
val isRect: Boolean
get() = try {
Stats.onNativeCall()
......@@ -42,6 +71,8 @@ class Region : Managed(Region_nMake(), _FinalizerHolder.PTR) {
} finally {
reachabilityBarrier(this)
}
/** Returns true if this region is represented by more than one rectangle. */
val isComplex: Boolean
get() = try {
Stats.onNativeCall()
......@@ -49,6 +80,8 @@ class Region : Managed(Region_nMake(), _FinalizerHolder.PTR) {
} finally {
reachabilityBarrier(this)
}
/** Returns the union bounds of all rectangles in this region. */
val bounds: IRect
get() = try {
Stats.onNativeCall()
......@@ -60,6 +93,10 @@ class Region : Managed(Region_nMake(), _FinalizerHolder.PTR) {
reachabilityBarrier(this)
}
/**
* Returns a value that increases with the number of elements in the region.
* Returns 0 for empty, 1 for a single rectangle, and larger values for complex regions.
*/
fun computeRegionComplexity(): Int {
return try {
Stats.onNativeCall()
......@@ -69,19 +106,36 @@ class Region : Managed(Region_nMake(), _FinalizerHolder.PTR) {
}
}
fun getBoundaryPath(p: Path?): Boolean {
/**
* Appends the boundary outline of this region into [pathBuilder].
*
* @return true if this region is not empty and the builder changed
*/
fun addBoundaryPath(pathBuilder: PathBuilder): Boolean {
return try {
Stats.onNativeCall()
Region_nAddBoundaryPath(_ptr, getPtr(pathBuilder))
} finally {
reachabilityBarrier(this)
reachabilityBarrier(pathBuilder)
}
}
/** Returns the boundary of this region as a new immutable [Path]. */
fun getBoundaryPath(): Path {
return try {
Stats.onNativeCall()
Region_nGetBoundaryPath(
_ptr,
getPtr(p)
)
Path(Region_nGetBoundaryPath(_ptr))
} finally {
reachabilityBarrier(this)
reachabilityBarrier(p)
}
}
/**
* Sets this region to empty.
*
* @return always false
*/
fun setEmpty(): Boolean {
return try {
Stats.onNativeCall()
......@@ -91,10 +145,12 @@ class Region : Managed(Region_nMake(), _FinalizerHolder.PTR) {
}
}
/** Sets this region to [rect]. Returns true if [rect] is not empty. */
fun setRect(rect: IRect): Boolean {
return setRect(rect.left, rect.top, rect.right, rect.bottom)
}
/** Sets this region to [left], [top], [right], [bottom]. */
fun setRect(left: Int, top: Int, right: Int, bottom: Int): Boolean {
return try {
Stats.onNativeCall()
......@@ -104,6 +160,11 @@ class Region : Managed(Region_nMake(), _FinalizerHolder.PTR) {
}
}
/**
* Sets this region to a union of [rects].
*
* @return true if the resulting region is not empty
*/
fun setRects(rects: Array<IRect>): Boolean {
return try {
val arr = IntArray(rects.size * 4)
......@@ -122,24 +183,30 @@ class Region : Managed(Region_nMake(), _FinalizerHolder.PTR) {
}
}
fun setRegion(r: Region?): Boolean {
/**
* Sets this region to [region].
*
* @return true if [region] is not empty
*/
fun setRegion(region: Region): Boolean {
return try {
Stats.onNativeCall()
Region_nSetRegion(_ptr, getPtr(r))
Region_nSetRegion(_ptr, getPtr(region))
} finally {
reachabilityBarrier(this)
reachabilityBarrier(r)
reachabilityBarrier(region)
}
}
fun setPath(path: Path?, clip: Region?): Boolean {
/**
* Sets this region to the rasterized outline of [path] clipped by [clip].
*
* @return true if the resulting region is not empty
*/
fun setPath(path: Path, clip: Region): Boolean {
return try {
Stats.onNativeCall()
Region_nSetPath(
_ptr,
getPtr(path),
getPtr(clip)
)
Region_nSetPath(_ptr, getPtr(path), getPtr(clip))
} finally {
reachabilityBarrier(this)
reachabilityBarrier(path)
......@@ -147,10 +214,12 @@ class Region : Managed(Region_nMake(), _FinalizerHolder.PTR) {
}
}
/** Returns true if this region intersects [rect]. */
fun intersects(rect: IRect): Boolean {
return intersects(rect.left, rect.top, rect.right, rect.bottom)
}
/** Returns true if this region intersects [left], [top], [right], [bottom]. */
fun intersects(left: Int, top: Int, right: Int, bottom: Int): Boolean {
return try {
Stats.onNativeCall()
......@@ -160,19 +229,18 @@ class Region : Managed(Region_nMake(), _FinalizerHolder.PTR) {
}
}
fun intersects(r: Region?): Boolean {
/** Returns true if this region intersects [region]. */
fun intersects(region: Region): Boolean {
return try {
Stats.onNativeCall()
Region_nIntersectsRegion(
_ptr,
getPtr(r)
)
Region_nIntersectsRegion(_ptr, getPtr(region))
} finally {
reachabilityBarrier(this)
reachabilityBarrier(r)
reachabilityBarrier(region)
}
}
/** Returns true if point ([x], [y]) is inside this region. */
fun contains(x: Int, y: Int): Boolean {
return try {
Stats.onNativeCall()
......@@ -182,6 +250,7 @@ class Region : Managed(Region_nMake(), _FinalizerHolder.PTR) {
}
}
/** Returns true if rectangle ([left], [top], [right], [bottom]) is fully inside this region. */
fun contains(left: Int, top: Int, right: Int, bottom: Int): Boolean {
return try {
Stats.onNativeCall()
......@@ -191,23 +260,31 @@ class Region : Managed(Region_nMake(), _FinalizerHolder.PTR) {
}
}
/** Returns true if [rect] is fully inside this region. */
operator fun contains(rect: IRect): Boolean {
return contains(rect.left, rect.top, rect.right, rect.bottom)
}
operator fun contains(r: Region?): Boolean {
/** Returns true if [region] is fully inside this region. */
operator fun contains(region: Region): Boolean {
return try {
Stats.onNativeCall()
Region_nContainsRegion(_ptr, getPtr(r))
Region_nContainsRegion(_ptr, getPtr(region))
} finally {
reachabilityBarrier(this)
reachabilityBarrier(r)
reachabilityBarrier(region)
}
}
/**
* Fast conservative containment check.
* Returns true only when this region is a single rectangle containing [rect].
*/
fun quickContains(rect: IRect): Boolean {
return quickContains(rect.left, rect.top, rect.right, rect.bottom)
}
/** Fast conservative containment check for rectangle coordinates. */
fun quickContains(left: Int, top: Int, right: Int, bottom: Int): Boolean {
return try {
Stats.onNativeCall()
......@@ -217,9 +294,12 @@ class Region : Managed(Region_nMake(), _FinalizerHolder.PTR) {
}
}
/** Fast conservative rejection check for [rect]. */
fun quickReject(rect: IRect): Boolean {
return quickReject(rect.left, rect.top, rect.right, rect.bottom)
}
/** Fast conservative rejection check for rectangle coordinates. */
fun quickReject(left: Int, top: Int, right: Int, bottom: Int): Boolean {
return try {
Stats.onNativeCall()
......@@ -229,19 +309,18 @@ class Region : Managed(Region_nMake(), _FinalizerHolder.PTR) {
}
}
fun quickReject(r: Region?): Boolean {
/** Fast conservative rejection check for [region]. */
fun quickReject(region: Region): Boolean {
return try {
Stats.onNativeCall()
Region_nQuickRejectRegion(
_ptr,
getPtr(r)
)
Region_nQuickRejectRegion(_ptr, getPtr(region))
} finally {
reachabilityBarrier(this)
reachabilityBarrier(r)
reachabilityBarrier(region)
}
}
/** Offsets this region by ([dx], [dy]). */
fun translate(dx: Int, dy: Int) {
try {
Stats.onNativeCall()
......@@ -251,111 +330,73 @@ class Region : Managed(Region_nMake(), _FinalizerHolder.PTR) {
}
}
/** Replaces this region with result of `this op rect`. */
fun op(rect: IRect, op: Op): Boolean {
return op(rect.left, rect.top, rect.right, rect.bottom, op)
}
/** Replaces this region with result of `this op rect`. */
fun op(left: Int, top: Int, right: Int, bottom: Int, op: Op): Boolean {
return try {
Stats.onNativeCall()
Region_nOpIRect(
_ptr,
left,
top,
right,
bottom,
op.ordinal
)
Region_nOpIRect(_ptr, left, top, right, bottom, op.ordinal)
} finally {
reachabilityBarrier(this)
}
}
fun op(r: Region?, op: Op): Boolean {
/** Replaces this region with result of `this op region`. */
fun op(region: Region, op: Op): Boolean {
return try {
Stats.onNativeCall()
Region_nOpRegion(
_ptr,
getPtr(r),
op.ordinal
)
Region_nOpRegion(_ptr, getPtr(region), op.ordinal)
} finally {
reachabilityBarrier(this)
reachabilityBarrier(r)
reachabilityBarrier(region)
}
}
fun op(rect: IRect, r: Region?, op: Op): Boolean {
return op(
rect.left,
rect.top,
rect.right,
rect.bottom,
r,
op
)
/** Replaces this region with result of `rect op region`. */
fun op(rect: IRect, region: Region, op: Op): Boolean {
return op(rect.left, rect.top, rect.right, rect.bottom, region, op)
}
fun op(left: Int, top: Int, right: Int, bottom: Int, r: Region?, op: Op): Boolean {
/** Replaces this region with result of `rect op region`. */
fun op(left: Int, top: Int, right: Int, bottom: Int, region: Region, op: Op): Boolean {
return try {
Stats.onNativeCall()
Region_nOpIRectRegion(
_ptr,
left,
top,
right,
bottom,
getPtr(r),
op.ordinal
)
Region_nOpIRectRegion(_ptr, left, top, right, bottom, getPtr(region), op.ordinal)
} finally {
reachabilityBarrier(this)
reachabilityBarrier(r)
reachabilityBarrier(region)
}
}
fun op(r: Region?, rect: IRect, op: Op): Boolean {
return op(
r,
rect.left,
rect.top,
rect.right,
rect.bottom,
op
)
/** Replaces this region with result of `region op rect`. */
fun op(region: Region, rect: IRect, op: Op): Boolean {
return op(region, rect.left, rect.top, rect.right, rect.bottom, op)
}
fun op(r: Region?, left: Int, top: Int, right: Int, bottom: Int, op: Op): Boolean {
/** Replaces this region with result of `region op rect`. */
fun op(region: Region, left: Int, top: Int, right: Int, bottom: Int, op: Op): Boolean {
return try {
Stats.onNativeCall()
Region_nOpRegionIRect(
_ptr,
getPtr(r),
left,
top,
right,
bottom,
op.ordinal
)
Region_nOpRegionIRect(_ptr, getPtr(region), left, top, right, bottom, op.ordinal)
} finally {
reachabilityBarrier(this)
reachabilityBarrier(r)
reachabilityBarrier(region)
}
}
fun op(a: Region?, b: Region?, op: Op): Boolean {
/** Replaces this region with result of `regionA op regionB`. */
fun op(regionA: Region, regionB: Region, op: Op): Boolean {
return try {
Stats.onNativeCall()
Region_nOpRegionRegion(
_ptr,
getPtr(a),
getPtr(b),
op.ordinal
)
Region_nOpRegionRegion(_ptr, getPtr(regionA), getPtr(regionB), op.ordinal)
} finally {
reachabilityBarrier(this)
reachabilityBarrier(a)
reachabilityBarrier(b)
reachabilityBarrier(regionA)
reachabilityBarrier(regionB)
}
}
......@@ -368,7 +409,6 @@ class Region : Managed(Region_nMake(), _FinalizerHolder.PTR) {
}
}
@ExternalSymbolName("org_jetbrains_skia_Region__1nMake")
private external fun Region_nMake(): NativePointer
......@@ -385,7 +425,7 @@ private external fun Region_nIsRect(ptr: NativePointer): Boolean
private external fun Region_nGetBounds(ptr: NativePointer, ltrb: InteropPointer)
@ExternalSymbolName("org_jetbrains_skia_Region__1nSet")
private external fun Region_nSet(ptr: NativePointer, regoinPtr: NativePointer): Boolean
private external fun Region_nSet(ptr: NativePointer, regionPtr: NativePointer): Boolean
@ExternalSymbolName("org_jetbrains_skia_Region__1nIsComplex")
private external fun Region_nIsComplex(ptr: NativePointer): Boolean
......@@ -393,8 +433,11 @@ private external fun Region_nIsComplex(ptr: NativePointer): Boolean
@ExternalSymbolName("org_jetbrains_skia_Region__1nComputeRegionComplexity")
private external fun Region_nComputeRegionComplexity(ptr: NativePointer): Int
@ExternalSymbolName("org_jetbrains_skia_Region__1nAddBoundaryPath")
private external fun Region_nAddBoundaryPath(ptr: NativePointer, pathBuilderPtr: NativePointer): Boolean
@ExternalSymbolName("org_jetbrains_skia_Region__1nGetBoundaryPath")
private external fun Region_nGetBoundaryPath(ptr: NativePointer, pathPtr: NativePointer): Boolean
private external fun Region_nGetBoundaryPath(ptr: NativePointer): NativePointer
@ExternalSymbolName("org_jetbrains_skia_Region__1nSetEmpty")
private external fun Region_nSetEmpty(ptr: NativePointer): Boolean
......@@ -455,7 +498,6 @@ private external fun Region_nOpIRectRegion(
op: Int
): Boolean
@ExternalSymbolName("org_jetbrains_skia_Region__1nOpRegionIRect")
private external fun Region_nOpRegionIRect(
ptr: NativePointer,
......@@ -467,11 +509,10 @@ private external fun Region_nOpRegionIRect(
op: Int
): Boolean
@ExternalSymbolName("org_jetbrains_skia_Region__1nOpRegionRegion")
private external fun Region_nOpRegionRegion(
ptr: NativePointer,
regionPtrA: NativePointer,
regionPtrB: NativePointer,
op: Int
): Boolean
\ No newline at end of file
): Boolean
......@@ -3,6 +3,10 @@ package org.jetbrains.skia.paragraph
import org.jetbrains.skia.FontEdging
import org.jetbrains.skia.FontHinting
@Deprecated(
message = "Replaced by separate properties in TextStyle: fontEdging, fontHinting, subpixel",
level = DeprecationLevel.ERROR,
)
data class FontRastrSettings(val edging: FontEdging,
val hinting: FontHinting,
val subpixel: Boolean)
\ No newline at end of file
val subpixel: Boolean)
......@@ -190,25 +190,19 @@ class ParagraphStyle : Managed(ParagraphStyle_nMake(), _FinalizerHolder.PTR) {
return this
}
@Suppress("DEPRECATION_ERROR")
@Deprecated(
message = "Replaced by separate properties in TextStyle: fontEdging, fontHinting, subpixel",
level = DeprecationLevel.ERROR,
)
var fontRastrSettings: FontRastrSettings
get() = try {
Stats.onNativeCall()
val edging = FontEdging.entries[_nGetEdging(_ptr)]
Stats.onNativeCall()
val hinting = FontHinting.entries[_nGetHinting(_ptr)]
Stats.onNativeCall()
// by some obscure reason kotlinjs makes difference between number encoded booleans returned from `_nGetSubpixel` and regular booleans
// AssertionError: Expected <FontRastrSettings(edging=ALIAS, hinting=NONE, subpixel=false)>, actual <FontRastrSettings(edging=ALIAS, hinting=NONE, subpixel=0)>
val subpixel = _nGetSubpixel(_ptr).not().not()
FontRastrSettings(edging, hinting, subpixel)
} finally {
reachabilityBarrier(this)
get() = textStyle.let {
FontRastrSettings(it.fontEdging, it.fontHinting, it.subpixel)
}
set(value) = try {
Stats.onNativeCall()
_nSetFontRastrSettings(_ptr, value.edging.ordinal, value.hinting.ordinal, value.subpixel)
} finally {
reachabilityBarrier(this)
set(value) = textStyle.let {
it.fontEdging = value.edging
it.fontHinting = value.hinting
it.subpixel = value.subpixel
}
var isApplyRoundingHackEnabled: Boolean
......@@ -317,18 +311,6 @@ private external fun _nIsHintingEnabled(ptr: NativePointer): Boolean
@ExternalSymbolName("org_jetbrains_skia_paragraph_ParagraphStyle__1nDisableHinting")
private external fun _nDisableHinting(ptr: NativePointer)
@ExternalSymbolName("org_jetbrains_skia_paragraph_ParagraphStyle__1nSetFontRastrSettings")
private external fun _nSetFontRastrSettings(ptr: NativePointer, edging: Int, hinting: Int, subpixel: Boolean)
@ExternalSymbolName("org_jetbrains_skia_paragraph_ParagraphStyle__1nGetEdging")
private external fun _nGetEdging(ptr: NativePointer): Int
@ExternalSymbolName("org_jetbrains_skia_paragraph_ParagraphStyle__1nGetHinting")
private external fun _nGetHinting(ptr: NativePointer): Int
@ExternalSymbolName("org_jetbrains_skia_paragraph_ParagraphStyle__1nGetSubpixel")
private external fun _nGetSubpixel(ptr: NativePointer): Boolean
@ExternalSymbolName("org_jetbrains_skia_paragraph_ParagraphStyle__1nGetApplyRoundingHack")
private external fun _nGetApplyRoundingHack(ptr: NativePointer): Boolean
......@@ -345,4 +327,4 @@ private external fun _nGetTextIndent(ptr: NativePointer, result: InteropPointer)
private external fun _nGetReplaceTabCharacters(ptr: NativePointer): Boolean
@ExternalSymbolName("org_jetbrains_skia_paragraph_ParagraphStyle__1nSetReplaceTabCharacters")
private external fun _nSetReplaceTabCharacters(ptr: NativePointer, value: Boolean)
\ No newline at end of file
private external fun _nSetReplaceTabCharacters(ptr: NativePointer, value: Boolean)
......@@ -509,7 +509,6 @@ class TextStyle internal constructor(ptr: NativePointer) : Managed(ptr, _Finaliz
return this
}
val fontMetrics: FontMetrics
get() = try {
Stats.onNativeCall()
......@@ -529,11 +528,57 @@ class TextStyle internal constructor(ptr: NativePointer) : Managed(ptr, _Finaliz
}
fun setPlaceholder(): TextStyle {
Stats.onNativeCall()
_nSetPlaceholder(_ptr)
try {
Stats.onNativeCall()
_nSetPlaceholder(_ptr)
} finally {
reachabilityBarrier(this)
}
return this
}
var fontEdging: FontEdging
get() = try {
Stats.onNativeCall()
FontEdging.entries[_nGetFontEdging(_ptr)]
} finally {
reachabilityBarrier(this)
}
set(value) = try {
Stats.onNativeCall()
_nSetFontEdging(_ptr, value.ordinal)
} finally {
reachabilityBarrier(this)
}
var subpixel: Boolean
get() = try {
Stats.onNativeCall()
_nGetSubpixel(_ptr)
} finally {
reachabilityBarrier(this)
}
set(value) = try {
Stats.onNativeCall()
_nSetSubpixel(_ptr, value)
} finally {
reachabilityBarrier(this)
}
var fontHinting: FontHinting
get() = try {
Stats.onNativeCall()
FontHinting.entries[_nGetFontHinting(_ptr)]
} finally {
reachabilityBarrier(this)
}
set(value) = try {
Stats.onNativeCall()
_nSetFontHinting(_ptr, value.ordinal)
} finally {
reachabilityBarrier(this)
}
internal object _FinalizerHolder {
val PTR = TextStyle_nGetFinalizer()
}
......@@ -688,3 +733,21 @@ private external fun _nIsPlaceholder(ptr: NativePointer): Boolean
@ExternalSymbolName("org_jetbrains_skia_paragraph_TextStyle__1nSetPlaceholder")
private external fun _nSetPlaceholder(ptr: NativePointer)
@ExternalSymbolName("org_jetbrains_skia_paragraph_TextStyle__1nGetFontEdging")
private external fun _nGetFontEdging(ptr: NativePointer): Int
@ExternalSymbolName("org_jetbrains_skia_paragraph_TextStyle__1nSetFontEdging")
private external fun _nSetFontEdging(ptr: NativePointer, fontEdging: Int)
@ExternalSymbolName("org_jetbrains_skia_paragraph_TextStyle__1nGetSubpixel")
private external fun _nGetSubpixel(ptr: NativePointer): Boolean
@ExternalSymbolName("org_jetbrains_skia_paragraph_TextStyle__1nSetSubpixel")
private external fun _nSetSubpixel(ptr: NativePointer, subpixel: Boolean)
@ExternalSymbolName("org_jetbrains_skia_paragraph_TextStyle__1nGetFontHinting")
private external fun _nGetFontHinting(ptr: NativePointer): Int
@ExternalSymbolName("org_jetbrains_skia_paragraph_TextStyle__1nSetFontHinting")
private external fun _nSetFontHinting(ptr: NativePointer, fontHinting: Int)
......@@ -96,10 +96,12 @@ class ImageTest {
return Surface.makeRasterN32Premul(100, 100).use { surface ->
val paint = Paint()
paint.color = -0x10000
Path().moveTo(20f, 80f)
PathBuilder()
.moveTo(20f, 80f)
.lineTo(50f, 20f)
.lineTo(80f, 80f)
.closePath()
.detach()
.use { path ->
val canvas = surface.canvas
canvas.drawPath(path, paint)
......
package org.jetbrains.skia
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertTrue
class PathBuilderTest {
@Test
fun testConstructors() {
// Default constructor
val builder1 = PathBuilder()
assertNotNull(builder1)
// Constructor with fillType
val builder2 = PathBuilder(PathFillMode.EVEN_ODD)
val path2 = builder2.detach()
assertEquals(PathFillMode.EVEN_ODD, path2.fillMode)
// Constructor from existing path
val existingPath = PathBuilder().moveTo(10f, 10f).lineTo(20f, 20f).detach()
val builder3 = PathBuilder(existingPath)
assertNotNull(builder3)
}
@Test
fun testSnapshotAndDetach() {
val builder = PathBuilder().moveTo(0f, 0f).lineTo(10f, 10f)
// snapshot() creates a copy without consuming builder
val snapshot1 = builder.snapshot()
assertNotNull(snapshot1)
assertEquals(2, snapshot1.pointsCount)
// Builder is still usable after snapshot
val snapshot2 = builder.lineTo(20f, 20f).snapshot()
assertEquals(3, snapshot2.pointsCount)
// detach() returns path and consumes builder
val detached = builder.detach()
assertNotNull(detached)
assertEquals(3, detached.pointsCount)
}
@Test
fun testSetFillType() {
val path = PathBuilder()
.setFillType(PathFillMode.INVERSE_WINDING)
.moveTo(0f, 0f)
.detach()
assertEquals(PathFillMode.INVERSE_WINDING, path.fillMode)
}
@Test
fun testReset() {
val builder = PathBuilder()
.moveTo(10f, 10f)
.lineTo(20f, 20f)
.reset()
.moveTo(5f, 5f)
val path = builder.detach()
assertEquals(1, path.pointsCount)
assertEquals(Point(5f, 5f), path.getPoint(0))
}
@Test
fun testIncReserve() {
// Test that incReserve doesn't crash (performance optimization)
val path = PathBuilder()
.incReserve(100)
.moveTo(0f, 0f)
.lineTo(10f, 10f)
.detach()
assertEquals(2, path.pointsCount)
}
@Test
fun testMoveToAndLineTo() {
// Test moveTo(x, y)
val path1 = PathBuilder()
.moveTo(10f, 20f)
.lineTo(30f, 40f)
.detach()
assertEquals(2, path1.pointsCount)
assertEquals(Point(10f, 20f), path1.getPoint(0))
assertEquals(Point(30f, 40f), path1.getPoint(1))
// Test moveTo(Point) and lineTo(Point)
val path2 = PathBuilder()
.moveTo(Point(5f, 10f))
.lineTo(Point(15f, 20f))
.detach()
assertEquals(2, path2.pointsCount)
assertEquals(Point(5f, 10f), path2.getPoint(0))
}
@Test
fun testRelativeMoveToAndLineTo() {
val path = PathBuilder()
.moveTo(10f, 10f)
.rMoveTo(5f, 5f) // Should be at (15, 15)
.rLineTo(10f, 10f) // Should be at (25, 25)
.detach()
assertEquals(2, path.pointsCount)
assertEquals(Point(15f, 15f), path.getPoint(0))
assertEquals(Point(25f, 25f), path.getPoint(1))
}
@Test
fun testQuadTo() {
// Test quadTo(x1, y1, x2, y2)
val path1 = PathBuilder()
.moveTo(0f, 0f)
.quadTo(10f, 20f, 20f, 0f)
.detach()
assertEquals(3, path1.pointsCount)
// Test quadTo(Point, Point)
val path2 = PathBuilder()
.moveTo(0f, 0f)
.quadTo(Point(10f, 20f), Point(20f, 0f))
.detach()
assertEquals(3, path2.pointsCount)
// Test rQuadTo
val path3 = PathBuilder()
.moveTo(0f, 0f)
.rQuadTo(10f, 20f, 20f, 0f)
.detach()
assertEquals(3, path3.pointsCount)
}
@Test
fun testConicTo() {
// Test conicTo(x1, y1, x2, y2, w)
val path1 = PathBuilder()
.moveTo(0f, 0f)
.conicTo(10f, 20f, 20f, 0f, 0.5f)
.detach()
assertEquals(3, path1.pointsCount)
// Test conicTo(Point, Point, w)
val path2 = PathBuilder()
.moveTo(0f, 0f)
.conicTo(Point(10f, 20f), Point(20f, 0f), 0.5f)
.detach()
assertEquals(3, path2.pointsCount)
// Test rConicTo
val path3 = PathBuilder()
.moveTo(0f, 0f)
.rConicTo(10f, 20f, 20f, 0f, 0.5f)
.detach()
assertEquals(3, path3.pointsCount)
}
@Test
fun testCubicTo() {
// Test cubicTo(x1, y1, x2, y2, x3, y3)
val path1 = PathBuilder()
.moveTo(0f, 0f)
.cubicTo(10f, 20f, 15f, 30f, 20f, 0f)
.detach()
assertEquals(4, path1.pointsCount)
// Test cubicTo(Point, Point, Point)
val path2 = PathBuilder()
.moveTo(0f, 0f)
.cubicTo(Point(10f, 20f), Point(15f, 30f), Point(20f, 0f))
.detach()
assertEquals(4, path2.pointsCount)
// Test rCubicTo
val path3 = PathBuilder()
.moveTo(0f, 0f)
.rCubicTo(10f, 20f, 15f, 30f, 20f, 0f)
.detach()
assertEquals(4, path3.pointsCount)
}
@Test
fun testArcTo() {
// Test arcTo with Rect
val path1 = PathBuilder()
.moveTo(0f, 0f)
.arcTo(Rect.makeXYWH(10f, 10f, 20f, 20f), 0f, 90f, false)
.detach()
assertTrue(path1.pointsCount > 0)
// Test arcTo with coordinates
val path2 = PathBuilder()
.moveTo(0f, 0f)
.arcTo(10f, 10f, 30f, 30f, 0f, 90f, false)
.detach()
assertTrue(path2.pointsCount > 0)
}
@Test
fun testTangentArcTo() {
// Test tangentArcTo with coordinates
val path1 = PathBuilder()
.moveTo(0f, 0f)
.tangentArcTo(10f, 0f, 10f, 10f, 5f)
.detach()
assertTrue(path1.pointsCount > 0)
// Test tangentArcTo with Points
val path2 = PathBuilder()
.moveTo(0f, 0f)
.tangentArcTo(Point(10f, 0f), Point(10f, 10f), 5f)
.detach()
assertTrue(path2.pointsCount > 0)
}
@Test
fun testEllipticalArcTo() {
// Test ellipticalArcTo
val path1 = PathBuilder()
.moveTo(0f, 0f)
.ellipticalArcTo(10f, 5f, 0f, PathEllipseArc.SMALLER, PathDirection.CLOCKWISE, 20f, 0f)
.detach()
assertTrue(path1.pointsCount > 0)
// Test ellipticalArcTo with Points
val path2 = PathBuilder()
.moveTo(0f, 0f)
.ellipticalArcTo(Point(10f, 5f), 0f, PathEllipseArc.SMALLER, PathDirection.CLOCKWISE, Point(20f, 0f))
.detach()
assertTrue(path2.pointsCount > 0)
// Test rEllipticalArcTo
val path3 = PathBuilder()
.moveTo(0f, 0f)
.rEllipticalArcTo(10f, 5f, 0f, PathEllipseArc.SMALLER, PathDirection.CLOCKWISE, 20f, 0f)
.detach()
assertTrue(path3.pointsCount > 0)
}
@Test
fun testClosePath() {
val path = PathBuilder()
.moveTo(0f, 0f)
.lineTo(10f, 10f)
.lineTo(10f, 0f)
.closePath()
.detach()
assertTrue(path.isLastContourClosed)
assertEquals(3, path.pointsCount)
}
@Test
fun testAddRect() {
// Test addRect with Rect
val path1 = PathBuilder()
.addRect(Rect.makeXYWH(10f, 10f, 20f, 20f))
.detach()
assertTrue(path1.pointsCount >= 4)
// Test addRect with coordinates
val path2 = PathBuilder()
.addRect(10f, 10f, 30f, 30f, PathDirection.COUNTER_CLOCKWISE, 1)
.detach()
assertTrue(path2.pointsCount >= 4)
}
@Test
fun testAddOval() {
// Test addOval with Rect
val path1 = PathBuilder()
.addOval(Rect.makeXYWH(10f, 10f, 20f, 20f))
.detach()
assertTrue(path1.pointsCount > 4)
// Test addOval with coordinates
val path2 = PathBuilder()
.addOval(10f, 10f, 30f, 30f, PathDirection.CLOCKWISE, 2)
.detach()
assertTrue(path2.pointsCount > 4)
}
@Test
fun testAddCircle() {
val path = PathBuilder()
.addCircle(50f, 50f, 25f, PathDirection.CLOCKWISE)
.detach()
assertTrue(path.pointsCount > 4)
}
@Test
fun testAddArc() {
// Test addArc with Rect
val path1 = PathBuilder()
.addArc(Rect.makeXYWH(10f, 10f, 20f, 20f), 0f, 90f)
.detach()
assertTrue(path1.pointsCount > 0)
// Test addArc with coordinates
val path2 = PathBuilder()
.addArc(10f, 10f, 30f, 30f, 0f, 180f)
.detach()
assertTrue(path2.pointsCount > 0)
}
@Test
fun testAddRRect() {
// Test addRRect with RRect
val rrect = RRect.makeXYWH(10f, 10f, 20f, 20f, 5f)
val path1 = PathBuilder()
.addRRect(rrect)
.detach()
assertTrue(path1.pointsCount > 4)
// Test addRRect with coordinates and radii
val radii = floatArrayOf(5f, 5f, 5f, 5f, 5f, 5f, 5f, 5f)
val path2 = PathBuilder()
.addRRect(10f, 10f, 30f, 30f, radii, PathDirection.CLOCKWISE)
.detach()
assertTrue(path2.pointsCount > 4)
}
@Test
fun testAddPoly() {
// Test addPoly with Array<Point>
val points = arrayOf(Point(0f, 0f), Point(10f, 10f), Point(20f, 0f))
val path1 = PathBuilder()
.addPoly(points, true)
.detach()
assertEquals(3, path1.pointsCount)
// Test addPoly with FloatArray
val coords = floatArrayOf(0f, 0f, 10f, 10f, 20f, 0f)
val path2 = PathBuilder()
.addPoly(coords, false)
.detach()
assertEquals(3, path2.pointsCount)
}
@Test
fun testAddPath() {
val srcPath = PathBuilder()
.moveTo(0f, 0f)
.lineTo(10f, 10f)
.detach()
// Test addPath with mode=APPEND
// Note: moveTo alone doesn't add a point until a drawing command follows
val path1 = PathBuilder()
.moveTo(20f, 20f)
.addPath(srcPath, PathAddMode.APPEND)
.detach()
assertEquals(2, path1.pointsCount)
// Test addPath with offset
val path2 = PathBuilder()
.addPath(srcPath, 5f, 5f, PathAddMode.APPEND)
.detach()
assertEquals(Point(5f, 5f), path2.getPoint(0))
// Test addPath with matrix
val matrix = Matrix33.makeTranslate(10f, 10f)
val path3 = PathBuilder()
.addPath(srcPath, matrix, PathAddMode.APPEND)
.detach()
assertEquals(Point(10f, 10f), path3.getPoint(0))
}
@Test
fun testSetLastPt() {
val path = PathBuilder()
.moveTo(0f, 0f)
.lineTo(10f, 10f)
.setLastPt(15f, 15f)
.detach()
assertEquals(Point(15f, 15f), path.lastPt)
}
@Test
fun testBuilderChaining() {
// Verify that all methods return PathBuilder for chaining
val path = PathBuilder()
.setFillType(PathFillMode.WINDING)
.incReserve(10)
.moveTo(0f, 0f)
.lineTo(10f, 0f)
.lineTo(10f, 10f)
.lineTo(0f, 10f)
.closePath()
.detach()
assertEquals(4, path.pointsCount)
assertTrue(path.isLastContourClosed)
}
@Test
fun testComplexPath() {
// Test a complex path that uses multiple operations
val path = PathBuilder()
.moveTo(0f, 0f)
.lineTo(50f, 0f)
.quadTo(75f, 25f, 50f, 50f)
.cubicTo(40f, 60f, 30f, 60f, 20f, 50f)
.arcTo(0f, 25f, 25f, 50f, 180f, 90f, false)
.closePath()
.addCircle(100f, 100f, 20f)
.addRect(150f, 150f, 200f, 200f)
.detach()
assertTrue(path.pointsCount > 10)
assertNotNull(path.bounds)
}
}
......@@ -11,7 +11,7 @@ class PathMeasureTest {
@Test
fun getRSXformTest() = runTest {
Path().moveTo(0f, 0f).lineTo(40f, 0f).moveTo(0f, 40f).lineTo(10f, 50f).use { path ->
PathBuilder().moveTo(0f, 0f).lineTo(40f, 0f).moveTo(0f, 40f).lineTo(10f, 50f).detach().use { path ->
PathMeasure(path, false).use { measure ->
assertEquals(RSXform(1.0f, 0f, 0.5f, 0f), measure.getRSXform(0.5f))
}
......@@ -20,7 +20,7 @@ class PathMeasureTest {
@Test
fun getTangent() = runTest {
Path().moveTo(0f, 0f).lineTo(20f, 0f).moveTo(0f, 40f).lineTo(30f, 50f).use { path ->
PathBuilder().moveTo(0f, 0f).lineTo(20f, 0f).moveTo(0f, 40f).lineTo(30f, 50f).detach().use { path ->
PathMeasure(path, false).use { measure ->
assertEquals(Point(1f, 0f), measure.getTangent(2f))
}
......@@ -29,7 +29,7 @@ class PathMeasureTest {
@Test
fun getPosition() = runTest {
Path().moveTo(0f, 10f).lineTo(20f, 0f).moveTo(0f, 40f).lineTo(30f, 50f).use { path ->
PathBuilder().moveTo(0f, 10f).lineTo(20f, 0f).moveTo(0f, 40f).lineTo(30f, 50f).detach().use { path ->
PathMeasure(path, false).use { measure ->
assertCloseEnough(Point(0.89442724f, 9.552787f), measure.getPosition(1f)!!)
}
......@@ -40,9 +40,9 @@ class PathMeasureTest {
@Test
@Ignore
fun pathMeasureTest() = runTest {
Path().moveTo(0f, 0f).lineTo(40f, 0f).moveTo(0f, 40f).lineTo(10f, 50f).use { path ->
PathBuilder().moveTo(0f, 0f).lineTo(40f, 0f).moveTo(0f, 40f).lineTo(10f, 50f).detach().use { path ->
PathMeasure(path, false).use { measure ->
Path().lineTo(10f, 10f).use { path2 ->
PathBuilder().lineTo(10f, 10f).detach().use { path2 ->
assertEquals(40f, measure.length)
assertCloseEnough(Point(0f, 0f), measure.getPosition(0f)!!)
assertCloseEnough(Point(1f, 0f), measure.getTangent(0f)!!)
......
package org.jetbrains.skia
import org.jetbrains.skia.impl.Native.Companion.NullPointer
import org.jetbrains.skia.tests.assertCloseEnough
import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertNotEquals
import kotlin.test.assertNull
import kotlin.test.assertTrue
class PathTest {
@Test
fun storageTest() {
val subpath: Path = Path().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).closePath()
val subpath: Path = PathBuilder()
.lineTo(40f, 40f)
.lineTo(40f, 0f)
.lineTo(0f, 40f)
.lineTo(0f, 0f)
.closePath()
.detach()
for (p in arrayOf(
Path().addPath(subpath),
Path().incReserve(10).addPath(subpath).closePath()
PathBuilder().addPath(subpath).detach(),
PathBuilder().incReserve(10).addPath(subpath).closePath().detach()
)) {
val p0 = Point(0f, 0f)
val p1 = Point(40f, 40f)
......@@ -29,21 +37,22 @@ class PathTest {
assertEquals(p3, p.getPoint(3))
assertEquals(p4, p.getPoint(4))
assertEquals(p4, p.lastPt)
p.lastPt = p5
assertEquals(p5, p.getPoint(4))
assertEquals(p5, p.lastPt)
assertEquals(5, p.getPoints(null, 0))
// lastPt is now read-only, test setLastPt through PathBuilder
val pModified = PathBuilder(p).setLastPt(p5.x, p5.y).detach()
assertEquals(p5, pModified.getPoint(4))
assertEquals(p5, pModified.lastPt)
assertEquals(5, pModified.getPoints(null, 0))
var pts = arrayOfNulls<Point?>(5)
p.getPoints(pts, 5)
pModified.getPoints(pts, 5)
assertContentEquals(arrayOf(p0, p1, p2, p3, p5), pts)
pts = arrayOfNulls(3)
p.getPoints(pts, 3)
pModified.getPoints(pts, 3)
assertContentEquals(arrayOf(p0, p1, p2), pts)
pts = arrayOfNulls(5)
p.getPoints(pts, 3)
pModified.getPoints(pts, 3)
assertContentEquals(arrayOf(p0, p1, p2, null, null), pts)
pts = arrayOfNulls(10)
p.getPoints(pts, 10)
pModified.getPoints(pts, 10)
assertContentEquals(arrayOf(p0, p1, p2, p3, p5, null, null, null, null, null), pts)
assertEquals(6, p.verbsCount)
assertEquals(6, p.getVerbs(null, 0))
......@@ -81,16 +90,103 @@ class PathTest {
null
), verbs
)
assertNotEquals(NullPointer, p.approximateBytesUsed)
assertTrue(p.approximateBytesUsed > 0, "approximateBytesUsed should return positive size")
assertEquals(PathSegmentMask.LINE, p.segmentMasks)
}
}
@Test
fun emptyPath() {
val emptyPath = Path()
assertEquals(0, emptyPath.pointsCount)
assertNull(emptyPath.lastPt)
}
@Test
fun canGetBounds() {
val path = Path().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).closePath()
val path = PathBuilder().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).closePath().detach()
val bounds = Rect(0.0f, 0.0f, 40.0f, 40.0f)
assertCloseEnough(bounds, path.bounds)
assertCloseEnough(bounds, path.computeTightBounds())
}
@Test
fun rawTest() {
val pts = arrayOf(Point(0f, 0f), Point(10f, 10f), Point(20f, 0f))
val verbs = arrayOf(PathVerb.MOVE, PathVerb.LINE, PathVerb.LINE)
val path = Path.Raw(pts, verbs)
assertEquals(3, path.pointsCount)
assertEquals(3, path.verbsCount)
assertCloseEnough(Rect(0f, 0f, 20f, 10f), path.bounds)
}
@Test
fun rectTest() {
val rect = Rect(10f, 20f, 30f, 40f)
val path = Path.Rect(rect)
assertEquals(4, path.pointsCount) // 4 corners
assertEquals(rect, path.isRect)
assertCloseEnough(rect, path.bounds)
}
@Test
fun ovalTest() {
val rect = Rect(10f, 20f, 30f, 40f)
val path = Path.Oval(rect)
assertEquals(rect, path.isOval)
assertCloseEnough(rect, path.bounds)
}
@Test
fun circleTest() {
val centerX = 50f
val centerY = 50f
val radius = 25f
val path = Path.Circle(centerX, centerY, radius)
val expectedBounds = Rect(centerX - radius, centerY - radius, centerX + radius, centerY + radius)
assertCloseEnough(expectedBounds, path.bounds)
assertEquals(expectedBounds, path.isOval)
}
@Test
fun rrectTest() {
val rect = Rect(10f, 20f, 110f, 120f)
val rx = 10f
val ry = 10f
val path = Path.RRect(rect, rx, ry)
assertCloseEnough(rect, path.bounds)
val rrect = path.isRRect
assertEquals(rect, rrect?.let { Rect(it.left, it.top, it.right, it.bottom) })
}
@Test
fun polygonTest() {
val pts = arrayOf(Point(0f, 0f), Point(10f, 0f), Point(10f, 10f), Point(0f, 10f))
val pathClosed = Path.Polygon(pts, true)
val pathOpen = Path.Polygon(pts, false)
assertEquals(4, pathClosed.pointsCount)
assertEquals(4, pathOpen.pointsCount)
assertTrue(pathClosed.isLastContourClosed)
assertFalse(pathOpen.isLastContourClosed)
}
@Test
fun lineTest() {
val p0 = Point(10f, 20f)
val p1 = Point(30f, 40f)
val path = Path.Line(p0, p1)
assertEquals(2, path.pointsCount)
val line = path.asLine
assertEquals(2, line?.size)
assertEquals(p0, line?.get(0))
assertEquals(p1, line?.get(1))
}
}
\ No newline at end of file
......@@ -16,7 +16,7 @@ import kotlin.test.assertNull
class PathTests {
@Test
fun iterTest() = runTest {
Path().moveTo(10f, 10f).lineTo(20f, 0f).lineTo(20f, 20f).closePath().use { p ->
PathBuilder().moveTo(10f, 10f).lineTo(20f, 0f).lineTo(20f, 20f).closePath().detach().use { p ->
p.iterator().use { i ->
assertTrue(i.hasNext())
......@@ -60,8 +60,8 @@ class PathTests {
@Test
fun convexityTest() = runTest {
Path().lineTo(40f, 20f).lineTo(0f, 40f).lineTo(0f, 0f).closePath().use { p -> assertTrue(p.isConvex) }
Path().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).closePath().use { p ->
PathBuilder().lineTo(40f, 20f).lineTo(0f, 40f).lineTo(0f, 0f).closePath().detach().use { p -> assertTrue(p.isConvex) }
PathBuilder().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).closePath().detach().use { p ->
assertFalse(p.isConvex)
}
}
......@@ -71,7 +71,7 @@ class PathTests {
fun isShapeTest() {
for (dir in PathDirection.entries) {
for (start in 0..3) {
Path().addRect(Rect.makeLTRB(0f, 0f, 40f, 20f), dir, start).use { p ->
PathBuilder().addRect(Rect.makeLTRB(0f, 0f, 40f, 20f), dir, start).detach().use { p ->
assertEquals(Rect.makeLTRB(0f, 0f, 40f, 20f), p.isRect)
assertNull(p.isOval)
assertNull(p.isRRect)
......@@ -80,7 +80,7 @@ class PathTests {
}
for (dir in PathDirection.entries) {
for (start in 0..3) {
Path().addOval(Rect.makeLTRB(0f, 0f, 40f, 20f), dir, start).use { p ->
PathBuilder().addOval(Rect.makeLTRB(0f, 0f, 40f, 20f), dir, start).detach().use { p ->
assertNull(p.isRect)
assertEquals(Rect.makeLTRB(0f, 0f, 40f, 20f), p.isOval)
assertNull(p.isRRect)
......@@ -88,7 +88,7 @@ class PathTests {
}
}
for (dir in PathDirection.entries) {
Path().addCircle(20f, 20f, 20f, dir).use { p ->
PathBuilder().addCircle(20f, 20f, 20f, dir).detach().use { p ->
assertNull(p.isRect)
assertEquals(Rect.makeLTRB(0f, 0f, 40f, 40f), p.isOval)
assertNull(p.isRRect)
......@@ -96,24 +96,24 @@ class PathTests {
}
for (dir in PathDirection.entries) {
for (start in 0..7) {
Path().addRRect(RRect.makeLTRB(0f, 0f, 40f, 20f, 5f), dir, start).use { p ->
PathBuilder().addRRect(RRect.makeLTRB(0f, 0f, 40f, 20f, 5f), dir, start).detach().use { p ->
assertNull(p.isRect)
assertNull(p.isOval)
assertEquals(RRect.makeLTRB(0f, 0f, 40f, 20f, 5f), p.isRRect)
}
Path().addRRect(RRect.makeLTRB(0f, 0f, 40f, 20f, 0f), dir, start).use { p ->
PathBuilder().addRRect(RRect.makeLTRB(0f, 0f, 40f, 20f, 0f), dir, start).detach().use { p ->
assertEquals(Rect.makeLTRB(0f, 0f, 40f, 20f), p.isRect)
assertNull(p.isOval)
assertNull(p.isRRect)
}
Path().addRRect(RRect.makeLTRB(0f, 0f, 40f, 20f, 20f, 10f), dir, start).use { p ->
PathBuilder().addRRect(RRect.makeLTRB(0f, 0f, 40f, 20f, 20f, 10f), dir, start).detach().use { p ->
assertNull(p.isRect)
assertEquals(Rect.makeLTRB(0f, 0f, 40f, 20f), p.isOval)
assertNull(p.isRRect)
}
}
}
Path().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).closePath().use { p ->
PathBuilder().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).closePath().detach().use { p ->
assertNull(p.isRect)
assertNull(p.isOval)
assertNull(p.isRRect)
......@@ -122,43 +122,42 @@ class PathTests {
@Test
fun checksTest() {
Path().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).closePath().use { p ->
PathBuilder().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).closePath().detach().use { p ->
assertFalse(p.isEmpty)
p.reset()
assertTrue(p.isEmpty)
}
Path().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).closePath().use { p ->
assertFalse(p.isEmpty)
p.rewind()
Path().use { p ->
assertTrue(p.isEmpty)
}
Path().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).use { p ->
PathBuilder().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).detach().use { p ->
assertFalse(p.isLastContourClosed)
p.closePath()
}
PathBuilder().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).closePath().detach().use { p ->
assertTrue(p.isLastContourClosed)
p.moveTo(100f, 100f).lineTo(140f, 140f).lineTo(140f, 100f).lineTo(100f, 140f)
}
PathBuilder().moveTo(100f, 100f).lineTo(140f, 140f).lineTo(140f, 100f).lineTo(100f, 140f).detach().use { p ->
assertFalse(p.isLastContourClosed)
p.closePath()
}
PathBuilder().moveTo(100f, 100f).lineTo(140f, 140f).lineTo(140f, 100f).lineTo(100f, 140f).closePath().detach().use { p ->
assertTrue(p.isLastContourClosed)
}
Path().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).use { p -> assertTrue(p.isFinite) }
Path().lineTo(40f, 40f).lineTo(Float.POSITIVE_INFINITY, 0f).lineTo(0f, 40f).lineTo(0f, 0f).closePath().use { p ->
PathBuilder().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).detach().use { p -> assertTrue(p.isFinite) }
PathBuilder().lineTo(40f, 40f).lineTo(Float.POSITIVE_INFINITY, 0f).lineTo(0f, 40f).lineTo(0f, 0f).closePath().detach().use { p ->
assertEquals(
false,
p.isFinite
)
}
Path().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).use { p ->
PathBuilder().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).detach().use { p ->
assertFalse(p.isVolatile)
p.setVolatile(true)
assertTrue(p.isVolatile)
p.setVolatile(false)
assertFalse(p.isVolatile)
}
Path().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).closePath().use { p ->
PathBuilder().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).closePath().detach().use { p ->
assertNull(p.asLine)
}
Path().moveTo(20f, 20f).lineTo(40f, 40f).use { p ->
PathBuilder().moveTo(20f, 20f).lineTo(40f, 40f).detach().use { p ->
assertContentEquals(
arrayOf(
Point(20f, 20f),
......@@ -170,18 +169,18 @@ class PathTests {
@Test
fun swapTest() {
Path().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).closePath().use { p1 ->
Path().lineTo(0f, 0f).lineTo(20f, 20f).use { p2 ->
PathBuilder().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).closePath().detach().use { p1 ->
PathBuilder().lineTo(0f, 0f).lineTo(20f, 20f).detach().use { p2 ->
p1.swap(p2)
assertEquals(Path().lineTo(0f, 0f).lineTo(20f, 20f), p1)
assertEquals(Path().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).closePath(), p2)
assertEquals(PathBuilder().lineTo(0f, 0f).lineTo(20f, 20f).detach(), p1)
assertEquals(PathBuilder().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).closePath().detach(), p2)
}
}
}
@Test
fun containsTest() {
Path().addRRect(RRect.makeLTRB(10f, 20f, 54f, 120f, 10f, 20f)).use { p ->
PathBuilder().addRRect(RRect.makeLTRB(10f, 20f, 54f, 120f, 10f, 20f)).detach().use { p ->
assertTrue(p.conservativelyContainsRect(Rect.makeLTRB(10f, 40f, 54f, 80f)))
assertTrue(p.conservativelyContainsRect(Rect.makeLTRB(25f, 20f, 39f, 120f)))
assertTrue(p.conservativelyContainsRect(Rect.makeLTRB(15f, 25f, 49f, 115f)))
......@@ -215,20 +214,20 @@ class PathTests {
),
Path.convertConicToQuads(Point(0f, 20f), Point(20f, 0f), Point(40f, 20f), 0.5f, 2)
)
Path().lineTo(40f, 40f).use { p ->
PathBuilder().lineTo(40f, 40f).detach().use { p ->
val g1 = p.generationId
p.lineTo(10f, 40f)
val g2 = p.generationId
val p2 = PathBuilder(p).lineTo(10f, 40f).detach()
val g2 = p2.generationId
assertNotEquals(g1, g2)
p.fillMode = PathFillMode.EVEN_ODD
val g3 = p.generationId
assertEquals(g2, g3)
val p3 = PathBuilder(p2).lineTo(20f, 20f).detach()
val g3 = p3.generationId
assertNotEquals(g2, g3)
}
}
@Test
fun serializeTest() {
Path().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).closePath().use { p ->
PathBuilder().lineTo(40f, 40f).lineTo(40f, 0f).lineTo(0f, 40f).lineTo(0f, 0f).closePath().detach().use { p ->
val p2: Path = Path.makeFromBytes(p.serializeToBytes())
assertEquals(p, p2)
}
......@@ -238,4 +237,4 @@ class PathTests {
fun svgTest() {
Path.makeFromSVGString("M0 0 L10 10 Z").use { }
}
}
\ No newline at end of file
}
......@@ -13,7 +13,7 @@ class PathUtilsTest {
strokeWidth = 10f
mode = PaintMode.STROKE
}
val path = Path().lineTo(40f, 40f)
val path = PathBuilder().lineTo(40f, 40f).detach()
val fillPath = PathUtils.fillPathWithPaint(path, paint)
......@@ -29,7 +29,7 @@ class PathUtilsTest {
strokeWidth = 10f
mode = PaintMode.STROKE
}
val path = Path().arcTo(0f, 0f, 40f, 40f, 0f, 90f, false)
val path = PathBuilder().arcTo(0f, 0f, 40f, 40f, 0f, 90f, false).detach()
val fillPath1 = PathUtils.fillPathWithPaint(path, paint,null, 1f)
val fillPath001 = PathUtils.fillPathWithPaint(path, paint,null, 0.01f)
......
......@@ -3,6 +3,7 @@ package org.jetbrains.skia
import org.jetbrains.skia.tests.assertCloseEnough
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue
class PictureTest {
@Test
......@@ -31,6 +32,8 @@ class PictureTest {
val canvas = recorder.beginRecording(size)
canvas.drawRect(Rect(10.0f, 10.0f, 20.0f, 20.0f), Paint().apply { color = Color.RED })
val pic = recorder.finishRecordingAsPicture()
assertTrue(pic.approximateBytesUsed > 0)
assertTrue(pic.approximateOpCount > 0)
val surface = Surface.makeRasterN32Premul(32, 32)
pic.playback(surface.canvas)
......
package org.jetbrains.skiko.paragraph
import org.jetbrains.skia.FontEdging
import org.jetbrains.skia.FontHinting
import org.jetbrains.skia.impl.use
import org.jetbrains.skia.paragraph.FontRastrSettings
import org.jetbrains.skia.paragraph.ParagraphStyle
import org.jetbrains.skia.paragraph.TextIndent
import kotlin.test.Test
......@@ -36,26 +33,6 @@ class ParagraphStyleTests {
}
}
@Test
fun paragraphStyleFontRastrSettingsTests() {
ParagraphStyle().use { paragraphStyle ->
val poorRasterSettings = FontRastrSettings(
edging = FontEdging.ALIAS,
hinting = FontHinting.NONE,
subpixel = false)
paragraphStyle.fontRastrSettings = poorRasterSettings
assertEquals(poorRasterSettings, paragraphStyle.fontRastrSettings)
val gloriousRasterSettings = FontRastrSettings(
edging = FontEdging.SUBPIXEL_ANTI_ALIAS,
hinting = FontHinting.FULL,
subpixel = true)
paragraphStyle.fontRastrSettings = gloriousRasterSettings
assertEquals(gloriousRasterSettings, paragraphStyle.fontRastrSettings)
}
}
@Test
fun paragraphStyleRoundingHackTests() {
ParagraphStyle().use { paragraphStyle ->
......
......@@ -2,12 +2,7 @@ package org.jetbrains.skiko.paragraph
import org.jetbrains.skia.*
import org.jetbrains.skia.impl.use
import org.jetbrains.skia.jbMonoPath
import org.jetbrains.skia.paragraph.DecorationLineStyle
import org.jetbrains.skia.paragraph.DecorationStyle
import org.jetbrains.skia.paragraph.Shadow
import org.jetbrains.skia.paragraph.TextStyle
import org.jetbrains.skia.paragraph.TextStyleAttribute
import org.jetbrains.skia.paragraph.*
import org.jetbrains.skia.tests.assertContentCloseEnough
import org.jetbrains.skia.tests.makeFromResource
import org.jetbrains.skiko.KotlinBackend
......@@ -152,6 +147,33 @@ class TextStyleTest {
}
}
@Test
fun textStyleFontEdgingTest() {
TextStyle().use { textStyle ->
assertEquals(FontEdging.ANTI_ALIAS, textStyle.fontEdging)
textStyle.fontEdging = FontEdging.SUBPIXEL_ANTI_ALIAS
assertEquals(FontEdging.SUBPIXEL_ANTI_ALIAS, textStyle.fontEdging)
}
}
@Test
fun textStyleSubpixelTest() {
TextStyle().use { textStyle ->
assertTrue(textStyle.subpixel)
textStyle.subpixel = false
assertFalse(textStyle.subpixel)
}
}
@Test
fun textStyleFontHintingTest() {
TextStyle().use { textStyle ->
assertEquals(FontHinting.SLIGHT, textStyle.fontHinting)
textStyle.fontHinting = FontHinting.FULL
assertEquals(FontHinting.FULL, textStyle.fontHinting)
}
}
@Test
fun textStyleMetricsContainsMeaningfulValues() = runTest {
val jbMono = Typeface.makeFromResource(jbMonoPath)
......@@ -171,5 +193,4 @@ class TextStyleTest {
assertTrue(!textStyle.fontMetrics.ascent.isNaN())
}
}
}
package org.jetbrains.skiko.tests
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.await
import kotlinx.coroutines.promise
import org.jetbrains.skiko.wasm.awaitSkiko
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine
import kotlin.js.Promise
private suspend fun <T> Promise<T>.await(): T = suspendCoroutine { cont ->
then({ cont.resume(it) }, { cont.resumeWithException(it) })
}
actual typealias TestReturnType = Any
/**
......@@ -24,4 +17,4 @@ actual fun runTest(block: suspend () -> Unit): TestReturnType = MainScope().prom
actual typealias SkipJsTarget = kotlin.test.Ignore
actual annotation class SkipWasmTarget
\ No newline at end of file
actual annotation class SkipWasmTarget
......@@ -37,7 +37,7 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_CanvasKt__1nDrawPoints
SkCanvas::PointMode skMode = static_cast<SkCanvas::PointMode>(mode);
jsize len = env->GetArrayLength(coords);
jfloat* arr = static_cast<jfloat*>(env->GetPrimitiveArrayCritical(coords, 0));
canvas->drawPoints(skMode, len / 2, reinterpret_cast<SkPoint*>(arr), *paint);
canvas->drawPoints(skMode, {reinterpret_cast<SkPoint*>(arr), len / 2}, *paint);
env->ReleasePrimitiveArrayCritical(coords, arr, 0);
}
......
......@@ -206,7 +206,7 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_FontKt__1nGetUTF32Glyp
SkFont* instance = reinterpret_cast<SkFont*>(static_cast<uintptr_t>(ptr));
std::vector<jshort> glyphs(uniArrLen);
jint* uni = env->GetIntArrayElements(uniArr, nullptr);
instance->unicharsToGlyphs(reinterpret_cast<SkUnichar*>(uni), uniArrLen, reinterpret_cast<SkGlyphID*>(glyphs.data()));
instance->unicharsToGlyphs({reinterpret_cast<SkUnichar*>(uni), uniArrLen}, {reinterpret_cast<SkGlyphID*>(glyphs.data()), uniArrLen});
env->ReleaseIntArrayElements(uniArr, uni, 0);
env->SetShortArrayRegion(resultGlyphs, 0, uniArrLen, glyphs.data());
}
......@@ -253,7 +253,7 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_FontKt__1nGetWidths
SkFont* instance = reinterpret_cast<SkFont*>(static_cast<uintptr_t>(ptr));
std::vector<jfloat> widths(count);
jshort* glyphs = env->GetShortArrayElements(glyphsArr, nullptr);
instance->getWidths(reinterpret_cast<SkGlyphID*>(glyphs), count, widths.data());
instance->getWidths({reinterpret_cast<SkGlyphID*>(glyphs), count}, {widths.data(), count});
env->ReleaseShortArrayElements(glyphsArr, glyphs, 0);
env->SetFloatArrayRegion(res, 0, count, widths.data());
}
......@@ -264,7 +264,7 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_FontKt__1nGetBounds
SkPaint* paint = reinterpret_cast<SkPaint*>(static_cast<uintptr_t>(paintPtr));
std::vector<SkRect> bounds(count);
jshort* glyphs = env->GetShortArrayElements(glyphsArr, nullptr);
instance->getBounds(reinterpret_cast<SkGlyphID*>(glyphs), count, bounds.data(), paint);
instance->getBounds({reinterpret_cast<SkGlyphID*>(glyphs), count}, {bounds.data(), count}, paint);
env->ReleaseShortArrayElements(glyphsArr, glyphs, 0);
for (int i = 0; i < count; ++i) {
......@@ -279,7 +279,7 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_FontKt__1nGetPositions
SkFont* instance = reinterpret_cast<SkFont*>(static_cast<uintptr_t>(ptr));
std::vector<SkPoint> positions(count);
jshort* glyphs = env->GetShortArrayElements(glyphsArr, nullptr);
instance->getPos(reinterpret_cast<SkGlyphID*>(glyphs), count, positions.data(), {dx, dy});
instance->getPos({reinterpret_cast<SkGlyphID*>(glyphs), count}, {positions.data(), count}, {dx, dy});
env->ReleaseShortArrayElements(glyphsArr, glyphs, 0);
std::vector<jfloat> r(count * 2);
......@@ -296,7 +296,7 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_FontKt__1nGetXPosition
SkFont* instance = reinterpret_cast<SkFont*>(static_cast<uintptr_t>(ptr));
std::vector<jfloat> positions(count);
jshort* glyphs = env->GetShortArrayElements(glyphsArr, nullptr);
instance->getXPos(reinterpret_cast<SkGlyphID*>(glyphs), count, positions.data(), dx);
instance->getXPos({reinterpret_cast<SkGlyphID*>(glyphs), count}, {positions.data(), count}, dx);
env->ReleaseShortArrayElements(glyphsArr, glyphs, 0);
env->SetFloatArrayRegion(res, 0, count, positions.data());
}
......@@ -304,9 +304,12 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_FontKt__1nGetXPosition
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_FontKt__1nGetPath
(JNIEnv* env, jclass jclass, jlong ptr, jshort glyph) {
SkFont* instance = reinterpret_cast<SkFont*>(static_cast<uintptr_t>(ptr));
SkPath* path = new SkPath();
instance->getPath(glyph, path);
return reinterpret_cast<jlong>(path);
std::optional<SkPath> pathOpt = instance->getPath(glyph);
if (pathOpt.has_value()) {
SkPath* path = new SkPath(pathOpt.value());
return reinterpret_cast<jlong>(path);
}
return 0;
}
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_FontKt__1nGetPaths
......@@ -319,11 +322,10 @@ extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_FontKt__1nGetPaths
std::vector<jlong>* paths;
} ctx = { new std::vector<jlong>() };
instance->getPaths(reinterpret_cast<SkGlyphID*>(glyphs), count, [](const SkPath* orig, const SkMatrix& mx, void* voidCtx) {
instance->getPaths({reinterpret_cast<SkGlyphID*>(glyphs), count}, [](const SkPath* orig, const SkMatrix& mx, void* voidCtx) {
Ctx* ctx = static_cast<Ctx*>(voidCtx);
if (orig) {
SkPath* path = new SkPath();
orig->transform(mx, path);
SkPath* path = new SkPath(orig->makeTransform(mx));
ctx->paths->push_back(reinterpret_cast<jlong>(path));
}
}, &ctx);
......
......@@ -96,16 +96,6 @@ extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_PathKt__1nIsRRect(
}
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt_Path_1nReset(JNIEnv* env, jclass jclass, jlong ptr) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
instance->reset();
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nRewind(JNIEnv* env, jclass jclass, jlong ptr) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
instance->rewind();
}
extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_PathKt__1nIsEmpty(JNIEnv* env, jclass jclass, jlong ptr) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
return instance->isEmpty();
......@@ -131,6 +121,12 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt_Path_1nSetVolat
instance->setIsVolatile(isVolatile);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt_Path_1nSwap(JNIEnv* env, jclass jclass, jlong ptr, jlong otherPtr) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
SkPath* other = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(otherPtr));
instance->swap(*other);
}
extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_PathKt__1nIsLineDegenerate(JNIEnv* env, jclass jclass, jfloat x0, jfloat y0, jfloat x1, jfloat y1, jboolean exact) {
return SkPath::IsLineDegenerate({x0, y0}, {x1, y1}, exact);
}
......@@ -168,7 +164,7 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nGetPoint(JNI
extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_PathKt__1nGetPoints(JNIEnv* env, jclass jclass, jlong ptr, jfloatArray pointsArray, jint max) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
jfloat* points = pointsArray == nullptr ? nullptr : env->GetFloatArrayElements(pointsArray, 0);
int count = instance->getPoints(reinterpret_cast<SkPoint*>(points), max);
int count = instance->getPoints({reinterpret_cast<SkPoint*>(points), max});
if (pointsArray != nullptr) {
env->ReleaseFloatArrayElements(pointsArray, points, 0);
}
......@@ -183,7 +179,7 @@ extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_PathKt__1nCountVerbs(J
extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_PathKt__1nGetVerbs(JNIEnv* env, jclass jclass, jlong ptr, jbyteArray verbsArray, jint max) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
jbyte* verbs = verbsArray == nullptr ? nullptr : env->GetByteArrayElements(verbsArray, 0);
int count = instance->getVerbs(reinterpret_cast<uint8_t *>(verbs), max);
int count = instance->getVerbs({reinterpret_cast<uint8_t *>(verbs), max});
if (verbsArray != nullptr)
env->ReleaseByteArrayElements(verbsArray, verbs, 0);
return count;
......@@ -191,13 +187,7 @@ extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_PathKt__1nGetVerbs(JNI
extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_PathKt__1nApproximateBytesUsed(JNIEnv* env, jclass jclass, jlong ptr) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
return (jint) instance->approximateBytesUsed();
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt_Path_1nSwap(JNIEnv* env, jclass jclass, jlong ptr, jlong otherPtr) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
SkPath* other = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(otherPtr));
instance->swap(*other);
return static_cast<jint>(instance->approximateBytesUsed());
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nGetBounds(JNIEnv* env, jclass jclass, jlong ptr, jfloatArray resultArray) {
......@@ -205,11 +195,6 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nGetBounds(JN
skija::Rect::copyToInterop(env, instance->getBounds(), resultArray);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nUpdateBoundsCache(JNIEnv* env, jclass jclass, jlong ptr) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
instance->updateBoundsCache();
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nComputeTightBounds(JNIEnv* env, jclass jclass, jlong ptr, jfloatArray resultArray) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
skija::Rect::copyToInterop(env, instance->computeTightBounds(), resultArray);
......@@ -221,86 +206,6 @@ extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_PathKt__1nConserva
return instance->conservativelyContainsRect(rect);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nIncReserve(JNIEnv* env, jclass jclass, jlong ptr, int extraPtCount) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
instance->incReserve(extraPtCount);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nMoveTo(JNIEnv* env, jclass jclass, jlong ptr, jfloat x, jfloat y) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
instance->moveTo(x, y);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nRMoveTo(JNIEnv* env, jclass jclass, jlong ptr, jfloat dx, jfloat dy) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
instance->rMoveTo(dx, dy);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nLineTo(JNIEnv* env, jclass jclass, jlong ptr, jfloat x, jfloat y) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
instance->lineTo(x, y);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nRLineTo(JNIEnv* env, jclass jclass, jlong ptr, jfloat dx, jfloat dy) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
instance->rLineTo(dx, dy);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nQuadTo(JNIEnv* env, jclass jclass, jlong ptr, jfloat x1, jfloat y1, jfloat x2, jfloat y2) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
instance->quadTo(x1, y1, x2, y2);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nRQuadTo(JNIEnv* env, jclass jclass, jlong ptr, jfloat dx1, jfloat dy1, jfloat dx2, jfloat dy2) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
instance->rQuadTo(dx1, dy1, dx2, dy2);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nConicTo(JNIEnv* env, jclass jclass, jlong ptr, jfloat x1, jfloat y1, jfloat x2, jfloat y2, jfloat w) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
instance->conicTo(x1, y1, x2, y2, w);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nRConicTo(JNIEnv* env, jclass jclass, jlong ptr, jfloat dx1, jfloat dy1, jfloat dx2, jfloat dy2, jfloat w) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
instance->rConicTo(dx1, dy1, dx2, dy2, w);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nCubicTo(JNIEnv* env, jclass jclass, jlong ptr, jfloat x1, jfloat y1, jfloat x2, jfloat y2, jfloat x3, jfloat y3) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
instance->cubicTo(x1, y1, x2, y2, x3, y3);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nRCubicTo(JNIEnv* env, jclass jclass, jlong ptr, jfloat dx1, jfloat dy1, jfloat dx2, jfloat dy2, jfloat dx3, jfloat dy3) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
instance->rCubicTo(dx1, dy1, dx2, dy2, dx3, dy3);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nArcTo(JNIEnv* env, jclass jclass, jlong ptr, jfloat left, jfloat top, jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle, jboolean forceMoveTo) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
instance->arcTo({left, top, right, bottom}, startAngle, sweepAngle, forceMoveTo);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nTangentArcTo(JNIEnv* env, jclass jclass, jlong ptr, jfloat x1, jfloat y1, jfloat x2, jfloat y2, jfloat radius) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
instance->arcTo(x1, y1, x2, y2, radius);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nEllipticalArcTo(JNIEnv* env, jclass jclass, jlong ptr, jfloat rx, jfloat ry, jfloat xAxisRotate, jint size, jint direction, jfloat x, float y) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
instance->arcTo(rx, ry, xAxisRotate, static_cast<SkPath::ArcSize>(size), static_cast<SkPathDirection>(direction), x, y);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nREllipticalArcTo(JNIEnv* env, jclass jclass, jlong ptr, jfloat rx, jfloat ry, jfloat xAxisRotate, jint size, jint direction, jfloat dx, float dy) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
instance->rArcTo(rx, ry, xAxisRotate, static_cast<SkPath::ArcSize>(size), static_cast<SkPathDirection>(direction), dx, dy);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nClosePath(JNIEnv* env, jclass jclass, jlong ptr) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
instance->close();
}
extern "C" JNIEXPORT jint Java_org_jetbrains_skia_PathKt__1nConvertConicToQuads
(JNIEnv* env, jclass jclass, jfloat x0, jfloat y0, jfloat x1, jfloat y1, jfloat x2, jfloat y2, jfloat w, jint pow2, jfloatArray resultArray) {
jfloat* points = env->GetFloatArrayElements(resultArray, 0);
......@@ -321,96 +226,19 @@ extern "C" JNIEXPORT jboolean Java_org_jetbrains_skia_PathKt__1nIsRect
}
}
extern "C" JNIEXPORT void Java_org_jetbrains_skia_PathKt__1nAddRect
(JNIEnv* env, jclass jclass, jlong ptr, jfloat l, jfloat t, jfloat r, jfloat b, jint dirInt, jint start) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
SkPathDirection dir = static_cast<SkPathDirection>(dirInt);
instance->addRect({l, t, r, b}, dir, start);
}
extern "C" JNIEXPORT void Java_org_jetbrains_skia_PathKt__1nAddOval
(JNIEnv* env, jclass jclass, jlong ptr, jfloat l, jfloat t, jfloat r, jfloat b, jint dirInt, jint start) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
SkPathDirection dir = static_cast<SkPathDirection>(dirInt);
instance->addOval({l, t, r, b}, dir, start);
}
extern "C" JNIEXPORT void Java_org_jetbrains_skia_PathKt__1nAddCircle
(JNIEnv* env, jclass jclass, jlong ptr, jfloat x, jfloat y, jfloat r, jint dirInt) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
SkPathDirection dir = static_cast<SkPathDirection>(dirInt);
instance->addCircle(x, y, r, dir);
}
extern "C" JNIEXPORT void Java_org_jetbrains_skia_PathKt__1nAddArc
(JNIEnv* env, jclass jclass, jlong ptr, jfloat l, jfloat t, jfloat r, jfloat b, jfloat startAngle, jfloat sweepAngle) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
instance->addArc({l, t, r, b}, startAngle, sweepAngle);
}
extern "C" JNIEXPORT void Java_org_jetbrains_skia_PathKt__1nAddRRect
(JNIEnv* env, jclass jclass, jlong ptr, jfloat l, jfloat t, jfloat r, jfloat b, jfloatArray radii, jint radiiSize, jint dirInt, jint start) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
SkRRect rrect = skija::RRect::toSkRRect(env, l, t, r, b, radii);
SkPathDirection dir = static_cast<SkPathDirection>(dirInt);
instance->addRRect(rrect, dir, start);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nAddPoly
(JNIEnv* env, jclass jclass, jlong ptr, jfloatArray coords, jint _count, jboolean close) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
jsize len = env->GetArrayLength(coords);
jfloat* arr = env->GetFloatArrayElements(coords, 0);
instance->addPoly(reinterpret_cast<SkPoint*>(arr), len / 2, close);
env->ReleaseFloatArrayElements(coords, arr, 0);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nAddPath
(JNIEnv* env, jclass jclass, jlong ptr, jlong srcPtr, jboolean extend) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
SkPath* src = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(srcPtr));
SkPath::AddPathMode mode = extend ? SkPath::AddPathMode::kExtend_AddPathMode : SkPath::AddPathMode::kAppend_AddPathMode;
instance->addPath(*src, mode);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nAddPathOffset
(JNIEnv* env, jclass jclass, jlong ptr, jlong srcPtr, jfloat dx, jfloat dy, jboolean extend) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
SkPath* src = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(srcPtr));
SkPath::AddPathMode mode = extend ? SkPath::AddPathMode::kExtend_AddPathMode : SkPath::AddPathMode::kAppend_AddPathMode;
instance->addPath(*src, dx, dy, mode);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nAddPathTransform
(JNIEnv* env, jclass jclass, jlong ptr, jlong srcPtr, jfloatArray matrixArr, jboolean extend) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
SkPath* src = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(srcPtr));
std::unique_ptr<SkMatrix> matrix = skMatrix(env, matrixArr);
SkPath::AddPathMode mode = extend ? SkPath::AddPathMode::kExtend_AddPathMode : SkPath::AddPathMode::kAppend_AddPathMode;
instance->addPath(*src, *matrix, mode);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nReverseAddPath
(JNIEnv* env, jclass jclass, jlong ptr, jlong srcPtr) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
SkPath* src = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(srcPtr));
instance->reverseAddPath(*src);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nOffset
(JNIEnv* env, jclass jclass, jlong ptr, jfloat dx, jfloat dy, jlong dstPtr) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
SkPath* dst = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(dstPtr));
instance->offset(dx, dy, dst);
*dst = instance->makeOffset(dx, dy);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nTransform
(JNIEnv* env, jclass jclass, jlong ptr, jfloatArray matrixArr, jlong dstPtr, jboolean pcBool) {
(JNIEnv* env, jclass jclass, jlong ptr, jfloatArray matrixArr, jlong dstPtr) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
SkPath* dst = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(dstPtr));
std::unique_ptr<SkMatrix> matrix = skMatrix(env, matrixArr);
SkApplyPerspectiveClip pc = pcBool ? SkApplyPerspectiveClip::kYes : SkApplyPerspectiveClip::kNo;
instance->transform(*matrix, dst, pc);
*dst = instance->makeTransform(*matrix);
}
extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_PathKt__1nGetLastPt
......@@ -425,12 +253,6 @@ extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_PathKt__1nGetLastP
}
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathKt__1nSetLastPt
(JNIEnv* env, jclass jclass, jlong ptr, jfloat x, jfloat y) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
instance->setLastPt(x, y);
}
extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_PathKt__1nGetSegmentMasks
(JNIEnv* env, jclass jclass, jlong ptr) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
......@@ -485,15 +307,14 @@ extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_PathKt__1nMakeCombini
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_PathKt__1nMakeFromBytes
(JNIEnv* env, jclass jclass, jbyteArray bytesArray, jint _size) {
SkPath* instance = new SkPath();
int count = env->GetArrayLength(bytesArray);
jbyte* bytes = env->GetByteArrayElements(bytesArray, 0);
if (instance->readFromMemory(bytes, count)) {
env->ReleaseByteArrayElements(bytesArray, bytes, 0);
std::optional<SkPath> pathOpt = SkPath::ReadFromMemory(bytes, count);
env->ReleaseByteArrayElements(bytesArray, bytes, 0);
if (pathOpt.has_value()) {
SkPath* instance = new SkPath(pathOpt.value());
return reinterpret_cast<jlong>(instance);
} else {
env->ReleaseByteArrayElements(bytesArray, bytes, 0);
delete instance;
return 0;
}
}
......@@ -508,4 +329,124 @@ extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_PathKt__1nIsValid
(JNIEnv* env, jclass jclass, jlong ptr) {
SkPath* instance = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(ptr));
return instance->isValid();
}
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_PathKt__1nMakeFromRaw
(JNIEnv* env, jclass jclass, jfloatArray ptsArray, jint ptsCount,
jbyteArray verbsArray, jint verbsCount,
jfloatArray conicWeightsArray, jint conicWeightsCount,
jint fillType, jboolean isVolatile) {
jfloat* pts = env->GetFloatArrayElements(ptsArray, 0);
jbyte* verbs = env->GetByteArrayElements(verbsArray, 0);
jfloat* conicWeights = conicWeightsCount > 0 ? env->GetFloatArrayElements(conicWeightsArray, 0) : nullptr;
SkPath path = SkPath::Raw(
SkSpan<const SkPoint>(reinterpret_cast<SkPoint*>(pts), ptsCount),
SkSpan<const SkPathVerb>(reinterpret_cast<SkPathVerb*>(verbs), verbsCount),
SkSpan<const SkScalar>(conicWeights, conicWeightsCount),
static_cast<SkPathFillType>(fillType),
isVolatile
);
env->ReleaseFloatArrayElements(ptsArray, pts, 0);
env->ReleaseByteArrayElements(verbsArray, verbs, 0);
if (conicWeights != nullptr) {
env->ReleaseFloatArrayElements(conicWeightsArray, conicWeights, 0);
}
SkPath* instance = new SkPath(path);
return reinterpret_cast<jlong>(instance);
}
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_PathKt__1nMakeFromRect
(JNIEnv* env, jclass jclass, jfloat left, jfloat top, jfloat right, jfloat bottom,
jint fillType, jint direction, jint startIndex) {
SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
SkPath path = SkPath::Rect(
rect,
static_cast<SkPathFillType>(fillType),
static_cast<SkPathDirection>(direction),
startIndex
);
SkPath* instance = new SkPath(path);
return reinterpret_cast<jlong>(instance);
}
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_PathKt__1nMakeFromOval
(JNIEnv* env, jclass jclass, jfloat left, jfloat top, jfloat right, jfloat bottom,
jint direction, jint startIndex) {
SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
SkPath path = SkPath::Oval(
rect,
static_cast<SkPathDirection>(direction),
startIndex
);
SkPath* instance = new SkPath(path);
return reinterpret_cast<jlong>(instance);
}
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_PathKt__1nMakeFromCircle
(JNIEnv* env, jclass jclass, jfloat centerX, jfloat centerY, jfloat radius, jint direction) {
SkPath path = SkPath::Circle(
centerX,
centerY,
radius,
static_cast<SkPathDirection>(direction)
);
SkPath* instance = new SkPath(path);
return reinterpret_cast<jlong>(instance);
}
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_PathKt__1nMakeFromRRect
(JNIEnv* env, jclass jclass, jfloatArray radiiArray,
jfloat left, jfloat top, jfloat right, jfloat bottom,
jint direction, jint startIndex) {
SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
jfloat* radii = env->GetFloatArrayElements(radiiArray, 0);
SkRRect rrect;
rrect.setRectRadii(rect, reinterpret_cast<SkVector*>(radii));
SkPath path = SkPath::RRect(
rrect,
static_cast<SkPathDirection>(direction),
startIndex
);
env->ReleaseFloatArrayElements(radiiArray, radii, 0);
SkPath* instance = new SkPath(path);
return reinterpret_cast<jlong>(instance);
}
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_PathKt__1nMakeFromRRectXY
(JNIEnv* env, jclass jclass, jfloat left, jfloat top, jfloat right, jfloat bottom,
jfloat rx, jfloat ry, jint direction) {
SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
SkPath path = SkPath::RRect(
rect,
rx,
ry,
static_cast<SkPathDirection>(direction)
);
SkPath* instance = new SkPath(path);
return reinterpret_cast<jlong>(instance);
}
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_PathKt__1nMakeFromPolygon
(JNIEnv* env, jclass jclass, jfloatArray ptsArray, jint ptsCount,
jboolean isClosed, jint fillType, jboolean isVolatile) {
jfloat* pts = env->GetFloatArrayElements(ptsArray, 0);
SkPath path = SkPath::Polygon(
SkSpan<const SkPoint>(reinterpret_cast<SkPoint*>(pts), ptsCount),
isClosed,
static_cast<SkPathFillType>(fillType),
isVolatile
);
env->ReleaseFloatArrayElements(ptsArray, pts, 0);
SkPath* instance = new SkPath(path);
return reinterpret_cast<jlong>(instance);
}
\ No newline at end of file
#include <jni.h>
#include "SkPathBuilder.h"
#include "SkPath.h"
#include "SkRRect.h"
#include "SkMatrix.h"
#include "interop.hh"
static void deletePathBuilder(SkPathBuilder* builder) {
delete builder;
}
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nGetFinalizer
(JNIEnv* env, jclass jclass) {
return static_cast<jlong>(reinterpret_cast<uintptr_t>(&deletePathBuilder));
}
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nMake
(JNIEnv* env, jclass jclass) {
SkPathBuilder* builder = new SkPathBuilder();
return reinterpret_cast<jlong>(builder);
}
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nMakeWithFillType
(JNIEnv* env, jclass jclass, jint fillType) {
SkPathBuilder* builder = new SkPathBuilder(static_cast<SkPathFillType>(fillType));
return reinterpret_cast<jlong>(builder);
}
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nMakeFromPath
(JNIEnv* env, jclass jclass, jlong pathPtr) {
SkPath* path = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(pathPtr));
SkPathBuilder* builder = new SkPathBuilder(*path);
return reinterpret_cast<jlong>(builder);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nReset
(JNIEnv* env, jclass jclass, jlong ptr) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
builder->reset();
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nSetFillType
(JNIEnv* env, jclass jclass, jlong ptr, jint fillType) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
builder->setFillType(static_cast<SkPathFillType>(fillType));
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nIncReserve
(JNIEnv* env, jclass jclass, jlong ptr, jint extraPtCount) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
builder->incReserve(extraPtCount);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nMoveTo
(JNIEnv* env, jclass jclass, jlong ptr, jfloat x, jfloat y) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
builder->moveTo(x, y);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nRMoveTo
(JNIEnv* env, jclass jclass, jlong ptr, jfloat dx, jfloat dy) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
builder->rMoveTo(dx, dy);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nLineTo
(JNIEnv* env, jclass jclass, jlong ptr, jfloat x, jfloat y) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
builder->lineTo(x, y);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nRLineTo
(JNIEnv* env, jclass jclass, jlong ptr, jfloat dx, jfloat dy) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
builder->rLineTo(dx, dy);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nQuadTo
(JNIEnv* env, jclass jclass, jlong ptr, jfloat x1, jfloat y1, jfloat x2, jfloat y2) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
builder->quadTo(x1, y1, x2, y2);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nRQuadTo
(JNIEnv* env, jclass jclass, jlong ptr, jfloat dx1, jfloat dy1, jfloat dx2, jfloat dy2) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
builder->rQuadTo(dx1, dy1, dx2, dy2);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nConicTo
(JNIEnv* env, jclass jclass, jlong ptr, jfloat x1, jfloat y1, jfloat x2, jfloat y2, jfloat w) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
builder->conicTo(x1, y1, x2, y2, w);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nRConicTo
(JNIEnv* env, jclass jclass, jlong ptr, jfloat dx1, jfloat dy1, jfloat dx2, jfloat dy2, jfloat w) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
builder->rConicTo(dx1, dy1, dx2, dy2, w);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nCubicTo
(JNIEnv* env, jclass jclass, jlong ptr, jfloat x1, jfloat y1, jfloat x2, jfloat y2, jfloat x3, jfloat y3) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
builder->cubicTo(x1, y1, x2, y2, x3, y3);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nRCubicTo
(JNIEnv* env, jclass jclass, jlong ptr, jfloat dx1, jfloat dy1, jfloat dx2, jfloat dy2, jfloat dx3, jfloat dy3) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
builder->rCubicTo(dx1, dy1, dx2, dy2, dx3, dy3);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nArcTo
(JNIEnv* env, jclass jclass, jlong ptr, jfloat left, jfloat top, jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle, jboolean forceMoveTo) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
builder->arcTo({left, top, right, bottom}, startAngle, sweepAngle, forceMoveTo);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nTangentArcTo
(JNIEnv* env, jclass jclass, jlong ptr, jfloat x1, jfloat y1, jfloat x2, jfloat y2, jfloat radius) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
builder->arcTo({x1, y1}, {x2, y2}, radius);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nEllipticalArcTo
(JNIEnv* env, jclass jclass, jlong ptr, jfloat rx, jfloat ry, jfloat xAxisRotate, jint size, jint direction, jfloat x, float y) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
builder->arcTo({rx, ry}, xAxisRotate, static_cast<SkPathBuilder::ArcSize>(size), static_cast<SkPathDirection>(direction), {x, y});
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nREllipticalArcTo
(JNIEnv* env, jclass jclass, jlong ptr, jfloat rx, jfloat ry, jfloat xAxisRotate, jint size, jint direction, jfloat dx, float dy) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
builder->rArcTo({rx, ry}, xAxisRotate, static_cast<SkPathBuilder::ArcSize>(size), static_cast<SkPathDirection>(direction), {dx, dy});
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nClosePath
(JNIEnv* env, jclass jclass, jlong ptr) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
builder->close();
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nAddRect
(JNIEnv* env, jclass jclass, jlong ptr, jfloat l, jfloat t, jfloat r, jfloat b, jint dirInt, jint start) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
SkPathDirection dir = static_cast<SkPathDirection>(dirInt);
builder->addRect({l, t, r, b}, dir, start);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nAddOval
(JNIEnv* env, jclass jclass, jlong ptr, jfloat l, jfloat t, jfloat r, jfloat b, jint dirInt, jint start) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
SkPathDirection dir = static_cast<SkPathDirection>(dirInt);
builder->addOval({l, t, r, b}, dir, start);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nAddCircle
(JNIEnv* env, jclass jclass, jlong ptr, jfloat x, jfloat y, jfloat r, jint dirInt) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
SkPathDirection dir = static_cast<SkPathDirection>(dirInt);
builder->addCircle(x, y, r, dir);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nAddArc
(JNIEnv* env, jclass jclass, jlong ptr, jfloat l, jfloat t, jfloat r, jfloat b, jfloat startAngle, jfloat sweepAngle) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
builder->addArc({l, t, r, b}, startAngle, sweepAngle);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nAddRRect
(JNIEnv* env, jclass jclass, jlong ptr, jfloat l, jfloat t, jfloat r, jfloat b, jfloatArray radii, jint radiiSize, jint dirInt, jint start) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
SkRRect rrect = skija::RRect::toSkRRect(env, l, t, r, b, radii);
SkPathDirection dir = static_cast<SkPathDirection>(dirInt);
builder->addRRect(rrect, dir, start);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nAddPoly
(JNIEnv* env, jclass jclass, jlong ptr, jfloatArray coords, jint _count, jboolean close) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
jsize len = env->GetArrayLength(coords);
jfloat* arr = env->GetFloatArrayElements(coords, 0);
builder->addPolygon({reinterpret_cast<SkPoint*>(arr), len / 2}, close);
env->ReleaseFloatArrayElements(coords, arr, 0);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nAddPath
(JNIEnv* env, jclass jclass, jlong ptr, jlong srcPtr, jint mode) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
SkPath* src = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(srcPtr));
builder->addPath(*src, static_cast<SkPath::AddPathMode>(mode));
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nAddPathOffset
(JNIEnv* env, jclass jclass, jlong ptr, jlong srcPtr, jfloat dx, jfloat dy, jint mode) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
SkPath* src = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(srcPtr));
builder->addPath(*src, dx, dy, static_cast<SkPath::AddPathMode>(mode));
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nAddPathTransform
(JNIEnv* env, jclass jclass, jlong ptr, jlong srcPtr, jfloatArray matrixArr, jint mode) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
SkPath* src = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(srcPtr));
std::unique_ptr<SkMatrix> matrix = skMatrix(env, matrixArr);
builder->addPath(*src, *matrix, static_cast<SkPath::AddPathMode>(mode));
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nSetLastPt
(JNIEnv* env, jclass jclass, jlong ptr, jfloat x, jfloat y) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
builder->setLastPt(x, y);
}
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nDetach
(JNIEnv* env, jclass jclass, jlong ptr) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
SkPath* path = new SkPath(builder->detach());
return reinterpret_cast<jlong>(path);
}
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nSnapshot
(JNIEnv* env, jclass jclass, jlong ptr) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
SkPath* path = new SkPath(builder->snapshot());
return reinterpret_cast<jlong>(path);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nOffset
(JNIEnv* env, jclass jclass, jlong ptr, jfloat dx, jfloat dy) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
builder->offset(dx, dy);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_PathBuilderKt_PathBuilder_1nTransform
(JNIEnv* env, jclass jclass, jlong ptr, jfloatArray matrixArr) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(ptr));
std::unique_ptr<SkMatrix> matrix = skMatrix(env, matrixArr);
builder->transform(*matrix);
}
......@@ -57,7 +57,7 @@ extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_PathEffectKt__1nMakeD
(JNIEnv* env, jclass jclass, jfloatArray intervalsArray, jint _count, jfloat phase) {
jsize len = env->GetArrayLength(intervalsArray);
jfloat* intervals = env->GetFloatArrayElements(intervalsArray, 0);
SkPathEffect* ptr = SkDashPathEffect::Make(intervals, len, phase).release();
SkPathEffect* ptr = SkDashPathEffect::Make({intervals, len}, phase).release();
env->ReleaseFloatArrayElements(intervalsArray, intervals, 0);
return reinterpret_cast<jlong>(ptr);
}
......
......@@ -71,10 +71,10 @@ extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_PictureKt__1nGetApprox
return instance->approximateOpCount();
}
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_PictureKt__1nGetApproximateBytesUsed
extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_PictureKt__1nGetApproximateBytesUsed
(JNIEnv* env, jclass jclass, jlong ptr) {
SkPicture* instance = reinterpret_cast<SkPicture*>(static_cast<uintptr_t>(ptr));
return instance->approximateBytesUsed();
return static_cast<jint>(instance->approximateBytesUsed());
}
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_PictureKt__1nMakeShader
......
#include <iostream>
#include <jni.h>
#include "SkRegion.h"
#include "SkPathBuilder.h"
#include "interop.hh"
static void deleteRegion(SkRegion* region) {
......@@ -50,10 +51,15 @@ extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_RegionKt_Region_1nComp
return instance->computeRegionComplexity();
}
extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_RegionKt_Region_1nGetBoundaryPath(JNIEnv* env, jclass jclass, jlong ptr, jlong pathPtr) {
extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_RegionKt_Region_1nAddBoundaryPath(JNIEnv* env, jclass jclass, jlong ptr, jlong pathBuilderPtr) {
SkRegion* instance = reinterpret_cast<SkRegion*>(static_cast<uintptr_t>(ptr));
SkPath* path = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(pathPtr));
return instance->getBoundaryPath(path);
SkPathBuilder* pathBuilder = reinterpret_cast<SkPathBuilder*>(static_cast<uintptr_t>(pathBuilderPtr));
return instance->addBoundaryPath(pathBuilder);
}
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_RegionKt_Region_1nGetBoundaryPath(JNIEnv* env, jclass jclass, jlong ptr) {
SkRegion* instance = reinterpret_cast<SkRegion*>(static_cast<uintptr_t>(ptr));
return reinterpret_cast<jlong>(new SkPath(instance->getBoundaryPath()));
}
extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_RegionKt_Region_1nSetEmpty(JNIEnv* env, jclass jclass, jlong ptr) {
......@@ -130,7 +136,7 @@ extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_RegionKt_Region_1n
extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_RegionKt_Region_1nQuickRejectRegion(JNIEnv* env, jclass jclass, jlong ptr, jlong regionPtr) {
SkRegion* instance = reinterpret_cast<SkRegion*>(static_cast<uintptr_t>(ptr));
SkRegion* region = reinterpret_cast<SkRegion*>(static_cast<uintptr_t>(regionPtr));
return instance->contains(*region);
return instance->quickReject(*region);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_RegionKt_Region_1nTranslate(JNIEnv* env, jclass jclass, jlong ptr, jint dx, jint dy) {
......
......@@ -57,8 +57,7 @@ extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_TextBlobKt__1nMakeFro
jshort* glyphs = env->GetShortArrayElements(glyphsArr, nullptr);
jfloat* xpos = env->GetFloatArrayElements(xposArr, nullptr);
SkFont* font = reinterpret_cast<SkFont*>(static_cast<uintptr_t>(fontPtr));
SkTextBlob* instance = SkTextBlob::MakeFromPosTextH(glyphs, glyphsLen * sizeof(jshort), xpos, ypos, *font, SkTextEncoding::kGlyphID).release();
SkTextBlob* instance = SkTextBlob::MakeFromPosTextH(glyphs, glyphsLen * sizeof(jshort), {xpos, glyphsLen}, ypos, *font, SkTextEncoding::kGlyphID).release();
env->ReleaseShortArrayElements(glyphsArr, glyphs, 0);
env->ReleaseFloatArrayElements(xposArr, xpos, 0);
......@@ -75,7 +74,7 @@ extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_TextBlobKt__1nMakeFro
SkTextBlob* instance = SkTextBlob::MakeFromPosText(
glyphs,
glyphsLen * sizeof(jshort),
reinterpret_cast<SkPoint*>(pos),
{reinterpret_cast<SkPoint*>(pos), glyphsLen},
*font,
SkTextEncoding::kGlyphID
).release();
......@@ -91,8 +90,7 @@ extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_TextBlobKt__1nMakeFro
jshort* glyphs = env->GetShortArrayElements(glyphsArr, nullptr);
jfloat* xform = env->GetFloatArrayElements(xformArr, nullptr);
SkFont* font = reinterpret_cast<SkFont*>(static_cast<uintptr_t>(fontPtr));
SkTextBlob* instance = SkTextBlob::MakeFromRSXform(glyphs, glyphsLen * sizeof(jshort), reinterpret_cast<SkRSXform*>(xform), *font, SkTextEncoding::kGlyphID).release();
SkTextBlob* instance = SkTextBlob::MakeFromRSXform(glyphs, glyphsLen * sizeof(jshort), {reinterpret_cast<SkRSXform*>(xform), glyphsLen}, *font, SkTextEncoding::kGlyphID).release();
env->ReleaseShortArrayElements(glyphsArr, glyphs, 0);
env->ReleaseFloatArrayElements(xformArr, xform, 0);
......
......@@ -19,7 +19,7 @@ extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_TypefaceKt__1nIsFi
extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_TypefaceKt__1nGetVariationsCount
(JNIEnv* env, jclass jclass, jlong ptr, jintArray res) {
SkTypeface* instance = reinterpret_cast<SkTypeface*>(static_cast<uintptr_t>(ptr));
return instance->getVariationDesignPosition(nullptr, 0);
return instance->getVariationDesignPosition({});
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_TypefaceKt__1nGetVariations
......@@ -27,7 +27,7 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_TypefaceKt__1nGetVaria
SkTypeface* instance = reinterpret_cast<SkTypeface*>(static_cast<uintptr_t>(ptr));
if (count > 0) {
std::vector<SkFontArguments::VariationPosition::Coordinate> coords(count);
instance->getVariationDesignPosition(coords.data(), count);
instance->getVariationDesignPosition({coords.data(), count});
for (int i=0; i < count; ++i) {
jint r[2] = {static_cast<jint>(coords[i].axis), rawBits(coords[i].value)};
env->SetIntArrayRegion(res, 2 * i, 2, r);
......@@ -38,7 +38,7 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_TypefaceKt__1nGetVaria
extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_TypefaceKt__1nGetVariationAxesCount
(JNIEnv* env, jclass jclass, jlong ptr, jfloat* axisData) {
SkTypeface* instance = reinterpret_cast<SkTypeface*>(static_cast<uintptr_t>(ptr));
return instance->getVariationDesignParameters(nullptr, 0);
return instance->getVariationDesignParameters({});
}
......@@ -47,7 +47,7 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_TypefaceKt__1nGetVaria
SkTypeface* instance = reinterpret_cast<SkTypeface*>(static_cast<uintptr_t>(ptr));
if (count > 0) {
std::vector<SkFontParameters::Variation::Axis> params(count);
instance->getVariationDesignParameters(params.data(), count);
instance->getVariationDesignParameters({params.data(), count});
for (int i = 0; i < count; ++i) {
jint p[5] = { static_cast<jint>(params[i].tag), rawBits(params[i].min), rawBits(params[i].def), rawBits(params[i].max), params[i].isHidden()};
env->SetIntArrayRegion(axisData, 5 * i, 5, p);
......@@ -92,7 +92,7 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_TypefaceKt_Typeface_1n
SkTypeface* instance = reinterpret_cast<SkTypeface*>(static_cast<uintptr_t>(ptr));
std::vector<short> glyphs(count);
jint* uni = env->GetIntArrayElements(uniArr, nullptr);
instance->unicharsToGlyphs(reinterpret_cast<SkUnichar*>(uni), count, reinterpret_cast<SkGlyphID*>(glyphs.data()));
instance->unicharsToGlyphs({reinterpret_cast<SkUnichar*>(uni), count}, {reinterpret_cast<SkGlyphID*>(glyphs.data()), count});
env->ReleaseIntArrayElements(uniArr, uni, 0);
env->SetShortArrayRegion(res, 0, count, glyphs.data());
}
......@@ -124,9 +124,9 @@ extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_TypefaceKt__1nGetTable
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_TypefaceKt__1nGetTableTags
(JNIEnv* env, jclass jclass, jlong ptr, jintArray res, jint count) {
SkTypeface* instance = reinterpret_cast<SkTypeface*>(static_cast<uintptr_t>(ptr));
std::vector<jint> tags(count);
instance->getTableTags(reinterpret_cast<SkFontTableTag*>(tags.data()));
env->SetIntArrayRegion(res, 0, count, tags.data());
std::vector<SkFontTableTag> tags(count);
int actualCount = instance->readTableTags({tags.data(), count});
env->SetIntArrayRegion(res, 0, actualCount, reinterpret_cast<jint*>(tags.data()));
}
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_TypefaceKt__1nGetTableSize
......@@ -155,8 +155,8 @@ extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_TypefaceKt__1nGetK
std::vector<jint> adjustments(count);
jshort* glyphs = env->GetShortArrayElements(glyphsArr, nullptr);
bool hasAdjustments = instance->getKerningPairAdjustments(
reinterpret_cast<SkGlyphID*>(glyphs), count,
reinterpret_cast<int32_t*>(adjustments.data())
{reinterpret_cast<SkGlyphID*>(glyphs), count},
{reinterpret_cast<int32_t*>(adjustments.data()), count}
);
env->ReleaseShortArrayElements(glyphsArr, glyphs, 0);
if (hasAdjustments) {
......
......@@ -75,7 +75,7 @@ extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_paragraph_FontCollect
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_paragraph_FontCollectionKt__1nDefaultFallbackChar
(JNIEnv* env, jclass jclass, jlong ptr, jint unicode, jint fontStyle, jstring locale) {
FontCollection* instance = reinterpret_cast<FontCollection*>(static_cast<uintptr_t>(ptr));
return reinterpret_cast<jlong>(instance->defaultFallback(unicode, skija::FontStyle::fromJava(fontStyle), skString(env, locale)).release());
return reinterpret_cast<jlong>(instance->defaultFallback(unicode, skija::FontStyle::fromJava(fontStyle), skString(env, locale), std::nullopt).release());
}
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_paragraph_FontCollectionKt__1nDefaultFallback
......
......@@ -157,37 +157,6 @@ extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_paragraph_Paragrap
return instance->hintingIsOn();
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_paragraph_ParagraphStyleKt__1nSetFontRastrSettings
(JNIEnv* env, jclass jclass, jlong ptr, jint edging, jint hinting, jboolean subpixel) {
ParagraphStyle* instance = reinterpret_cast<ParagraphStyle*>(static_cast<uintptr_t>(ptr));
FontRastrSettings fontRastrSettings;
fontRastrSettings.fEdging = static_cast<SkFont::Edging>(edging);
fontRastrSettings.fHinting = static_cast<SkFontHinting>(hinting);
fontRastrSettings.fSubpixel = subpixel;
instance->setFontRastrSettings(fontRastrSettings);
}
extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_paragraph_ParagraphStyleKt__1nGetEdging
(JNIEnv* env, jclass jclass, jlong ptr) {
ParagraphStyle* instance = reinterpret_cast<ParagraphStyle*>(static_cast<uintptr_t>(ptr));
FontRastrSettings fontRastrSettings = instance->getFontRastrSettings();
return static_cast<jint>(fontRastrSettings.fEdging);
}
extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_paragraph_ParagraphStyleKt__1nGetHinting
(JNIEnv* env, jclass jclass, jlong ptr) {
ParagraphStyle* instance = reinterpret_cast<ParagraphStyle*>(static_cast<uintptr_t>(ptr));
FontRastrSettings fontRastrSettings = instance->getFontRastrSettings();
return static_cast<jint>(fontRastrSettings.fHinting);
}
extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_paragraph_ParagraphStyleKt__1nGetSubpixel
(JNIEnv* env, jclass jclass, jlong ptr) {
ParagraphStyle* instance = reinterpret_cast<ParagraphStyle*>(static_cast<uintptr_t>(ptr));
FontRastrSettings fontRastrSettings = instance->getFontRastrSettings();
return fontRastrSettings.fSubpixel;
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_paragraph_ParagraphStyleKt__1nDisableHinting
(JNIEnv* env, jclass jclass, jlong ptr) {
ParagraphStyle* instance = reinterpret_cast<ParagraphStyle*>(static_cast<uintptr_t>(ptr));
......
......@@ -394,3 +394,39 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_paragraph_TextStyleKt_
TextStyle* instance = reinterpret_cast<TextStyle*>(static_cast<uintptr_t>(ptr));
instance->setPlaceholder();
}
extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_paragraph_TextStyleKt__1nGetFontEdging
(JNIEnv* env, jclass jclass, jlong ptr) {
TextStyle* instance = reinterpret_cast<TextStyle*>(static_cast<uintptr_t>(ptr));
return static_cast<jint>(instance->getFontEdging());
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_paragraph_TextStyleKt__1nSetFontEdging
(JNIEnv* env, jclass jclass, jlong ptr, jint fontEdging) {
TextStyle* instance = reinterpret_cast<TextStyle*>(static_cast<uintptr_t>(ptr));
instance->setFontEdging(static_cast<SkFont::Edging>(fontEdging));
}
extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_paragraph_TextStyleKt__1nGetSubpixel
(JNIEnv* env, jclass jclass, jlong ptr) {
TextStyle* instance = reinterpret_cast<TextStyle*>(static_cast<uintptr_t>(ptr));
return static_cast<jboolean>(instance->getSubpixel());
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_paragraph_TextStyleKt__1nSetSubpixel
(JNIEnv* env, jclass jclass, jlong ptr, jboolean subpixel) {
TextStyle* instance = reinterpret_cast<TextStyle*>(static_cast<uintptr_t>(ptr));
instance->setSubpixel(subpixel);
}
extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_paragraph_TextStyleKt__1nGetFontHinting
(JNIEnv* env, jclass jclass, jlong ptr) {
TextStyle* instance = reinterpret_cast<TextStyle*>(static_cast<uintptr_t>(ptr));
return static_cast<jint>(instance->getFontHinting());
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_paragraph_TextStyleKt__1nSetFontHinting
(JNIEnv* env, jclass jclass, jlong ptr, jint fontHinting) {
TextStyle* instance = reinterpret_cast<TextStyle*>(static_cast<uintptr_t>(ptr));
instance->setFontHinting(static_cast<SkFontHinting>(fontHinting));
}
......@@ -37,9 +37,9 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_svg_SVGSVGKt_SVGSVG_1n
extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_svg_SVGSVGKt_SVGSVG_1nGetViewBox
(JNIEnv* env, jclass jclass, jlong ptr, jfloatArray result) {
SkSVGSVG* instance = reinterpret_cast<SkSVGSVG*>(static_cast<uintptr_t>(ptr));
SkTLazy<SkSVGViewBoxType> viewBox = instance->getViewBox();
if (viewBox.isValid()) {
skija::Rect::copyToInterop(env, *viewBox.get(), result);
std::optional<SkSVGViewBoxType> viewBox = instance->getViewBox();
if (viewBox.has_value()) {
skija::Rect::copyToInterop(env, viewBox.value(), result);
return true;
} else {
return false;
......
......@@ -3,6 +3,7 @@ package org.jetbrains.skiko
import org.jetbrains.skia.EncodedImageFormat
import org.jetbrains.skia.Paint
import org.jetbrains.skia.Path
import org.jetbrains.skia.PathBuilder
import org.jetbrains.skia.Surface
import java.io.File
import java.nio.file.Files
......@@ -15,7 +16,7 @@ class ImageTest {
Surface.makeRasterN32Premul(100, 100).use { surface ->
val paint = Paint()
paint.color = -0x10000
Path().moveTo(20f, 80f).lineTo(50f, 20f).lineTo(80f, 80f).closePath().use { path ->
PathBuilder().moveTo(20f, 80f).lineTo(50f, 20f).lineTo(80f, 80f).closePath().detach().use { path ->
val canvas = surface.canvas
canvas.drawPath(path, paint)
surface.makeImageSnapshot().use { image ->
......
......@@ -35,7 +35,7 @@ SKIKO_EXPORT void org_jetbrains_skia_Canvas__1nDrawPoints
SkCanvas* canvas = reinterpret_cast<SkCanvas*>((canvasPtr));
SkPaint* paint = reinterpret_cast<SkPaint*>((paintPtr));
SkCanvas::PointMode skMode = static_cast<SkCanvas::PointMode>(mode);
canvas->drawPoints(skMode, coordsCount / 2, reinterpret_cast<SkPoint*>(coords), *paint);
canvas->drawPoints(skMode, {reinterpret_cast<SkPoint*>(coords), coordsCount / 2}, *paint);
}
SKIKO_EXPORT void org_jetbrains_skia_Canvas__1nDrawLine
......
......@@ -204,8 +204,8 @@ SKIKO_EXPORT void org_jetbrains_skia_Font__1nGetUTF32Glyphs
(KNativePointer ptr, KInt* uniArr, KInt uniArrLen, KShort* resultGlyphs) {
SkFont* instance = reinterpret_cast<SkFont*>(ptr);
instance->unicharsToGlyphs(
reinterpret_cast<SkUnichar*>(uniArr), uniArrLen,
reinterpret_cast<SkGlyphID*>(resultGlyphs)
{reinterpret_cast<SkUnichar*>(uniArr), uniArrLen},
{reinterpret_cast<SkGlyphID*>(resultGlyphs), uniArrLen}
);
}
......@@ -246,7 +246,7 @@ SKIKO_EXPORT KFloat org_jetbrains_skia_Font__1nMeasureTextWidth
SKIKO_EXPORT void org_jetbrains_skia_Font__1nGetWidths
(KNativePointer ptr, KShort* glyphs, KInt count, KFloat* widths) {
SkFont* instance = reinterpret_cast<SkFont*>(ptr);
instance->getWidths(reinterpret_cast<SkGlyphID*>(glyphs), count, widths);
instance->getWidths({reinterpret_cast<SkGlyphID*>(glyphs), count}, {widths, count});
}
SKIKO_EXPORT void org_jetbrains_skia_Font__1nGetBounds
......@@ -254,7 +254,7 @@ SKIKO_EXPORT void org_jetbrains_skia_Font__1nGetBounds
SkFont* instance = reinterpret_cast<SkFont*>(ptr);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
std::vector<SkRect> bounds(count);
instance->getBounds(reinterpret_cast<SkGlyphID*>(glyphs), count, bounds.data(), paint);
instance->getBounds({reinterpret_cast<SkGlyphID*>(glyphs), count}, {bounds.data(), count}, paint);
for (int i = 0; i < count; ++i) {
SkRect b = bounds[i];
......@@ -270,7 +270,7 @@ SKIKO_EXPORT void org_jetbrains_skia_Font__1nGetPositions
SkFont* instance = reinterpret_cast<SkFont*>(ptr);
std::vector<SkPoint> positions(count);
instance->getPos(reinterpret_cast<SkGlyphID*>(glyphs), count, positions.data(), {dx, dy});
instance->getPos({reinterpret_cast<SkGlyphID*>(glyphs), count}, {positions.data(), count}, {dx, dy});
for (int i = 0; i < count; i++) {
res[2*i] = positions[i].fX;
......@@ -281,15 +281,18 @@ SKIKO_EXPORT void org_jetbrains_skia_Font__1nGetPositions
SKIKO_EXPORT void org_jetbrains_skia_Font__1nGetXPositions
(KNativePointer ptr, KShort* glyphs, KFloat dx, KInt count, KFloat* positions) {
SkFont* instance = reinterpret_cast<SkFont*>(ptr);
instance->getXPos(reinterpret_cast<SkGlyphID*>(glyphs), count, positions, dx);
instance->getXPos({reinterpret_cast<SkGlyphID*>(glyphs), count}, {positions, count}, dx);
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_Font__1nGetPath
(KNativePointer ptr, KShort glyph) {
SkFont* instance = reinterpret_cast<SkFont*>(ptr);
SkPath* path = new SkPath();
instance->getPath(glyph, path);
return reinterpret_cast<KNativePointer>(path);
std::optional<SkPath> pathOpt = instance->getPath(glyph);
if (pathOpt.has_value()) {
SkPath* path = new SkPath(pathOpt.value());
return reinterpret_cast<KNativePointer>(path);
}
return 0;
}
......@@ -301,11 +304,10 @@ SKIKO_EXPORT KNativePointer org_jetbrains_skia_Font__1nGetPaths
std::vector<KNativePointer>* paths;
} ctx = { new std::vector<KNativePointer>() };
instance->getPaths(reinterpret_cast<SkGlyphID*>(glyphs), count, [](const SkPath* orig, const SkMatrix& mx, void* voidCtx) {
instance->getPaths({reinterpret_cast<SkGlyphID*>(glyphs), count}, [](const SkPath* orig, const SkMatrix& mx, void* voidCtx) {
Ctx* ctx = static_cast<Ctx*>(voidCtx);
if (orig) {
SkPath* path = new SkPath();
orig->transform(mx, path);
SkPath* path = new SkPath(orig->makeTransform(mx));
ctx->paths->push_back(reinterpret_cast<KNativePointer>(path));
}
}, &ctx);
......
......@@ -73,7 +73,6 @@ SKIKO_EXPORT KBoolean org_jetbrains_skia_Path__1nIsConvex(KNativePointer ptr) {
return instance->isConvex();
}
SKIKO_EXPORT KBoolean org_jetbrains_skia_Path__1nIsOval(KNativePointer ptr, KInteropPointer resultArray) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
SkRect bounds;
......@@ -96,17 +95,6 @@ SKIKO_EXPORT KBoolean org_jetbrains_skia_Path__1nIsRRect(KNativePointer ptr, KIn
}
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nReset(KNativePointer ptr) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
instance->reset();
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nRewind(KNativePointer ptr) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
instance->rewind();
}
SKIKO_EXPORT KBoolean org_jetbrains_skia_Path__1nIsEmpty(KNativePointer ptr) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
return instance->isEmpty();
......@@ -132,6 +120,12 @@ SKIKO_EXPORT void org_jetbrains_skia_Path__1nSetVolatile(KNativePointer ptr, KBo
instance->setIsVolatile(isVolatile);
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nSwap(KNativePointer ptr, KNativePointer otherPtr) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
SkPath* other = reinterpret_cast<SkPath*>((otherPtr));
instance->swap(*other);
}
SKIKO_EXPORT KBoolean org_jetbrains_skia_Path__1nIsLineDegenerate(KFloat x0, KFloat y0, KFloat x1, KFloat y1, KBoolean exact) {
return SkPath::IsLineDegenerate({x0, y0}, {x1, y1}, exact);
}
......@@ -144,7 +138,6 @@ SKIKO_EXPORT KBoolean org_jetbrains_skia_Path__1nIsCubicDegenerate(KFloat x0, KF
return SkPath::IsCubicDegenerate({x0, y0}, {x1, y1}, {x2, y2}, {x3, y3}, exact);
}
SKIKO_EXPORT KBoolean org_jetbrains_skia_Path__1nMaybeGetAsLine(KNativePointer ptr, KInteropPointer resultArray) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
SkPoint line[2];
......@@ -157,7 +150,6 @@ SKIKO_EXPORT KBoolean org_jetbrains_skia_Path__1nMaybeGetAsLine(KNativePointer p
}
}
SKIKO_EXPORT KInt org_jetbrains_skia_Path__1nGetPointsCount(KNativePointer ptr) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
return instance->countPoints();
......@@ -171,7 +163,7 @@ SKIKO_EXPORT void org_jetbrains_skia_Path__1nGetPoint(KNativePointer ptr, KInt i
SKIKO_EXPORT KInt org_jetbrains_skia_Path__1nGetPoints(KNativePointer ptr, KInteropPointer pointsArray, KInt max) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
SkPoint* points = reinterpret_cast<SkPoint*>(pointsArray);
return instance->getPoints(points, max);
return instance->getPoints({points, max});
}
SKIKO_EXPORT KInt org_jetbrains_skia_Path__1nCountVerbs(KNativePointer ptr) {
......@@ -181,19 +173,12 @@ SKIKO_EXPORT KInt org_jetbrains_skia_Path__1nCountVerbs(KNativePointer ptr) {
SKIKO_EXPORT KInt org_jetbrains_skia_Path__1nGetVerbs(KNativePointer ptr, KByte* verbsArray, KInt max) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
return instance->getVerbs(reinterpret_cast<uint8_t *>(verbsArray), max);
return instance->getVerbs({reinterpret_cast<uint8_t *>(verbsArray), max});
}
SKIKO_EXPORT KInt org_jetbrains_skia_Path__1nApproximateBytesUsed(KNativePointer ptr) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
return (KInt) instance->approximateBytesUsed();
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nSwap(KNativePointer ptr, KNativePointer otherPtr) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
SkPath* other = reinterpret_cast<SkPath*>((otherPtr));
instance->swap(*other);
return static_cast<KInt>(instance->approximateBytesUsed());
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nGetBounds(KNativePointer ptr, KInteropPointer resultArray) {
......@@ -202,11 +187,6 @@ SKIKO_EXPORT void org_jetbrains_skia_Path__1nGetBounds(KNativePointer ptr, KInte
skija::Rect::copyToInterop(bounds, resultArray);
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nUpdateBoundsCache(KNativePointer ptr) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
instance->updateBoundsCache();
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nComputeTightBounds(KNativePointer ptr, KInteropPointer resultArray) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
SkRect bounds = instance->computeTightBounds();
......@@ -219,94 +199,12 @@ SKIKO_EXPORT KBoolean org_jetbrains_skia_Path__1nConservativelyContainsRect(KNat
return instance->conservativelyContainsRect(rect);
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nIncReserve(KNativePointer ptr, int extraPtCount) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
instance->incReserve(extraPtCount);
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nMoveTo(KNativePointer ptr, KFloat x, KFloat y) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
instance->moveTo(x, y);
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nRMoveTo(KNativePointer ptr, KFloat dx, KFloat dy) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
instance->rMoveTo(dx, dy);
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nLineTo(KNativePointer ptr, KFloat x, KFloat y) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
instance->lineTo(x, y);
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nRLineTo(KNativePointer ptr, KFloat dx, KFloat dy) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
instance->rLineTo(dx, dy);
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nQuadTo(KNativePointer ptr, KFloat x1, KFloat y1, KFloat x2, KFloat y2) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
instance->quadTo(x1, y1, x2, y2);
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nRQuadTo(KNativePointer ptr, KFloat dx1, KFloat dy1, KFloat dx2, KFloat dy2) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
instance->rQuadTo(dx1, dy1, dx2, dy2);
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nConicTo(KNativePointer ptr, KFloat x1, KFloat y1, KFloat x2, KFloat y2, KFloat w) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
instance->conicTo(x1, y1, x2, y2, w);
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nRConicTo(KNativePointer ptr, KFloat dx1, KFloat dy1, KFloat dx2, KFloat dy2, KFloat w) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
instance->rConicTo(dx1, dy1, dx2, dy2, w);
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nCubicTo(KNativePointer ptr, KFloat x1, KFloat y1, KFloat x2, KFloat y2, KFloat x3, KFloat y3) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
instance->cubicTo(x1, y1, x2, y2, x3, y3);
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nRCubicTo(KNativePointer ptr, KFloat dx1, KFloat dy1, KFloat dx2, KFloat dy2, KFloat dx3, KFloat dy3) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
instance->rCubicTo(dx1, dy1, dx2, dy2, dx3, dy3);
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nArcTo(KNativePointer ptr, KFloat left, KFloat top, KFloat right, KFloat bottom, KFloat startAngle, KFloat sweepAngle, KBoolean forceMoveTo) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
instance->arcTo({left, top, right, bottom}, startAngle, sweepAngle, forceMoveTo);
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nTangentArcTo(KNativePointer ptr, KFloat x1, KFloat y1, KFloat x2, KFloat y2, KFloat radius) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
instance->arcTo(x1, y1, x2, y2, radius);
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nEllipticalArcTo(KNativePointer ptr, KFloat rx, KFloat ry, KFloat xAxisRotate, KInt size, KInt direction, KFloat x, float y) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
instance->arcTo(rx, ry, xAxisRotate, static_cast<SkPath::ArcSize>(size), static_cast<SkPathDirection>(direction), x, y);
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nREllipticalArcTo(KNativePointer ptr, KFloat rx, KFloat ry, KFloat xAxisRotate, KInt size, KInt direction, KFloat dx, float dy) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
instance->rArcTo(rx, ry, xAxisRotate, static_cast<SkPath::ArcSize>(size), static_cast<SkPathDirection>(direction), dx, dy);
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nClosePath(KNativePointer ptr) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
instance->close();
}
SKIKO_EXPORT KInt org_jetbrains_skia_Path__1nConvertConicToQuads
(KFloat x0, KFloat y0, KFloat x1, KFloat y1, KFloat x2, KFloat y2, KFloat w, KInt pow2, KInteropPointer resultArray) {
SkPoint* result = reinterpret_cast<SkPoint*>(resultArray);
return SkPath::ConvertConicToQuads({x0, y0}, {x1, y1}, {x2, y2}, w, result, pow2);
}
SKIKO_EXPORT KBoolean org_jetbrains_skia_Path__1nIsRect
(KNativePointer ptr, KInteropPointer resultArray) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
......@@ -319,101 +217,21 @@ SKIKO_EXPORT KBoolean org_jetbrains_skia_Path__1nIsRect
}
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nAddRect
(KNativePointer ptr, KFloat l, KFloat t, KFloat r, KFloat b, KInt dirInt, KInt start) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
SkPathDirection dir = static_cast<SkPathDirection>(dirInt);
instance->addRect({l, t, r, b}, dir, start);
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nAddOval
(KNativePointer ptr, KFloat l, KFloat t, KFloat r, KFloat b, KInt dirInt, KInt start) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
SkPathDirection dir = static_cast<SkPathDirection>(dirInt);
instance->addOval({l, t, r, b}, dir, start);
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nAddCircle
(KNativePointer ptr, KFloat x, KFloat y, KFloat r, KInt dirInt) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
SkPathDirection dir = static_cast<SkPathDirection>(dirInt);
instance->addCircle(x, y, r, dir);
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nAddArc
(KNativePointer ptr, KFloat l, KFloat t, KFloat r, KFloat b, KFloat startAngle, KFloat sweepAngle) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
instance->addArc({l, t, r, b}, startAngle, sweepAngle);
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nAddRRect
(KNativePointer ptr, KFloat l, KFloat t, KFloat r, KFloat b, KFloat* radii, KInt radiiSize, KInt dirInt, KInt start) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
SkRRect rrect = skija::RRect::toSkRRect(l, t, r, b, radii, radiiSize);
SkPathDirection dir = static_cast<SkPathDirection>(dirInt);
instance->addRRect(rrect, dir, start);
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nAddPoly
(KNativePointer ptr, KFloat* coords, KInt count, KBoolean close) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
instance->addPoly(reinterpret_cast<SkPoint*>(coords), count, close);
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nAddPath
(KNativePointer ptr, KNativePointer srcPtr, KBoolean extend) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
SkPath* src = reinterpret_cast<SkPath*>((srcPtr));
SkPath::AddPathMode mode = extend ? SkPath::AddPathMode::kExtend_AddPathMode : SkPath::AddPathMode::kAppend_AddPathMode;
instance->addPath(*src, mode);
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nAddPathOffset
(KNativePointer ptr, KNativePointer srcPtr, KFloat dx, KFloat dy, KBoolean extend) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
SkPath* src = reinterpret_cast<SkPath*>((srcPtr));
SkPath::AddPathMode mode = extend ? SkPath::AddPathMode::kExtend_AddPathMode : SkPath::AddPathMode::kAppend_AddPathMode;
instance->addPath(*src, dx, dy, mode);
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nAddPathTransform
(KNativePointer ptr, KNativePointer srcPtr, KFloat* matrixArr, KBoolean extend) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
SkPath* src = reinterpret_cast<SkPath*>((srcPtr));
std::unique_ptr<SkMatrix> matrix = skMatrix(matrixArr);
SkPath::AddPathMode mode = extend ? SkPath::AddPathMode::kExtend_AddPathMode : SkPath::AddPathMode::kAppend_AddPathMode;
instance->addPath(*src, *matrix, mode);
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nReverseAddPath
(KNativePointer ptr, KNativePointer srcPtr) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
SkPath* src = reinterpret_cast<SkPath*>((srcPtr));
instance->reverseAddPath(*src);
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nOffset
(KNativePointer ptr, KFloat dx, KFloat dy, KNativePointer dstPtr) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
SkPath* dst = reinterpret_cast<SkPath*>((dstPtr));
instance->offset(dx, dy, dst);
*dst = instance->makeOffset(dx, dy);
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nTransform
(KNativePointer ptr, KFloat* matrixArr, KNativePointer dstPtr, KBoolean pcBool) {
(KNativePointer ptr, KFloat* matrixArr, KNativePointer dstPtr) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
SkPath* dst = reinterpret_cast<SkPath*>((dstPtr));
std::unique_ptr<SkMatrix> matrix = skMatrix(matrixArr);
SkApplyPerspectiveClip pc = pcBool ? SkApplyPerspectiveClip::kYes : SkApplyPerspectiveClip::kNo;
instance->transform(*matrix, dst, pc);
*dst = instance->makeTransform(*matrix);
}
SKIKO_EXPORT KBoolean org_jetbrains_skia_Path__1nGetLastPt
(KNativePointer ptr, KInteropPointer resultArray) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
......@@ -426,13 +244,6 @@ SKIKO_EXPORT KBoolean org_jetbrains_skia_Path__1nGetLastPt
}
}
SKIKO_EXPORT void org_jetbrains_skia_Path__1nSetLastPt
(KNativePointer ptr, KFloat x, KFloat y) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
instance->setLastPt(x, y);
}
SKIKO_EXPORT KInt org_jetbrains_skia_Path__1nGetSegmentMasks
(KNativePointer ptr) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
......@@ -457,7 +268,6 @@ SKIKO_EXPORT void org_jetbrains_skia_Path__1nDumpHex
instance->dumpHex();
}
SKIKO_EXPORT KInt org_jetbrains_skia_Path__1nSerializeToBytes
(KNativePointer ptr, KInteropPointer dst) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
......@@ -469,7 +279,6 @@ SKIKO_EXPORT KInt org_jetbrains_skia_Path__1nSerializeToBytes
}
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_Path__1nMakeCombining
(KNativePointer aPtr, KNativePointer bPtr, KInt jop) {
SkPath* a = reinterpret_cast<SkPath*>((aPtr));
......@@ -482,20 +291,18 @@ SKIKO_EXPORT KNativePointer org_jetbrains_skia_Path__1nMakeCombining
return 0;
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_Path__1nMakeFromBytes
(KByte* bytesArray, KInt size) {
SkPath* instance = new SkPath();
void* bytes = reinterpret_cast<void*>(bytesArray);
if (instance->readFromMemory(bytes, size)) {
std::optional<SkPath> pathOpt = SkPath::ReadFromMemory(bytes, size);
if (pathOpt.has_value()) {
SkPath* instance = new SkPath(pathOpt.value());
return reinterpret_cast<KNativePointer>(instance);
} else {
delete instance;
return 0;
}
}
SKIKO_EXPORT KInt org_jetbrains_skia_Path__1nGetGenerationId
(KNativePointer ptr) {
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
......@@ -507,3 +314,106 @@ SKIKO_EXPORT KBoolean org_jetbrains_skia_Path__1nIsValid
SkPath* instance = reinterpret_cast<SkPath*>((ptr));
return instance->isValid();
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_Path__1nMakeFromRaw
(KFloat* ptsArray, KInt ptsCount,
KByte* verbsArray, KInt verbsCount,
KFloat* conicWeightsArray, KInt conicWeightsCount,
KInt fillType, KBoolean isVolatile) {
SkPath path = SkPath::Raw(
SkSpan<const SkPoint>(reinterpret_cast<const SkPoint*>(ptsArray), ptsCount),
SkSpan<const SkPathVerb>(reinterpret_cast<const SkPathVerb*>(verbsArray), verbsCount),
SkSpan<const SkScalar>(conicWeightsArray, conicWeightsCount),
static_cast<SkPathFillType>(fillType),
isVolatile
);
SkPath* instance = new SkPath(path);
return reinterpret_cast<KNativePointer>(instance);
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_Path__1nMakeFromRect
(KFloat left, KFloat top, KFloat right, KFloat bottom,
KInt fillType, KInt direction, KInt startIndex) {
SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
SkPath path = SkPath::Rect(
rect,
static_cast<SkPathFillType>(fillType),
static_cast<SkPathDirection>(direction),
startIndex
);
SkPath* instance = new SkPath(path);
return reinterpret_cast<KNativePointer>(instance);
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_Path__1nMakeFromOval
(KFloat left, KFloat top, KFloat right, KFloat bottom,
KInt direction, KInt startIndex) {
SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
SkPath path = SkPath::Oval(
rect,
static_cast<SkPathDirection>(direction),
startIndex
);
SkPath* instance = new SkPath(path);
return reinterpret_cast<KNativePointer>(instance);
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_Path__1nMakeFromCircle
(KFloat centerX, KFloat centerY, KFloat radius, KInt direction) {
SkPath path = SkPath::Circle(
centerX,
centerY,
radius,
static_cast<SkPathDirection>(direction)
);
SkPath* instance = new SkPath(path);
return reinterpret_cast<KNativePointer>(instance);
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_Path__1nMakeFromRRect
(KFloat* radiiArray,
KFloat left, KFloat top, KFloat right, KFloat bottom,
KInt direction, KInt startIndex) {
SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
SkRRect rrect;
rrect.setRectRadii(rect, reinterpret_cast<const SkVector*>(radiiArray));
SkPath path = SkPath::RRect(
rrect,
static_cast<SkPathDirection>(direction),
startIndex
);
SkPath* instance = new SkPath(path);
return reinterpret_cast<KNativePointer>(instance);
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_Path__1nMakeFromRRectXY
(KFloat left, KFloat top, KFloat right, KFloat bottom,
KFloat rx, KFloat ry, KInt direction) {
SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
SkPath path = SkPath::RRect(
rect,
rx,
ry,
static_cast<SkPathDirection>(direction)
);
SkPath* instance = new SkPath(path);
return reinterpret_cast<KNativePointer>(instance);
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_Path__1nMakeFromPolygon
(KFloat* ptsArray, KInt ptsCount,
KBoolean isClosed, KInt fillType, KBoolean isVolatile) {
SkPath path = SkPath::Polygon(
SkSpan<const SkPoint>(reinterpret_cast<const SkPoint*>(ptsArray), ptsCount),
isClosed,
static_cast<SkPathFillType>(fillType),
isVolatile
);
SkPath* instance = new SkPath(path);
return reinterpret_cast<KNativePointer>(instance);
}
#include "SkPathBuilder.h"
#include "SkPath.h"
#include "SkRRect.h"
#include "SkMatrix.h"
#include "common.h"
static void deletePathBuilder(SkPathBuilder* builder) {
delete builder;
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_PathBuilder__1nGetFinalizer() {
return reinterpret_cast<KNativePointer>((&deletePathBuilder));
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_PathBuilder__1nMake() {
SkPathBuilder* builder = new SkPathBuilder();
return reinterpret_cast<KNativePointer>(builder);
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_PathBuilder__1nMakeWithFillType(KInt fillType) {
SkPathBuilder* builder = new SkPathBuilder(static_cast<SkPathFillType>(fillType));
return reinterpret_cast<KNativePointer>(builder);
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_PathBuilder__1nMakeFromPath(KNativePointer pathPtr) {
SkPath* path = reinterpret_cast<SkPath*>((pathPtr));
SkPathBuilder* builder = new SkPathBuilder(*path);
return reinterpret_cast<KNativePointer>(builder);
}
SKIKO_EXPORT void org_jetbrains_skia_PathBuilder__1nReset(KNativePointer ptr) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
builder->reset();
}
SKIKO_EXPORT void org_jetbrains_skia_PathBuilder__1nSetFillType(KNativePointer ptr, KInt fillType) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
builder->setFillType(static_cast<SkPathFillType>(fillType));
}
SKIKO_EXPORT void org_jetbrains_skia_PathBuilder__1nIncReserve(KNativePointer ptr, KInt extraPtCount) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
builder->incReserve(extraPtCount);
}
SKIKO_EXPORT void org_jetbrains_skia_PathBuilder__1nMoveTo(KNativePointer ptr, KFloat x, KFloat y) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
builder->moveTo(x, y);
}
SKIKO_EXPORT void org_jetbrains_skia_PathBuilder__1nRMoveTo(KNativePointer ptr, KFloat dx, KFloat dy) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
builder->rMoveTo(dx, dy);
}
SKIKO_EXPORT void org_jetbrains_skia_PathBuilder__1nLineTo(KNativePointer ptr, KFloat x, KFloat y) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
builder->lineTo(x, y);
}
SKIKO_EXPORT void org_jetbrains_skia_PathBuilder__1nRLineTo(KNativePointer ptr, KFloat dx, KFloat dy) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
builder->rLineTo(dx, dy);
}
SKIKO_EXPORT void org_jetbrains_skia_PathBuilder__1nQuadTo(KNativePointer ptr, KFloat x1, KFloat y1, KFloat x2, KFloat y2) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
builder->quadTo(x1, y1, x2, y2);
}
SKIKO_EXPORT void org_jetbrains_skia_PathBuilder__1nRQuadTo(KNativePointer ptr, KFloat dx1, KFloat dy1, KFloat dx2, KFloat dy2) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
builder->rQuadTo(dx1, dy1, dx2, dy2);
}
SKIKO_EXPORT void org_jetbrains_skia_PathBuilder__1nConicTo(KNativePointer ptr, KFloat x1, KFloat y1, KFloat x2, KFloat y2, KFloat w) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
builder->conicTo(x1, y1, x2, y2, w);
}
SKIKO_EXPORT void org_jetbrains_skia_PathBuilder__1nRConicTo(KNativePointer ptr, KFloat dx1, KFloat dy1, KFloat dx2, KFloat dy2, KFloat w) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
builder->rConicTo(dx1, dy1, dx2, dy2, w);
}
SKIKO_EXPORT void org_jetbrains_skia_PathBuilder__1nCubicTo(KNativePointer ptr, KFloat x1, KFloat y1, KFloat x2, KFloat y2, KFloat x3, KFloat y3) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
builder->cubicTo(x1, y1, x2, y2, x3, y3);
}
SKIKO_EXPORT void org_jetbrains_skia_PathBuilder__1nRCubicTo(KNativePointer ptr, KFloat dx1, KFloat dy1, KFloat dx2, KFloat dy2, KFloat dx3, KFloat dy3) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
builder->rCubicTo(dx1, dy1, dx2, dy2, dx3, dy3);
}
SKIKO_EXPORT void org_jetbrains_skia_PathBuilder__1nArcTo(KNativePointer ptr, KFloat left, KFloat top, KFloat right, KFloat bottom, KFloat startAngle, KFloat sweepAngle, KBoolean forceMoveTo) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
builder->arcTo({left, top, right, bottom}, startAngle, sweepAngle, forceMoveTo);
}
SKIKO_EXPORT void org_jetbrains_skia_PathBuilder__1nTangentArcTo(KNativePointer ptr, KFloat x1, KFloat y1, KFloat x2, KFloat y2, KFloat radius) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
builder->arcTo({x1, y1}, {x2, y2}, radius);
}
SKIKO_EXPORT void org_jetbrains_skia_PathBuilder__1nEllipticalArcTo(KNativePointer ptr, KFloat rx, KFloat ry, KFloat xAxisRotate, KInt size, KInt direction, KFloat x, KFloat y) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
builder->arcTo({rx, ry}, xAxisRotate, static_cast<SkPathBuilder::ArcSize>(size), static_cast<SkPathDirection>(direction), {x, y});
}
SKIKO_EXPORT void org_jetbrains_skia_PathBuilder__1nREllipticalArcTo(KNativePointer ptr, KFloat rx, KFloat ry, KFloat xAxisRotate, KInt size, KInt direction, KFloat dx, KFloat dy) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
builder->rArcTo({rx, ry}, xAxisRotate, static_cast<SkPathBuilder::ArcSize>(size), static_cast<SkPathDirection>(direction), {dx, dy});
}
SKIKO_EXPORT void org_jetbrains_skia_PathBuilder__1nClosePath(KNativePointer ptr) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
builder->close();
}
SKIKO_EXPORT void org_jetbrains_skia_PathBuilder__1nAddRect(KNativePointer ptr, KFloat l, KFloat t, KFloat r, KFloat b, KInt dirInt, KInt start) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
SkPathDirection dir = static_cast<SkPathDirection>(dirInt);
builder->addRect({l, t, r, b}, dir, start);
}
SKIKO_EXPORT void org_jetbrains_skia_PathBuilder__1nAddOval(KNativePointer ptr, KFloat l, KFloat t, KFloat r, KFloat b, KInt dirInt, KInt start) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
SkPathDirection dir = static_cast<SkPathDirection>(dirInt);
builder->addOval({l, t, r, b}, dir, start);
}
SKIKO_EXPORT void org_jetbrains_skia_PathBuilder__1nAddCircle(KNativePointer ptr, KFloat x, KFloat y, KFloat r, KInt dirInt) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
SkPathDirection dir = static_cast<SkPathDirection>(dirInt);
builder->addCircle(x, y, r, dir);
}
SKIKO_EXPORT void org_jetbrains_skia_PathBuilder__1nAddArc(KNativePointer ptr, KFloat l, KFloat t, KFloat r, KFloat b, KFloat startAngle, KFloat sweepAngle) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
builder->addArc({l, t, r, b}, startAngle, sweepAngle);
}
SKIKO_EXPORT void org_jetbrains_skia_PathBuilder__1nAddRRect(KNativePointer ptr, KFloat l, KFloat t, KFloat r, KFloat b, KInteropPointer radii, KInt radiiSize, KInt dirInt, KInt start) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
SkRRect rrect = skija::RRect::toSkRRect(l, t, r, b, reinterpret_cast<KFloat*>(radii), radiiSize);
SkPathDirection dir = static_cast<SkPathDirection>(dirInt);
builder->addRRect(rrect, dir, start);
}
SKIKO_EXPORT void org_jetbrains_skia_PathBuilder__1nAddPoly(KNativePointer ptr, KInteropPointer coords, KInt _count, KBoolean close) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
float* arr = reinterpret_cast<float*>(coords);
builder->addPolygon({reinterpret_cast<SkPoint*>(arr), _count}, close);
}
SKIKO_EXPORT void org_jetbrains_skia_PathBuilder__1nAddPath(KNativePointer ptr, KNativePointer srcPtr, KInt mode) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
SkPath* src = reinterpret_cast<SkPath*>((srcPtr));
builder->addPath(*src, static_cast<SkPath::AddPathMode>(mode));
}
SKIKO_EXPORT void org_jetbrains_skia_PathBuilder__1nAddPathOffset(KNativePointer ptr, KNativePointer srcPtr, KFloat dx, KFloat dy, KInt mode) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
SkPath* src = reinterpret_cast<SkPath*>((srcPtr));
builder->addPath(*src, dx, dy, static_cast<SkPath::AddPathMode>(mode));
}
SKIKO_EXPORT void org_jetbrains_skia_PathBuilder__1nAddPathTransform(KNativePointer ptr, KNativePointer srcPtr, KInteropPointer matrixArr, KInt mode) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
SkPath* src = reinterpret_cast<SkPath*>((srcPtr));
std::unique_ptr<SkMatrix> matrix = skMatrix(reinterpret_cast<KFloat*>(matrixArr));
builder->addPath(*src, *matrix, static_cast<SkPath::AddPathMode>(mode));
}
SKIKO_EXPORT void org_jetbrains_skia_PathBuilder__1nSetLastPt(KNativePointer ptr, KFloat x, KFloat y) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
builder->setLastPt(x, y);
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_PathBuilder__1nDetach(KNativePointer ptr) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
SkPath* path = new SkPath(builder->detach());
return reinterpret_cast<KNativePointer>(path);
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_PathBuilder__1nSnapshot(KNativePointer ptr) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
SkPath* path = new SkPath(builder->snapshot());
return reinterpret_cast<KNativePointer>(path);
}
SKIKO_EXPORT void org_jetbrains_skia_PathBuilder__1nOffset(KNativePointer ptr, KFloat dx, KFloat dy) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
builder->offset(dx, dy);
}
SKIKO_EXPORT void org_jetbrains_skia_PathBuilder__1nTransform(KNativePointer ptr, KInteropPointer matrixArr) {
SkPathBuilder* builder = reinterpret_cast<SkPathBuilder*>((ptr));
std::unique_ptr<SkMatrix> matrix = skMatrix(reinterpret_cast<KFloat*>(matrixArr));
builder->transform(*matrix);
}
......@@ -54,7 +54,7 @@ SKIKO_EXPORT KNativePointer org_jetbrains_skia_PathEffect__1nMakeCorner
SKIKO_EXPORT KNativePointer org_jetbrains_skia_PathEffect__1nMakeDash
(KFloat* intervalsArray, KInt count, KFloat phase) {
SkPathEffect* ptr = SkDashPathEffect::Make(reinterpret_cast<float*>(intervalsArray), count, phase).release();
SkPathEffect* ptr = SkDashPathEffect::Make({reinterpret_cast<float*>(intervalsArray), count}, phase).release();
return reinterpret_cast<KNativePointer>(ptr);
}
......
......@@ -70,10 +70,10 @@ SKIKO_EXPORT KInt org_jetbrains_skia_Picture__1nGetApproximateOpCount
return instance->approximateOpCount();
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_Picture__1nGetApproximateBytesUsed
SKIKO_EXPORT KInt org_jetbrains_skia_Picture__1nGetApproximateBytesUsed
(KNativePointer ptr) {
SkPicture* instance = reinterpret_cast<SkPicture*>((ptr));
return reinterpret_cast<KNativePointer>(instance->approximateBytesUsed());
return static_cast<KInt>(instance->approximateBytesUsed());
}
......
#include <iostream>
#include "SkRegion.h"
#include "SkPathBuilder.h"
#include "common.h"
static void deleteRegion(SkRegion* region) {
......@@ -54,10 +55,15 @@ SKIKO_EXPORT KInt org_jetbrains_skia_Region__1nComputeRegionComplexity(KNativePo
return instance->computeRegionComplexity();
}
SKIKO_EXPORT KBoolean org_jetbrains_skia_Region__1nGetBoundaryPath(KNativePointer ptr, KNativePointer pathPtr) {
SKIKO_EXPORT KBoolean org_jetbrains_skia_Region__1nAddBoundaryPath(KNativePointer ptr, KNativePointer pathBuilderPtr) {
SkRegion* instance = reinterpret_cast<SkRegion*>((ptr));
SkPath* path = reinterpret_cast<SkPath*>((pathPtr));
return instance->getBoundaryPath(path);
SkPathBuilder* pathBuilder = reinterpret_cast<SkPathBuilder*>((pathBuilderPtr));
return instance->addBoundaryPath(pathBuilder);
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_Region__1nGetBoundaryPath(KNativePointer ptr) {
SkRegion* instance = reinterpret_cast<SkRegion*>((ptr));
return reinterpret_cast<KNativePointer>(new SkPath(instance->getBoundaryPath()));
}
SKIKO_EXPORT KBoolean org_jetbrains_skia_Region__1nSetEmpty(KNativePointer ptr) {
......@@ -131,7 +137,7 @@ SKIKO_EXPORT KBoolean org_jetbrains_skia_Region__1nQuickRejectIRect(KNativePoint
SKIKO_EXPORT KBoolean org_jetbrains_skia_Region__1nQuickRejectRegion(KNativePointer ptr, KNativePointer regionPtr) {
SkRegion* instance = reinterpret_cast<SkRegion*>((ptr));
SkRegion* region = reinterpret_cast<SkRegion*>((regionPtr));
return instance->contains(*region);
return instance->quickReject(*region);
}
SKIKO_EXPORT void org_jetbrains_skia_Region__1nTranslate(KNativePointer ptr, KInt dx, KInt dy) {
......
......@@ -56,7 +56,7 @@ SKIKO_EXPORT KNativePointer org_jetbrains_skia_TextBlob__1nMakeFromPosH
SkTextBlob* instance = SkTextBlob::MakeFromPosTextH(
glyphsArr,
glyphsLen * sizeof(short),
xposArr, ypos,
{xposArr, glyphsLen}, ypos,
*font,
SkTextEncoding::kGlyphID
).release();
......@@ -71,7 +71,7 @@ SKIKO_EXPORT KNativePointer org_jetbrains_skia_TextBlob__1nMakeFromPos
SkTextBlob* instance = SkTextBlob::MakeFromPosText(
glyphsArr,
glyphsLen * sizeof(KShort),
reinterpret_cast<SkPoint*>(posArr),
{reinterpret_cast<SkPoint*>(posArr), glyphsLen},
*font,
SkTextEncoding::kGlyphID
).release();
......@@ -85,7 +85,7 @@ SKIKO_EXPORT KNativePointer org_jetbrains_skia_TextBlob__1nMakeFromRSXform
SkTextBlob* instance = SkTextBlob::MakeFromRSXform(
glyphsArr, glyphsLen * sizeof(short),
reinterpret_cast<SkRSXform*>(xformArr),
{reinterpret_cast<SkRSXform*>(xformArr), glyphsLen},
*font, SkTextEncoding::kGlyphID
).release();
......
......@@ -20,7 +20,7 @@ SKIKO_EXPORT KBoolean org_jetbrains_skia_Typeface__1nIsFixedPitch
SKIKO_EXPORT KInt org_jetbrains_skia_Typeface__1nGetVariationsCount
(KNativePointer ptr) {
SkTypeface* instance = reinterpret_cast<SkTypeface*>(ptr);
return instance->getVariationDesignPosition(nullptr, 0);
return instance->getVariationDesignPosition({});
}
SKIKO_EXPORT void org_jetbrains_skia_Typeface__1nGetVariations
......@@ -28,7 +28,7 @@ SKIKO_EXPORT void org_jetbrains_skia_Typeface__1nGetVariations
SkTypeface* instance = reinterpret_cast<SkTypeface*>(ptr);
if (count > 0) {
std::vector<SkFontArguments::VariationPosition::Coordinate> coords(count);
instance->getVariationDesignPosition(coords.data(), count);
instance->getVariationDesignPosition({coords.data(), count});
for (int i=0; i < count; ++i) {
res[2*i] = static_cast<KInt>(coords[i].axis);
res[2*i + 1] = rawBits(coords[i].value);
......@@ -39,7 +39,7 @@ SKIKO_EXPORT void org_jetbrains_skia_Typeface__1nGetVariations
SKIKO_EXPORT KInt org_jetbrains_skia_Typeface__1nGetVariationAxesCount
(KNativePointer ptr) {
SkTypeface* instance = reinterpret_cast<SkTypeface*>(ptr);
return instance->getVariationDesignParameters(nullptr, 0);
return instance->getVariationDesignParameters({});
}
......@@ -48,7 +48,7 @@ SKIKO_EXPORT void org_jetbrains_skia_Typeface__1nGetVariationAxes
SkTypeface* instance = reinterpret_cast<SkTypeface*>(ptr);
if (count > 0) {
std::vector<SkFontParameters::Variation::Axis> params(count);
instance->getVariationDesignParameters(params.data(), count);
instance->getVariationDesignParameters({params.data(), count});
for (int i = 0, j = 0; i < count; ++i) {
int p[5] = { static_cast<int>(params[i].tag), rawBits(params[i].min), rawBits(params[i].def), rawBits(params[i].max), params[i].isHidden()};
memcpy(axis + 5 * i, p, sizeof p);
......@@ -90,7 +90,7 @@ SKIKO_EXPORT KNativePointer org_jetbrains_skia_Typeface__1nMakeClone
SKIKO_EXPORT void org_jetbrains_skia_Typeface__1nGetUTF32Glyphs
(KNativePointer ptr, KInt* uni, KInt count, KShort* res) {
SkTypeface* instance = reinterpret_cast<SkTypeface*>(ptr);
instance->unicharsToGlyphs(reinterpret_cast<SkUnichar*>(uni), count, reinterpret_cast<SkGlyphID*>(res));
instance->unicharsToGlyphs({reinterpret_cast<SkUnichar*>(uni), count}, {reinterpret_cast<SkGlyphID*>(res), count});
}
SKIKO_EXPORT KShort org_jetbrains_skia_Typeface__1nGetUTF32Glyph
......@@ -120,9 +120,9 @@ SKIKO_EXPORT KInt org_jetbrains_skia_Typeface__1nGetTableTagsCount
SKIKO_EXPORT void org_jetbrains_skia_Typeface__1nGetTableTags
(KNativePointer ptr, KInt* res, KInt count) {
SkTypeface* instance = reinterpret_cast<SkTypeface*>(ptr);
std::vector<int> tags(count);
instance->getTableTags(reinterpret_cast<SkFontTableTag*>(tags.data()));
memcpy(res, tags.data(), tags.size() * sizeof(KInt));
std::vector<SkFontTableTag> tags(count);
int actualCount = instance->readTableTags({tags.data(), count});
memcpy(res, tags.data(), actualCount * sizeof(KInt));
}
SKIKO_EXPORT KInt org_jetbrains_skia_Typeface__1nGetTableSize
......@@ -149,10 +149,9 @@ SKIKO_EXPORT bool org_jetbrains_skia_Typeface__1nGetKerningPairAdjustments
(KNativePointer ptr, KInteropPointer glyphs, KInt count, KInt* res) {
SkTypeface* instance = reinterpret_cast<SkTypeface*>(ptr);
if (count > 0) {
std::vector<int> adjustments(count);
return instance->getKerningPairAdjustments(
reinterpret_cast<SkGlyphID*>(glyphs), count,
reinterpret_cast<int32_t*>(res)
{reinterpret_cast<SkGlyphID*>(glyphs), count},
{reinterpret_cast<int32_t*>(res), count}
);
}
......
......@@ -77,7 +77,7 @@ SKIKO_EXPORT KNativePointer org_jetbrains_skia_paragraph_FontCollection__1nFindT
SKIKO_EXPORT KNativePointer org_jetbrains_skia_paragraph_FontCollection__1nDefaultFallbackChar
(KNativePointer ptr, KInt unicode, KInt fontStyle, KInteropPointer locale) {
FontCollection* instance = reinterpret_cast<FontCollection*>(ptr);
return reinterpret_cast<KNativePointer>(instance->defaultFallback(unicode, skija::FontStyle::fromKotlin(fontStyle), skString(locale)).release());
return reinterpret_cast<KNativePointer>(instance->defaultFallback(unicode, skija::FontStyle::fromKotlin(fontStyle), skString(locale), std::nullopt).release());
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_paragraph_FontCollection__1nDefaultFallback
......
......@@ -160,37 +160,6 @@ SKIKO_EXPORT void org_jetbrains_skia_paragraph_ParagraphStyle__1nDisableHinting
instance->turnHintingOff();
}
SKIKO_EXPORT void org_jetbrains_skia_paragraph_ParagraphStyle__1nSetFontRastrSettings
(KNativePointer ptr, KInt edging, KInt hinting, KBoolean subpixel) {
ParagraphStyle* instance = reinterpret_cast<ParagraphStyle*>(ptr);
FontRastrSettings fontRastrSettings;
fontRastrSettings.fEdging = static_cast<SkFont::Edging>(edging);
fontRastrSettings.fHinting = static_cast<SkFontHinting>(hinting);
fontRastrSettings.fSubpixel = subpixel;
instance->setFontRastrSettings(fontRastrSettings);
}
SKIKO_EXPORT KInt org_jetbrains_skia_paragraph_ParagraphStyle__1nGetEdging
(KNativePointer ptr) {
ParagraphStyle* instance = reinterpret_cast<ParagraphStyle*>(ptr);
FontRastrSettings fontRastrSettings = instance->getFontRastrSettings();
return static_cast<KInt>(fontRastrSettings.fEdging);
}
SKIKO_EXPORT KInt org_jetbrains_skia_paragraph_ParagraphStyle__1nGetHinting
(KNativePointer ptr) {
ParagraphStyle* instance = reinterpret_cast<ParagraphStyle*>(ptr);
FontRastrSettings fontRastrSettings = instance->getFontRastrSettings();
return static_cast<KInt>(fontRastrSettings.fHinting);
}
SKIKO_EXPORT KBoolean org_jetbrains_skia_paragraph_ParagraphStyle__1nGetSubpixel
(KNativePointer ptr) {
ParagraphStyle* instance = reinterpret_cast<ParagraphStyle*>(ptr);
FontRastrSettings fontRastrSettings = instance->getFontRastrSettings();
return fontRastrSettings.fSubpixel;
}
SKIKO_EXPORT KBoolean org_jetbrains_skia_paragraph_ParagraphStyle__1nGetApplyRoundingHack
(KNativePointer ptr) {
ParagraphStyle* instance = reinterpret_cast<ParagraphStyle*>(ptr);
......
......@@ -390,3 +390,39 @@ SKIKO_EXPORT void org_jetbrains_skia_paragraph_TextStyle__1nSetPlaceholder
TextStyle* instance = reinterpret_cast<TextStyle*>(ptr);
instance->setPlaceholder();
}
SKIKO_EXPORT KInt org_jetbrains_skia_paragraph_TextStyle__1nGetFontEdging
(KNativePointer ptr) {
TextStyle* instance = reinterpret_cast<TextStyle*>(ptr);
return static_cast<KInt>(instance->getFontEdging());
}
SKIKO_EXPORT void org_jetbrains_skia_paragraph_TextStyle__1nSetFontEdging
(KNativePointer ptr, KInt fontEdging) {
TextStyle* instance = reinterpret_cast<TextStyle*>(ptr);
instance->setFontEdging(static_cast<SkFont::Edging>(fontEdging));
}
SKIKO_EXPORT KBoolean org_jetbrains_skia_paragraph_TextStyle__1nGetSubpixel
(KNativePointer ptr) {
TextStyle* instance = reinterpret_cast<TextStyle*>(ptr);
return instance->getSubpixel();
}
SKIKO_EXPORT void org_jetbrains_skia_paragraph_TextStyle__1nSetSubpixel
(KNativePointer ptr, KBoolean subpixel) {
TextStyle* instance = reinterpret_cast<TextStyle*>(ptr);
instance->setSubpixel(subpixel);
}
SKIKO_EXPORT KInt org_jetbrains_skia_paragraph_TextStyle__1nGetFontHinting
(KNativePointer ptr) {
TextStyle* instance = reinterpret_cast<TextStyle*>(ptr);
return static_cast<KInt>(instance->getFontHinting());
}
SKIKO_EXPORT void org_jetbrains_skia_paragraph_TextStyle__1nSetFontHinting
(KNativePointer ptr, KInt fontHinting) {
TextStyle* instance = reinterpret_cast<TextStyle*>(ptr);
instance->setFontHinting(static_cast<SkFontHinting>(fontHinting));
}
......@@ -37,9 +37,9 @@ SKIKO_EXPORT void org_jetbrains_skia_svg_SVGSVG__1nGetPreserveAspectRatio
SKIKO_EXPORT KBoolean org_jetbrains_skia_svg_SVGSVG__1nGetViewBox
(KNativePointer ptr, KInteropPointer result) {
SkSVGSVG* instance = reinterpret_cast<SkSVGSVG*>((ptr));
SkTLazy<SkSVGViewBoxType> viewBox = instance->getViewBox();
if (viewBox.isValid()) {
skija::Rect::copyToInterop(*viewBox.get(), result);
std::optional<SkSVGViewBoxType> viewBox = instance->getViewBox();
if (viewBox.has_value()) {
skija::Rect::copyToInterop(viewBox.value(), result);
return true;
} else {
return false;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment