/* * Copyright (c) 1999, 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. */ /* * * See TestJustification.html for main test. */ import java.applet.*; import java.awt.*; import java.awt.event.*; import java.awt.font.*; import java.awt.geom.*; import java.text.*; public class TestJustification extends Applet { JustificationPanel panel; public void init() { setLayout(new BorderLayout()); panel = new JustificationPanel("Bitstream Cyberbit"); add("Center", panel); } public void destroy() { remove(panel); } // calls system.exit, not for use in tests. public static void main(String args[]) { TestJustification justificationTest = new TestJustification(); justificationTest.init(); justificationTest.start(); Frame f = new Frame("Test Justification"); f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); f.add("Center", justificationTest); f.setSize(500, 500); f.show(); } public String getAppletInfo() { return "Test TextLayout.getJustifiedLayout()"; } static class JustificationPanel extends Panel { TextLayout[] layouts; String fontname; float height; float oldfsize; AttributedCharacterIterator lineText; TextLayout[] lines; int linecount; float oldwidth; JustificationPanel(String fontname) { this.fontname = fontname; } private static final String[] texts = { "This is an english Highlighting demo.", "Highlighting", "This is an arabic \u0627\u0628\u062a\u062c \u062e\u0644\u0627\u062e demo.", "arabic \u0627\u0628\u062a\u062c", "This is a hebrew \u05d0\u05d1\u05d2 \u05d3\u05d4\u05d5 demo.", "hebrew \u05d0\u05d1\u05d2", "This is a cjk \u4e00\u4e01\u4e02\uac00\uac01\uc4fa\uf900\uf901\uf902 demo.", "cjk", "NoSpaceCJK:\u4e00\u4e01\u4e02and\uac00\uac01\uc4faand\uf900\uf901\uf902", "No", "NoSpaceRoman", "Space" }; public void paint(Graphics g) { Graphics2D g2d = (Graphics2D)g; Dimension d = getSize(); Insets insets = getInsets(); float w = d.width - insets.left - insets.right; float h = d.height - insets.top - insets.bottom; int fsize = (int)w/25; FontRenderContext frc = g2d.getFontRenderContext(); if (layouts == null || fsize != oldfsize) { oldfsize = fsize; Font f0 = new Font(fontname, Font.PLAIN, fsize); Font f1 = new Font(fontname, Font.ITALIC, (int)(fsize * 1.5)); if (layouts == null) { layouts = new TextLayout[texts.length / 2]; } height = 0; for (int i = 0; i < layouts.length; ++i) { String text = texts[i*2]; String target = texts[i*2+1]; AttributedString astr = new AttributedString(text); astr.addAttribute(TextAttribute.FONT, f0, 0, text.length()); int start = text.indexOf(target); int limit = start + target.length(); astr.addAttribute(TextAttribute.FONT, f1, start, limit); TextLayout layout = new TextLayout(astr.getIterator(), frc); layout = layout.getJustifiedLayout(w - 20); layouts[i] = layout; height += layout.getAscent() + layout.getDescent() + layout.getLeading(); } } g2d.setColor(Color.white); g2d.fill(new Rectangle.Float(insets.left, insets.top, w, h)); float basey = 20; for (int i = 0; i < layouts.length; ++i) { TextLayout layout = layouts[i]; float la = layout.getAscent(); float ld = layout.getDescent(); float ll = layout.getLeading(); float lw = layout.getAdvance(); float lh = la + ld + ll; float lx = (w - lw) / 2f; float ly = basey + layout.getAscent(); g2d.setColor(Color.black); g2d.translate(insets.left + lx, insets.top + ly); Rectangle2D bounds = new Rectangle2D.Float(0, -la, lw, lh); g2d.draw(bounds); layout.draw(g2d, 0, 0); g2d.setColor(Color.red); for (int j = 0, e = layout.getCharacterCount(); j <= e; ++j) { Shape[] carets = layout.getCaretShapes(j, bounds); g2d.draw(carets[0]); } g2d.translate(-insets.left - lx, -insets.top - ly); basey += layout.getAscent() + layout.getDescent() + layout.getLeading(); } // add LineBreakMeasurer-generated layouts if (lineText == null) { String text = "This is a long line of text that should be broken across multiple " + "lines and then justified to fit the break width. This test should pass if " + "these lines are justified to the same width, and fail otherwise. It should " + "also format the hebrew (\u05d0\u05d1\u05d2 \u05d3\u05d4\u05d5) and arabic " + "(\u0627\u0628\u062a\u062c \u062e\u0644\u0627\u062e) and CJK " + "(\u4e00\u4e01\u4e02\uac00\uac01\uc4fa\u67b1\u67b2\u67b3\u67b4\u67b5\u67b6\u67b7" + "\u67b8\u67b9) text correctly."; Float regular = new Float(16.0); Float big = new Float(24.0); AttributedString astr = new AttributedString(text); astr.addAttribute(TextAttribute.SIZE, regular, 0, text.length()); astr.addAttribute(TextAttribute.FAMILY, fontname, 0, text.length()); int ix = text.indexOf("broken"); astr.addAttribute(TextAttribute.SIZE, big, ix, ix + 6); ix = text.indexOf("hebrew"); astr.addAttribute(TextAttribute.SIZE, big, ix, ix + 6); ix = text.indexOf("arabic"); astr.addAttribute(TextAttribute.SIZE, big, ix, ix + 6); ix = text.indexOf("CJK"); astr.addAttribute(TextAttribute.SIZE, big, ix, ix + 3); lineText = astr.getIterator(); } float width = w - 20; if (lines == null || width != oldwidth) { oldwidth = width; lines = new TextLayout[10]; linecount = 0; LineBreakMeasurer measurer = new LineBreakMeasurer(lineText, frc); for (;;) { TextLayout layout = measurer.nextLayout(width); if (layout == null) { break; } // justify all but last line if (linecount > 0) { lines[linecount - 1] = lines[linecount - 1].getJustifiedLayout(width); } if (linecount == lines.length) { TextLayout[] nlines = new TextLayout[lines.length * 2]; System.arraycopy(lines, 0, nlines, 0, lines.length); lines = nlines; } lines[linecount++] = layout; } } float basex = insets.left + 10; basey += 10; g2d.setColor(Color.black); for (int i = 0; i < linecount; ++i) { TextLayout layout = lines[i]; basey += layout.getAscent(); float adv = layout.getAdvance(); float dx = layout.isLeftToRight() ? 0 : width - adv; layout.draw(g2d, basex + dx, basey); basey += layout.getDescent() + layout.getLeading(); } } } }