Unverified Commit 7e9e0beb authored by Shagen Ogandzhanian's avatar Shagen Ogandzhanian Committed by GitHub

Commonization - leftovers (#404)

parent 0428658f
......@@ -537,7 +537,15 @@ class Font : Managed {
fun getPaths(glyphs: ShortArray?): Array<Path> {
return try {
Stats.onNativeCall()
_nGetPaths(_ptr, glyphs)
arrayDecoderScope({
ArrayDecoder(
interopScope { _nGetPaths(_ptr, toInterop(glyphs), glyphs?.size ?: 0) }, Path_nGetFinalizer()
)
}) { arrayDecoder ->
(0 until arrayDecoder.size).map { i->
Path(arrayDecoder.release(i))
}.toTypedArray()
}
} finally {
reachabilityBarrier(this)
}
......@@ -702,7 +710,7 @@ private external fun _nGetXPositions(ptr: NativePointer, glyphs: InteropPointer,
private external fun _nGetPath(ptr: NativePointer, glyph: Short): NativePointer
@ExternalSymbolName("org_jetbrains_skia_Font__1nGetPaths")
private external fun _nGetPaths(ptr: NativePointer, glyphs: ShortArray?): Array<Path>
private external fun _nGetPaths(ptr: NativePointer, glyphs: InteropPointer, count: Int): NativePointer
@ExternalSymbolName("org_jetbrains_skia_Font__1nGetMetrics")
private external fun _nGetMetrics(ptr: NativePointer, metrics: InteropPointer)
......
......@@ -45,7 +45,7 @@ class FontFeature(val _tag: Int, val value: Int, val start: UInt, val end: UInt)
override fun equals(other: Any?): Boolean {
if (other === this) return true
if (other !is FontFeature) return false
if (this.tag != other) return false
if (this.tag != other.tag) return false
if (value != other.value) return false
if (start != other.start) return false
return end == other.end
......
......@@ -2164,7 +2164,7 @@ class Path internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerHol
@ExternalSymbolName("org_jetbrains_skia_Path__1nGetFinalizer")
private external fun Path_nGetFinalizer(): NativePointer
internal external fun Path_nGetFinalizer(): NativePointer
@ExternalSymbolName("org_jetbrains_skia_Path__1nMake")
private external fun Path_nMake(): NativePointer
......
......@@ -33,7 +33,7 @@ class Typeface internal constructor(ptr: NativePointer) : RefCnt(ptr) {
*/
fun makeFromName(name: String?, style: FontStyle): Typeface {
Stats.onNativeCall()
return Typeface(_nMakeFromName(name, style._value))
return interopScope { Typeface(_nMakeFromName(toInterop(name), style._value)) }
}
/**
......@@ -395,7 +395,9 @@ class Typeface internal constructor(ptr: NativePointer) : RefCnt(ptr) {
val bounds: Rect
get() = try {
Stats.onNativeCall()
Typeface_nGetBounds(_ptr)
Rect.fromInteropPointer {
Typeface_nGetBounds(_ptr, it)
}
} finally {
reachabilityBarrier(this)
}
......@@ -422,7 +424,7 @@ private external fun Typeface_nGetUTF32Glyphs(
private external fun Typeface_nGetUTF32Glyph(ptr: NativePointer, unichar: Int): Short
@ExternalSymbolName("org_jetbrains_skia_Typeface__1nGetBounds")
private external fun Typeface_nGetBounds(ptr: NativePointer): Rect
private external fun Typeface_nGetBounds(ptr: NativePointer, bounds: InteropPointer)
@ExternalSymbolName("org_jetbrains_skia_Typeface__1nGetFontStyle")
private external fun _nGetFontStyle(ptr: NativePointer): Int
......@@ -443,7 +445,7 @@ private external fun _nGetVariationAxesCount(ptr: NativePointer): Int
private external fun _nGetVariationAxes(ptr: NativePointer, axisData: InteropPointer, axisCount: Int)
@ExternalSymbolName("org_jetbrains_skia_Typeface__1nMakeFromName")
private external fun _nMakeFromName(name: String?, fontStyle: Int): NativePointer
private external fun _nMakeFromName(name: InteropPointer, fontStyle: Int): NativePointer
@ExternalSymbolName("org_jetbrains_skia_Typeface__1nMakeFromFile")
internal external fun _nMakeFromFile(path: InteropPointer, index: Int): NativePointer
......
......@@ -16,7 +16,7 @@ class FontCollection internal constructor(ptr: NativePointer) : RefCnt(ptr) {
Stats.onNativeCall()
}
val fontManagersCount: NativePointer
val fontManagersCount: Int
get() = try {
Stats.onNativeCall()
_nGetFontManagersCount(_ptr)
......@@ -104,7 +104,7 @@ class FontCollection internal constructor(ptr: NativePointer) : RefCnt(ptr) {
fun defaultFallback(unicode: Int, style: FontStyle, locale: String?): Typeface? {
return try {
Stats.onNativeCall()
val ptr = _nDefaultFallbackChar(_ptr, unicode, style._value, locale)
val ptr = interopScope { _nDefaultFallbackChar(_ptr, unicode, style._value, toInterop(locale)) }
if (ptr == NullPointer) null else Typeface(ptr)
} finally {
reachabilityBarrier(this)
......@@ -140,7 +140,7 @@ class FontCollection internal constructor(ptr: NativePointer) : RefCnt(ptr) {
private external fun _nMake(): NativePointer
@ExternalSymbolName("org_jetbrains_skia_paragraph_FontCollection__1nGetFontManagersCount")
private external fun _nGetFontManagersCount(ptr: NativePointer): NativePointer
private external fun _nGetFontManagersCount(ptr: NativePointer): Int
@ExternalSymbolName("org_jetbrains_skia_paragraph_FontCollection__1nSetAssetFontManager")
private external fun _nSetAssetFontManager(ptr: NativePointer, fontManagerPtr: NativePointer): NativePointer
......@@ -161,7 +161,7 @@ private external fun _nGetFallbackManager(ptr: NativePointer): NativePointer
private external fun _nFindTypefaces(ptr: NativePointer, familyNames: InteropPointer, len: Int, fontStyle: Int): NativePointer
@ExternalSymbolName("org_jetbrains_skia_paragraph_FontCollection__1nDefaultFallbackChar")
private external fun _nDefaultFallbackChar(ptr: NativePointer, unicode: Int, fontStyle: Int, locale: String?): NativePointer
private external fun _nDefaultFallbackChar(ptr: NativePointer, unicode: Int, fontStyle: Int, locale: InteropPointer): NativePointer
@ExternalSymbolName("org_jetbrains_skia_paragraph_FontCollection__1nDefaultFallback")
private external fun _nDefaultFallback(ptr: NativePointer): NativePointer
......
package org.jetbrains.skia.paragraph
import org.jetbrains.skia.Point
import org.jetbrains.skia.impl.InteropPointer
import org.jetbrains.skia.impl.InteropScope
import org.jetbrains.skia.impl.withResult
class Shadow(val color: Int, val offsetX: Float, val offsetY: Float, val blurSigma: Double) {
......@@ -48,4 +51,13 @@ class Shadow(val color: Int, val offsetX: Float, val offsetY: Float, val blurSig
fun withBlurSigma(_blurSigma: Double): Shadow {
return if (blurSigma == _blurSigma) this else Shadow(color, offsetX, offsetY, _blurSigma)
}
companion object
}
fun Shadow.Companion.fromInteropPointer(shadowsCount: Int, block: InteropScope.(InteropPointer) -> Unit): Array<Shadow> {
return withResult(IntArray(shadowsCount * 5), block).toList().chunked(5).map { (color, offsetX, offsetY, blurSigmaA, blurSigmaB) ->
val blurSigma = (blurSigmaA.toLong() shl 32) or (blurSigmaB.toLong() and 0xFFFFFFFFL)
Shadow(color, Float.fromBits(offsetX), Float.fromBits(offsetY), Double.fromBits(blurSigma))
}.toTypedArray()
}
\ No newline at end of file
......@@ -154,10 +154,12 @@ class TextStyle internal constructor(ptr: NativePointer) : Managed(ptr, _Finaliz
return this
}
val shadows: Array<org.jetbrains.skia.paragraph.Shadow>
val shadows: Array<Shadow>
get() = try {
Stats.onNativeCall()
_nGetShadows(_ptr)
Shadow.fromInteropPointer(_nGetShadowsCount(_ptr)) {
_nGetShadows(_ptr, it)
}
} finally {
reachabilityBarrier(this)
}
......@@ -195,7 +197,9 @@ class TextStyle internal constructor(ptr: NativePointer) : Managed(ptr, _Finaliz
fun addFontFeature(f: FontFeature): TextStyle {
Stats.onNativeCall()
_nAddFontFeature(_ptr, f.tag, f.value)
interopScope {
_nAddFontFeature(_ptr, toInterop(f.tag), f.value)
}
return this
}
......@@ -230,7 +234,9 @@ class TextStyle internal constructor(ptr: NativePointer) : Managed(ptr, _Finaliz
var fontFamilies: Array<String>
get() = try {
Stats.onNativeCall()
TextStyle_nGetFontFamilies(_ptr)
arrayDecoderScope({ ArrayDecoder(TextStyle_nGetFontFamilies(_ptr), ManagedString_nGetFinalizer()) }) { arrayDecoder ->
(0 until arrayDecoder.size).map { i -> withStringResult(arrayDecoder.release(i)) }
}.toTypedArray()
} finally {
reachabilityBarrier(this)
}
......@@ -434,7 +440,7 @@ private external fun TextStyle_nGetFontSize(ptr: NativePointer): Float
private external fun TextStyle_nSetFontSize(ptr: NativePointer, size: Float)
@ExternalSymbolName("org_jetbrains_skia_paragraph_TextStyle__1nGetFontFamilies")
private external fun TextStyle_nGetFontFamilies(ptr: NativePointer): Array<String>
private external fun TextStyle_nGetFontFamilies(ptr: NativePointer): NativePointer
@ExternalSymbolName("org_jetbrains_skia_paragraph_TextStyle__1nGetHeight")
private external fun TextStyle_nGetHeight(ptr: NativePointer): Float
......@@ -484,8 +490,11 @@ private external fun _nSetDecorationStyle(
thicknessMultiplier: Float
)
@ExternalSymbolName("org_jetbrains_skia_paragraph_TextStyle__1nGetShadowsCount")
private external fun _nGetShadowsCount(ptr: NativePointer): Int
@ExternalSymbolName("org_jetbrains_skia_paragraph_TextStyle__1nGetShadows")
private external fun _nGetShadows(ptr: NativePointer): Array<Shadow>
private external fun _nGetShadows(ptr: NativePointer, res: InteropPointer)
@ExternalSymbolName("org_jetbrains_skia_paragraph_TextStyle__1nAddShadow")
private external fun _nAddShadow(ptr: NativePointer, color: Int, offsetX: Float, offsetY: Float, blurSigma: Double)
......@@ -500,7 +509,7 @@ private external fun _nGetFontFeatures(ptr: NativePointer, resultIntsArray: Inte
private external fun _nGetFontFeaturesSize(ptr: NativePointer): Int
@ExternalSymbolName("org_jetbrains_skia_paragraph_TextStyle__1nAddFontFeature")
private external fun _nAddFontFeature(ptr: NativePointer, name: String?, value: Int)
private external fun _nAddFontFeature(ptr: NativePointer, name: InteropPointer, value: Int)
@ExternalSymbolName("org_jetbrains_skia_paragraph_TextStyle__1nClearFontFeatures")
private external fun _nClearFontFeatures(ptr: NativePointer)
......
......@@ -51,6 +51,8 @@ class FontTests {
10e-3f
)
assertContentEquals(font.getPath(glyphs[0])!!.points, font.getPaths(glyphs)[0].points)
assertContentCloseEnough(
arrayOf(
Point(0f, 0f),
......
......@@ -4,11 +4,8 @@ import org.jetbrains.skia.FontMgr
import org.jetbrains.skia.FontStyle
import org.jetbrains.skia.Typeface
import org.jetbrains.skia.impl.use
import org.jetbrains.skia.paragraph.FontCollection
import org.jetbrains.skia.paragraph.TypefaceFontProvider
import org.jetbrains.skia.tests.makeFromResource
import org.jetbrains.skiko.tests.SkipJsTarget
import org.jetbrains.skiko.tests.SkipNativeTarget
import org.jetbrains.skiko.kotlinBackend
import org.jetbrains.skiko.tests.runTest
import kotlin.test.Test
import kotlin.test.assertContentEquals
......@@ -17,7 +14,7 @@ import kotlin.test.assertEquals
class FontCollectionTest {
@Test
fun fontCollectionTest() = runTest {
fun familyNameTest() = runTest {
val fm = TypefaceFontProvider()
val jbMono = Typeface.makeFromResource("./fonts/JetBrainsMono-Regular.ttf", 0)
fm.registerTypeface(jbMono)
......@@ -32,4 +29,67 @@ class FontCollectionTest {
}
}
}
@Test
fun fontCollectionTest() = runTest {
val fm = TypefaceFontProvider()
val jbMono = Typeface.makeFromResource("./fonts/JetBrainsMono-Regular.ttf", 0)
fm.registerTypeface(jbMono)
val inter = Typeface.makeFromResource("./fonts/Inter-Hinted-Regular.ttf", 0)
fm.registerTypeface(inter, "Interface")
// FontCollection
val fontCollection = FontCollection()
fontCollection.setAssetFontManager(fm)
assertEquals(1, fontCollection.fontManagersCount)
assertEquals(2, jbMono.refCount)
fontCollection.findTypefaces(arrayOf("JetBrains Mono"), FontStyle.NORMAL)[0]!!.use { jbMono2 ->
assertEquals(4, jbMono.refCount)
assertEquals(4, jbMono2.refCount)
fontCollection.findTypefaces(arrayOf("JetBrains Mono"), FontStyle.NORMAL)[0]!!.use { jbMono3 ->
assertEquals(5, jbMono.refCount)
assertEquals(5, jbMono2.refCount)
assertEquals(5, jbMono3.refCount)
}
assertEquals(4, jbMono.refCount)
assertEquals(4, jbMono2.refCount)
}
//TODO: commented out assertions seem not to be isolated and are turned off till further investigation
assertContentEquals(arrayOf(), fontCollection.findTypefaces(arrayOf("No Such Font"), FontStyle.NORMAL))
assertContentEquals(arrayOf(jbMono), fontCollection.findTypefaces(arrayOf("JetBrains Mono"), FontStyle.NORMAL))
assertContentEquals(arrayOf(), fontCollection.findTypefaces(arrayOf("Inter"), FontStyle.NORMAL))
assertContentEquals(arrayOf(inter), fontCollection.findTypefaces(arrayOf("Interface"), FontStyle.NORMAL))
assertContentEquals(
arrayOf(jbMono, inter),
fontCollection.findTypefaces(arrayOf("JetBrains Mono", "Interface"), FontStyle.NORMAL)
)
val defaultFM = FontMgr.default
fontCollection.setDefaultFontManager(defaultFM)
assertEquals(2, fontCollection.fontManagersCount)
fontCollection.fallbackManager!!.use { ffm ->
//assertEquals(4, defaultFM.refCount)
assertEquals(defaultFM, ffm)
}
if (kotlinBackend.isNotJs()) {
fontCollection.defaultFallback(65 /* A */, FontStyle.NORMAL, "en-US")!!.use { t1 ->
val refCnt: Int = t1.refCount
fontCollection.defaultFallback(65 /* A */, FontStyle.NORMAL, "en-US")!!.use { t2 ->
assertEquals(refCnt + 1, t1.refCount)
assertEquals(refCnt + 1, t2.refCount)
assertEquals(t1, t2)
}
}
}
}
}
\ No newline at end of file
......@@ -5,6 +5,7 @@ import org.jetbrains.skia.FontMetrics
import org.jetbrains.skia.Matrix33
import org.jetbrains.skia.Point
import org.jetbrains.skia.Rect
import org.jetbrains.skia.paragraph.Shadow
import org.jetbrains.skia.paragraph.TextBox
import org.jetbrains.skiko.KotlinBackend
import org.jetbrains.skiko.kotlinBackend
......@@ -14,11 +15,17 @@ import kotlin.test.assertTrue
private val EPSILON = if (kotlinBackend == KotlinBackend.JS) 0.00001f else 0.00000001f
private inline fun Float?.isCloseEnoughTo(b: Float?, epsilon: Float) =
if (this == null) b == null else if (b == null) false else abs(this - b) < epsilon
if (this == null) b == null else if (b == null) false else if (epsilon == 0f) this == b else abs(this - b) < epsilon
private inline fun Point.isCloseEnoughTo(b: Point, epsilon: Float) =
x.isCloseEnoughTo(b.x, epsilon) && y.isCloseEnoughTo(b.y, epsilon)
private inline fun Shadow.isCloseEnoughTo(b: Shadow, epsilon: Float) =
(color == b.color)
&& (offsetX.isCloseEnoughTo(b.offsetX, epsilon))
&& (offsetY.isCloseEnoughTo(b.offsetY, epsilon))
&& (blurSigma == b.blurSigma)
private inline fun Color4f.isCloseEnoughTo(otherColor: Color4f, epsilon: Float) =
r.isCloseEnoughTo(otherColor.r, epsilon) && g.isCloseEnoughTo(
otherColor.g,
......@@ -120,3 +127,7 @@ internal fun assertContentCloseEnough(expected: List<Point>, actual: List<Point>
internal fun assertContentCloseEnough(expected: Array<TextBox>, actual: Array<TextBox>, epsilon: Float = EPSILON) {
assertContentEquivalent(expected.iterator(), actual.iterator()) { a, b -> a.isCloseEnoughTo(b, epsilon) }
}
internal fun assertContentCloseEnough(expected: Array<Shadow>, actual: Array<Shadow>, epsilon: Float = EPSILON) {
assertContentEquivalent(expected.iterator(), actual.iterator()) { a, b -> a.isCloseEnoughTo(b, epsilon) }
}
package org.jetbrains.skiko
import org.jetbrains.skia.*
import org.jetbrains.skia.tests.assertCloseEnough
import org.jetbrains.skia.tests.makeFromResource
import org.jetbrains.skiko.tests.SkipJsTarget
import org.jetbrains.skiko.tests.SkipNativeTarget
......@@ -36,6 +37,8 @@ class TypefaceTest {
assertTrue(inter.getTableData("loca")!!.size > 0)
assertEquals(2816, inter.unitsPerEm)
assertCloseEnough(Rect(left=-0.7386364f, top=-1.0909091f, right=2.5830965f, bottom=0.31960228f), inter.bounds, 10e-4f)
}
@Test
......
package org.jetbrains.skiko.paragraph
import org.jetbrains.skia.Color
import org.jetbrains.skia.FontFeature
import org.jetbrains.skia.impl.use
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.tests.assertContentCloseEnough
import org.jetbrains.skiko.KotlinBackend
import org.jetbrains.skiko.kotlinBackend
import kotlin.test.*
class TextStyleTest {
......@@ -45,6 +50,7 @@ class TextStyleTest {
ts1.fontFamilies = arrayOf("foo", "qux")
ts2.fontFamilies = arrayOf("foo", "qux")
assertEquals(ts1, ts2)
assertContentEquals(ts1.fontFamilies, ts2.fontFamilies)
ts1.fontFamilies = arrayOf("foo", "qux")
ts2.fontFamilies = arrayOf("bar", "zig")
assertNotEquals(ts1, ts2)
......@@ -52,6 +58,19 @@ class TextStyleTest {
}
}
@Test
fun textStyleAddFontFeatureTest() {
TextStyle().use { textStyle ->
textStyle.addFontFeature(FontFeature("FONT", true))
textStyle.addFontFeatures(arrayOf(FontFeature("TONF", true), FontFeature("IDDI", false)))
assertContentEquals(arrayOf(
FontFeature(84, 1, 0u, 4294967295u),
FontFeature(70, 1, 0u, 4294967295u),
FontFeature(73, 0, 0u, 4294967295u),
), textStyle.fontFeatures)
}
}
@Test
fun textStyleLocaleTest() {
TextStyle().use { textStyle ->
......@@ -97,6 +116,22 @@ class TextStyleTest {
}
@Test
fun textShadowsTest() {
TextStyle().use { textStyle ->
textStyle.addShadow(Shadow(200, 0.2f, 0.4f, 1.4))
textStyle.addShadows(arrayOf(Shadow(100, 0.3f, 0.1f, 2.0)))
assertContentCloseEnough(
arrayOf(
Shadow(200, 0.2f, 0.4f, 1.4),
Shadow(100, 0.3f, 0.1f, 2.0)
), textStyle.shadows, if (kotlinBackend == KotlinBackend.JS) 0.00001f else 0f
)
}
}
fun textStyleBaselineTest() {
TextStyle().use { textStyle ->
assertEquals(0.0f, textStyle.baselineShift)
......
......@@ -310,33 +310,27 @@ extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_FontKt__1nGetPath
return reinterpret_cast<jlong>(path);
}
extern "C" JNIEXPORT jobjectArray JNICALL Java_org_jetbrains_skia_FontKt__1nGetPaths
(JNIEnv* env, jclass jclass, jlong ptr, jshortArray glyphsArr) {
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_FontKt__1nGetPaths
(JNIEnv* env, jclass jclass, jlong ptr, jshortArray glyphsArr, jint count) {
SkFont* instance = reinterpret_cast<SkFont*>(static_cast<uintptr_t>(ptr));
int count = env->GetArrayLength(glyphsArr);
jshort* glyphs = env->GetShortArrayElements(glyphsArr, nullptr);
struct Ctx {
jobjectArray paths;
jsize idx;
JNIEnv* env;
} ctx = { env->NewObjectArray(count, skija::Path::cls, nullptr), 0, env };
std::vector<jlong>* paths;
} ctx = { new std::vector<jlong>() };
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);
jobject pathObj = ctx->env->NewObject(skija::Path::cls, skija::Path::ctor, reinterpret_cast<jlong>(path));
ctx->env->SetObjectArrayElement(ctx->paths, ctx->idx, pathObj);
ctx->env->DeleteLocalRef(pathObj);
++ctx->idx;
ctx->paths->push_back(reinterpret_cast<jlong>(path));
}
}, &ctx);
env->ReleaseShortArrayElements(glyphsArr, glyphs, 0);
return ctx.paths;
return reinterpret_cast<jlong>(ctx.paths);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_FontKt__1nGetMetrics
......
......@@ -78,8 +78,7 @@ extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_TypefaceKt__1nMakeFro
SkString name = skString(env, nameStr);
SkFontStyle style = skija::FontStyle::fromJava(styleValue);
sk_sp<SkTypeface> instance = SkTypeface::MakeFromName(name.c_str(), style);
SkTypeface* ptr = instance.release();
return reinterpret_cast<jlong>(ptr);
return reinterpret_cast<jlong>(instance.release());
}
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_TypefaceKt__1nMakeFromFile
......@@ -222,8 +221,10 @@ extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_TypefaceKt__1nGetFami
return reinterpret_cast<jlong>(new SkString(name));
}
extern "C" JNIEXPORT jobject JNICALL Java_org_jetbrains_skia_TypefaceKt_Typeface_1nGetBounds
(JNIEnv* env, jclass jclass, jlong ptr) {
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_TypefaceKt_Typeface_1nGetBounds
(JNIEnv* env, jclass jclass, jlong ptr, jfloatArray res) {
SkTypeface* instance = reinterpret_cast<SkTypeface*>(static_cast<uintptr_t>(ptr));
return skija::Rect::fromSkRect(env, instance->getBounds());
SkRect b = instance->getBounds();
float r[4] = {b.left(), b.top(), b.right(), b.bottom()};
env->SetFloatArrayRegion(res, 0, 4, r);
}
\ No newline at end of file
......@@ -400,6 +400,15 @@ static inline jint rawBits(jfloat f) {
return u.i;
}
static inline jlong rawBits(jdouble d) {
union {
jdouble d;
jlong l;
} u;
u.d = d;
return u.l;
}
static inline jfloat fromBits(jint i) {
union {
jfloat f;
......
......@@ -13,7 +13,7 @@ extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_paragraph_FontCollect
return reinterpret_cast<jlong>(ptr);
}
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_paragraph_FontCollectionKt__1nGetFontManagersCount
extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_paragraph_FontCollectionKt__1nGetFontManagersCount
(JNIEnv* env, jclass jclass, jlong ptr) {
FontCollection* instance = reinterpret_cast<FontCollection*>(static_cast<uintptr_t>(ptr));
return instance->getFontManagersCount();
......
......@@ -144,17 +144,23 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_paragraph_TextStyleKt_
instance->setFontStyle(skija::FontStyle::fromJava(fontStyleValue));
}
extern "C" JNIEXPORT jobjectArray JNICALL Java_org_jetbrains_skia_paragraph_TextStyleKt__1nGetShadows
extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skia_paragraph_TextStyleKt__1nGetShadowsCount
(JNIEnv* env, jclass jclass, jlong ptr) {
TextStyle* instance = reinterpret_cast<TextStyle*>(static_cast<uintptr_t>(ptr));
return static_cast<jint>(instance->getShadows().size());
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_paragraph_TextStyleKt__1nGetShadows
(JNIEnv* env, jclass jclass, jlong ptr, jintArray res) {
TextStyle* instance = reinterpret_cast<TextStyle*>(static_cast<uintptr_t>(ptr));
std::vector<TextShadow> shadows = instance->getShadows();
jobjectArray shadowsArr = env->NewObjectArray((jsize) shadows.size(), skija::paragraph::Shadow::cls, nullptr);
for (int i = 0; i < shadows.size(); ++i) {
const TextShadow& s = shadows[i];
skija::AutoLocal<jobject> shadowObj(env, env->NewObject(skija::paragraph::Shadow::cls, skija::paragraph::Shadow::ctor, s.fColor, s.fOffset.fX, s.fOffset.fY, s.fBlurSigma));
env->SetObjectArrayElement(shadowsArr, i, shadowObj.get());
jlong blurSigma = rawBits(s.fBlurSigma);
jint r[5] = {static_cast<jint>(s.fColor), rawBits(s.fOffset.fX), rawBits(s.fOffset.fY), (jint)(blurSigma >> 32), (jint)blurSigma };
env->SetIntArrayRegion(res, 5 * i, 5, r);
}
return shadowsArr;
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_paragraph_TextStyleKt__1nAddShadow
......@@ -210,10 +216,14 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_paragraph_TextStyleKt_
instance->setFontSize(size);
}
extern "C" JNIEXPORT jobjectArray JNICALL Java_org_jetbrains_skia_paragraph_TextStyleKt_TextStyle_1nGetFontFamilies
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skia_paragraph_TextStyleKt_TextStyle_1nGetFontFamilies
(JNIEnv* env, jclass jclass, jlong ptr) {
TextStyle* instance = reinterpret_cast<TextStyle*>(static_cast<uintptr_t>(ptr));
return javaStringArray(env, instance->getFontFamilies());
std::vector<jlong>* res = new std::vector<jlong>();
for (auto& f : instance->getFontFamilies()) {
res->push_back(reinterpret_cast<jlong>(new SkString(f)));
}
return reinterpret_cast<jlong>(res);
}
extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skia_paragraph_TextStyleKt__1nSetFontFamilies
......
package org.jetbrains.skiko.paragraph
import org.jetbrains.skia.FontMgr
import org.jetbrains.skia.FontStyle
import org.jetbrains.skia.Typeface
import org.jetbrains.skia.paragraph.FontCollection
import org.jetbrains.skia.paragraph.TypefaceFontProvider
import org.jetbrains.skia.tests.makeFromResource
import org.jetbrains.skiko.tests.runTest
import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
class FontCollectionTest {
@Test
fun fontCollectionTest() = runTest {
val fm = TypefaceFontProvider()
val jbMono = Typeface.makeFromResource("./fonts/JetBrainsMono-Regular.ttf", 0)
fm.registerTypeface(jbMono)
val inter = Typeface.makeFromResource("./fonts/Inter-Hinted-Regular.ttf", 0)
fm.registerTypeface(inter, "Interface")
// FontCollection
val fontCollection = FontCollection()
fontCollection.setAssetFontManager(fm)
assertEquals(1L, fontCollection.fontManagersCount)
assertEquals(2, jbMono.refCount)
fontCollection.findTypefaces(arrayOf("JetBrains Mono"), FontStyle.NORMAL)[0]!!.use { jbMono2 ->
assertEquals(4, jbMono.refCount)
assertEquals(4, jbMono2.refCount)
fontCollection.findTypefaces(arrayOf("JetBrains Mono"), FontStyle.NORMAL)[0]!!.use { jbMono3 ->
assertEquals(5, jbMono.refCount)
assertEquals(5, jbMono2.refCount)
assertEquals(5, jbMono3.refCount)
}
assertEquals(4, jbMono.refCount)
assertEquals(4, jbMono2.refCount)
}
//TODO: commented out assertions seem not to be isolated and are turned off till further investigation
// assertEquals(3, jbMono.refCount)
assertContentEquals(arrayOf(), fontCollection.findTypefaces(arrayOf("No Such Font"), FontStyle.NORMAL))
assertContentEquals(arrayOf(jbMono), fontCollection.findTypefaces(arrayOf("JetBrains Mono"), FontStyle.NORMAL))
assertContentEquals(arrayOf(), fontCollection.findTypefaces(arrayOf("Inter"), FontStyle.NORMAL))
assertContentEquals(arrayOf(inter), fontCollection.findTypefaces(arrayOf("Interface"), FontStyle.NORMAL))
assertContentEquals(
arrayOf(jbMono, inter),
fontCollection.findTypefaces(arrayOf("JetBrains Mono", "Interface"), FontStyle.NORMAL)
)
val defaultFM = FontMgr.default
fontCollection.setDefaultFontManager(defaultFM)
assertEquals(2L, fontCollection.fontManagersCount)
// assertEquals(3, defaultFM.refCount)
fontCollection.fallbackManager.use { ffm ->
//assertEquals(4, defaultFM.refCount)
assertEquals(defaultFM, ffm)
}
// assertEquals(3, defaultFM.refCount)
fontCollection.defaultFallback(65 /* A */, FontStyle.NORMAL, "en-US")!!.use { t1 ->
val refCnt: Int = t1.refCount
fontCollection.defaultFallback(65 /* A */, FontStyle.NORMAL, "en-US")!!.use { t2 ->
assertEquals(refCnt + 1, t1.refCount)
assertEquals(refCnt + 1, t2.refCount)
assertEquals(t1, t2)
}
}
}
}
\ No newline at end of file
......@@ -303,42 +303,25 @@ SKIKO_EXPORT KNativePointer org_jetbrains_skia_Font__1nGetPath
}
SKIKO_EXPORT KInteropPointerArray org_jetbrains_skia_Font__1nGetPaths
(KNativePointer ptr, KShort* glyphsArr) {
TODO("implement org_jetbrains_skia_Font__1nGetPaths");
}
#if 0
SKIKO_EXPORT KInteropPointerArray org_jetbrains_skia_Font__1nGetPaths
(KNativePointer ptr, KShort* glyphsArr) {
SKIKO_EXPORT KNativePointer org_jetbrains_skia_Font__1nGetPaths
(KNativePointer ptr, KShort* glyphs, KInt count) {
SkFont* instance = reinterpret_cast<SkFont*>(ptr);
int count = env->GetArrayLength(glyphsArr);
KShort* glyphs = env->GetShortArrayElements(glyphsArr, nullptr);
struct Ctx {
KInteropPointerArray paths;
jsize idx;
JNIEnv* env;
} ctx = { env->NewObjectArray(count, skija::Path::cls, nullptr), 0, env };
std::vector<KNativePointer>* paths;
} ctx = { new std::vector<KNativePointer>() };
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);
KInteropPointer pathObj = ctx->env->NewObject(skija::Path::cls, skija::Path::ctor, reinterpret_cast<KNativePointer>(path));
ctx->env->SetObjectArrayElement(ctx->paths, ctx->idx, pathObj);
ctx->env->DeleteLocalRef(pathObj);
++ctx->idx;
ctx->paths->push_back(reinterpret_cast<KNativePointer>(path));
}
}, &ctx);
env->ReleaseShortArrayElements(glyphsArr, glyphs, 0);
return ctx.paths;
return reinterpret_cast<KNativePointer>(ctx.paths);
}
#endif
SKIKO_EXPORT void org_jetbrains_skia_Font__1nGetMetrics
(KNativePointer ptr, KFloat* fontMetrics) {
......
......@@ -62,25 +62,6 @@ SKIKO_EXPORT KNativePointer org_jetbrains_skia_FontMgr__1nMatchFamilyStyleCharac
return reinterpret_cast<KNativePointer>(typeface);
}
#if 0
SKIKO_EXPORT KNativePointer org_jetbrains_skia_FontMgr__1nMatchFamilyStyleCharacter
(KNativePointer ptr, KInteropPointer familyNameStr, KInt fontStyle, KInteropPointerArray bcp47Array, KInt character) {
SkFontMgr* instance = reinterpret_cast<SkFontMgr*>((ptr));
SkString familyName = skString(env, familyNameStr);
std::vector<SkString> bcp47Strings = skStringVector(env, bcp47Array);
std::vector<const char*> bcp47(bcp47Strings.size());
for (int i = 0; i < bcp47.size(); ++i)
bcp47[i] = bcp47Strings[i].c_str();
SkTypeface* typeface = instance->matchFamilyStyleCharacter(familyName.c_str(), skija::FontStyle::fromJava(fontStyle), bcp47.data(), (int) bcp47.size(), character);
return reinterpret_cast<KNativePointer>(typeface);
}
#endif
SKIKO_EXPORT KNativePointer org_jetbrains_skia_FontMgr__1nMakeFromData
(KNativePointer ptr, KNativePointer dataPtr, KInt ttcIndex) {
SkFontMgr* instance = reinterpret_cast<SkFontMgr*>((ptr));
......
......@@ -80,7 +80,10 @@ SKIKO_EXPORT KNativePointer org_jetbrains_skia_Typeface__1nMakeDefault
SKIKO_EXPORT KNativePointer org_jetbrains_skia_Typeface__1nMakeFromName
(KInteropPointer nameStr, KInt styleValue) {
TODO("implement org_jetbrains_skia_Typeface__1nMakeFromName");
SkString name = skString(nameStr);
SkFontStyle style = skija::FontStyle::fromKotlin(styleValue);
sk_sp<SkTypeface> instance = SkTypeface::MakeFromName(name.c_str(), style);
return reinterpret_cast<KNativePointer>(instance.release());
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_Typeface__1nMakeFromFile
......@@ -214,16 +217,12 @@ SKIKO_EXPORT KInteropPointer org_jetbrains_skia_Typeface__1nGetFamilyName
return new SkString(name);
}
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_Typeface__1nGetBounds
(KNativePointer ptr) {
TODO("implement org_jetbrains_skia_Typeface__1nGetBounds");
}
#if 0
SKIKO_EXPORT KInteropPointer org_jetbrains_skia_Typeface__1nGetBounds
(KNativePointer ptr) {
SkTypeface* instance = reinterpret_cast<SkTypeface*>((ptr));
return skija::Rect::fromSkRect(env, instance->getBounds());
SKIKO_EXPORT void org_jetbrains_skia_Typeface__1nGetBounds
(KNativePointer ptr, KFloat* bounds) {
SkTypeface* instance = reinterpret_cast<SkTypeface*>(ptr);
SkRect b = instance->getBounds();
bounds[0] = b.left();
bounds[1] = b.top();
bounds[2] = b.right();
bounds[3] = b.bottom();
}
#endif
......@@ -145,6 +145,15 @@ static inline KInt rawBits(KFloat f) {
return u.i;
}
static inline KLong rawBits(KDouble d) {
union {
KDouble d;
KLong l;
} u;
u.d = d;
return u.l;
}
static inline KFloat fromBits(KInt i) {
union {
KFloat f;
......
......@@ -79,7 +79,8 @@ 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) {
TODO("implement org_jetbrains_skia_paragraph_FontCollection__1nDefaultFallbackChar");
FontCollection* instance = reinterpret_cast<FontCollection*>(ptr);
return reinterpret_cast<KNativePointer>(instance->defaultFallback(unicode, skija::FontStyle::fromKotlin(fontStyle), skString(locale)).release());
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_paragraph_FontCollection__1nDefaultFallback
......
......@@ -141,26 +141,27 @@ SKIKO_EXPORT void org_jetbrains_skia_paragraph_TextStyle__1nSetFontStyle
instance->setFontStyle(skija::FontStyle::fromKotlin(fontStyleValue));
}
SKIKO_EXPORT KInteropPointerArray org_jetbrains_skia_paragraph_TextStyle__1nGetShadows
SKIKO_EXPORT KInt org_jetbrains_skia_paragraph_TextStyle__1nGetShadowsCount
(KNativePointer ptr) {
TODO("implement org_jetbrains_skia_paragraph_TextStyle__1nGetShadows");
TextStyle* instance = reinterpret_cast<TextStyle*>(ptr);
return static_cast<KInt>(instance->getShadows().size());
}
#if 0
SKIKO_EXPORT KInteropPointerArray org_jetbrains_skia_paragraph_TextStyle__1nGetShadows
(KNativePointer ptr) {
SKIKO_EXPORT void org_jetbrains_skia_paragraph_TextStyle__1nGetShadows
(KNativePointer ptr, KInt* res) {
TextStyle* instance = reinterpret_cast<TextStyle*>(ptr);
std::vector<TextShadow> shadows = instance->getShadows();
KInteropPointerArray shadowsArr = env->NewObjectArray((jsize) shadows.size(), skija::paragraph::Shadow::cls, nullptr);
for (int i = 0; i < shadows.size(); ++i) {
const TextShadow& s = shadows[i];
skija::AutoLocal<KInteropPointer> shadowObj(env, env->NewObject(skija::paragraph::Shadow::cls, skija::paragraph::Shadow::ctor, s.fColor, s.fOffset.fX, s.fOffset.fY, s.fBlurSigma));
env->SetObjectArrayElement(shadowsArr, i, shadowObj.get());
KLong blurSigma = rawBits(s.fBlurSigma);
res[5*i] = s.fColor;
res[5*i + 1] = rawBits(s.fOffset.fX);
res[5*i + 2] = rawBits(s.fOffset.fY);
res[5*i + 3] = (KInt)(blurSigma >> 32);
res[5*i + 4] = (KInt)blurSigma;
}
return shadowsArr;
}
#endif
SKIKO_EXPORT void org_jetbrains_skia_paragraph_TextStyle__1nAddShadow
(KNativePointer ptr, KInt color, KFloat offsetX, KFloat offsetY, KDouble blurSigma) {
......@@ -189,19 +190,11 @@ SKIKO_EXPORT void org_jetbrains_skia_paragraph_TextStyle__1nGetFontFeatures
}
SKIKO_EXPORT void org_jetbrains_skia_paragraph_TextStyle__1nAddFontFeature
(KNativePointer ptr, KInteropPointer nameStr, KInt value) {
TODO("implement org_jetbrains_skia_paragraph_TextStyle__1nAddFontFeature");
}
#if 0
SKIKO_EXPORT void org_jetbrains_skia_paragraph_TextStyle__1nAddFontFeature
(KNativePointer ptr, KInteropPointer nameStr, KInt value) {
TextStyle* instance = reinterpret_cast<TextStyle*>(ptr);
instance->addFontFeature(skString(env, nameStr), value);
instance->addFontFeature(skString(nameStr), value);
}
#endif
SKIKO_EXPORT void org_jetbrains_skia_paragraph_TextStyle__1nClearFontFeatures
(KNativePointer ptr) {
......@@ -222,19 +215,15 @@ SKIKO_EXPORT void org_jetbrains_skia_paragraph_TextStyle__1nSetFontSize
}
SKIKO_EXPORT KInteropPointerArray org_jetbrains_skia_paragraph_TextStyle__1nGetFontFamilies
(KNativePointer ptr) {
TODO("implement org_jetbrains_skia_paragraph_TextStyle__1nGetFontFamilies");
}
#if 0
SKIKO_EXPORT KInteropPointerArray org_jetbrains_skia_paragraph_TextStyle__1nGetFontFamilies
SKIKO_EXPORT KNativePointer org_jetbrains_skia_paragraph_TextStyle__1nGetFontFamilies
(KNativePointer ptr) {
TextStyle* instance = reinterpret_cast<TextStyle*>(ptr);
return javaStringArray(env, instance->getFontFamilies());
std::vector<KNativePointer>* res = new std::vector<KNativePointer>();
for (auto& f : instance->getFontFamilies()) {
res->push_back(reinterpret_cast<KNativePointer>(new SkString(f)));
}
return reinterpret_cast<KNativePointer>(res);
}
#endif
SKIKO_EXPORT void org_jetbrains_skia_paragraph_TextStyle__1nSetFontFamilies
......@@ -244,7 +233,6 @@ SKIKO_EXPORT void org_jetbrains_skia_paragraph_TextStyle__1nSetFontFamilies
}
SKIKO_EXPORT KFloat org_jetbrains_skia_paragraph_TextStyle__1nGetHeight
(KNativePointer ptr) {
TextStyle* instance = reinterpret_cast<TextStyle*>(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