Unverified Commit 10bb62f3 authored by Shagen Ogandzhanian's avatar Shagen Ogandzhanian Committed by GitHub

Array serialization revisited (#387)

parent 30b588f5
......@@ -22,6 +22,10 @@ namespace skikoMpp {
int getClustersLength(SkTextBlob* instance);
bool getClusters(SkTextBlob* instance, int* clusters);
}
namespace finalizers {
void deleteString(void* instance);
}
}
namespace skija {
......
#include "mppinterop.h"
#include "RunRecordClone.hh"
#include "src/utils/SkUTF.h"
#include <iostream>
namespace skikoMpp {
namespace skrect {
......@@ -192,6 +193,12 @@ namespace skikoMpp {
return true;
}
}
namespace finalizers {
void deleteString(void* instance) {
delete reinterpret_cast<SkString*>(instance);
}
}
}
......
......@@ -62,7 +62,7 @@ class ManagedString internal constructor(ptr: NativePointer, managed: Boolean =
}
@ExternalSymbolName("org_jetbrains_skia_ManagedString__1nGetFinalizer")
private external fun ManagedString_nGetFinalizer(): NativePointer
internal external fun ManagedString_nGetFinalizer(): NativePointer
@ExternalSymbolName("org_jetbrains_skia_ManagedString__1nMake")
private external fun _nMake(s: InteropPointer): NativePointer
......
package org.jetbrains.skia
import org.jetbrains.skia.impl.NativePointer
@ExternalSymbolName("org_jetbrains_skia_StdVectorDecoder__1nGetArraySize")
private external fun StdVectorDecoder_nGetArraySize(array: NativePointer): Int
@ExternalSymbolName("org_jetbrains_skia_StdVectorDecoder__1nDisposeArray")
private external fun StdVectorDecoder_nDisposeArray(array: NativePointer, disposePtr: NativePointer)
@ExternalSymbolName("org_jetbrains_skia_StdVectorDecoder__1nReleaseElement")
private external fun StdVectorDecoder_nReleaseElement(array: NativePointer, index: Int): NativePointer
class ArrayDecoder(private val ptr: NativePointer, private val disposePtr: NativePointer) {
fun dispose() {
StdVectorDecoder_nDisposeArray(ptr, disposePtr)
}
fun release(index: Int): NativePointer {
return StdVectorDecoder_nReleaseElement(ptr, index)
}
val size: Int
get() = StdVectorDecoder_nGetArraySize(ptr)
}
inline fun <T> arrayDecoderScope(arrayDecoderBlock: () -> ArrayDecoder, block: (arrayCode: ArrayDecoder) -> T): T {
var arrayDecoder: ArrayDecoder? = null
return try {
arrayDecoder = arrayDecoderBlock()
block.invoke(arrayDecoder)
} finally {
arrayDecoder?.dispose()
}
}
\ No newline at end of file
package org.jetbrains.skia
import org.jetbrains.skia.impl.*
import org.jetbrains.skia.impl.InteropPointer
import org.jetbrains.skia.impl.Library.Companion.staticLoad
import org.jetbrains.skiko.kotlinBackend
import org.jetbrains.skia.impl.Native
import org.jetbrains.skia.impl.NativePointer
import org.jetbrains.skia.impl.RefCnt
import org.jetbrains.skia.impl.Stats
import org.jetbrains.skia.impl.getPtr
import org.jetbrains.skia.impl.interopScope
import org.jetbrains.skia.impl.reachabilityBarrier
import org.jetbrains.skia.impl.withNullableResult
import org.jetbrains.skia.impl.withResult
import org.jetbrains.skia.impl.withStringResult
class Typeface internal constructor(ptr: NativePointer) : RefCnt(ptr) {
companion object {
......@@ -119,7 +128,13 @@ class Typeface internal constructor(ptr: NativePointer) : RefCnt(ptr) {
}
(0 until axisCount).map { i ->
val j = 5 * i
FontVariationAxis(axisData[j], Float.fromBits(axisData[j + 1]), Float.fromBits(axisData[j + 2]), Float.fromBits(axisData[j + 3]), axisData[j + 4] != 0)
FontVariationAxis(
axisData[j],
Float.fromBits(axisData[j + 1]),
Float.fromBits(axisData[j + 2]),
Float.fromBits(axisData[j + 3]),
axisData[j + 4] != 0
)
}.toTypedArray()
}
} finally {
......@@ -177,8 +192,9 @@ class Typeface internal constructor(ptr: NativePointer) : RefCnt(ptr) {
return try {
if (variations.size == 0) return this
Stats.onNativeCall()
val variationsData = variations.asList().flatMap { listOf(it._tag, it.value.toRawBits())}.toIntArray()
val ptr = interopScope { _nMakeClone(_ptr, toInterop(variationsData), 2 * variations.size, collectionIndex) }
val variationsData = variations.asList().flatMap { listOf(it._tag, it.value.toRawBits()) }.toIntArray()
val ptr =
interopScope { _nMakeClone(_ptr, toInterop(variationsData), 2 * variations.size, collectionIndex) }
require(ptr != NullPointer) {
"Failed to clone Typeface $this with $variations"
}
......@@ -339,12 +355,24 @@ class Typeface internal constructor(ptr: NativePointer) : RefCnt(ptr) {
* @return all of the family names specified by the font
*/
val familyNames: Array<FontFamilyName>
get() = try {
get() {
return try {
Stats.onNativeCall()
_nGetFamilyNames(_ptr)
arrayDecoderScope({
ArrayDecoder(_nGetFamilyNames(_ptr), ManagedString_nGetFinalizer())
}) { arrayDecoder ->
val size = arrayDecoder.size
(0 until size / 2).map { i ->
val name = withStringResult(arrayDecoder.release(2 * i))
val language = withStringResult(arrayDecoder.release(2 * i + 1))
FontFamilyName(name, language)
}.toTypedArray()
}
} finally {
reachabilityBarrier(this)
}
}
/**
* @return the family name for this typeface. The language of the name is whatever the host platform chooses
......@@ -383,7 +411,12 @@ private external fun Typeface_nEquals(ptr: NativePointer, otherPtr: NativePointe
private external fun Typeface_nMakeDefault(): NativePointer
@ExternalSymbolName("org_jetbrains_skia_Typeface__1nGetUTF32Glyphs")
private external fun Typeface_nGetUTF32Glyphs(ptr: NativePointer, uni: InteropPointer, count: Int, glyphs: InteropPointer)
private external fun Typeface_nGetUTF32Glyphs(
ptr: NativePointer,
uni: InteropPointer,
count: Int,
glyphs: InteropPointer
)
@ExternalSymbolName("org_jetbrains_skia_Typeface__1nGetUTF32Glyph")
private external fun Typeface_nGetUTF32Glyph(ptr: NativePointer, unichar: Int): Short
......@@ -419,7 +452,12 @@ internal external fun _nMakeFromFile(path: InteropPointer, index: Int): NativePo
private external fun _nMakeFromData(dataPtr: NativePointer, index: Int): NativePointer
@ExternalSymbolName("org_jetbrains_skia_Typeface__1nMakeClone")
private external fun _nMakeClone(ptr: NativePointer, variations: InteropPointer, variationsCount: Int, collectionIndex: Int): NativePointer
private external fun _nMakeClone(
ptr: NativePointer,
variations: InteropPointer,
variationsCount: Int,
collectionIndex: Int
): NativePointer
@ExternalSymbolName("org_jetbrains_skia_Typeface__1nGetGlyphsCount")
private external fun _nGetGlyphsCount(ptr: NativePointer): Int
......@@ -443,10 +481,15 @@ private external fun _nGetTableData(ptr: NativePointer, tag: Int): NativePointer
private external fun _nGetUnitsPerEm(ptr: NativePointer): Int
@ExternalSymbolName("org_jetbrains_skia_Typeface__1nGetKerningPairAdjustments")
private external fun _nGetKerningPairAdjustments(ptr: NativePointer, glyphs: ShortArray, count: Int, adjustments: InteropPointer): Boolean
private external fun _nGetKerningPairAdjustments(
ptr: NativePointer,
glyphs: ShortArray,
count: Int,
adjustments: InteropPointer
): Boolean
@ExternalSymbolName("org_jetbrains_skia_Typeface__1nGetFamilyNames")
private external fun _nGetFamilyNames(ptr: NativePointer): Array<FontFamilyName>
private external fun _nGetFamilyNames(ptr: NativePointer): NativePointer
@ExternalSymbolName("org_jetbrains_skia_Typeface__1nGetFamilyName")
private external fun _nGetFamilyName(ptr: NativePointer): NativePointer
\ No newline at end of file
......@@ -135,8 +135,12 @@ inline fun withResult(result: NativePointerArray, block: InteropScope.(InteropPo
*/
@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE")
inline fun withStringResult(block: () -> NativePointer): String {
val string = ManagedString(block())
return string.toString()
return ManagedString(block()).use { it.toString() }
}
@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE")
inline fun withStringResult(pointer: NativePointer): String {
return ManagedString(pointer).use { it.toString() }
}
/**
......
......@@ -86,9 +86,7 @@ class TypefaceTest {
assertNull(jbMono.getKerningPairAdjustments(null))
assertNull(jbMono.getKerningPairAdjustments(jbMono.getStringGlyphs("TAV")))
if (kotlinBackend == KotlinBackend.JVM) {
assertContentEquals(arrayOf(FontFamilyName("Inter", "en-US")), interV.familyNames)
}
assertEquals("Inter", interV.familyName)
}
......
#include <jni.h>
#include "interop.hh"
#include "mppinterop.h"
#include "SkString.h"
static void deleteString(SkString* instance) {
delete instance;
}
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_ManagedStringKt_ManagedString_1nGetFinalizer
(JNIEnv* env, jclass jclass) {
return static_cast<jlong>(reinterpret_cast<uintptr_t>(&deleteString));
return static_cast<jlong>(reinterpret_cast<uintptr_t>(&skikoMpp::finalizers::deleteString));
}
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_ManagedStringKt__1nMake
......
#include <jni.h>
#include "interop.hh"
extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_StdVectorDecoderKt_StdVectorDecoder_1nGetArraySize
(JNIEnv* env, jclass jclass, jlong ptr) {
std::vector<void*>* vec = reinterpret_cast<std::vector<void*> *>(ptr);
return static_cast<jint>(vec->size());
}
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_StdVectorDecoderKt_StdVectorDecoder_1nReleaseElement
(JNIEnv* env, jclass jclass, jlong ptr, jint index) {
auto& vec = *reinterpret_cast<std::vector<void*> *>(ptr);
auto res = vec[index];
vec[index] = nullptr;
return reinterpret_cast<jlong>(res);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_StdVectorDecoderKt_StdVectorDecoder_1nDisposeArray
(JNIEnv* env, jclass jclass, jlong ptr, jlong disposePtr) {
std::vector<void*>* vec = reinterpret_cast<std::vector<void*> *>(ptr);
void (*dtor)(void*) = reinterpret_cast<void (*)(void*)>(disposePtr);
while (!vec->empty()){
auto res = vec->back();
if (res != nullptr) {
dtor(res);
}
vec->pop_back();
}
delete vec;
}
\ No newline at end of file
......@@ -198,24 +198,20 @@ extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skia_TypefaceKt__1nGetK
return false;
}
extern "C" JNIEXPORT jobjectArray JNICALL Java_org_jetbrains_skia_TypefaceKt__1nGetFamilyNames
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_TypefaceKt__1nGetFamilyNames
(JNIEnv* env, jclass jclass, jlong ptr) {
SkTypeface* instance = reinterpret_cast<SkTypeface*>(static_cast<uintptr_t>(ptr));
SkTypeface::LocalizedStrings* iter = instance->createFamilyNameIterator();
std::vector<SkTypeface::LocalizedString> names;
SkTypeface::LocalizedString name;
std::vector<jlong>* res = new std::vector<jlong>();
while (iter->next(&name)) {
names.push_back(name);
}
iter->unref();
jobjectArray res = env->NewObjectArray((jsize) names.size(), skija::FontFamilyName::cls, nullptr);
for (int i = 0; i < names.size(); ++i) {
skija::AutoLocal<jstring> nameStr(env, javaString(env, names[i].fString));
skija::AutoLocal<jstring> langStr(env, javaString(env, names[i].fLanguage));
skija::AutoLocal<jobject> obj(env, env->NewObject(skija::FontFamilyName::cls, skija::FontFamilyName::ctor, nameStr.get(), langStr.get()));
env->SetObjectArrayElement(res, i, obj.get());
res->push_back(reinterpret_cast<jlong>(new SkString(name.fString)));
res->push_back(reinterpret_cast<jlong>(new SkString(name.fLanguage)));
}
return res;
return reinterpret_cast<jlong>(res);
}
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_TypefaceKt__1nGetFamilyName
......
......@@ -3,14 +3,12 @@
#include "SkString.h"
#include "common.h"
#include "mppinterop.h"
static void deleteString(SkString* instance) {
delete instance;
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_ManagedString__1nGetFinalizer
() {
return reinterpret_cast<KNativePointer>((&deleteString));
return reinterpret_cast<KNativePointer>(&skikoMpp::finalizers::deleteString);
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_ManagedString__1nMake
......
#include "common.h"
SKIKO_EXPORT KInt org_jetbrains_skia_StdVectorDecoder__1nGetArraySize
(KNativePointer ptr) {
std::vector<KNativePointer>* vec = reinterpret_cast<std::vector<KNativePointer> *>(ptr);
return vec->size();
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_StdVectorDecoder__1nReleaseElement
(KNativePointer ptr, KInt index) {
auto& vec = *reinterpret_cast<std::vector<void*> *>(ptr);
auto res = vec[index];
vec[index] = nullptr;
return res;
}
SKIKO_EXPORT void org_jetbrains_skia_StdVectorDecoder__1nDisposeArray
(KNativePointer ptr, KNativePointer disposePtr) {
std::vector<KNativePointer>* vec = reinterpret_cast<std::vector<KNativePointer> *>(ptr);
void (*dtor)(void*) = reinterpret_cast<void (*)(void*)>(disposePtr);
while (!vec->empty()){
auto res = vec->back();
if (res != nullptr) {
dtor(res);
}
vec->pop_back();
}
delete vec;
}
......@@ -190,34 +190,21 @@ SKIKO_EXPORT bool org_jetbrains_skia_Typeface__1nGetKerningPairAdjustments
return false;
}
SKIKO_EXPORT KInteropPointerArray org_jetbrains_skia_Typeface__1nGetFamilyNames
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_Typeface__1nGetFamilyNames
(KNativePointer ptr) {
TODO("implement org_jetbrains_skia_Typeface__1nGetFamilyNames");
}
#if 0
SKIKO_EXPORT KInteropPointerArray org_jetbrains_skia_Typeface__1nGetFamilyNames
(KNativePointer ptr) {
SkTypeface* instance = reinterpret_cast<SkTypeface*>((ptr));
SkTypeface* instance = reinterpret_cast<SkTypeface*>(ptr);
SkTypeface::LocalizedStrings* iter = instance->createFamilyNameIterator();
std::vector<SkTypeface::LocalizedString> names;
SkTypeface::LocalizedString name;
std::vector<KInteropPointer>* res = new std::vector<KInteropPointer>();
while (iter->next(&name)) {
names.push_back(name);
}
iter->unref();
KInteropPointerArray res = env->NewObjectArray((jsize) names.size(), skija::FontFamilyName::cls, nullptr);
for (int i = 0; i < names.size(); ++i) {
skija::AutoLocal<KInteropPointer> nameStr(env, javaString(env, names[i].fString));
skija::AutoLocal<KInteropPointer> langStr(env, javaString(env, names[i].fLanguage));
skija::AutoLocal<KInteropPointer> obj(env, env->NewObject(skija::FontFamilyName::cls, skija::FontFamilyName::ctor, nameStr.get(), langStr.get()));
env->SetObjectArrayElement(res, i, obj.get());
res->push_back(reinterpret_cast<KInteropPointer>(new SkString(name.fString)));
res->push_back(reinterpret_cast<KInteropPointer>(new SkString(name.fLanguage)));
}
return res;
}
#endif
return reinterpret_cast<KInteropPointer>(res);
}
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_Typeface__1nGetFamilyName
(KNativePointer ptr) {
......
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