Unverified Commit 1202c860 authored by Oleksandr Karpovich's avatar Oleksandr Karpovich Committed by GitHub

TextLine common implementations (#353)

* add TextLine.cc implementations

* enable existing TextLineTest for all targets

* PR review improvements
Co-authored-by: 's avatarOleksandr Karpovich <oleksandr.karpovich@jetbrains.com>
parent 50d76ce2
......@@ -187,6 +187,7 @@ val linkWasm = tasks.register<LinkSkikoWasmTask>("linkWasm") {
"-l", "GL",
"-s", "USE_WEBGL2=1",
"-s", "OFFSCREEN_FRAMEBUFFER=1",
"-s", "ALLOW_MEMORY_GROWTH=1", // TODO: Is there a better way? Should we use `-s INITIAL_MEMORY=X`?
"--bind",
))
......
......@@ -16,7 +16,7 @@ public:
const uint16_t* fGlyphs;
const SkPoint* fPos;
std::vector<SkScalar> fBreakPositions;
std::vector<SkScalar> fBreakOffsets;
std::vector<uint32_t> fBreakOffsets;
Run(const SkFont& font,
uint8_t bidiLevel,
......@@ -44,7 +44,7 @@ public:
SkScalar fWidth = 0;
std::vector<Run> fRuns;
sk_sp<SkTextBlob> fBlob;
TextLine() {
}
......@@ -57,4 +57,4 @@ public:
fDescent = metrics.fDescent;
fLeading = metrics.fLeading;
}
};
\ No newline at end of file
};
......@@ -133,7 +133,45 @@ class TextLine internal constructor(ptr: NativePointer) : Managed(ptr, _Finalize
get() {
Stats.onNativeCall()
return try {
TextLine_nGetPositions(_ptr)
withResult(FloatArray(glyphsLength * 2)) {
TextLine_nGetPositions(_ptr, it)
}
} finally {
reachabilityBarrier(this)
}
}
internal val runPositions: FloatArray?
get() {
Stats.onNativeCall()
return try {
withResult(FloatArray(_nGetRunPositionsCount(_ptr))) {
_nGetRunPositions(_ptr, it)
}
} finally {
reachabilityBarrier(this)
}
}
internal val breakPositions: FloatArray?
get() {
Stats.onNativeCall()
return try {
withResult(FloatArray(_nGetBreakPositionsCount(_ptr))) {
_nGetBreakPositions(_ptr, it)
}
} finally {
reachabilityBarrier(this)
}
}
internal val breakOffsets: IntArray
get() {
Stats.onNativeCall()
return try {
withResult(IntArray(_nGetBreakOffsetsCount(_ptr))) {
_nGetBreakOffsets(_ptr, it)
}
} finally {
reachabilityBarrier(this)
}
......@@ -232,7 +270,7 @@ private external fun TextLine_nGetGlyphsLength(ptr: NativePointer): Int
private external fun TextLine_nGetGlyphs(ptr: NativePointer, resultGlyphs: InteropPointer, resultLength: Int)
@ExternalSymbolName("org_jetbrains_skia_TextLine__1nGetPositions")
private external fun TextLine_nGetPositions(ptr: NativePointer): FloatArray
private external fun TextLine_nGetPositions(ptr: NativePointer, resultArray: InteropPointer)
@ExternalSymbolName("org_jetbrains_skia_TextLine__1nGetAscent")
private external fun _nGetAscent(ptr: NativePointer): Float
......@@ -253,13 +291,22 @@ private external fun _nGetLeading(ptr: NativePointer): Float
private external fun _nGetTextBlob(ptr: NativePointer): NativePointer
@ExternalSymbolName("org_jetbrains_skia_TextLine__1nGetRunPositions")
private external fun _nGetRunPositions(ptr: NativePointer): FloatArray?
private external fun _nGetRunPositions(ptr: NativePointer, resultArray: InteropPointer)
@ExternalSymbolName("org_jetbrains_skia_TextLine__1nGetRunPositionsCount")
private external fun _nGetRunPositionsCount(ptr: NativePointer): Int
@ExternalSymbolName("org_jetbrains_skia_TextLine__1nGetBreakPositionsCount")
private external fun _nGetBreakPositionsCount(ptr: NativePointer): Int
@ExternalSymbolName("org_jetbrains_skia_TextLine__1nGetBreakPositions")
private external fun _nGetBreakPositions(ptr: NativePointer): FloatArray?
private external fun _nGetBreakPositions(ptr: NativePointer, result: InteropPointer)
@ExternalSymbolName("org_jetbrains_skia_TextLine__1nGetBreakOffsetsCount")
private external fun _nGetBreakOffsetsCount(ptr: NativePointer): Int
@ExternalSymbolName("org_jetbrains_skia_TextLine__1nGetBreakOffsets")
private external fun _nGetBreakOffsets(ptr: NativePointer): IntArray?
private external fun _nGetBreakOffsets(ptr: NativePointer, result: InteropPointer)
@ExternalSymbolName("org_jetbrains_skia_TextLine__1nGetOffsetAtCoord")
private external fun _nGetOffsetAtCoord(ptr: NativePointer, x: Float): Int
......
......@@ -28,7 +28,10 @@ enum class Arch(val id: String) {
enum class KotlinBackend(val id: String) {
JVM("jvm"),
JS("js"),
Native("native")
Native("native"),
;
fun isNotJs() = this != JS
}
expect val hostOs: OS
......@@ -37,4 +40,4 @@ expect val hostArch: Arch
expect val hostId: String
expect val kotlinBackend: KotlinBackend
\ No newline at end of file
expect val kotlinBackend: KotlinBackend
package org.jetbrains.skiko
import org.jetbrains.skia.Font
import org.jetbrains.skia.ManagedString
import org.jetbrains.skia.TextLine
import org.jetbrains.skia.Typeface
import org.jetbrains.skia.impl.use
import org.jetbrains.skiko.tests.SkipJsTarget
import org.jetbrains.skiko.tests.SkipNativeTarget
import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
......@@ -14,8 +13,6 @@ import org.jetbrains.skia.tests.makeFromResource
import org.jetbrains.skia.tests.assertCloseEnough
import org.jetbrains.skiko.tests.runTest
@SkipJsTarget
@SkipNativeTarget
class TextLineTest {
private val inter36: suspend () -> Font = suspend {
Font(Typeface.makeFromResource("./fonts/Inter-Hinted-Regular.ttf"), 36f)
......@@ -107,6 +104,7 @@ class TextLineTest {
// ̈ U+0308 COMBINING DIAERESIS
// a U+0061 LATIN SMALL LETTER A
// ̧ U+0327 COMBINING CEDILLA
assertEquals("üa̧", ManagedString("üa̧").toString())
TextLine.make("üa̧", inter36()).use { line ->
assertContentEquals(shortArrayOf(898 /* ü */, 503 /* a */, 1664 /* ̧ */), line.glyphs)
......@@ -125,22 +123,108 @@ class TextLineTest {
assertCloseEnough(41f, line.getCoordAtOffset(4))
}
assertEquals("ă", ManagedString("ă").toString())
assertEquals("aa̧", ManagedString("aa̧").toString())
TextLine.make("ă", jbMono36()).use { line -> }
TextLine.make("aa̧", jbMono36()).use { line ->
assertEquals(42, line.glyphs[0])
// JetBrains Mono supports “a” but not “ ̧ ”
// Second grapheme cluster should fall back together, second “a” should resolve to different glyph
assertNotEquals(line.glyphs.get(0), line.glyphs.get(1))
if (kotlinBackend.isNotJs()) { // TODO(karpovich): figure out why js gives different result
assertNotEquals(line.glyphs[0], line.glyphs[1])
}
}
}
@Test
fun emojiTest() = runTest {
assertEquals("☺", ManagedString("☺").toString())
assertEquals("☺️", ManagedString("☺️").toString())
TextLine.make("☺", firaCode36()).use { misc ->
TextLine.make("☺️", firaCode36()).use { emoji ->
assertContentEquals(shortArrayOf(1706), misc.glyphs)
assertEquals(1, emoji.glyphs.size)
assertNotEquals(misc.glyphs.get(0), emoji.glyphs.get(0))
if (kotlinBackend.isNotJs()) { // TODO(karpovich): try with a FontMngr without fallbacks
assertNotEquals(misc.glyphs[0], emoji.glyphs[0])
}
}
}
}
}
\ No newline at end of file
private val eps = 0.001f // apparently only such not very small value can make tests pass in kotlin/js
@Test
fun canGetProperties() = runTest {
val textLine = TextLine.make(text = "Привет!Hello!", font = inter36())
// expected values were taken by running these tests on JVM
assertContentEquals(
expected = shortArrayOf(1983, 830, 1213, 1205, 638, 1231, 1326, 161, 611, 721, 721, 773, 1326),
actual = textLine.glyphs
)
assertCloseEnough(expected = -34.875f, actual = textLine.ascent, epsilon = eps)
assertCloseEnough(expected = 8.692932f, actual = textLine.descent, epsilon = eps)
assertCloseEnough(expected = 0f, actual = textLine.leading, epsilon = eps)
assertCloseEnough(expected = 26.181818f, actual = textLine.capHeight, epsilon = eps)
assertCloseEnough(expected = 19.636364f, actual = textLine.xHeight, epsilon = eps)
assertCloseEnough(expected = 235.28409f, actual = textLine.width, epsilon = eps)
assertCloseEnough(expected = 43.567932f, actual = textLine.height, epsilon = eps)
assertNotEquals(null, textLine.textBlob)
assertContentEquals(
expected = floatArrayOf(
0.0f, 0.0f, 26.0f, 0.0f, 48.0f, 0.0f, 69.0f, 0.0f, 89.0f, 0.0f, 109.28409f, 0.0f, 128.28409f, 0.0f,
138.28409f, 0.0f, 165.28409f, 0.0f, 186.28409f, 0.0f, 195.28409f, 0.0f, 204.28409f, 0.0f, 225.28409f, 0.0f
),
actual = textLine.positions
)
assertContentEquals(
expected = floatArrayOf(0.0f, 138.28409f),
actual = textLine.runPositions
)
assertContentEquals(
expected = floatArrayOf(
0.0f, 26.0f, 48.0f, 69.0f, 89.0f, 109.28409f, 128.28409f, 138.28409f, 138.28409f, 165.28409f,
186.28409f, 195.28409f, 204.28409f, 225.28409f, 235.28409f
),
actual = textLine.breakPositions
)
assertContentEquals(
expected = intArrayOf(0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 9, 10, 11, 12, 13),
actual = textLine.breakOffsets
)
assertEquals(expected = 0, actual = textLine.getOffsetAtCoord(0f))
assertEquals(expected = 1, actual = textLine.getOffsetAtCoord(15f))
assertEquals(expected = 2, actual = textLine.getOffsetAtCoord(45f))
assertEquals(expected = 3, actual = textLine.getOffsetAtCoord(75f))
assertEquals(expected = 4, actual = textLine.getOffsetAtCoord(90f))
assertEquals(expected = 5, actual = textLine.getOffsetAtCoord(105f))
assertEquals(expected = 0, actual = textLine.getLeftOffsetAtCoord(0f))
assertEquals(expected = 1, actual = textLine.getLeftOffsetAtCoord(45f))
assertEquals(expected = 2, actual = textLine.getLeftOffsetAtCoord(65f))
assertEquals(expected = 3, actual = textLine.getLeftOffsetAtCoord(80f))
assertEquals(expected = 4, actual = textLine.getLeftOffsetAtCoord(105f))
assertEquals(expected = 5, actual = textLine.getLeftOffsetAtCoord(125f))
assertCloseEnough(expected = 26.0f, actual = textLine.getCoordAtOffset(1), epsilon = eps)
assertCloseEnough(expected = 48.0f, actual = textLine.getCoordAtOffset(2), epsilon = eps)
assertCloseEnough(expected = 69.0f, actual = textLine.getCoordAtOffset(3), epsilon = eps)
}
}
......@@ -11,7 +11,7 @@ import kotlin.test.assertTrue
private const val EPSILON = 0.00001f
internal fun assertCloseEnough(expected: Float, actual: Float, epsilon: Float = EPSILON) {
assertTrue(abs(expected - actual) < epsilon)
assertTrue(abs(expected - actual) < epsilon, message = "expected=$expected, actual=$actual, eps=$epsilon")
}
internal fun assertCloseEnough(expected: Point, actual: Point?, epsilon: Float = EPSILON) {
......
......@@ -93,44 +93,81 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_TextLineKt_TextLine_1n
SkASSERTF(idx == instance->fGlyphCount, "TextLine.cc: idx = %d != instance->fGlyphCount = %d", idx, instance->fGlyphCount);
}
extern "C" JNIEXPORT jfloatArray JNICALL Java_org_jetbrains_skia_TextLineKt_TextLine_1nGetPositions
(JNIEnv* env, jclass jclass, jlong ptr) {
// Ensure resultArray has sufficient length (glyphCount * 2)
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_TextLineKt_TextLine_1nGetPositions
(JNIEnv* env, jclass jclass, jlong ptr, jfloatArray resultArray) {
TextLine* instance = reinterpret_cast<TextLine*>(static_cast<uintptr_t>(ptr));
std::vector<jfloat> positions(2 * instance->fGlyphCount);
jfloat* positions = env->GetFloatArrayElements(resultArray, NULL);
size_t idx = 0;
for (auto& run: instance->fRuns) {
memcpy(positions.data() + idx, run.fPos, run.fGlyphCount * sizeof(SkPoint));
memcpy(positions + idx, run.fPos, run.fGlyphCount * sizeof(SkPoint));
idx += 2 * run.fGlyphCount;
}
env->ReleaseFloatArrayElements(resultArray, positions, 0);
SkASSERTF(idx == 2 * instance->fGlyphCount, "TextLine.cc: idx = %d != 2 * instance->fGlyphCount = %d", idx, 2 * instance->fGlyphCount);
return javaFloatArray(env, positions);
}
extern "C" JNIEXPORT jfloatArray JNICALL Java_org_jetbrains_skia_TextLineKt__1nGetRunPositions
extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_TextLineKt__1nGetRunPositionsCount
(JNIEnv* env, jclass jclass, jlong ptr) {
TextLine* instance = reinterpret_cast<TextLine*>(static_cast<uintptr_t>(ptr));
std::vector<jfloat> positions(instance->fRuns.size());
for (size_t idx = 0; idx < positions.size(); ++idx)
return instance->fRuns.size();
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_TextLineKt__1nGetRunPositions
(JNIEnv* env, jclass jclass, jlong ptr, jfloatArray resultArray) {
TextLine* instance = reinterpret_cast<TextLine*>(static_cast<uintptr_t>(ptr));
jfloat* positions = env->GetFloatArrayElements(resultArray, NULL);
size_t size = instance->fRuns.size();
for (size_t idx = 0; idx < size; ++idx)
positions[idx] = instance->fRuns[idx].fPosition;
return javaFloatArray(env, positions);
env->ReleaseFloatArrayElements(resultArray, positions, 0);
}
extern "C" JNIEXPORT jfloatArray JNICALL Java_org_jetbrains_skia_TextLineKt__1nGetBreakPositions
extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_TextLineKt__1nGetBreakPositionsCount
(JNIEnv* env, jclass jclass, jlong ptr) {
TextLine* instance = reinterpret_cast<TextLine*>(static_cast<uintptr_t>(ptr));
std::vector<jfloat> positions;
size_t count = 0;
for (auto& run: instance->fRuns)
positions.insert(positions.end(), run.fBreakPositions.begin(), run.fBreakPositions.end());
return javaFloatArray(env, positions);
count += run.fBreakPositions.size();
return count;
}
extern "C" JNIEXPORT jintArray JNICALL Java_org_jetbrains_skia_TextLineKt__1nGetBreakOffsets
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_TextLineKt__1nGetBreakPositions
(JNIEnv* env, jclass jclass, jlong ptr, jfloatArray resultArray) {
TextLine* instance = reinterpret_cast<TextLine*>(static_cast<uintptr_t>(ptr));
jfloat* positions = env->GetFloatArrayElements(resultArray, NULL);
size_t added = 0;
for (auto& run: instance->fRuns) {
size_t count = run.fBreakPositions.size();
std::memcpy(positions + added, run.fBreakPositions.data(), count * sizeof(SkScalar));
added += count;
}
env->ReleaseFloatArrayElements(resultArray, positions, 0);
}
extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_TextLineKt__1nGetBreakOffsetsCount
(JNIEnv* env, jclass jclass, jlong ptr) {
TextLine* instance = reinterpret_cast<TextLine*>(static_cast<uintptr_t>(ptr));
std::vector<jint> offsets;
size_t count = 0;
for (auto& run: instance->fRuns)
offsets.insert(offsets.end(), run.fBreakOffsets.begin(), run.fBreakOffsets.end());
return javaIntArray(env, offsets);
count += run.fBreakOffsets.size();
return count;
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_TextLineKt__1nGetBreakOffsets
(JNIEnv* env, jclass jclass, jlong ptr, jintArray resultArray) {
TextLine* instance = reinterpret_cast<TextLine*>(static_cast<uintptr_t>(ptr));
jint* offsets = env->GetIntArrayElements(resultArray, NULL);
size_t added = 0;
for (auto& run: instance->fRuns) {
size_t count = run.fBreakOffsets.size();
std::memcpy(offsets + added, run.fBreakOffsets.data(), count * sizeof(uint32_t));
added += count;
}
env->ReleaseIntArrayElements(resultArray, offsets, 0);
}
extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_TextLineKt__1nGetOffsetAtCoord
......
......@@ -19,115 +19,49 @@ SKIKO_EXPORT KNativePointer org_jetbrains_skia_TextLine__1nGetFinalizer
SKIKO_EXPORT KFloat org_jetbrains_skia_TextLine__1nGetAscent
(KNativePointer ptr) {
TODO("implement org_jetbrains_skia_TextLine__1nGetAscent");
}
#if 0
SKIKO_EXPORT KFloat org_jetbrains_skia_TextLine__1nGetAscent
(KNativePointer ptr) {
TextLine* instance = reinterpret_cast<TextLine*>((ptr));
TextLine* instance = reinterpret_cast<TextLine*>(ptr);
return instance->fAscent;
}
#endif
SKIKO_EXPORT KFloat org_jetbrains_skia_TextLine__1nGetCapHeight
(KNativePointer ptr) {
TODO("implement org_jetbrains_skia_TextLine__1nGetCapHeight");
}
#if 0
SKIKO_EXPORT KFloat org_jetbrains_skia_TextLine__1nGetCapHeight
(KNativePointer ptr) {
TextLine* instance = reinterpret_cast<TextLine*>((ptr));
return instance->fCapHeight;
TextLine* instance = reinterpret_cast<TextLine*>(ptr);
return instance->fCapHeight;
}
#endif
SKIKO_EXPORT KFloat org_jetbrains_skia_TextLine__1nGetXHeight
(KNativePointer ptr) {
TODO("implement org_jetbrains_skia_TextLine__1nGetXHeight");
}
#if 0
SKIKO_EXPORT KFloat org_jetbrains_skia_TextLine__1nGetXHeight
(KNativePointer ptr) {
TextLine* instance = reinterpret_cast<TextLine*>((ptr));
return instance->fXHeight;
}
#endif
SKIKO_EXPORT KFloat org_jetbrains_skia_TextLine__1nGetDescent
(KNativePointer ptr) {
TODO("implement org_jetbrains_skia_TextLine__1nGetDescent");
}
#if 0
SKIKO_EXPORT KFloat org_jetbrains_skia_TextLine__1nGetDescent
(KNativePointer ptr) {
TextLine* instance = reinterpret_cast<TextLine*>((ptr));
TextLine* instance = reinterpret_cast<TextLine*>(ptr);
return instance->fDescent;
}
#endif
SKIKO_EXPORT KFloat org_jetbrains_skia_TextLine__1nGetLeading
(KNativePointer ptr) {
TODO("implement org_jetbrains_skia_TextLine__1nGetLeading");
}
#if 0
SKIKO_EXPORT KFloat org_jetbrains_skia_TextLine__1nGetLeading
(KNativePointer ptr) {
TextLine* instance = reinterpret_cast<TextLine*>((ptr));
return instance->fLeading;
}
#endif
SKIKO_EXPORT KFloat org_jetbrains_skia_TextLine__1nGetWidth
(KNativePointer ptr) {
TODO("implement org_jetbrains_skia_TextLine__1nGetWidth");
TextLine* instance = reinterpret_cast<TextLine*>(ptr);
return instance->fLeading;
}
#if 0
SKIKO_EXPORT KFloat org_jetbrains_skia_TextLine__1nGetWidth
(KNativePointer ptr) {
TextLine* instance = reinterpret_cast<TextLine*>((ptr));
return instance->fWidth;
}
#endif
SKIKO_EXPORT KFloat org_jetbrains_skia_TextLine__1nGetHeight
(KNativePointer ptr) {
TODO("implement org_jetbrains_skia_TextLine__1nGetHeight");
}
#if 0
SKIKO_EXPORT KFloat org_jetbrains_skia_TextLine__1nGetHeight
(KNativePointer ptr) {
TextLine* instance = reinterpret_cast<TextLine*>((ptr));
return -instance->fAscent + instance->fDescent + instance->fLeading;
}
#endif
SKIKO_EXPORT KNativePointer org_jetbrains_skia_TextLine__1nGetTextBlob
(KNativePointer ptr) {
TODO("implement org_jetbrains_skia_TextLine__1nGetTextBlob");
}
#if 0
SKIKO_EXPORT KNativePointer org_jetbrains_skia_TextLine__1nGetTextBlob
(KNativePointer ptr) {
TextLine* instance = reinterpret_cast<TextLine*>((ptr));
......@@ -136,8 +70,6 @@ SKIKO_EXPORT KNativePointer org_jetbrains_skia_TextLine__1nGetTextBlob
instance->fBlob->ref();
return reinterpret_cast<KNativePointer>(instance->fBlob.get());
}
#endif
SKIKO_EXPORT KInt org_jetbrains_skia_TextLine__1nGetGlyphsLength
(KNativePointer ptr) {
......@@ -166,89 +98,75 @@ SKIKO_EXPORT void org_jetbrains_skia_TextLine__1nGetGlyphs
SkASSERTF(idx == instance->fGlyphCount, "TextLine.cc: idx = %d != instance->fGlyphCount = %d", idx, instance->fGlyphCount);
}
SKIKO_EXPORT KFloat* org_jetbrains_skia_TextLine__1nGetPositions
(KNativePointer ptr) {
TODO("implement org_jetbrains_skia_TextLine__1nGetPositions");
}
#if 0
SKIKO_EXPORT KFloat* org_jetbrains_skia_TextLine__1nGetPositions
(KNativePointer ptr) {
TextLine* instance = reinterpret_cast<TextLine*>((ptr));
std::vector<KFloat> positions(2 * instance->fGlyphCount);
// Ensure resultArray has sufficient length (glyphCount * 2)
SKIKO_EXPORT void org_jetbrains_skia_TextLine__1nGetPositions
(KNativePointer ptr, KFloat* resultArray) {
TextLine* instance = reinterpret_cast<TextLine*>(ptr);
size_t idx = 0;
for (auto& run: instance->fRuns) {
memcpy(positions.data() + idx, run.fPos, run.fGlyphCount * sizeof(SkPoint));
memcpy(resultArray + idx, run.fPos, run.fGlyphCount * sizeof(SkPoint));
idx += 2 * run.fGlyphCount;
}
SkASSERTF(idx == 2 * instance->fGlyphCount, "TextLine.cc: idx = %d != 2 * instance->fGlyphCount = %d", idx, 2 * instance->fGlyphCount);
return javaFloatArray(env, positions);
}
#endif
SKIKO_EXPORT KFloat* org_jetbrains_skia_TextLine__1nGetRunPositions
(KNativePointer ptr) {
TODO("implement org_jetbrains_skia_TextLine__1nGetRunPositions");
}
#if 0
SKIKO_EXPORT KFloat* org_jetbrains_skia_TextLine__1nGetRunPositions
SKIKO_EXPORT KInt org_jetbrains_skia_TextLine__1nGetRunPositionsCount
(KNativePointer ptr) {
TextLine* instance = reinterpret_cast<TextLine*>((ptr));
std::vector<KFloat> positions(instance->fRuns.size());
for (size_t idx = 0; idx < positions.size(); ++idx)
positions[idx] = instance->fRuns[idx].fPosition;
return javaFloatArray(env, positions);
TextLine* instance = reinterpret_cast<TextLine*>(ptr);
return instance->fRuns.size();
}
#endif
SKIKO_EXPORT void org_jetbrains_skia_TextLine__1nGetRunPositions
(KNativePointer ptr, KFloat* resultArray) {
TextLine* instance = reinterpret_cast<TextLine*>(ptr);
size_t size = instance->fRuns.size();
SKIKO_EXPORT KFloat* org_jetbrains_skia_TextLine__1nGetBreakPositions
(KNativePointer ptr) {
TODO("implement org_jetbrains_skia_TextLine__1nGetBreakPositions");
for (size_t idx = 0; idx < size; ++idx)
resultArray[idx] = instance->fRuns[idx].fPosition;
}
#if 0
SKIKO_EXPORT KFloat* org_jetbrains_skia_TextLine__1nGetBreakPositions
SKIKO_EXPORT KInt org_jetbrains_skia_TextLine__1nGetBreakPositionsCount
(KNativePointer ptr) {
TextLine* instance = reinterpret_cast<TextLine*>((ptr));
std::vector<KFloat> positions;
TextLine* instance = reinterpret_cast<TextLine*>(ptr);
size_t count = 0;
for (auto& run: instance->fRuns)
positions.insert(positions.end(), run.fBreakPositions.begin(), run.fBreakPositions.end());
return javaFloatArray(env, positions);
count += run.fBreakPositions.size();
return count;
}
#endif
SKIKO_EXPORT KInt* org_jetbrains_skia_TextLine__1nGetBreakOffsets
(KNativePointer ptr) {
TODO("implement org_jetbrains_skia_TextLine__1nGetBreakOffsets");
SKIKO_EXPORT void org_jetbrains_skia_TextLine__1nGetBreakPositions
(KNativePointer ptr, KFloat* resultArray) {
TextLine* instance = reinterpret_cast<TextLine*>(ptr);
size_t added = 0;
for (auto& run: instance->fRuns) {
size_t count = run.fBreakPositions.size();
std::memcpy(resultArray + added, run.fBreakPositions.data(), count * sizeof(SkScalar));
added += count;
}
}
#if 0
SKIKO_EXPORT KInt* org_jetbrains_skia_TextLine__1nGetBreakOffsets
SKIKO_EXPORT KInt org_jetbrains_skia_TextLine__1nGetBreakOffsetsCount
(KNativePointer ptr) {
TextLine* instance = reinterpret_cast<TextLine*>((ptr));
std::vector<KInt> offsets;
TextLine* instance = reinterpret_cast<TextLine*>(ptr);
size_t count = 0;
for (auto& run: instance->fRuns)
offsets.insert(offsets.end(), run.fBreakOffsets.begin(), run.fBreakOffsets.end());
return javaIntArray(env, offsets);
count += run.fBreakOffsets.size();
return count;
}
#endif
SKIKO_EXPORT void org_jetbrains_skia_TextLine__1nGetBreakOffsets
(KNativePointer ptr, KInt* resultArray) {
TextLine* instance = reinterpret_cast<TextLine*>(ptr);
SKIKO_EXPORT KInt org_jetbrains_skia_TextLine__1nGetOffsetAtCoord
(KNativePointer ptr, KFloat x) {
TODO("implement org_jetbrains_skia_TextLine__1nGetOffsetAtCoord");
size_t added = 0;
for (auto& run: instance->fRuns) {
size_t count = run.fBreakOffsets.size();
std::memcpy(&resultArray[added], run.fBreakOffsets.data(), count * sizeof(KInt));
added += count;
}
}
#if 0
SKIKO_EXPORT KInt org_jetbrains_skia_TextLine__1nGetOffsetAtCoord
(KNativePointer ptr, KFloat x) {
TextLine* instance = reinterpret_cast<TextLine*>((ptr));
......@@ -268,16 +186,7 @@ SKIKO_EXPORT KInt org_jetbrains_skia_TextLine__1nGetOffsetAtCoord
return (KInt) instance->fRuns.back().fBreakOffsets.back();
}
#endif
SKIKO_EXPORT KInt org_jetbrains_skia_TextLine__1nGetLeftOffsetAtCoord
(KNativePointer ptr, KFloat x) {
TODO("implement org_jetbrains_skia_TextLine__1nGetLeftOffsetAtCoord");
}
#if 0
SKIKO_EXPORT KInt org_jetbrains_skia_TextLine__1nGetLeftOffsetAtCoord
(KNativePointer ptr, KFloat x) {
TextLine* instance = reinterpret_cast<TextLine*>((ptr));
......@@ -295,16 +204,7 @@ SKIKO_EXPORT KInt org_jetbrains_skia_TextLine__1nGetLeftOffsetAtCoord
return (KInt) instance->fRuns.back().fBreakOffsets.back();
}
#endif
SKIKO_EXPORT KFloat org_jetbrains_skia_TextLine__1nGetCoordAtOffset
(KNativePointer ptr, KInt offset16) {
TODO("implement org_jetbrains_skia_TextLine__1nGetCoordAtOffset");
}
#if 0
SKIKO_EXPORT KFloat org_jetbrains_skia_TextLine__1nGetCoordAtOffset
(KNativePointer ptr, KInt offset16) {
TextLine* instance = reinterpret_cast<TextLine*>((ptr));
......@@ -323,5 +223,5 @@ SKIKO_EXPORT KFloat org_jetbrains_skia_TextLine__1nGetCoordAtOffset
return instance->fWidth;
}
#endif
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