--- /dev/null 2015-09-11 11:06:08.592686920 -0400 +++ new/modules/graphics/src/test/java/test/com/sun/javafx/text/TextLayoutTest.java 2015-09-11 21:24:59.869286591 -0400 @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2012, 2013, 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. 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 test.com.sun.javafx.text; + +import javafx.scene.text.Font; + +import com.sun.javafx.font.PGFont; +import com.sun.javafx.geom.RectBounds; +import com.sun.javafx.scene.text.GlyphList; +import com.sun.javafx.scene.text.TextSpan; +import com.sun.javafx.scene.text.TextLine; +import com.sun.javafx.text.PrismTextLayout; +import com.sun.javafx.text.PrismTextLayout; + +import org.junit.Ignore; +import org.junit.Test; + +import sun.font.CharToGlyphMapper; +import static org.junit.Assert.*; + +public class TextLayoutTest { + private String J = "\u3041"; //Japanese not complex + private String D = "\u0907"; //Devanagari complex + private String T = "\u0E34"; //Devanagari complex + + class TestSpan implements TextSpan { + String text; + Object font; + TestSpan(Object text, Object font) { + this.text = (String)text; + this.font = font; + } + @Override public String getText() { + return text; + } + @Override public Object getFont() { + return font; + } + @Override public RectBounds getBounds() { + return null; + } + } + + public TextLayoutTest() { + } + + private void setContent(PrismTextLayout layout, Object... content) { + int count = content.length / 2; + TextSpan[] spans = new TextSpan[count]; + int i = 0; + while (i < content.length) { + spans[i>>1] = new TestSpan(content[i++], content[i++]); + } + layout.setContent(spans); + } + + private void verifyLayout(PrismTextLayout layout, int lineCount, int runCount, int... glyphCount) { + TextLine[] lines = layout.getLines(); + assertEquals("lineCount", lineCount, lines.length); + GlyphList[] runs = layout.getRuns(); + assertEquals("runCount", runCount, runs.length); + assertEquals("runCount", runCount, glyphCount.length); + for (int i = 0; i < runs.length; i++) { + assertEquals("run " +i, glyphCount[i], runs[i].getGlyphCount()); + } + } + + private void verifyComplex(PrismTextLayout layout, boolean... complex) { + GlyphList[] runs = layout.getRuns(); + for (int i = 0; i < runs.length; i++) { + assertEquals("run " +i, complex[i], runs[i].isComplex()); + } + } + + @SuppressWarnings("deprecation") + @Ignore("RT-31357") + @Test public void buildRuns() { + + PrismTextLayout layout = new PrismTextLayout(); + PGFont font = (PGFont)Font.font("Monaco", 12).impl_getNativeFont(); + PGFont font2 = (PGFont)Font.font("Tahoma", 12).impl_getNativeFont(); + + /* simple case */ + layout.setContent("hello", font); + verifyLayout(layout, 1, 1, 5); + + /* simple case, two workd*/ + layout.setContent("hello world", font); + verifyLayout(layout, 1, 1, 11); + + /* empty string */ + layout.setContent("", font); + verifyLayout(layout, 1, 1, 0); + + /* line break */ + layout.setContent("\n", font); //first line has the line break (glyphCount=0), + verifyLayout(layout, 2, 2, 0,0); + layout.setContent("\r", font); + verifyLayout(layout, 2, 2, 0,0); + layout.setContent("\r\n", font); + verifyLayout(layout, 2, 2, 0,0); + layout.setContent("a\nb", font); + verifyLayout(layout, 2, 3, 1, 0, 1); + layout.setContent("\n\n\r\r\n", font); + verifyLayout(layout, 5, 5, 0,0,0,0,0); + + /* tabs */ + layout.setContent("\t", font); + verifyLayout(layout, 1, 1, 0); + layout.setContent("\t\t", font); + verifyLayout(layout, 1, 2, 0,0); + layout.setContent("a\tb", font); + verifyLayout(layout, 1, 3, 1,0,1); + + /* complex */ + layout.setContent("aa"+J+J, font); + verifyLayout(layout, 1, 1, 4);// no complex (english to japanese) + verifyComplex(layout, false); + + + layout.setContent(D, font); + verifyLayout(layout, 1, 1, 1);// complex (english to devanagari) + verifyComplex(layout, true); + + layout.setContent("aa"+D+D, font); + verifyLayout(layout, 1, 2, 2,2);// complex (english to devanagari) + verifyComplex(layout, false, true); + + layout.setContent(D+D+"aa", font); + verifyLayout(layout, 1, 2, 2,2);// complex (devanagari to english) + verifyComplex(layout, true, false); + + layout.setContent("aa"+D+D+J+J, font); + verifyLayout(layout, 1, 3, 2,2,2);// complex (english to devanagari to japanese) + verifyComplex(layout, false, true, false); + + /*Tahoma has Thai but no Hindi, font slot break expected*/ + layout.setContent(D+D+T+T, font2); + verifyLayout(layout, 1, 2, 2,2);// complex (devanagari to thai) + verifyComplex(layout, true, true); + + layout.setContent(T+T+D+D+T+T, font2); + verifyLayout(layout, 1, 3, 2,2,2); + verifyComplex(layout, true, true, true); + + layout.setContent(T+T+D+D+"aa", font2); + verifyLayout(layout, 1, 3, 2,2,2); + verifyComplex(layout, true, true, false); + + layout.setContent(T+T+"aa"+T+T, font2); + verifyLayout(layout, 1, 3, 2,2,2); + verifyComplex(layout, true, false, true); + + layout.setContent("aa"+D+D+T+T, font2); + verifyLayout(layout, 1, 3, 2,2,2); + verifyComplex(layout, false, true, true); + + /* Rich Text test */ + + setContent(layout, "hello ", font, "world", font); + verifyLayout(layout, 1, 2, 6,5); + verifyComplex(layout, false, false); + + setContent(layout, "aaa", font, J+J+J, font); + verifyLayout(layout, 1, 2, 3,3); + verifyComplex(layout, false, false); + + setContent(layout, "aaa", font, D+D+D, font); + verifyLayout(layout, 1, 2, 3,3); + verifyComplex(layout, false, true); + + /* can't merge \r\n in different spans*/ + setContent(layout, "aa\r", font, "\nbb", font); + verifyLayout(layout, 3, 4, 2,0,0,2); + verifyComplex(layout, false, false, false, false); + + setContent(layout, "aa\r\n", font, "bb", font); + verifyLayout(layout, 2, 3, 2,0,2); + verifyComplex(layout, false, false, false); + + /* can't merge surrogate pairs in different spans*/ + setContent(layout, "\uD840\uDC0B", font, "\uD840\uDC89\uD840\uDCA2", font); + verifyLayout(layout, 1, 2, 2, 4); + GlyphList[] runs = layout.getRuns(); + assertTrue(runs[0].getGlyphCode(0) != CharToGlyphMapper.INVISIBLE_GLYPH_ID); + assertTrue(runs[0].getGlyphCode(1) == CharToGlyphMapper.INVISIBLE_GLYPH_ID); + assertTrue(runs[1].getGlyphCode(0) != CharToGlyphMapper.INVISIBLE_GLYPH_ID); + assertTrue(runs[1].getGlyphCode(1) == CharToGlyphMapper.INVISIBLE_GLYPH_ID); + assertTrue(runs[1].getGlyphCode(2) != CharToGlyphMapper.INVISIBLE_GLYPH_ID); + assertTrue(runs[1].getGlyphCode(3) == CharToGlyphMapper.INVISIBLE_GLYPH_ID); + + /* Split surrogate pair*/ + setContent(layout, "\uD840\uDC0B\uD840", font, "\uDC89\uD840\uDCA2", font); + verifyLayout(layout, 1, 2, 3, 3); + runs = layout.getRuns(); + assertTrue(runs[0].getGlyphCode(0) != CharToGlyphMapper.INVISIBLE_GLYPH_ID); + assertTrue(runs[0].getGlyphCode(1) == CharToGlyphMapper.INVISIBLE_GLYPH_ID); + assertTrue(runs[0].getGlyphCode(2) != CharToGlyphMapper.INVISIBLE_GLYPH_ID);//broken pair, results in missing glyph + assertTrue(runs[1].getGlyphCode(0) != CharToGlyphMapper.INVISIBLE_GLYPH_ID);//broken pair, results in missing glyph + assertTrue(runs[1].getGlyphCode(1) != CharToGlyphMapper.INVISIBLE_GLYPH_ID); + assertTrue(runs[1].getGlyphCode(2) == CharToGlyphMapper.INVISIBLE_GLYPH_ID); + + } + +}