shared/java/shaper/Shaper.java (180 lines of code) (raw):

package org.jetbrains.skija.shaper; import java.lang.ref.*; import java.util.*; import org.jetbrains.annotations.*; import org.jetbrains.skija.*; import org.jetbrains.skija.impl.*; /** * Shapes text using HarfBuzz and places the shaped text into a * client-managed buffer. */ public class Shaper extends Managed { static { Library.staticLoad(); } @NotNull @Contract("-> new") public static Shaper makePrimitive() { Stats.onNativeCall(); return new Shaper(_nMakePrimitive()); } @NotNull @Contract("-> new") public static Shaper makeShaperDrivenWrapper() { return makeShaperDrivenWrapper(null); } @NotNull @Contract("_ -> new") public static Shaper makeShaperDrivenWrapper(@Nullable FontMgr fontMgr) { try { Stats.onNativeCall(); return new Shaper(_nMakeShaperDrivenWrapper(Native.getPtr(fontMgr))); } finally { Reference.reachabilityFence(fontMgr); } } @NotNull @Contract("-> new") public static Shaper makeShapeThenWrap() { return makeShapeThenWrap(null); } @NotNull @Contract("_ -> new") public static Shaper makeShapeThenWrap(@Nullable FontMgr fontMgr) { try { Stats.onNativeCall(); return new Shaper(_nMakeShapeThenWrap(Native.getPtr(fontMgr))); } finally { Reference.reachabilityFence(fontMgr); } } @NotNull @Contract("-> new") public static Shaper makeShapeDontWrapOrReorder() { return makeShapeDontWrapOrReorder(null); } @NotNull @Contract("_ -> new") public static Shaper makeShapeDontWrapOrReorder(@Nullable FontMgr fontMgr) { try { Stats.onNativeCall(); return new Shaper(_nMakeShapeDontWrapOrReorder(Native.getPtr(fontMgr))); } finally { Reference.reachabilityFence(fontMgr); } } /** * <p>Only works on macOS</p> * * <p>WARN broken in m87 https://bugs.chromium.org/p/skia/issues/detail?id=10897</p> * * @return Shaper on macOS, throws UnsupportedOperationException elsewhere */ @NotNull @Contract("-> new") public static Shaper makeCoreText() { Stats.onNativeCall(); long ptr = _nMakeCoreText(); if (ptr == 0) throw new UnsupportedOperationException("CoreText not available"); return new Shaper(ptr); } @NotNull @Contract("-> new") public static Shaper make() { return make(null); } @NotNull @Contract("_ -> new") public static Shaper make(@Nullable FontMgr fontMgr) { try { Stats.onNativeCall(); return new Shaper(_nMake(Native.getPtr(fontMgr))); } finally { Reference.reachabilityFence(fontMgr); } } @Nullable @Contract("_, _ -> new") public TextBlob shape(String text, Font font) { return shape(text, font, ShapingOptions.DEFAULT, Float.POSITIVE_INFINITY, Point.ZERO); } @Nullable @Contract("_, _, _ -> new") public TextBlob shape(String text, Font font, float width) { return shape(text, font, ShapingOptions.DEFAULT, width, Point.ZERO); } @Nullable @Contract("_, _, _, _ -> new") public TextBlob shape(String text, Font font, float width, @NotNull Point offset) { return shape(text, font, ShapingOptions.DEFAULT, width, offset); } @Nullable @Contract("_, _, _, _, _ -> new") public TextBlob shape(String text, Font font, @NotNull ShapingOptions opts, float width, @NotNull Point offset) { try { assert opts != null : "Can’t Shaper::shape with opts == null"; Stats.onNativeCall(); long ptr = _nShapeBlob(_ptr, text, Native.getPtr(font), opts, width, offset._x, offset._y); return 0 == ptr ? null : new TextBlob(ptr); } finally { Reference.reachabilityFence(this); Reference.reachabilityFence(font); } } @NotNull @Contract("_, _, _, _, _ -> this") public Shaper shape(String text, Font font, @NotNull ShapingOptions opts, float width, RunHandler runHandler) { try (ManagedString textUtf8 = new ManagedString(text); FontMgrRunIterator fontIter = new FontMgrRunIterator(textUtf8, false, font, opts); IcuBidiRunIterator bidiIter = new IcuBidiRunIterator(textUtf8, false, opts._leftToRight ? java.text.Bidi.DIRECTION_LEFT_TO_RIGHT : java.text.Bidi.DIRECTION_RIGHT_TO_LEFT); HbIcuScriptRunIterator scriptIter = new HbIcuScriptRunIterator(textUtf8, false);) { Iterator<LanguageRun> langIter = new TrivialLanguageRunIterator(text, Locale.getDefault().toLanguageTag()); return shape(textUtf8, fontIter, bidiIter, scriptIter, langIter, opts, width, runHandler); } } @NotNull @Contract("_, _, _, _, _, _, _ -> this") public Shaper shape(@NotNull String text, @NotNull Iterator<FontRun> fontIter, @NotNull Iterator<BidiRun> bidiIter, @NotNull Iterator<ScriptRun> scriptIter, @NotNull Iterator<LanguageRun> langIter, @NotNull ShapingOptions opts, float width, @NotNull RunHandler runHandler) { try (ManagedString textUtf8 = new ManagedString(text);) { return shape(textUtf8, fontIter, bidiIter, scriptIter, langIter, opts, width, runHandler); } } @NotNull @Contract("_, _, _, _, _, _, _ -> this") public Shaper shape(@NotNull ManagedString textUtf8, @NotNull Iterator<FontRun> fontIter, @NotNull Iterator<BidiRun> bidiIter, @NotNull Iterator<ScriptRun> scriptIter, @NotNull Iterator<LanguageRun> langIter, @NotNull ShapingOptions opts, float width, @NotNull RunHandler runHandler) { assert fontIter != null : "FontRunIterator == null"; assert bidiIter != null : "BidiRunIterator == null"; assert scriptIter != null : "ScriptRunIterator == null"; assert langIter != null : "LanguageRunIterator == null"; assert opts != null : "Can’t Shaper::shape with opts == null"; Stats.onNativeCall(); _nShape(_ptr, Native.getPtr(textUtf8), fontIter, bidiIter, scriptIter, langIter, opts, width, runHandler); return this; } @NotNull @Contract("_, _, _ -> new") public TextLine shapeLine(String text, Font font, @NotNull ShapingOptions opts) { try { assert opts != null : "Can’t Shaper::shapeLine with opts == null"; Stats.onNativeCall(); return new TextLine(_nShapeLine(_ptr, text, Native.getPtr(font), opts)); } finally { Reference.reachabilityFence(this); Reference.reachabilityFence(font); } } @NotNull @Contract("_, _, _ -> new") public TextLine shapeLine(String text, Font font) { return shapeLine(text, font, ShapingOptions.DEFAULT); } @ApiStatus.Internal public Shaper(long ptr) { super(ptr, _FinalizerHolder.PTR); } @ApiStatus.Internal public static class _FinalizerHolder { public static final long PTR = _nGetFinalizer(); } public static native long _nGetFinalizer(); public static native long _nMakePrimitive(); public static native long _nMakeShaperDrivenWrapper(long fontMgrPtr); public static native long _nMakeShapeThenWrap(long fontMgrPtr); public static native long _nMakeShapeDontWrapOrReorder(long fontMgrPtr); public static native long _nMakeCoreText(); public static native long _nMake(long fontMgrPtr); public static native long _nShapeBlob(long ptr, String text, long fontPtr, ShapingOptions opts, float width, float offsetX, float offsetY); public static native long _nShapeLine(long ptr, String text, long fontPtr, ShapingOptions opts); public static native void _nShape(long ptr, long textPtr, Iterator<FontRun> fontIter, Iterator<BidiRun> bidiIter, Iterator<ScriptRun> scriptIter, Iterator<LanguageRun> langIter, ShapingOptions opts, float width, RunHandler runHandler); }