mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2025-12-06 09:29:38 +01:00
JBR-7232 Refactor deriveFontWithFeatures & JBRFileDialog JBR API
This commit is contained in:
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2023 JetBrains s.r.o.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.jetbrains.desktop;
|
||||
|
||||
import com.jetbrains.internal.JBRApi;
|
||||
|
||||
import java.awt.*;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class FontExtensions {
|
||||
private interface FontExtension {
|
||||
FontExtension INSTANCE = (FontExtension) JBRApi.internalServiceBuilder(MethodHandles.lookup())
|
||||
.withStatic("getFeatures", "getFeatures", "java.awt.Font")
|
||||
.withStatic("isComplexRendering", "isComplexRendering", "java.awt.Font")
|
||||
.withStatic("isKerning", "isKerning", "java.awt.Font")
|
||||
.build();
|
||||
|
||||
TreeMap<String, Integer> getFeatures(Font font);
|
||||
boolean isComplexRendering(Font font);
|
||||
boolean isKerning(Font font);
|
||||
}
|
||||
|
||||
public static String[] featuresToStringArray(Map<String, Integer> features) {
|
||||
return features.entrySet().stream().map(feature -> (feature.getKey() + "=" + feature.getValue())).
|
||||
toArray(String[]::new);
|
||||
}
|
||||
|
||||
public static TreeMap<String, Integer> getFeatures(Font font) {
|
||||
return FontExtension.INSTANCE.getFeatures(font);
|
||||
}
|
||||
|
||||
public static boolean isComplexRendering(Font font) {
|
||||
return FontExtension.INSTANCE.isComplexRendering(font);
|
||||
}
|
||||
|
||||
public static boolean isKerning(Font font) {
|
||||
return FontExtension.INSTANCE.isKerning(font);
|
||||
}
|
||||
}
|
||||
@@ -61,6 +61,7 @@ public class JBRApiModule {
|
||||
.withStatic("getSubpixelResolution", "getSubpixelResolution", "sun.font.FontUtilities")
|
||||
.withStatic("deriveFontWithFeatures", "deriveFont", "java.awt.Font")
|
||||
.withStatic("getAvailableFeatures", "getAvailableFeatures", "java.awt.Font")
|
||||
.withStatic("getEnabledFeatures", "getEnabledFeatures", "java.awt.Font")
|
||||
.service("com.jetbrains.FontOpenTypeFeatures")
|
||||
.withStatic("getAvailableFeatures", "getAvailableFeatures", "java.awt.Font")
|
||||
.clientProxy("java.awt.Font$Features", "com.jetbrains.FontExtensions$Features")
|
||||
|
||||
@@ -6,6 +6,7 @@ import java.lang.annotation.Native;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.awt.*;
|
||||
import java.util.Objects;
|
||||
|
||||
public class JBRFileDialog implements Serializable {
|
||||
|
||||
@@ -25,28 +26,19 @@ public class JBRFileDialog implements Serializable {
|
||||
return (JBRFileDialog) getter.get(dialog);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to select files, directories or both (used when common file dialogs are enabled on Windows, or on macOS)
|
||||
*/
|
||||
@Native public static final int SELECT_FILES_HINT = 1, SELECT_DIRECTORIES_HINT = 2;
|
||||
/**
|
||||
* Whether to allow creating directories or not (used on macOS)
|
||||
*/
|
||||
@Native public static final int CREATE_DIRECTORIES_HINT = 4;
|
||||
|
||||
public static final String OPEN_FILE_BUTTON_KEY = "jbrFileDialogOpenFile";
|
||||
public static final String OPEN_DIRECTORY_BUTTON_KEY = "jbrFileDialogSelectDir";
|
||||
public static final String ALL_FILES_COMBO_KEY = "jbrFileDialogAllFiles";
|
||||
|
||||
public int hints = CREATE_DIRECTORIES_HINT;
|
||||
|
||||
/**
|
||||
* Text for "Open" button (used when common file dialogs are enabled on
|
||||
* Windows).
|
||||
*/
|
||||
public String openButtonText;
|
||||
|
||||
/**
|
||||
* Text for "Select Folder" button (used when common file dialogs are
|
||||
* enabled on Windows).
|
||||
*/
|
||||
public String selectFolderButtonText;
|
||||
public String allFilesFilterDescription;
|
||||
public String fileFilterDescription;
|
||||
public String[] fileFilterExtensions;
|
||||
|
||||
public void setHints(int hints) {
|
||||
this.hints = hints;
|
||||
@@ -55,9 +47,23 @@ public class JBRFileDialog implements Serializable {
|
||||
return hints;
|
||||
}
|
||||
|
||||
public void setLocalizationStrings(String openButtonText, String selectFolderButtonText) {
|
||||
this.openButtonText = openButtonText;
|
||||
this.selectFolderButtonText = selectFolderButtonText;
|
||||
public void setLocalizationString(String key, String text) {
|
||||
Objects.requireNonNull(key);
|
||||
switch (key) {
|
||||
case OPEN_FILE_BUTTON_KEY -> openButtonText = text;
|
||||
case OPEN_DIRECTORY_BUTTON_KEY -> selectFolderButtonText = text;
|
||||
case ALL_FILES_COMBO_KEY -> allFilesFilterDescription = text;
|
||||
default -> throw new IllegalArgumentException("unrecognized key: " + key);
|
||||
}
|
||||
}
|
||||
|
||||
public void setLocalizationStrings(String openButtonText, String selectFolderButtonText) {
|
||||
setLocalizationString(OPEN_FILE_BUTTON_KEY, openButtonText);
|
||||
setLocalizationString(OPEN_DIRECTORY_BUTTON_KEY, selectFolderButtonText);
|
||||
}
|
||||
|
||||
public void setFileFilterExtensions(String fileFilterDescription, String[] fileFilterExtensions) {
|
||||
this.fileFilterDescription = fileFilterDescription;
|
||||
this.fileFilterExtensions = fileFilterExtensions;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,17 +48,11 @@ import java.security.AccessController;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.text.AttributedCharacterIterator.Attribute;
|
||||
import java.text.CharacterIterator;
|
||||
import java.util.EventListener;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.*;
|
||||
|
||||
import sun.awt.ComponentFactory;
|
||||
import sun.font.AttributeMap;
|
||||
import sun.font.AttributeValues;
|
||||
import sun.font.CompositeFont;
|
||||
import sun.font.CoreMetrics;
|
||||
import sun.font.CreatedFontTracker;
|
||||
import sun.font.Font2D;
|
||||
@@ -284,6 +278,28 @@ public class Font implements java.io.Serializable
|
||||
public FontPeer getFontPeer(final Font font) {
|
||||
return font.getFontPeer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getFeatures(Font font) {
|
||||
int size = font.features == null ? 0 : font.features.length;
|
||||
String[] fs = new String[size + 3];
|
||||
if (size > 0) System.arraycopy(font.features, 0, fs, 0, size);
|
||||
fs[size++] = KERN_FEATURE + "=" + font.getAttributeValues().getKerning();
|
||||
fs[size++] = LIGA_FEATURE + "=" + font.getAttributeValues().getLigatures();
|
||||
fs[size] = CALT_FEATURE + "=" + font.getAttributeValues().getLigatures();
|
||||
return fs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isComplexRendering(Font font) {
|
||||
return (font.values != null && (font.values.getLigatures() != 0 || font.values.getTracking() != 0 ||
|
||||
font.values.getBaselineTransform() != null)) || font.features != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isKerning(Font font) {
|
||||
return font.values != null && (font.values.getKerning() != 0);
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
@@ -455,10 +471,9 @@ public class Font implements java.io.Serializable
|
||||
* Ordered map choose intentionally as field's type. It allows to correctly comparing two Font objects
|
||||
*
|
||||
* @serial
|
||||
* @see #getFeatures
|
||||
* @see #deriveFont(Font, Features)
|
||||
*/
|
||||
private TreeMap<String, Integer> features = new TreeMap<String, Integer>();
|
||||
private String[] features;
|
||||
|
||||
/**
|
||||
* The platform specific font information.
|
||||
@@ -561,10 +576,6 @@ public class Font implements java.io.Serializable
|
||||
return font2DHandle.font2D;
|
||||
}
|
||||
|
||||
private boolean anyEnabledFeatures() {
|
||||
return features.values().stream().anyMatch(x -> x != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@code Font} from the specified name, style and
|
||||
* point size.
|
||||
@@ -628,7 +639,7 @@ public class Font implements java.io.Serializable
|
||||
this.pointSize = size;
|
||||
}
|
||||
|
||||
private Font(String name, int style, float sizePts, TreeMap<String, Integer> features) {
|
||||
private Font(String name, int style, float sizePts, String[] features) {
|
||||
this.name = (name != null) ? name : "Default";
|
||||
this.style = (style & ~0x03) == 0 ? style : 0;
|
||||
this.size = (int)(sizePts + 0.5);
|
||||
@@ -639,7 +650,7 @@ public class Font implements java.io.Serializable
|
||||
/* This constructor is used by deriveFont when attributes is null */
|
||||
private Font(String name, int style, float sizePts,
|
||||
boolean created, boolean withFallback,
|
||||
Font2DHandle handle, boolean useOldHandle, TreeMap<String, Integer> features) {
|
||||
Font2DHandle handle, boolean useOldHandle, String[] features) {
|
||||
this(name, style, sizePts, features);
|
||||
this.createdFont = created;
|
||||
this.withFallback = withFallback;
|
||||
@@ -704,7 +715,7 @@ public class Font implements java.io.Serializable
|
||||
*/
|
||||
private Font(AttributeValues values, String oldName, int oldStyle,
|
||||
boolean created, boolean withFallback,
|
||||
Font2DHandle handle, boolean useOldHandle, TreeMap<String, Integer> features) {
|
||||
Font2DHandle handle, boolean useOldHandle, String[] features) {
|
||||
|
||||
this.features = features;
|
||||
this.createdFont = created;
|
||||
@@ -768,6 +779,11 @@ public class Font implements java.io.Serializable
|
||||
* @since 1.6
|
||||
*/
|
||||
protected Font(Font font) {
|
||||
this(font, font.features);
|
||||
}
|
||||
|
||||
private Font(Font font, String[] features) {
|
||||
this.features = features;
|
||||
if (font.values != null) {
|
||||
initFromValues(font.getAttributeValues().clone());
|
||||
} else {
|
||||
@@ -779,12 +795,6 @@ public class Font implements java.io.Serializable
|
||||
this.font2DHandle = font.font2DHandle;
|
||||
this.createdFont = font.createdFont;
|
||||
this.withFallback = font.withFallback;
|
||||
this.features = font.features;
|
||||
}
|
||||
|
||||
private Font(Font font, TreeMap<String, Integer> features) {
|
||||
this(font);
|
||||
this.features = features;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -834,7 +844,7 @@ public class Font implements java.io.Serializable
|
||||
if (values.getPosture() >= .2f) this.style |= ITALIC; // not == .2f
|
||||
|
||||
this.nonIdentityTx = values.anyNonDefault(EXTRA_MASK);
|
||||
this.hasLayoutAttributes = values.anyNonDefault(LAYOUT_MASK);
|
||||
this.hasLayoutAttributes = this.features != null || values.anyNonDefault(LAYOUT_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -915,7 +925,7 @@ public class Font implements java.io.Serializable
|
||||
values.merge(attributes, SECONDARY_MASK);
|
||||
return new Font(values, font.name, font.style,
|
||||
font.createdFont, font.withFallback,
|
||||
font.font2DHandle, false, new TreeMap<String, Integer>());
|
||||
font.font2DHandle, false, null);
|
||||
}
|
||||
return new Font(attributes);
|
||||
}
|
||||
@@ -927,7 +937,7 @@ public class Font implements java.io.Serializable
|
||||
values.merge(attributes, SECONDARY_MASK);
|
||||
return new Font(values, font.name, font.style,
|
||||
font.createdFont, font.withFallback,
|
||||
font.font2DHandle, false, new TreeMap<String, Integer>());
|
||||
font.font2DHandle, false, null);
|
||||
}
|
||||
|
||||
return font;
|
||||
@@ -1648,17 +1658,7 @@ public class Font implements java.io.Serializable
|
||||
* @since 1.6
|
||||
*/
|
||||
public boolean hasLayoutAttributes() {
|
||||
return anyEnabledFeatures() || hasLayoutAttributes;
|
||||
}
|
||||
|
||||
private static TreeMap<String, Integer> getFeatures(Font font) {
|
||||
TreeMap<String, Integer> res = new TreeMap<>();
|
||||
res.putAll(font.features);
|
||||
res.put(KERN_FEATURE, font.getAttributeValues().getKerning());
|
||||
res.put(LIGA_FEATURE, font.getAttributeValues().getLigatures());
|
||||
res.put(CALT_FEATURE, font.getAttributeValues().getLigatures());
|
||||
|
||||
return res;
|
||||
return hasLayoutAttributes;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1866,7 +1866,7 @@ public class Font implements java.io.Serializable
|
||||
*/
|
||||
public int hashCode() {
|
||||
if (hash == 0) {
|
||||
hash = name.hashCode() ^ style ^ size ^ features.hashCode();
|
||||
hash = name.hashCode() ^ style ^ size ^ Arrays.hashCode(features);
|
||||
/* It is possible many fonts differ only in transform.
|
||||
* So include the transform in the hash calculation.
|
||||
* nonIdentityTx is set whenever there is a transform in
|
||||
@@ -1905,7 +1905,7 @@ public class Font implements java.io.Serializable
|
||||
pointSize == font.pointSize &&
|
||||
withFallback == font.withFallback &&
|
||||
name.equals(font.name) &&
|
||||
features.equals(font.features)) {
|
||||
Arrays.equals(features, font.features)) {
|
||||
|
||||
/* 'values' is usually initialized lazily, except when
|
||||
* the font is constructed from a Map, or derived using
|
||||
@@ -2029,17 +2029,13 @@ public class Font implements java.io.Serializable
|
||||
}
|
||||
values = getAttributeValues().merge(extras);
|
||||
this.nonIdentityTx = values.anyNonDefault(EXTRA_MASK);
|
||||
this.hasLayoutAttributes = values.anyNonDefault(LAYOUT_MASK);
|
||||
this.hasLayoutAttributes = this.features != null || values.anyNonDefault(LAYOUT_MASK);
|
||||
} catch (Throwable t) {
|
||||
throw new IOException(t);
|
||||
} finally {
|
||||
fRequestedAttributes = null; // don't need it any more
|
||||
}
|
||||
}
|
||||
|
||||
if (features == null) {
|
||||
features = new TreeMap<>();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2270,7 +2266,48 @@ public class Font implements java.io.Serializable
|
||||
}
|
||||
|
||||
private static Font deriveFont(Font font, Features features) {
|
||||
return new Font(font, features.getAsTreeMap());
|
||||
TreeMap<String, Integer> map = features.getAsTreeMap();
|
||||
String[] array = new String[map.size()];
|
||||
int i = 0;
|
||||
for (Map.Entry<String, Integer> e : map.entrySet()) {
|
||||
validateFeature(array[i++] = e.getKey() + "=" + e.getValue());
|
||||
}
|
||||
return new Font(font, array);
|
||||
}
|
||||
|
||||
private static void validateFeature(String f) {
|
||||
int len = f.length();
|
||||
invalid:if ((len == 4 || len > 5) &&
|
||||
Character.isLetterOrDigit(f.charAt(0)) &&
|
||||
Character.isLetterOrDigit(f.charAt(1)) &&
|
||||
Character.isLetterOrDigit(f.charAt(2)) &&
|
||||
Character.isLetterOrDigit(f.charAt(3))) {
|
||||
if (len > 5 && f.charAt(4) == '=') {
|
||||
for (int i = 5; i < len; i++) {
|
||||
if (!Character.isDigit(f.charAt(i))) break invalid;
|
||||
}
|
||||
if (f.startsWith("kern")) throw new IllegalArgumentException(
|
||||
"\"kern\" feature is not allowed here, use java.awt.font.TextAttribute.KERNING instead");
|
||||
if (f.startsWith("liga") || f.startsWith("calt")) throw new IllegalArgumentException(
|
||||
"\"liga\" and \"calt\" features are not allowed here, use java.awt.font.TextAttribute.LIGATURES instead");
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Invalid feature: \"" + f + "\", allowed syntax: \"kern\", or \"aalt=2\"");
|
||||
}
|
||||
|
||||
private static Font deriveFont(Font font, String... features) {
|
||||
if (features == null || features.length == 0) return new Font(font, null);
|
||||
for (String f : features) validateFeature(f);
|
||||
return new Font(font, Arrays.copyOf(features, features.length));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of OpenType's features enabled on the current Font.
|
||||
* @return array of enabled OpenType's features
|
||||
*/
|
||||
private static String[] getEnabledFeatures(Font font) {
|
||||
return font.features == null ? new String[0] : Arrays.copyOf(font.features, font.features.length);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2724,19 +2761,10 @@ public class Font implements java.io.Serializable
|
||||
return metrics.charsBounds(chars, beginIndex, limit - beginIndex);
|
||||
}
|
||||
|
||||
private static boolean isComplexRendering(Font font) {
|
||||
return (font.values != null && (font.values.getLigatures() != 0 || font.values.getTracking() != 0 ||
|
||||
font.values.getBaselineTransform() != null)) || font.anyEnabledFeatures();
|
||||
}
|
||||
|
||||
private static boolean isKerning(Font font) {
|
||||
return font.values != null && (font.values.getKerning() != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of OpenType's features supported by current Font.
|
||||
* Implementation of such logic goes to HarfBuzz library.
|
||||
* @return list of OpenType's features concatenated to String
|
||||
* @return set of available OpenType's features
|
||||
*/
|
||||
private static Set<String> getAvailableFeatures(Font font) {
|
||||
return SunLayoutEngine.getAvailableFeatures(FontUtilities.getFont2D(font));
|
||||
|
||||
@@ -27,6 +27,7 @@ package sun.font;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.peer.FontPeer;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public abstract class FontAccess {
|
||||
|
||||
@@ -47,4 +48,7 @@ public abstract class FontAccess {
|
||||
public abstract void setWithFallback(Font f);
|
||||
public abstract boolean isCreatedFont(Font f);
|
||||
public abstract FontPeer getFontPeer(Font f);
|
||||
public abstract String[] getFeatures(Font font);
|
||||
public abstract boolean isComplexRendering(Font font);
|
||||
public abstract boolean isKerning(Font font);
|
||||
}
|
||||
|
||||
@@ -43,7 +43,6 @@ import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import com.jetbrains.desktop.FontExtensions;
|
||||
import sun.java2d.Disposer;
|
||||
import sun.java2d.DisposerRecord;
|
||||
|
||||
@@ -481,7 +480,7 @@ public final class FontDesignMetrics extends FontMetrics {
|
||||
assert (data instanceof String || data instanceof char[]);
|
||||
float width = 0;
|
||||
|
||||
if (overrider == null && FontExtensions.isComplexRendering(font) && len > 0) {
|
||||
if (overrider == null && FontAccess.getFontAccess().isComplexRendering(font) && len > 0) {
|
||||
return textLayoutBounds(data, off, len);
|
||||
}
|
||||
|
||||
@@ -492,7 +491,7 @@ public final class FontDesignMetrics extends FontMetrics {
|
||||
return new Rectangle2D.Float(0f, -ascent, width, height);
|
||||
}
|
||||
|
||||
boolean isKerning = FontExtensions.isKerning(font);
|
||||
boolean isKerning = FontAccess.getFontAccess().isKerning(font);
|
||||
float consecutiveDoubleCharacterWidth = 0f;
|
||||
char prev = 0;
|
||||
for (int i = off; i < off + len; i++) {
|
||||
@@ -608,7 +607,7 @@ public final class FontDesignMetrics extends FontMetrics {
|
||||
return height;
|
||||
}
|
||||
|
||||
private static class Accessor { // used by JBR API
|
||||
private static final class Accessor {
|
||||
// Keeping metrics instances here prevents them from being garbage collected
|
||||
// and being re-created by FontDesignMetrics.getMetrics method
|
||||
private final Set<FontDesignMetrics> PINNED_METRICS = new HashSet<>();
|
||||
@@ -647,7 +646,7 @@ public final class FontDesignMetrics extends FontMetrics {
|
||||
}
|
||||
}
|
||||
|
||||
private interface Overrider { // used by JBR API
|
||||
private interface Overrider {
|
||||
float charWidth(int codePoint);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,8 +68,6 @@
|
||||
|
||||
package sun.font;
|
||||
|
||||
import com.jetbrains.desktop.FontExtensions;
|
||||
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.awt.Font;
|
||||
import java.awt.font.FontRenderContext;
|
||||
@@ -176,7 +174,7 @@ public final class GlyphLayout {
|
||||
* leave pt and the gvdata unchanged.
|
||||
*/
|
||||
public void layout(FontStrikeDesc sd, float[] mat, float ptSize, int gmask, int baseIndex, TextRecord text,
|
||||
boolean ltrDirection, Map<String, Integer> features, Point2D.Float pt, GVData data);
|
||||
boolean ltrDirection, String[] features, Point2D.Float pt, GVData data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -452,7 +450,7 @@ public final class GlyphLayout {
|
||||
EngineRecord er = _erecords.get(ix);
|
||||
for (;;) {
|
||||
try {
|
||||
er.layout(ltrDirection, FontExtensions.getFeatures(font));
|
||||
er.layout(ltrDirection, FontAccess.getFontAccess().getFeatures(font));
|
||||
break;
|
||||
}
|
||||
catch (IndexOutOfBoundsException e) {
|
||||
@@ -658,7 +656,7 @@ public final class GlyphLayout {
|
||||
this.engine = _lef.getEngine(key); // flags?
|
||||
}
|
||||
|
||||
void layout(boolean ltrDirection, Map<String, Integer> features) {
|
||||
void layout(boolean ltrDirection, String[] features) {
|
||||
_textRecord.start = start;
|
||||
_textRecord.limit = limit;
|
||||
engine.layout(_sd, _mat, ptSize, gmask, start - _offset, _textRecord,
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
|
||||
package sun.font;
|
||||
|
||||
import com.jetbrains.desktop.FontExtensions;
|
||||
import sun.font.GlyphLayout.*;
|
||||
import sun.java2d.Disposer;
|
||||
import sun.java2d.DisposerRecord;
|
||||
@@ -174,7 +173,7 @@ public final class SunLayoutEngine implements LayoutEngine, LayoutEngineFactory
|
||||
}
|
||||
|
||||
public void layout(FontStrikeDesc desc, float[] mat, float ptSize, int gmask,
|
||||
int baseIndex, TextRecord tr, boolean ltrDirection, Map<String, Integer> features,
|
||||
int baseIndex, TextRecord tr, boolean ltrDirection, String[] features,
|
||||
Point2D.Float pt, GVData data) {
|
||||
Font2D font = key.font();
|
||||
FontStrike strike = font.getStrike(desc);
|
||||
@@ -183,7 +182,7 @@ public final class SunLayoutEngine implements LayoutEngine, LayoutEngineFactory
|
||||
shape(font, strike, ptSize, mat, pFace,
|
||||
tr.text, data, key.script(),
|
||||
tr.start, tr.limit, baseIndex, pt,
|
||||
ltrDirection, FontExtensions.featuresToStringArray(features), gmask);
|
||||
ltrDirection, features, gmask);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,9 +42,6 @@ import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.jetbrains.desktop.FontExtensions.featuresToStringArray;
|
||||
import static com.jetbrains.desktop.FontExtensions.getFeatures;
|
||||
|
||||
public class FontExtensionsTest {
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
private @interface JBRTest {}
|
||||
@@ -96,10 +93,6 @@ public class FontExtensionsTest {
|
||||
return isImageEquals(image1, image2);
|
||||
}
|
||||
|
||||
private static String[] fontFeaturesAsString(Font font) {
|
||||
return featuresToStringArray(getFeatures(font));
|
||||
}
|
||||
|
||||
@JBRTest
|
||||
private static Boolean testFeatureFromString() {
|
||||
return FontExtensions.FeatureTag.getFeatureTag("frac").isPresent() &&
|
||||
@@ -108,23 +101,24 @@ public class FontExtensionsTest {
|
||||
FontExtensions.FeatureTag.getFeatureTag("tttt").isEmpty();
|
||||
}
|
||||
|
||||
@JBRTest
|
||||
private static Boolean testFeaturesToString1() {
|
||||
Font font = JBR.getFontExtensions().deriveFontWithFeatures(BASE_FONT, new FontExtensions.Features(Map.of(
|
||||
FontExtensions.FeatureTag.ZERO, FontExtensions.FEATURE_ON,
|
||||
FontExtensions.FeatureTag.SALT, 123,
|
||||
FontExtensions.FeatureTag.FRAC, FontExtensions.FEATURE_OFF)));
|
||||
String[] features = {"calt=0", "frac=0", "kern=0", "liga=0", "salt=123", "zero=1"};
|
||||
return Arrays.equals(fontFeaturesAsString(font), features);
|
||||
}
|
||||
|
||||
@JBRTest
|
||||
private static Boolean testFeaturesToString2() {
|
||||
Font font = BASE_FONT.deriveFont(Map.of(TextAttribute.LIGATURES, TextAttribute.LIGATURES_ON,
|
||||
TextAttribute.KERNING, TextAttribute.KERNING_ON));
|
||||
String[] features = {"calt=1", "kern=1", "liga=1"};
|
||||
return Arrays.equals(fontFeaturesAsString(font), features);
|
||||
}
|
||||
// TODO uncomment these tests when API for retrieving enabled font features is availbale
|
||||
// @JBRTest
|
||||
// private static Boolean testFeaturesToString1() {
|
||||
// Font font = JBR.getFontExtensions().deriveFontWithFeatures(BASE_FONT, new FontExtensions.Features(Map.of(
|
||||
// FontExtensions.FeatureTag.ZERO, FontExtensions.FEATURE_ON,
|
||||
// FontExtensions.FeatureTag.SALT, 123,
|
||||
// FontExtensions.FeatureTag.FRAC, FontExtensions.FEATURE_OFF)));
|
||||
// String[] features = {"calt=0", "frac=0", "kern=0", "liga=0", "salt=123", "zero=1"};
|
||||
// return Arrays.equals(fontFeaturesAsString(font), features);
|
||||
// }
|
||||
//
|
||||
// @JBRTest
|
||||
// private static Boolean testFeaturesToString2() {
|
||||
// Font font = BASE_FONT.deriveFont(Map.of(TextAttribute.LIGATURES, TextAttribute.LIGATURES_ON,
|
||||
// TextAttribute.KERNING, TextAttribute.KERNING_ON));
|
||||
// String[] features = {"calt=1", "kern=1", "liga=1"};
|
||||
// return Arrays.equals(fontFeaturesAsString(font), features);
|
||||
// }
|
||||
|
||||
@JBRTest
|
||||
private static Boolean testDisablingLigatureByDefault() {
|
||||
@@ -257,7 +251,7 @@ public class FontExtensionsTest {
|
||||
}
|
||||
}
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException("JBR: internal error during testing");
|
||||
throw new RuntimeException("JBR: internal error during testing", e);
|
||||
}
|
||||
|
||||
if (!error.isEmpty()) {
|
||||
|
||||
Reference in New Issue
Block a user