blob: 417ddd5adfc601713388dac30cfe269656165d4d [file] [log] [blame]
/*
* 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();
}
}
}
}