8146324: Add sun.font.FontUtilities.isComplexCharCode or related method
Reviewed-by: serb, ssadetsky
--- a/jdk/src/java.desktop/share/classes/java/awt/Font.java Tue Apr 05 21:13:44 2016 +0400
+++ b/jdk/src/java.desktop/share/classes/java/awt/Font.java Tue Apr 05 11:52:52 2016 -0700
@@ -766,6 +766,49 @@
}
/**
+ * Returns true if any part of the specified text is from a
+ * complex script for which the implementation will need to invoke
+ * layout processing in order to render correctly when using
+ * {@link Graphics#drawString(String,int,int) drawString(String,int,int)}
+ * and other text rendering methods. Measurement of the text
+ * may similarly need the same extra processing.
+ * The {@code start} and {@code end} indices are provided so that
+ * the application can request only a subset of the text be considered.
+ * The last char index examined is at {@code "end-1"},
+ * i.e a request to examine the entire array would be
+ * <pre>
+ * {@code Font.textRequiresLayout(chars, 0, chars.length);}
+ * </pre>
+ * An application may find this information helpful in
+ * performance sensitive code.
+ * <p>
+ * Note that even if this method returns {@code false}, layout processing
+ * may still be invoked when used with any {@code Font}
+ * for which {@link #hasLayoutAttributes()} returns {@code true},
+ * so that method will need to be consulted for the specific font,
+ * in order to obtain an answer which accounts for such font attributes.
+ *
+ * @param chars the text.
+ * @param start the index of the first char to examine.
+ * @param end the ending index, exclusive.
+ * @return {@code true} if the specified text will need special layout.
+ * @throws NullPointerException if {@code chars} is null.
+ * @throws ArrayIndexOutOfBoundsException if {@code start} is negative or
+ * {@code end} is greater than the length of the {@code chars} array.
+ * @since 9
+ */
+ public static boolean textRequiresLayout(char[] chars,
+ int start, int end) {
+ if (chars == null) {
+ throw new NullPointerException("null char array");
+ }
+ if (start < 0 || end > chars.length) {
+ throw new ArrayIndexOutOfBoundsException("start < 0 or end > len");
+ }
+ return FontUtilities.isComplexScript(chars, start, end);
+ }
+
+ /**
* Returns a {@code Font} appropriate to the attributes.
* If {@code attributes} contains a {@code FONT} attribute
* with a valid {@code Font} as its value, it will be
--- a/jdk/src/java.desktop/share/classes/sun/font/FontUtilities.java Tue Apr 05 21:13:44 2016 +0400
+++ b/jdk/src/java.desktop/share/classes/sun/font/FontUtilities.java Tue Apr 05 11:52:52 2016 -0700
@@ -183,6 +183,25 @@
}
/**
+ * Return true if there any characters which would trigger layout.
+ * This method considers supplementary characters to be simple,
+ * since we do not presently invoke layout on any code points in
+ * outside the BMP.
+ */
+ public static boolean isComplexScript(char [] chs, int start, int limit) {
+
+ for (int i = start; i < limit; i++) {
+ if (chs[i] < MIN_LAYOUT_CHARCODE) {
+ continue;
+ }
+ else if (isComplexCharCode(chs[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
* If there is anything in the text which triggers a case
* where char->glyph does not map 1:1 in straightforward
* left->right ordering, then this method returns true.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/FontClass/TextRequiresLayoutTest.java Tue Apr 05 11:52:52 2016 -0700
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8146324
+ * @summary Test Font.textRequiresLayout
+ */
+
+import java.awt.Font;
+
+public class TextRequiresLayoutTest {
+
+ public static void main(String args[]) {
+
+ String simpleStr = "Hello World";
+ String complexStr = "\u0641\u0642\u0643";
+ char[] simpleChars = simpleStr.toCharArray();
+ char[] complexChars = complexStr.toCharArray();
+
+ if (Font.textRequiresLayout(simpleChars, 0, simpleChars.length)) {
+ throw new RuntimeException("Simple text should not need layout");
+ }
+
+ if (!Font.textRequiresLayout(complexChars, 0, complexChars.length)) {
+ throw new RuntimeException("Complex text should need layout");
+ }
+
+ if (Font.textRequiresLayout(complexChars, 0, 0)) {
+ throw new RuntimeException("Empty text should not need layout");
+ }
+
+ boolean except = false;
+ try {
+ Font.textRequiresLayout(null, 0, 0);
+ } catch (NullPointerException npe) {
+ except = true;
+ }
+ if (!except) {
+ throw new RuntimeException("No expected IllegalArgumentException");
+ }
+
+ except = false;
+ try {
+ Font.textRequiresLayout(complexChars, -1, 0);
+ } catch (ArrayIndexOutOfBoundsException aioobe) {
+ except = true;
+ }
+ if (!except) {
+ throw new
+ RuntimeException("No expected ArrayIndexOutOfBoundsException");
+ }
+
+ except = false;
+ try {
+ Font.textRequiresLayout(complexChars, 0, complexChars.length+1);
+ } catch (ArrayIndexOutOfBoundsException aioobe) {
+ except = true;
+ }
+ if (!except) {
+ throw new
+ RuntimeException("No expected ArrayIndexOutOfBoundsException");
+ }
+ }
+}