Skip to content

Commit

Permalink
BreakIterator, U16String
Browse files Browse the repository at this point in the history
  • Loading branch information
tonsky committed Mar 18, 2021
1 parent ccf303e commit f5e3a45
Show file tree
Hide file tree
Showing 8 changed files with 873 additions and 1 deletion.
112 changes: 112 additions & 0 deletions examples/scenes/src/BreakIteratorScene.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package org.jetbrains.skija.examples.scenes;

import java.util.stream.*;
import org.jetbrains.skija.*;

public class BreakIteratorScene extends Scene {
Font mono11 = new Font(jbMono, 11);
int x, y;

public BreakIteratorScene() {
_variants = new String[] { "ICU", "java.text" };
}

@Override
public void draw(Canvas canvas, int width, int height, float dpi, int xpos, int ypos) {
x = 20;
y = 40;

var text = "🐉☺️❤️👮🏿👨‍👩‍👧‍👦🚵🏼‍♀️🇷🇺🏴󠁧󠁢󠁥󠁮󠁧󠁿*️⃣ǍǍZ̵̡̢͇͓͎͖͎̪͑͜ͅͅबिक्";
if ("ICU".equals(_variants[_variantIdx]))
drawCharacterICU(canvas, height, text);
else
drawCharacterJavaText(canvas, height, text);
x = width / 2 + 10;
y = 40;

text = "One, (two; three). FoUr,five!";
if ("ICU".equals(_variants[_variantIdx]))
drawWordICU(canvas, height, text);
else
drawWordJavaText(canvas, height, text);
}

public void drawUnicode(Canvas canvas, String str) {
var decoded = str.codePoints()
.mapToObj(c -> String.format("U+%4s", Long.toString(c, 16).toUpperCase()).replaceAll(" ", "0"))
.collect(Collectors.joining(" "));

try (var line = TextLine.make(decoded, mono11); ) {
canvas.drawTextLine(line, x + 50, y, blackFill);
}
}

public void drawSubstring(Canvas canvas, String str, int height) {
try (var line = TextLine.make(str, inter13); ) {
canvas.drawTextLine(line, x, y, blackFill);
}

y += 20;
if (y + 20 > height - 20) {
x += 100;
y = 20;
}
}

public void drawCharacterICU(Canvas canvas, int height, String text) {
try (var iter = BreakIterator.makeCharacterInstance();) {
iter.setText(text);
int start = iter.first();
while (true) {
int end = iter.next();
if (end == BreakIterator.DONE)
break;
drawUnicode(canvas, text.substring(start, end));
drawSubstring(canvas, text.substring(start, end), height);
start = end;
}
}
}

public void drawCharacterJavaText(Canvas canvas, int height, String text) {
var iter = java.text.BreakIterator.getCharacterInstance();
iter.setText(text);
int start = iter.first();
while (true) {
int end = iter.next();
if (end == java.text.BreakIterator.DONE)
break;
drawUnicode(canvas, text.substring(start, end));
drawSubstring(canvas, text.substring(start, end), height);
start = end;
}
}

public void drawWordICU(Canvas canvas, int height, String text) {
try (var iter = BreakIterator.makeWordInstance();) {
iter.setText(text);
int start = iter.first();
while (true) {
int end = iter.next();
if (end == BreakIterator.DONE)
break;
if (iter.getRuleStatus() != BreakIterator.WORD_NONE)
drawSubstring(canvas, text.substring(start, end), height);
start = end;
}
}
}

public void drawWordJavaText(Canvas canvas, int height, String text) {
var iter = java.text.BreakIterator.getWordInstance();
iter.setText(text);
int start = iter.first();
while (true) {
int end = iter.next();
if (end == java.text.BreakIterator.DONE)
break;
drawSubstring(canvas, text.substring(start, end), height);
start = end;
}
}
}
3 changes: 2 additions & 1 deletion examples/scenes/src/Scenes.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

public class Scenes {
public static TreeMap<String, Scene> scenes;
public static String currentScene = "Codec";
public static String currentScene = "Break Iterator";
public static HUD hud = new HUD();
public static boolean vsync = true;
public static boolean stats = true;
Expand All @@ -16,6 +16,7 @@ public class Scenes {
scenes.put("Bitmap", null);
scenes.put("Bitmap Image", null);
scenes.put("Blends", null);
scenes.put("Break Iterator", null);
scenes.put("Codec", null);
scenes.put("Color Filters", null);
scenes.put("Decorations Bench", null);
Expand Down
119 changes: 119 additions & 0 deletions native/src/BreakIterator.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#include <jni.h>
#include "interop.hh"
#include "unicode/ubrk.h"

static void deleteBreakIterator(UBreakIterator* instance) {
ubrk_close(instance);
}

extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skija_BreakIterator__1nGetFinalizer(JNIEnv* env, jclass jclass) {
return static_cast<jlong>(reinterpret_cast<uintptr_t>(&deleteBreakIterator));
}

extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skija_BreakIterator__1nMake
(JNIEnv* env, jclass jclass, jint type, jstring localeStr) {
UErrorCode status = U_ZERO_ERROR;
UBreakIterator* instance;
if (localeStr == nullptr)
instance = ubrk_open(static_cast<UBreakIteratorType>(type), uloc_getDefault(), nullptr, 0, &status);
else {
SkString locale = skString(env, localeStr);
instance = ubrk_open(static_cast<UBreakIteratorType>(type), locale.c_str(), nullptr, 0, &status);
}

if (U_FAILURE(status)) {
env->ThrowNew(java::lang::RuntimeException::cls, u_errorName(status));
return 0;
} else
return reinterpret_cast<jlong>(instance);
}

extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skija_BreakIterator__1nClone
(JNIEnv* env, jclass jclass, jlong ptr) {
UBreakIterator* instance = reinterpret_cast<UBreakIterator*>(static_cast<uintptr_t>(ptr));
UErrorCode status = U_ZERO_ERROR;
UBreakIterator* clone = ubrk_safeClone(instance, nullptr, 0, &status);
if (U_FAILURE(status)) {
env->ThrowNew(java::lang::RuntimeException::cls, u_errorName(status));
return 0;
} else
return reinterpret_cast<jlong>(clone);
}

extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skija_BreakIterator__1nCurrent
(JNIEnv* env, jclass jclass, jlong ptr) {
UBreakIterator* instance = reinterpret_cast<UBreakIterator*>(static_cast<uintptr_t>(ptr));
return ubrk_current(instance);
}

extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skija_BreakIterator__1nNext
(JNIEnv* env, jclass jclass, jlong ptr) {
UBreakIterator* instance = reinterpret_cast<UBreakIterator*>(static_cast<uintptr_t>(ptr));
return ubrk_next(instance);
}

extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skija_BreakIterator__1nPrevious
(JNIEnv* env, jclass jclass, jlong ptr) {
UBreakIterator* instance = reinterpret_cast<UBreakIterator*>(static_cast<uintptr_t>(ptr));
return ubrk_previous(instance);
}

extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skija_BreakIterator__1nFirst
(JNIEnv* env, jclass jclass, jlong ptr) {
UBreakIterator* instance = reinterpret_cast<UBreakIterator*>(static_cast<uintptr_t>(ptr));
return ubrk_first(instance);
}

extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skija_BreakIterator__1nLast
(JNIEnv* env, jclass jclass, jlong ptr) {
UBreakIterator* instance = reinterpret_cast<UBreakIterator*>(static_cast<uintptr_t>(ptr));
return ubrk_last(instance);
}

extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skija_BreakIterator__1nPreceding
(JNIEnv* env, jclass jclass, jlong ptr, jint offset) {
UBreakIterator* instance = reinterpret_cast<UBreakIterator*>(static_cast<uintptr_t>(ptr));
return ubrk_preceding(instance, offset);
}

extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skija_BreakIterator__1nFollowing
(JNIEnv* env, jclass jclass, jlong ptr, jint offset) {
UBreakIterator* instance = reinterpret_cast<UBreakIterator*>(static_cast<uintptr_t>(ptr));
return ubrk_following(instance, offset);
}

extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skija_BreakIterator__1nIsBoundary
(JNIEnv* env, jclass jclass, jlong ptr, jint offset) {
UBreakIterator* instance = reinterpret_cast<UBreakIterator*>(static_cast<uintptr_t>(ptr));
return ubrk_isBoundary(instance, offset);
}

extern "C" JNIEXPORT jint JNICALL Java_org_jetbrains_skija_BreakIterator__1nGetRuleStatus
(JNIEnv* env, jclass jclass, jlong ptr) {
UBreakIterator* instance = reinterpret_cast<UBreakIterator*>(static_cast<uintptr_t>(ptr));
return ubrk_getRuleStatus(instance);
}

extern "C" JNIEXPORT jintArray JNICALL Java_org_jetbrains_skija_BreakIterator__1nGetRuleStatuses
(JNIEnv* env, jclass jclass, jlong ptr) {
UBreakIterator* instance = reinterpret_cast<UBreakIterator*>(static_cast<uintptr_t>(ptr));
UErrorCode status = U_ZERO_ERROR;
int32_t len = ubrk_getRuleStatusVec(instance, nullptr, 0, &status);
if (U_FAILURE(status))
env->ThrowNew(java::lang::RuntimeException::cls, u_errorName(status));
std::vector<jint> vec(len);
ubrk_getRuleStatusVec(instance, reinterpret_cast<int32_t*>(vec.data()), len, &status);
if (U_FAILURE(status))
env->ThrowNew(java::lang::RuntimeException::cls, u_errorName(status));
return javaIntArray(env, vec);
}

extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skija_BreakIterator__1nSetText
(JNIEnv* env, jclass jclass, jlong ptr, jlong textPtr) {
UBreakIterator* instance = reinterpret_cast<UBreakIterator*>(static_cast<uintptr_t>(ptr));
std::vector<jchar>* text = reinterpret_cast<std::vector<jchar>*>(static_cast<uintptr_t>(textPtr));
UErrorCode status = U_ZERO_ERROR;
ubrk_setText(instance, reinterpret_cast<UChar *>(text->data()), text->size(), &status);
if (U_FAILURE(status))
env->ThrowNew(java::lang::RuntimeException::cls, u_errorName(status));
}
27 changes: 27 additions & 0 deletions native/src/U16String.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include <string>
#include <jni.h>
#include "interop.hh"
#include "SkString.h"

static void deleteU16String(std::vector<jchar>* instance) {
delete instance;
}

extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skija_U16String__1nGetFinalizer
(JNIEnv* env, jclass jclass) {
return static_cast<jlong>(reinterpret_cast<uintptr_t>(&deleteU16String));
}

extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skija_U16String__1nMake
(JNIEnv* env, jclass jclass, jstring str) {
jsize len = env->GetStringLength(str);
std::vector<jchar>* instance = new std::vector<jchar>(len);
env->GetStringRegion(str, 0, len, instance->data());
return reinterpret_cast<jlong>(instance);
}

extern "C" JNIEXPORT jobject JNICALL Java_org_jetbrains_skija_U16String__1nToString
(JNIEnv* env, jclass jclass, jlong ptr) {
std::vector<jchar>* instance = reinterpret_cast<std::vector<jchar>*>(static_cast<uintptr_t>(ptr));
return env->NewString(instance->data(), instance->size());
}
15 changes: 15 additions & 0 deletions native/src/interop.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,19 @@ namespace java {
}
}

namespace RuntimeException {
jclass cls;

void onLoad(JNIEnv* env) {
jclass local = env->FindClass("java/lang/RuntimeException");
cls = static_cast<jclass>(env->NewGlobalRef(local));
}

void onUnload(JNIEnv* env) {
env->DeleteGlobalRef(cls);
}
}

namespace String {
jclass cls;

Expand Down Expand Up @@ -111,6 +124,7 @@ namespace java {
void onLoad(JNIEnv* env) {
io::OutputStream::onLoad(env);
lang::Float::onLoad(env);
lang::RuntimeException::onLoad(env);
lang::String::onLoad(env);
lang::Throwable::onLoad(env);
util::Iterator::onLoad(env);
Expand All @@ -121,6 +135,7 @@ namespace java {
util::function::BooleanSupplier::onUnload(env);
util::Iterator::onUnload(env);
lang::String::onUnload(env);
lang::RuntimeException::onUnload(env);
lang::Float::onUnload(env);
}
}
Expand Down
6 changes: 6 additions & 0 deletions native/src/interop.hh
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ namespace java {
void onUnload(JNIEnv* env);
}

namespace RuntimeException {
extern jclass cls;
void onLoad(JNIEnv* env);
void onUnload(JNIEnv* env);
}

namespace String {
extern jclass cls;
void onLoad(JNIEnv* env);
Expand Down
Loading

0 comments on commit f5e3a45

Please sign in to comment.