Unverified Commit 3340df22 authored by Oleksandr Karpovich's avatar Oleksandr Karpovich Committed by GitHub

Common TextBlob Builder (#368)

* TextBlobBuilder: common appendRun

* TextBlobBuilder: common appendRunPosH

* TextBlobBuilder: canAppendRunWithRSXform, canAppendRunWithPosition, canAppendMultipleTimes

* drop commit (duplicates code from PR #356)

* TextBlobBuilder: nAppendRun impl

* TextBlobBuilder: appendRunPosH impl

* TextBlobBuilder: AppendRunPos impl

* TextBlobBuilder: appendRunRSXform impl

* fix js test
Co-authored-by: 's avatarOleksandr Karpovich <oleksandr.karpovich@jetbrains.com>
parent ab3e19e4
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
namespace skikoMpp { namespace skikoMpp {
namespace skrect { namespace skrect {
void serializeAs4Floats(const SkRect& rect, float* result); void serializeAs4Floats(const SkRect& rect, float* result);
std::unique_ptr<SkRect> toSkRect(float* topLeftRightBottom);
} }
namespace textblob { namespace textblob {
......
...@@ -10,6 +10,19 @@ namespace skikoMpp { ...@@ -10,6 +10,19 @@ namespace skikoMpp {
result[2] = rect.fRight; result[2] = rect.fRight;
result[3] = rect.fBottom; result[3] = rect.fBottom;
} }
std::unique_ptr<SkRect> toSkRect(float* topLeftRightBottom) {
if (topLeftRightBottom == nullptr) {
return std::unique_ptr<SkRect>(nullptr);
} else {
SkRect* rect = new SkRect();
rect->setLTRB(
topLeftRightBottom[0], topLeftRightBottom[1],
topLeftRightBottom[2], topLeftRightBottom[3]
);
return std::unique_ptr<SkRect>(rect);
}
}
} }
namespace textblob { namespace textblob {
......
package org.jetbrains.skia package org.jetbrains.skia
import org.jetbrains.skia.impl.*
import org.jetbrains.skia.impl.Library.Companion.staticLoad import org.jetbrains.skia.impl.Library.Companion.staticLoad
import org.jetbrains.skia.impl.Managed
import org.jetbrains.skia.impl.Native
import org.jetbrains.skia.impl.Stats
import org.jetbrains.skia.impl.reachabilityBarrier
import org.jetbrains.skia.impl.NativePointer
import org.jetbrains.skia.impl.getPtr
class Font : Managed { class Font : Managed {
companion object { companion object {
...@@ -332,7 +327,9 @@ class Font : Managed { ...@@ -332,7 +327,9 @@ class Font : Managed {
fun getUTF32Glyphs(uni: IntArray?): ShortArray { fun getUTF32Glyphs(uni: IntArray?): ShortArray {
return try { return try {
Stats.onNativeCall() Stats.onNativeCall()
_nGetUTF32Glyphs(_ptr, uni) withResult(ShortArray(uni?.size ?: 0)) {
_nGetUTF32Glyphs(_ptr, toInterop(uni), uni?.size ?: 0, it)
}
} finally { } finally {
reachabilityBarrier(this) reachabilityBarrier(this)
} }
...@@ -640,7 +637,7 @@ private external fun _nGetStringGlyphs(ptr: NativePointer, str: String?): ShortA ...@@ -640,7 +637,7 @@ private external fun _nGetStringGlyphs(ptr: NativePointer, str: String?): ShortA
private external fun _nGetUTF32Glyph(ptr: NativePointer, uni: Int): Short private external fun _nGetUTF32Glyph(ptr: NativePointer, uni: Int): Short
@ExternalSymbolName("org_jetbrains_skia_Font__1nGetUTF32Glyphs") @ExternalSymbolName("org_jetbrains_skia_Font__1nGetUTF32Glyphs")
private external fun _nGetUTF32Glyphs(ptr: NativePointer, uni: IntArray?): ShortArray private external fun _nGetUTF32Glyphs(ptr: NativePointer, uni: InteropPointer, uniArrLen: Int, resultGlyphs: InteropPointer)
@ExternalSymbolName("org_jetbrains_skia_Font__1nGetStringGlyphsCount") @ExternalSymbolName("org_jetbrains_skia_Font__1nGetStringGlyphsCount")
private external fun _nGetStringGlyphsCount(ptr: NativePointer, str: String?): Int private external fun _nGetStringGlyphsCount(ptr: NativePointer, str: String?): Int
......
...@@ -53,6 +53,11 @@ open class Rect constructor(val left: Float, val top: Float, val right: Float, v ...@@ -53,6 +53,11 @@ open class Rect constructor(val left: Float, val top: Float, val right: Float, v
) )
} }
// This is a helper to pass Rect instance through interop border
internal fun serializeToFloatArray(): FloatArray {
return floatArrayOf(left, top, right, bottom)
}
val isEmpty: Boolean val isEmpty: Boolean
get() = right == left || top == bottom get() = right == left || top == bottom
......
...@@ -51,30 +51,10 @@ class TextBlobBuilder internal constructor(ptr: NativePointer) : Managed(ptr, _F ...@@ -51,30 +51,10 @@ class TextBlobBuilder internal constructor(ptr: NativePointer) : Managed(ptr, _F
* @param text Text to append in this run * @param text Text to append in this run
* @param x horizontal offset within the blob * @param x horizontal offset within the blob
* @param y vertical offset within the blob * @param y vertical offset within the blob
* @return this
*/
fun appendRun(font: Font, text: String, x: Float, y: Float): TextBlobBuilder {
return appendRun(font, font.getStringGlyphs(text), x, y, null)
}
/**
*
* Glyphs are positioned on a baseline at (x, y), using font metrics to
* determine their relative placement.
*
*
* bounds defines an optional bounding box, used to suppress drawing when TextBlob
* bounds does not intersect Surface bounds. If bounds is null, TextBlob bounds
* is computed from (x, y) and glyphs metrics.
*
* @param font Font used for this run
* @param text Text to append in this run
* @param x horizontal offset within the blob
* @param y vertical offset within the blob
* @param bounds optional run bounding box * @param bounds optional run bounding box
* @return this * @return this
*/ */
fun appendRun(font: Font, text: String, x: Float, y: Float, bounds: Rect?): TextBlobBuilder { fun appendRun(font: Font, text: String, x: Float, y: Float, bounds: Rect? = null): TextBlobBuilder {
return appendRun(font, font.getStringGlyphs(text), x, y, bounds) return appendRun(font, font.getStringGlyphs(text), x, y, bounds)
} }
...@@ -103,9 +83,10 @@ class TextBlobBuilder internal constructor(ptr: NativePointer) : Managed(ptr, _F ...@@ -103,9 +83,10 @@ class TextBlobBuilder internal constructor(ptr: NativePointer) : Managed(ptr, _F
_ptr, _ptr,
getPtr(font), getPtr(font),
toInterop(glyphs), toInterop(glyphs),
glyphs?.size ?: 0,
x, x,
y, y,
bounds toInterop(bounds?.serializeToFloatArray())
) )
} }
this this
...@@ -149,14 +130,17 @@ class TextBlobBuilder internal constructor(ptr: NativePointer) : Managed(ptr, _F ...@@ -149,14 +130,17 @@ class TextBlobBuilder internal constructor(ptr: NativePointer) : Managed(ptr, _F
return try { return try {
require(glyphs.size == xs.size) { "glyphs.length " + glyphs.size + " != xs.length " + xs.size } require(glyphs.size == xs.size) { "glyphs.length " + glyphs.size + " != xs.length " + xs.size }
Stats.onNativeCall() Stats.onNativeCall()
interopScope {
_nAppendRunPosH( _nAppendRunPosH(
_ptr, _ptr,
getPtr(font), getPtr(font),
glyphs, toInterop(glyphs),
xs, glyphs.size,
toInterop(xs),
y, y,
bounds toInterop(bounds?.serializeToFloatArray())
) )
}
this this
} finally { } finally {
reachabilityBarrier(font) reachabilityBarrier(font)
...@@ -200,8 +184,9 @@ class TextBlobBuilder internal constructor(ptr: NativePointer) : Managed(ptr, _F ...@@ -200,8 +184,9 @@ class TextBlobBuilder internal constructor(ptr: NativePointer) : Managed(ptr, _F
_ptr, _ptr,
getPtr(font), getPtr(font),
toInterop(glyphs), toInterop(glyphs),
glyphs.size,
toInterop(floatPos), toInterop(floatPos),
bounds toInterop(bounds?.serializeToFloatArray())
) )
} }
this this
...@@ -226,6 +211,7 @@ class TextBlobBuilder internal constructor(ptr: NativePointer) : Managed(ptr, _F ...@@ -226,6 +211,7 @@ class TextBlobBuilder internal constructor(ptr: NativePointer) : Managed(ptr, _F
_ptr, _ptr,
getPtr(font), getPtr(font),
toInterop(glyphs), toInterop(glyphs),
glyphs.size,
toInterop(floatXform) toInterop(floatXform)
) )
} }
...@@ -251,21 +237,36 @@ private external fun TextBlobBuilder_nMake(): NativePointer ...@@ -251,21 +237,36 @@ private external fun TextBlobBuilder_nMake(): NativePointer
private external fun _nBuild(ptr: NativePointer): NativePointer private external fun _nBuild(ptr: NativePointer): NativePointer
@ExternalSymbolName("org_jetbrains_skia_TextBlobBuilder__1nAppendRun") @ExternalSymbolName("org_jetbrains_skia_TextBlobBuilder__1nAppendRun")
private external fun _nAppendRun(ptr: NativePointer, fontPtr: NativePointer, glyphs: InteropPointer, x: Float, y: Float, bounds: Rect?) private external fun _nAppendRun(
ptr: NativePointer, fontPtr: NativePointer,
glyphs: InteropPointer, glyphsLen: Int,
x: Float, y: Float,
bounds: InteropPointer
)
@ExternalSymbolName("org_jetbrains_skia_TextBlobBuilder__1nAppendRunPosH") @ExternalSymbolName("org_jetbrains_skia_TextBlobBuilder__1nAppendRunPosH")
private external fun _nAppendRunPosH( private external fun _nAppendRunPosH(
ptr: NativePointer, ptr: NativePointer,
fontPtr: NativePointer, fontPtr: NativePointer,
glyphs: ShortArray?, glyphs: InteropPointer,
xs: FloatArray?, glyphsLen: Int,
xs: InteropPointer,
y: Float, y: Float,
bounds: Rect? bounds: InteropPointer
) )
@ExternalSymbolName("org_jetbrains_skia_TextBlobBuilder__1nAppendRunPos") @ExternalSymbolName("org_jetbrains_skia_TextBlobBuilder__1nAppendRunPos")
private external fun _nAppendRunPos(ptr: NativePointer, fontPtr: NativePointer, glyphs: InteropPointer, pos: InteropPointer, bounds: Rect?) private external fun _nAppendRunPos(
ptr: NativePointer, fontPtr: NativePointer,
glyphs: InteropPointer, glyphsLen: Int,
pos: InteropPointer,
bounds: InteropPointer
)
@ExternalSymbolName("org_jetbrains_skia_TextBlobBuilder__1nAppendRunRSXform") @ExternalSymbolName("org_jetbrains_skia_TextBlobBuilder__1nAppendRunRSXform")
private external fun _nAppendRunRSXform(ptr: NativePointer, fontPtr: NativePointer, glyphs: InteropPointer, xform: InteropPointer) private external fun _nAppendRunRSXform(
ptr: NativePointer, fontPtr: NativePointer,
glyphs: InteropPointer, glyphsLen: Int,
xform: InteropPointer
)
package org.jetbrains.skia
import org.jetbrains.skia.tests.assertCloseEnough
import org.jetbrains.skia.tests.assertContentCloseEnough
import org.jetbrains.skia.tests.makeFromResource
import org.jetbrains.skiko.KotlinBackend
import org.jetbrains.skiko.kotlinBackend
import org.jetbrains.skiko.tests.runTest
import kotlin.math.cos
import kotlin.math.sin
import kotlin.test.*
class TextBlobBuilderTest {
private val inter36: suspend () -> Font = suspend {
Font(Typeface.makeFromResource("./fonts/Inter-Hinted-Regular.ttf"), 36f)
}
@Test
fun canAppendRunWithText() = runTest {
val glyphs = shortArrayOf(1983, 830, 1213, 1205, 638, 1231, 1326, 161, 611, 721, 721, 773, 1326)
val textBlob = TextBlobBuilder().appendRun(
font = inter36(),
text = "Привет!Hello!",
x = 0f,
y = 0f
).build()!!
assertContentEquals(
expected = glyphs,
actual = textBlob.glyphs
)
// We don't make assertions because bounds vary on platforms. So at least ensure this doesn't throw an exception.
val bounds = textBlob.bounds
}
@Test
fun canAppendRunWithTextAndBounds() = runTest {
val textBlob = TextBlobBuilder().appendRun(
font = inter36(),
text = "Привет!Hello!",
x = 0f,
y = 0f,
bounds = Rect(0f, 0f, 50f, 40f)
).build()!!
assertContentEquals(
expected = shortArrayOf(1983, 830, 1213, 1205, 638, 1231, 1326, 161, 611, 721, 721, 773, 1326),
actual = textBlob.glyphs
)
assertCloseEnough(
expected = Rect(0f, 0f, 50f, 40f),
textBlob.bounds
)
}
@Test
fun canAppendRunWithPositionH() = runTest {
val font = inter36()
val str = "Привет!Hello!"
val glyphs = font.getStringGlyphs(str)
assertEquals(str.length, glyphs.size)
val textBlob = TextBlobBuilder().appendRunPosH(
font = font,
glyphs = glyphs,
bounds = Rect(0f, 0f, 50f, 40f),
xs = FloatArray(glyphs.size) { (it + 1) * 10f },
y = 5f
).build()!!
assertContentEquals(
expected = shortArrayOf(1983, 830, 1213, 1205, 638, 1231, 1326, 161, 611, 721, 721, 773, 1326),
actual = textBlob.glyphs
)
assertContentEquals(
expected = FloatArray(glyphs.size) { (it + 1) * 10f },
actual = textBlob.positions
)
assertCloseEnough(
expected = Rect(0f, 0f, 50f, 40f),
textBlob.bounds
)
}
@Test
fun canAppendRunWithPosition() = runTest {
val font = inter36()
val str = "Привет!Hello!"
val glyphs = font.getStringGlyphs(str)
assertEquals(str.length, glyphs.size)
val positions = FloatArray(glyphs.size * 2) {
if (it % 2 == 1) it + 1f else (it + 1) * 10f
}.toList().chunked(2).map { Point(it[0], it[1]) }.toTypedArray()
val textBlob = TextBlobBuilder().appendRunPos(
font = font,
glyphs = glyphs,
bounds = Rect(0f, 0f, 150f, 40f),
pos = positions
).build()!!
assertContentEquals(
expected = shortArrayOf(1983, 830, 1213, 1205, 638, 1231, 1326, 161, 611, 721, 721, 773, 1326),
actual = textBlob.glyphs
)
assertContentEquals(
expected = positions,
actual = textBlob.positions.toList().chunked(2).map { Point(it[0], it[1]) }.toTypedArray()
)
assertCloseEnough(
expected = Rect(0f, 0f, 150f, 40f),
textBlob.bounds
)
}
@Test
fun canAppendRunWithRSXform() = runTest {
val font = inter36()
val glyphs = shortArrayOf(1983, 830, 1213, 1205, 638, 1231, 1326, 161, 611, 721, 721, 773, 1326)
var angle = 0f
var scale = 1f
val rsxForms = glyphs.map {
val s = sin(angle.toDouble()).toFloat() * scale
val c = cos(angle.toDouble()).toFloat() * scale
angle += .45f
scale += .2f
RSXform(scos = c, ssin = s, tx = -s * 16, ty = c * 16)
}.toTypedArray()
val textBlob = TextBlobBuilder().appendRunRSXform(
font = font,
glyphs = glyphs,
xform = rsxForms
).build()!!
assertContentEquals(
expected = shortArrayOf(1983, 830, 1213, 1205, 638, 1231, 1326, 161, 611, 721, 721, 773, 1326),
actual = textBlob.glyphs
)
assertCloseEnough(
expected = Rect(-243.59294f, -306.74146f, 272.9392f, 173.94711f),
actual = textBlob.bounds,
epsilon = 0.2f
)
assertContentCloseEnough(
expected = floatArrayOf(
1.0f, 0.0f, -0.0f, 16.0f, 1.0805366f, 0.52195865f, -8.351338f, 17.288586f, 0.87025404f, 1.0966578f,
-17.546524f, 13.924065f, 0.35041088f, 1.5611575f, -24.97852f, 5.606574f, -0.4089637f, 1.7529259f,
-28.046814f, -6.5434194f, -1.2563474f, 1.5561466f, -24.898346f, -20.101559f, -1.9889591f, 0.9402358f,
-15.043773f, -31.823345f, -2.3999155f, -0.020177627f, 0.32284203f, -38.398647f, -2.331572f, -1.1505536f,
18.408857f, -37.305153f, -1.7220064f, -2.2078712f, 35.32594f, -27.552103f, -0.6323875f, -2.9325907f,
46.92145f, -10.1182f, 0.75322014f, -3.1100905f, 49.761448f, 12.051522f, 2.1579552f, -2.6274006f,
42.03841f, 34.527283f
),
actual = textBlob.positions,
epsilon = .2f
)
}
@Test
fun canAppendMultipleTimes() = runTest {
val font = inter36()
val textBlob = TextBlobBuilder()
.appendRun(font = font, text = "Привет,", x = 0f, y = 0f)
.appendRun(font = font, text = "Мир!", x = 0f, y = 50f)
.appendRun(font = font, text = "Hello", x = 0f, y = 100f)
.appendRun(font = font, text = "World!", x = 0f, y = 150f)
.build()!!
assertContentEquals(
expected = shortArrayOf(
1983, 830, 1213, 1205, 638, 1231, 1398, 297, 1213, 830, 1326,
161, 611, 721, 721, 773, 455, 773, 835, 721, 593, 1326
),
actual = textBlob.glyphs
)
// We don't make assertions because bounds vary on platforms. So at least ensure this doesn't throw an exception.
val bounds = textBlob.bounds
}
}
...@@ -220,15 +220,14 @@ extern "C" JNIEXPORT jshortArray JNICALL Java_org_jetbrains_skia_FontKt__1nGetSt ...@@ -220,15 +220,14 @@ extern "C" JNIEXPORT jshortArray JNICALL Java_org_jetbrains_skia_FontKt__1nGetSt
return javaShortArray(env, glyphs); return javaShortArray(env, glyphs);
} }
extern "C" JNIEXPORT jshortArray JNICALL Java_org_jetbrains_skia_FontKt__1nGetUTF32Glyphs extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_FontKt__1nGetUTF32Glyphs
(JNIEnv* env, jclass jclass, jlong ptr, jintArray uniArr) { (JNIEnv* env, jclass jclass, jlong ptr, jintArray uniArr, jint uniArrLen, jshortArray resultGlyphs) {
SkFont* instance = reinterpret_cast<SkFont*>(static_cast<uintptr_t>(ptr)); SkFont* instance = reinterpret_cast<SkFont*>(static_cast<uintptr_t>(ptr));
int count = env->GetArrayLength(uniArr); jshort* shorts = env->GetShortArrayElements(resultGlyphs, nullptr);
std::vector<jshort> glyphs(count);
jint* uni = env->GetIntArrayElements(uniArr, nullptr); jint* uni = env->GetIntArrayElements(uniArr, nullptr);
instance->unicharsToGlyphs(reinterpret_cast<SkUnichar*>(uni), count, reinterpret_cast<SkGlyphID*>(glyphs.data())); instance->unicharsToGlyphs(reinterpret_cast<SkUnichar*>(uni), uniArrLen, reinterpret_cast<SkGlyphID*>(shorts));
env->ReleaseIntArrayElements(uniArr, uni, 0); env->ReleaseIntArrayElements(uniArr, uni, 0);
return javaShortArray(env, glyphs); env->ReleaseShortArrayElements(resultGlyphs, shorts, 0);
} }
extern "C" JNIEXPORT jshort JNICALL Java_org_jetbrains_skia_FontKt__1nGetUTF32Glyph extern "C" JNIEXPORT jshort JNICALL Java_org_jetbrains_skia_FontKt__1nGetUTF32Glyph
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include <jni.h> #include <jni.h>
#include "SkTextBlob.h" #include "SkTextBlob.h"
#include "interop.hh" #include "interop.hh"
#include "mppinterop.h"
static void deleteTextBlobBuilder(SkTextBlobBuilder* ptr) { static void deleteTextBlobBuilder(SkTextBlobBuilder* ptr) {
delete ptr; delete ptr;
...@@ -24,43 +25,57 @@ extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_TextBlobBuilderKt__1n ...@@ -24,43 +25,57 @@ extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_TextBlobBuilderKt__1n
} }
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_TextBlobBuilderKt__1nAppendRun extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_TextBlobBuilderKt__1nAppendRun
(JNIEnv* env, jclass jclass, jlong ptr, jlong fontPtr, jshortArray glyphsArr, jfloat x, jfloat y, jobject boundsObj) { (JNIEnv* env, jclass jclass, jlong ptr, jlong fontPtr, jshortArray glyphsArr, jint glyphsLen, jfloat x, jfloat y, jfloatArray rectFloats) {
SkTextBlobBuilder* instance = reinterpret_cast<SkTextBlobBuilder*>(static_cast<uintptr_t>(ptr)); SkTextBlobBuilder* instance = reinterpret_cast<SkTextBlobBuilder*>(static_cast<uintptr_t>(ptr));
SkFont* font = reinterpret_cast<SkFont*>(static_cast<uintptr_t>(fontPtr)); SkFont* font = reinterpret_cast<SkFont*>(static_cast<uintptr_t>(fontPtr));
jsize len = env->GetArrayLength(glyphsArr);
std::unique_ptr<SkRect> bounds = skija::Rect::toSkRect(env, boundsObj); jfloat* skRectFloats = rectFloats != NULL ? env->GetFloatArrayElements(rectFloats, NULL) : NULL;
SkTextBlobBuilder::RunBuffer run = instance->allocRun(*font, len, x, y, bounds.get()); std::unique_ptr<SkRect> bounds = skikoMpp::skrect::toSkRect(reinterpret_cast<float*>(skRectFloats));
env->GetShortArrayRegion(glyphsArr, 0, len, reinterpret_cast<jshort*>(run.glyphs)); if (rectFloats != NULL) {
env->ReleaseFloatArrayElements(rectFloats, skRectFloats, 0);
}
SkTextBlobBuilder::RunBuffer run = instance->allocRun(*font, glyphsLen, x, y, bounds.get());
env->GetShortArrayRegion(glyphsArr, 0, glyphsLen, reinterpret_cast<jshort*>(run.glyphs));
} }
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_TextBlobBuilderKt__1nAppendRunPosH extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_TextBlobBuilderKt__1nAppendRunPosH
(JNIEnv* env, jclass jclass, jlong ptr, jlong fontPtr, jshortArray glyphsArr, jfloatArray xsArr, jfloat y, jobject boundsObj) { (JNIEnv* env, jclass jclass, jlong ptr, jlong fontPtr, jshortArray glyphsArr, jint glyphsLen, jfloatArray xsArr, jfloat y, jfloatArray rectFloats) {
SkTextBlobBuilder* instance = reinterpret_cast<SkTextBlobBuilder*>(static_cast<uintptr_t>(ptr)); SkTextBlobBuilder* instance = reinterpret_cast<SkTextBlobBuilder*>(static_cast<uintptr_t>(ptr));
SkFont* font = reinterpret_cast<SkFont*>(static_cast<uintptr_t>(fontPtr)); SkFont* font = reinterpret_cast<SkFont*>(static_cast<uintptr_t>(fontPtr));
jsize len = env->GetArrayLength(glyphsArr);
std::unique_ptr<SkRect> bounds = skija::Rect::toSkRect(env, boundsObj); jfloat* skRectFloats = rectFloats != NULL ? env->GetFloatArrayElements(rectFloats, NULL) : NULL;
SkTextBlobBuilder::RunBuffer run = instance->allocRunPosH(*font, len, y, bounds.get()); std::unique_ptr<SkRect> bounds = skikoMpp::skrect::toSkRect(reinterpret_cast<float*>(skRectFloats));
env->GetShortArrayRegion(glyphsArr, 0, len, reinterpret_cast<jshort*>(run.glyphs)); if (rectFloats != NULL) {
env->GetFloatArrayRegion(xsArr, 0, len, reinterpret_cast<jfloat*>(run.pos)); env->ReleaseFloatArrayElements(rectFloats, skRectFloats, 0);
}
SkTextBlobBuilder::RunBuffer run = instance->allocRunPosH(*font, glyphsLen, y, bounds.get());
env->GetShortArrayRegion(glyphsArr, 0, glyphsLen, reinterpret_cast<jshort*>(run.glyphs));
env->GetFloatArrayRegion(xsArr, 0, glyphsLen, reinterpret_cast<jfloat*>(run.pos));
} }
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_TextBlobBuilderKt__1nAppendRunPos extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_TextBlobBuilderKt__1nAppendRunPos
(JNIEnv* env, jclass jclass, jlong ptr, jlong fontPtr, jshortArray glyphsArr, jfloatArray posArr, jobject boundsObj) { (JNIEnv* env, jclass jclass, jlong ptr, jlong fontPtr, jshortArray glyphsArr, jint glyphsLen, jfloatArray posArr, jfloatArray rectFloats) {
SkTextBlobBuilder* instance = reinterpret_cast<SkTextBlobBuilder*>(static_cast<uintptr_t>(ptr)); SkTextBlobBuilder* instance = reinterpret_cast<SkTextBlobBuilder*>(static_cast<uintptr_t>(ptr));
SkFont* font = reinterpret_cast<SkFont*>(static_cast<uintptr_t>(fontPtr)); SkFont* font = reinterpret_cast<SkFont*>(static_cast<uintptr_t>(fontPtr));
jsize len = env->GetArrayLength(glyphsArr);
std::unique_ptr<SkRect> bounds = skija::Rect::toSkRect(env, boundsObj); jfloat* skRectFloats = rectFloats != NULL ? env->GetFloatArrayElements(rectFloats, NULL) : NULL;
SkTextBlobBuilder::RunBuffer run = instance->allocRunPos(*font, len, bounds.get()); std::unique_ptr<SkRect> bounds = skikoMpp::skrect::toSkRect(reinterpret_cast<float*>(skRectFloats));
env->GetShortArrayRegion(glyphsArr, 0, len, reinterpret_cast<jshort*>(run.glyphs)); if (rectFloats != NULL) {
env->GetFloatArrayRegion(posArr, 0, len * 2, reinterpret_cast<jfloat*>(run.pos)); env->ReleaseFloatArrayElements(rectFloats, skRectFloats, 0);
}
SkTextBlobBuilder::RunBuffer run = instance->allocRunPos(*font, glyphsLen, bounds.get());
env->GetShortArrayRegion(glyphsArr, 0, glyphsLen, reinterpret_cast<jshort*>(run.glyphs));
env->GetFloatArrayRegion(posArr, 0, glyphsLen * 2, reinterpret_cast<jfloat*>(run.pos));
} }
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_TextBlobBuilderKt__1nAppendRunRSXform extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_TextBlobBuilderKt__1nAppendRunRSXform
(JNIEnv* env, jclass jclass, jlong ptr, jlong fontPtr, jshortArray glyphsArr, jfloatArray xformArr) { (JNIEnv* env, jclass jclass, jlong ptr, jlong fontPtr, jshortArray glyphsArr, jint glyphsLen, jfloatArray xformArr) {
SkTextBlobBuilder* instance = reinterpret_cast<SkTextBlobBuilder*>(static_cast<uintptr_t>(ptr)); SkTextBlobBuilder* instance = reinterpret_cast<SkTextBlobBuilder*>(static_cast<uintptr_t>(ptr));
SkFont* font = reinterpret_cast<SkFont*>(static_cast<uintptr_t>(fontPtr)); SkFont* font = reinterpret_cast<SkFont*>(static_cast<uintptr_t>(fontPtr));
jsize len = env->GetArrayLength(glyphsArr); SkTextBlobBuilder::RunBuffer run = instance->allocRunRSXform(*font, glyphsLen);
SkTextBlobBuilder::RunBuffer run = instance->allocRunRSXform(*font, len); env->GetShortArrayRegion(glyphsArr, 0, glyphsLen, reinterpret_cast<jshort*>(run.glyphs));
env->GetShortArrayRegion(glyphsArr, 0, len, reinterpret_cast<jshort*>(run.glyphs)); env->GetFloatArrayRegion(xformArr, 0, glyphsLen * 4, reinterpret_cast<jfloat*>(run.pos));
env->GetFloatArrayRegion(xformArr, 0, len * 4, reinterpret_cast<jfloat*>(run.pos));
} }
...@@ -230,26 +230,15 @@ SKIKO_EXPORT KShort* org_jetbrains_skia_Font__1nGetStringGlyphs ...@@ -230,26 +230,15 @@ SKIKO_EXPORT KShort* org_jetbrains_skia_Font__1nGetStringGlyphs
} }
#endif #endif
SKIKO_EXPORT void org_jetbrains_skia_Font__1nGetUTF32Glyphs
(KNativePointer ptr, KInt* uniArr, KInt uniArrLen, KShort* resultGlyphs) {
SKIKO_EXPORT KShort* org_jetbrains_skia_Font__1nGetUTF32Glyphs SkFont* instance = reinterpret_cast<SkFont*>(ptr);
(KNativePointer ptr, KInt* uniArr) { instance->unicharsToGlyphs(
TODO("implement org_jetbrains_skia_Font__1nGetUTF32Glyphs"); reinterpret_cast<SkUnichar*>(uniArr), uniArrLen,
reinterpret_cast<SkGlyphID*>(resultGlyphs)
);
} }
#if 0
SKIKO_EXPORT KShort* org_jetbrains_skia_Font__1nGetUTF32Glyphs
(KNativePointer ptr, KInt* uniArr) {
SkFont* instance = reinterpret_cast<SkFont*>((ptr));
int count = env->GetArrayLength(uniArr);
std::vector<KShort> glyphs(count);
KInt* uni = env->GetIntArrayElements(uniArr, nullptr);
instance->unicharsToGlyphs(reinterpret_cast<SkUnichar*>(uni), count, reinterpret_cast<SkGlyphID*>(glyphs.data()));
env->ReleaseIntArrayElements(uniArr, uni, 0);
return javaShortArray(env, glyphs);
}
#endif
SKIKO_EXPORT KShort org_jetbrains_skia_Font__1nGetUTF32Glyph SKIKO_EXPORT KShort org_jetbrains_skia_Font__1nGetUTF32Glyph
(KNativePointer ptr, KInt uni) { (KNativePointer ptr, KInt uni) {
......
...@@ -25,80 +25,49 @@ SKIKO_EXPORT KNativePointer org_jetbrains_skia_TextBlobBuilder__1nBuild ...@@ -25,80 +25,49 @@ SKIKO_EXPORT KNativePointer org_jetbrains_skia_TextBlobBuilder__1nBuild
return reinterpret_cast<KNativePointer>(instance->make().release()); return reinterpret_cast<KNativePointer>(instance->make().release());
} }
SKIKO_EXPORT void org_jetbrains_skia_TextBlobBuilder__1nAppendRun SKIKO_EXPORT void org_jetbrains_skia_TextBlobBuilder__1nAppendRun
(KNativePointer ptr, KNativePointer fontPtr, KShort* glyphsArr, KFloat x, KFloat y, KInteropPointer boundsObj) { (KNativePointer ptr, KNativePointer fontPtr, KShort* glyphsArr, KInt glyphsLen, KFloat x, KFloat y, KFloat* rectFloats) {
TODO("implement org_jetbrains_skia_TextBlobBuilder__1nAppendRun");
}
#if 0 SkTextBlobBuilder* instance = reinterpret_cast<SkTextBlobBuilder*>(ptr);
SKIKO_EXPORT void org_jetbrains_skia_TextBlobBuilder__1nAppendRun SkFont* font = reinterpret_cast<SkFont*>(fontPtr);
(KNativePointer ptr, KNativePointer fontPtr, KShort* glyphsArr, KFloat x, KFloat y, KInteropPointer boundsObj) { std::unique_ptr<SkRect> bounds = skikoMpp::skrect::toSkRect(reinterpret_cast<float*>(rectFloats));
SkTextBlobBuilder* instance = reinterpret_cast<SkTextBlobBuilder*>((ptr)); SkTextBlobBuilder::RunBuffer run = instance->allocRun(*font, glyphsLen, x, y, bounds.get());
SkFont* font = reinterpret_cast<SkFont*>((fontPtr)); memcpy(run.glyphs, glyphsArr, glyphsLen * sizeof(KShort));
jsize len = env->GetArrayLength(glyphsArr);
std::unique_ptr<SkRect> bounds = skija::Rect::toSkRect(env, boundsObj);
SkTextBlobBuilder::RunBuffer run = instance->allocRun(*font, len, x, y, bounds.get());
env->GetShortArrayRegion(glyphsArr, 0, len, reinterpret_cast<KShort*>(run.glyphs));
} }
#endif
SKIKO_EXPORT void org_jetbrains_skia_TextBlobBuilder__1nAppendRunPosH SKIKO_EXPORT void org_jetbrains_skia_TextBlobBuilder__1nAppendRunPosH
(KNativePointer ptr, KNativePointer fontPtr, KShort* glyphsArr, KFloat* xsArr, KFloat y, KInteropPointer boundsObj) { (KNativePointer ptr, KNativePointer fontPtr, KShort* glyphsArr, KInt glyphsLen, KFloat* xsArr, KFloat y, KFloat* rectFloats) {
TODO("implement org_jetbrains_skia_TextBlobBuilder__1nAppendRunPosH");
}
#if 0
SKIKO_EXPORT void org_jetbrains_skia_TextBlobBuilder__1nAppendRunPosH
(KNativePointer ptr, KNativePointer fontPtr, KShort* glyphsArr, KFloat* xsArr, KFloat y, KInteropPointer boundsObj) {
SkTextBlobBuilder* instance = reinterpret_cast<SkTextBlobBuilder*>((ptr)); SkTextBlobBuilder* instance = reinterpret_cast<SkTextBlobBuilder*>((ptr));
SkFont* font = reinterpret_cast<SkFont*>((fontPtr)); SkFont* font = reinterpret_cast<SkFont*>((fontPtr));
jsize len = env->GetArrayLength(glyphsArr);
std::unique_ptr<SkRect> bounds = skija::Rect::toSkRect(env, boundsObj);
SkTextBlobBuilder::RunBuffer run = instance->allocRunPosH(*font, len, y, bounds.get());
env->GetShortArrayRegion(glyphsArr, 0, len, reinterpret_cast<KShort*>(run.glyphs));
env->GetFloatArrayRegion(xsArr, 0, len, reinterpret_cast<KFloat*>(run.pos));
}
#endif
std::unique_ptr<SkRect> bounds = skikoMpp::skrect::toSkRect(reinterpret_cast<float*>(rectFloats));
SkTextBlobBuilder::RunBuffer run = instance->allocRunPosH(*font, glyphsLen, y, bounds.get());
SKIKO_EXPORT void org_jetbrains_skia_TextBlobBuilder__1nAppendRunPos memcpy(run.glyphs, glyphsArr, glyphsLen * sizeof(KShort));
(KNativePointer ptr, KNativePointer fontPtr, KShort* glyphsArr, KFloat* posArr, KInteropPointer boundsObj) { memcpy(run.pos, xsArr, glyphsLen * sizeof(KFloat)); // 1 float per position
TODO("implement org_jetbrains_skia_TextBlobBuilder__1nAppendRunPos");
} }
#if 0
SKIKO_EXPORT void org_jetbrains_skia_TextBlobBuilder__1nAppendRunPos
(KNativePointer ptr, KNativePointer fontPtr, KShort* glyphsArr, KFloat* posArr, KInteropPointer boundsObj) {
SkTextBlobBuilder* instance = reinterpret_cast<SkTextBlobBuilder*>((ptr));
SkFont* font = reinterpret_cast<SkFont*>((fontPtr));
jsize len = env->GetArrayLength(glyphsArr);
std::unique_ptr<SkRect> bounds = skija::Rect::toSkRect(env, boundsObj);
SkTextBlobBuilder::RunBuffer run = instance->allocRunPos(*font, len, bounds.get());
env->GetShortArrayRegion(glyphsArr, 0, len, reinterpret_cast<KShort*>(run.glyphs));
env->GetFloatArrayRegion(posArr, 0, len * 2, reinterpret_cast<KFloat*>(run.pos));
}
#endif
SKIKO_EXPORT void org_jetbrains_skia_TextBlobBuilder__1nAppendRunPos
(KNativePointer ptr, KNativePointer fontPtr, KShort* glyphsArr, KInt glyphsLen, KFloat* posArr, KFloat* rectFloats) {
SkTextBlobBuilder* instance = reinterpret_cast<SkTextBlobBuilder*>(ptr);
SkFont* font = reinterpret_cast<SkFont*>(fontPtr);
std::unique_ptr<SkRect> bounds = skikoMpp::skrect::toSkRect(reinterpret_cast<float*>(rectFloats));
SkTextBlobBuilder::RunBuffer run = instance->allocRunPos(*font, glyphsLen, bounds.get());
SKIKO_EXPORT void org_jetbrains_skia_TextBlobBuilder__1nAppendRunRSXform memcpy(run.glyphs, glyphsArr, glyphsLen * sizeof(KShort));
(KNativePointer ptr, KNativePointer fontPtr, KShort* glyphsArr, KFloat* xformArr) { memcpy(run.pos, posArr, 2 * glyphsLen * sizeof(KFloat)); // 2 floats per position
TODO("implement org_jetbrains_skia_TextBlobBuilder__1nAppendRunRSXform");
} }
#if 0
SKIKO_EXPORT void org_jetbrains_skia_TextBlobBuilder__1nAppendRunRSXform SKIKO_EXPORT void org_jetbrains_skia_TextBlobBuilder__1nAppendRunRSXform
(KNativePointer ptr, KNativePointer fontPtr, KShort* glyphsArr, KFloat* xformArr) { (KNativePointer ptr, KNativePointer fontPtr, KShort* glyphsArr, KInt glyphsLen, KFloat* xformArr) {
SkTextBlobBuilder* instance = reinterpret_cast<SkTextBlobBuilder*>((ptr)); SkTextBlobBuilder* instance = reinterpret_cast<SkTextBlobBuilder*>((ptr));
SkFont* font = reinterpret_cast<SkFont*>((fontPtr)); SkFont* font = reinterpret_cast<SkFont*>((fontPtr));
jsize len = env->GetArrayLength(glyphsArr);
SkTextBlobBuilder::RunBuffer run = instance->allocRunRSXform(*font, len);
env->GetShortArrayRegion(glyphsArr, 0, len, reinterpret_cast<KShort*>(run.glyphs));
env->GetFloatArrayRegion(xformArr, 0, len * 4, reinterpret_cast<KFloat*>(run.pos));
}
#endif
SkTextBlobBuilder::RunBuffer run = instance->allocRunRSXform(*font, glyphsLen);
memcpy(run.glyphs, glyphsArr, glyphsLen * sizeof(KShort));
memcpy(run.pos, xformArr, 4 * glyphsLen * sizeof(KFloat)); // 4 floats per position
}
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