shared/java/Typeface.java (251 lines of code) (raw):

package org.jetbrains.skija; import java.lang.ref.*; import java.util.*; import org.jetbrains.annotations.*; import org.jetbrains.skija.impl.*; public class Typeface extends RefCnt { static { Library.staticLoad(); } /** * @return the typeface’s intrinsic style attributes */ public FontStyle getFontStyle() { try { Stats.onNativeCall(); return new FontStyle(_nGetFontStyle(_ptr)); } finally { Reference.reachabilityFence(this); } } /** * @return true if {@link #getFontStyle()} has the bold bit set */ public boolean isBold() { return getFontStyle().getWeight() >= FontWeight.SEMI_BOLD; } /** * @return true if {@link #getFontStyle()} has the italic bit set */ public boolean isItalic() { return getFontStyle().getSlant() != FontSlant.UPRIGHT; } /** * This is a style bit, advance widths may vary even if this returns true. * @return true if the typeface claims to be fixed-pitch */ public boolean isFixedPitch() { try { Stats.onNativeCall(); return _nIsFixedPitch(_ptr); } finally { Reference.reachabilityFence(this); } } /** * It is possible the number of axes can be retrieved but actual position cannot. * @return the variation coordinates describing the position of this typeface in design variation space, null if there’s no variations */ @Nullable public FontVariation[] getVariations() { try { Stats.onNativeCall(); return _nGetVariations(_ptr); } finally { Reference.reachabilityFence(this); } } /** * It is possible the number of axes can be retrieved but actual position cannot. * @return the variation coordinates describing the position of this typeface in design variation space, null if there’s no variations */ @Nullable public FontVariationAxis[] getVariationAxes() { try { Stats.onNativeCall(); return _nGetVariationAxes(_ptr); } finally { Reference.reachabilityFence(this); } } /** * @return a 32bit value for this typeface, unique for the underlying font data. Never 0 */ public int getUniqueId() { try { Stats.onNativeCall(); return _nGetUniqueId(_ptr); } finally { Reference.reachabilityFence(this); } } /** * @return true if the two typefaces reference the same underlying font, treating null as the default font */ @ApiStatus.Internal @Override public boolean _nativeEquals(Native other) { try { return _nEquals(_ptr, Native.getPtr(other)); } finally { Reference.reachabilityFence(this); Reference.reachabilityFence(other); } } /** * @return the default normal typeface, which is never null */ @NotNull public static Typeface makeDefault() { Stats.onNativeCall(); return new Typeface(_nMakeDefault()); } /** * Creates a new reference to the typeface that most closely matches the * requested name and style. This method allows extended font * face specifiers as in the {@link FontStyle} type. Will never return null. * @param name May be null. The name of the font family * @param style The style of the typeface * @return reference to the closest-matching typeface */ @NotNull public static Typeface makeFromName(String name, FontStyle style) { Stats.onNativeCall(); return new Typeface(_nMakeFromName(name, style._value)); } /** * @return a new typeface given a file * @throws IllegalArgumentException If the file does not exist, or is not a valid font file */ @NotNull public static Typeface makeFromFile(String path) { return makeFromFile(path, 0); } /** * @return a new typeface given a file * @throws IllegalArgumentException If the file does not exist, or is not a valid font file */ @NotNull public static Typeface makeFromFile(String path, int index) { Stats.onNativeCall(); long ptr = _nMakeFromFile(path, index); if (ptr == 0) throw new IllegalArgumentException("Failed to create Typeface from path=\"" + path + "\" index=" + index); return new Typeface(ptr); } /** * @return a new typeface given a Data * @throws IllegalArgumentException If the data is null, or is not a valid font file */ @NotNull public static Typeface makeFromData(Data data) { return makeFromData(data, 0); } /** * @return a new typeface given a Data * @throws IllegalArgumentException If the data is null, or is not a valid font file */ @NotNull public static Typeface makeFromData(Data data, int index) { try { Stats.onNativeCall(); long ptr = _nMakeFromData(Native.getPtr(data), index); if (ptr == 0) throw new IllegalArgumentException("Failed to create Typeface from data " + data); return new Typeface(ptr); } finally { Reference.reachabilityFence(data); } } /** * Return a new typeface based on this typeface but parameterized as specified in the * variation. If the variation does not supply an argument for a parameter * in the font then the value from this typeface will be used as the value for that argument. * @return same typeface if variation already matches, new typeface otherwise * @throws IllegalArgumentException on failure */ public Typeface makeClone(FontVariation variation) { return makeClone(new FontVariation[] { variation }, 0); } /** * Return a new typeface based on this typeface but parameterized as specified in the * variations. If the variations does not supply an argument for a parameter * in the font then the value from this typeface will be used as the value for that argument. * @return same typeface if all variation already match, new typeface otherwise * @throws IllegalArgumentException on failure */ public Typeface makeClone(FontVariation[] variations) { return makeClone(variations, 0); } /** * Return a new typeface based on this typeface but parameterized as specified in the * variations. If the variations does not supply an argument for a parameter * in the font then the value from this typeface will be used as the value for that argument. * @return same typeface if all variation already match, new typeface otherwise * @throws IllegalArgumentException on failure */ public Typeface makeClone(FontVariation[] variations, int collectionIndex) { try { if (variations.length == 0) return this; Stats.onNativeCall(); long ptr = _nMakeClone(_ptr, variations, collectionIndex); if (ptr == 0) throw new IllegalArgumentException("Failed to clone Typeface " + this + " with " + Arrays.toString(variations)); return new Typeface(ptr); } finally { Reference.reachabilityFence(this); } } /** * Given a string, returns corresponding glyph ids. * * @return the corresponding glyph ids for each character. */ public short[] getStringGlyphs(String s) { return getUTF32Glyphs(s.codePoints().toArray()); } /** * Given an array of UTF32 character codes, return their corresponding glyph IDs. * * @return the corresponding glyph IDs for each character. */ public short[] getUTF32Glyphs(int[] uni) { try { Stats.onNativeCall(); return _nGetUTF32Glyphs(_ptr, uni); } finally { Reference.reachabilityFence(this); } } /** * This is a short-cut for calling {@link #getUTF32Glyphs(int[])}. * @return the glyph that corresponds to the specified unicode code-point (in UTF32 encoding). If the unichar is not supported, returns 0 */ public short getUTF32Glyph(int unichar) { try { Stats.onNativeCall(); return _nGetUTF32Glyph(_ptr, unichar); } finally { Reference.reachabilityFence(this); } } /** * @return the number of glyphs in the typeface */ public int getGlyphsCount() { try { Stats.onNativeCall(); return _nGetGlyphsCount(_ptr); } finally { Reference.reachabilityFence(this); } } /** * @return the number of tables in the font */ public int getTablesCount() { try { Stats.onNativeCall(); return _nGetTablesCount(_ptr); } finally { Reference.reachabilityFence(this); } } /** * @return the list of table tags in the font */ public String[] getTableTags() { try { Stats.onNativeCall(); return Arrays.stream(_nGetTableTags(_ptr)).mapToObj(FourByteTag::toString).toArray(String[]::new); } finally { Reference.reachabilityFence(this); } } /** * Given a table tag, return the size of its contents, or 0 if not present */ public long getTableSize(String tag) { try { Stats.onNativeCall(); return _nGetTableSize(_ptr, FourByteTag.fromString(tag)); } finally { Reference.reachabilityFence(this); } } /** * Return an immutable copy of the requested font table, or null if that table was * not found. * * @param tag The table tag whose contents are to be copied * @return an immutable copy of the table's data, or null */ @Nullable public Data getTableData(String tag) { try { Stats.onNativeCall(); long ptr = _nGetTableData(_ptr, FourByteTag.fromString(tag)); return ptr == 0 ? null : new Data(ptr); } finally { Reference.reachabilityFence(this); } } /** * @return the units-per-em value for this typeface, or zero if there is an error */ public int getUnitsPerEm() { try { Stats.onNativeCall(); return _nGetUnitsPerEm(_ptr); } finally { Reference.reachabilityFence(this); } } /** * Given a run of glyphs, return the associated horizontal adjustments. * Adjustments are in "design units", which are integers relative to the * typeface's units per em (see {@link #getUnitsPerEm()}). * * Some typefaces are known to never support kerning. Calling this with null, * if it returns null then it will always return null (no kerning) for all * possible glyph runs. If it returns int[0], then it *may* return non-null * adjustments for some glyph runs. * * @return adjustment array (one less than glyphs), or null if no kerning should be applied */ @Nullable public int[] getKerningPairAdjustments(short[] glyphs) { try { Stats.onNativeCall(); return _nGetKerningPairAdjustments(_ptr, glyphs); } finally { Reference.reachabilityFence(this); } } /** * @return all of the family names specified by the font */ public FontFamilyName[] getFamilyNames() { try { Stats.onNativeCall(); return _nGetFamilyNames(_ptr); } finally { Reference.reachabilityFence(this); } } /** * @return the family name for this typeface. The language of the name is whatever the host platform chooses */ public String getFamilyName() { try { Stats.onNativeCall(); return _nGetFamilyName(_ptr); } finally { Reference.reachabilityFence(this); } } /** * Return a rectangle (scaled to 1-pt) that represents the union of the bounds of all * of the glyphs, but each one positioned at (0,). This may be conservatively large, and * will not take into account any hinting or other size-specific adjustments. */ public Rect getBounds() { try { Stats.onNativeCall(); return _nGetBounds(_ptr); } finally { Reference.reachabilityFence(this); } } @ApiStatus.Internal public Typeface(long ptr) { super(ptr); } @ApiStatus.Internal public static native int _nGetFontStyle(long ptr); @ApiStatus.Internal public static native boolean _nIsFixedPitch(long ptr); @ApiStatus.Internal public static native FontVariation[] _nGetVariations(long ptr); @ApiStatus.Internal public static native FontVariationAxis[] _nGetVariationAxes(long ptr); @ApiStatus.Internal public static native int _nGetUniqueId(long ptr); @ApiStatus.Internal public static native boolean _nEquals(long ptr, long otherPtr); @ApiStatus.Internal public static native long _nMakeDefault(); @ApiStatus.Internal public static native long _nMakeFromName(String name, int fontStyle); @ApiStatus.Internal public static native long _nMakeFromFile(String path, int index); @ApiStatus.Internal public static native long _nMakeFromData(long dataPtr, int index); @ApiStatus.Internal public static native long _nMakeClone(long ptr, FontVariation[] variations, int collectionIndex); @ApiStatus.Internal public static native short[] _nGetUTF32Glyphs(long ptr, int[] uni); @ApiStatus.Internal public static native short _nGetUTF32Glyph(long ptr, int unichar); @ApiStatus.Internal public static native int _nGetGlyphsCount(long ptr); @ApiStatus.Internal public static native int _nGetTablesCount(long ptr); @ApiStatus.Internal public static native int[] _nGetTableTags(long ptr); @ApiStatus.Internal public static native long _nGetTableSize(long ptr, int tag); @ApiStatus.Internal public static native long _nGetTableData(long ptr, int tag); @ApiStatus.Internal public static native int _nGetUnitsPerEm(long ptr); @ApiStatus.Internal public static native int[] _nGetKerningPairAdjustments(long ptr, short[] glyphs); @ApiStatus.Internal public static native FontFamilyName[] _nGetFamilyNames(long ptr); @ApiStatus.Internal public static native String _nGetFamilyName(long ptr); @ApiStatus.Internal public static native Rect _nGetBounds(long ptr); }