8edb98df3d
Co-authored-by: Jason Fordham <jclf@azul.com> Reviewed-by: prr
166 lines
5.9 KiB
Java
166 lines
5.9 KiB
Java
/*
|
|
* Copyright (c) 2022, 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 8165943
|
|
* @summary LineBreakMeasurer does not measure correctly if TextAttribute.TRACKING is set
|
|
* @library ../../regtesthelpers
|
|
* @build PassFailJFrame
|
|
* @run main/manual LineBreakWithTracking
|
|
*/
|
|
|
|
import javax.swing.*;
|
|
import java.awt.*;
|
|
import java.awt.event.ActionEvent;
|
|
import java.awt.event.ActionListener;
|
|
import java.awt.event.WindowAdapter;
|
|
import java.awt.event.WindowEvent;
|
|
import java.awt.font.FontRenderContext;
|
|
import java.awt.font.LineBreakMeasurer;
|
|
import java.awt.font.TextAttribute;
|
|
import java.awt.font.TextLayout;
|
|
import java.text.AttributedString;
|
|
import java.util.Hashtable;
|
|
import java.lang.reflect.InvocationTargetException;
|
|
|
|
class LineBreakPanel extends JPanel implements ActionListener {
|
|
|
|
private float textTracking = 0.0f;
|
|
private static String fontName = "Dialog";
|
|
private static String text = "This is a long line of text that should be broken across multiple lines. "
|
|
+ "Please set the different tracking values to test via menu! This test should pass if "
|
|
+ "these lines are broken to fit the 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.";
|
|
|
|
private LineBreakMeasurer lineMeasurer;
|
|
|
|
public void actionPerformed(ActionEvent e) {
|
|
textTracking = (float)((JRadioButtonMenuItem)e.getSource()).getClientProperty( "tracking" );
|
|
lineMeasurer = null;
|
|
invalidate();
|
|
repaint();
|
|
}
|
|
|
|
public void paintComponent(Graphics g) {
|
|
super.paintComponent(g);
|
|
setBackground(Color.white);
|
|
|
|
Graphics2D g2d = (Graphics2D)g;
|
|
|
|
if (lineMeasurer == null) {
|
|
Float regular = Float.valueOf(16.0f);
|
|
Float big = Float.valueOf(24.0f);
|
|
|
|
Hashtable map = new Hashtable();
|
|
map.put(TextAttribute.SIZE, (float)18.0);
|
|
map.put(TextAttribute.TRACKING, (float)textTracking);
|
|
|
|
AttributedString astr = new AttributedString(text, map);
|
|
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);
|
|
|
|
FontRenderContext frc = g2d.getFontRenderContext();
|
|
lineMeasurer = new LineBreakMeasurer(astr.getIterator(), frc);
|
|
}
|
|
|
|
lineMeasurer.setPosition(0);
|
|
|
|
float w = (float)getSize().width;
|
|
float x = 0, y = 0;
|
|
TextLayout layout;
|
|
while ((layout = lineMeasurer.nextLayout(w)) != null) {
|
|
x = layout.isLeftToRight() ? 0 : w - layout.getAdvance();
|
|
y += layout.getAscent();
|
|
layout.draw(g2d, x, y);
|
|
y += layout.getDescent() + layout.getLeading();
|
|
}
|
|
}
|
|
}
|
|
|
|
public class LineBreakWithTracking {
|
|
|
|
private static final String INSTRUCTIONS = """
|
|
This manual test verifies that LineBreakMeasurer measures the lines'
|
|
breaks correctly taking into account the TextAttribute.TRACKING value.
|
|
The test string includes Latin, Arabic, CJK and Hebrew.
|
|
|
|
You should choose a tracking value from the menu and resize the window.
|
|
If the text lines break exactly to the wrapping width:
|
|
no room for one more word exists and
|
|
the text lines are not too long for given wrapping width, -
|
|
then press PASS, otherwise - FAIL.
|
|
""";
|
|
|
|
public void createGUI(JFrame frame) {
|
|
|
|
LineBreakPanel panel = new LineBreakPanel();
|
|
frame.getContentPane().add(panel, BorderLayout.CENTER);
|
|
|
|
JMenuBar menuBar = new JMenuBar();
|
|
|
|
JMenu menu = new JMenu("Tracking");
|
|
ButtonGroup btnGroup = new ButtonGroup();
|
|
String btnLabels[] = {"-0.1", "0", "0.1", "0.2", "0.3"};
|
|
float val = -0.1f;
|
|
for (String label : btnLabels) {
|
|
JRadioButtonMenuItem btn = new JRadioButtonMenuItem(label);
|
|
btn.putClientProperty( "tracking", val );
|
|
btn.addActionListener(panel);
|
|
btnGroup.add(btn);
|
|
menu.add(btn);
|
|
val += 0.1f;
|
|
}
|
|
menuBar.add(menu);
|
|
|
|
frame.setJMenuBar(menuBar);
|
|
}
|
|
|
|
public static void main(String[] args) throws InterruptedException, InvocationTargetException {
|
|
|
|
JFrame frame = new JFrame("LineBreakMeasurer with Tracking");
|
|
frame.setSize(new Dimension(640, 480));
|
|
|
|
LineBreakWithTracking controller = new LineBreakWithTracking();
|
|
controller.createGUI(frame);
|
|
|
|
PassFailJFrame passFailJFrame = new PassFailJFrame(INSTRUCTIONS);
|
|
PassFailJFrame.addTestWindow(frame);
|
|
PassFailJFrame.positionTestWindow(frame, PassFailJFrame.Position.HORIZONTAL);
|
|
frame.setVisible(true);
|
|
passFailJFrame.awaitAndCheck();
|
|
}
|
|
}
|