1 /* 2 * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 25 /** 26 * @test 27 * @bug 6216010 28 * @summary check to see that underline thickness scales. 29 * @run main UnderlineTest 30 */ 31 32 import java.awt.Color; 33 import java.awt.Container; 34 import java.awt.Dimension; 35 import java.awt.Font; 36 import java.awt.Graphics; 37 import java.awt.Graphics2D; 38 import java.awt.GridLayout; 39 import java.awt.font.FontRenderContext; 40 import java.awt.font.LineMetrics; 41 import java.awt.font.TextAttribute; 42 import java.awt.font.TextLayout; 43 import java.awt.geom.AffineTransform; 44 import java.util.HashMap; 45 import javax.swing.JComponent; 46 import javax.swing.JFrame; 47 import javax.swing.JScrollPane; 48 49 public class UnderlineTest { 50 static class FontsPanel extends Container { FontsPanel(Font[] fonts)51 FontsPanel(Font[] fonts) { 52 setLayout(new GridLayout(0, 1)); 53 for (int i = 0; i < fonts.length; ++i) { 54 add(new FontPanel(fonts[i])); 55 } 56 } 57 } 58 59 static String fps = "Stellar glyphs"; 60 static Dimension fpd = new Dimension(600, 120); 61 static class FontPanel extends JComponent { 62 Font f; FontPanel(Font f)63 FontPanel(Font f) { 64 this.f = f; 65 setPreferredSize(fpd); 66 setMinimumSize(fpd); 67 setMaximumSize(fpd); 68 setSize(fpd); 69 } 70 paintComponent(Graphics g)71 public void paintComponent(Graphics g) { 72 g.setColor(Color.WHITE); 73 g.fillRect(0, 0, fpd.width, fpd.height); 74 75 g.setColor(Color.RED); 76 FontRenderContext frc = ((Graphics2D)g).getFontRenderContext(); 77 LineMetrics lm = f.getLineMetrics(fps, frc); 78 int h = (int)(fpd.height - 20 - lm.getAscent()); 79 g.drawLine(20, h, fpd.width - 20, h); 80 h = fpd.height - 20; 81 g.drawLine(20, h, fpd.width - 20, h); 82 h = (int)(fpd.height - 20 + lm.getDescent()); 83 g.drawLine(20, h, fpd.width - 20, h); 84 85 g.setColor(Color.BLACK); 86 g.setFont(f); 87 g.drawString(fps, 50, fpd.height - 20); 88 } 89 } 90 main(String args[])91 public static void main(String args[]) { 92 String fontName = "Lucida Sans"; 93 if (args.length > 0) { 94 fontName = args[0]; 95 } 96 FontRenderContext frc = new FontRenderContext(null, false, false); 97 FontRenderContext frc2 = new FontRenderContext(AffineTransform.getScaleInstance(1.5, 1.5), false, false); 98 99 Font font0 = new Font(fontName, 0, 20); 100 HashMap map = new HashMap(); 101 map.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON); 102 map.put(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON); 103 Font font = font0.deriveFont(map); 104 105 System.out.println("Using font: " + font); 106 107 double rot = -Math.PI/4; 108 AffineTransform scrtx = AffineTransform.getRotateInstance(rot); 109 scrtx.scale(1, 2); 110 111 Font[] fonts = { 112 font.deriveFont(1f), 113 font.deriveFont(20f), 114 font.deriveFont(40f), 115 font.deriveFont(80f), 116 font.deriveFont(AffineTransform.getRotateInstance(rot)), 117 font.deriveFont(AffineTransform.getScaleInstance(1, 2)), 118 font.deriveFont(AffineTransform.getScaleInstance(2, 4)), 119 font.deriveFont(scrtx), 120 }; 121 122 LineMetrics[] metrics = new LineMetrics[fonts.length * 2]; 123 for (int i = 0; i < metrics.length; ++i) { 124 Font f = fonts[i % fonts.length]; 125 FontRenderContext frcx = i < fonts.length ? frc : frc2; 126 metrics[i] = f.getLineMetrics("X", frcx); 127 // dumpMetrics("Metrics for " + f.getSize2D() + " pt. font,\n tx: " + 128 // f.getTransform() + ",\n frctx: " + frcx.getTransform(), metrics[i]); 129 } 130 131 // test for linear scale 132 // this seems to work, might need to get fancy to deal with last-significant-bit issues? 133 double ds1 = metrics[2].getStrikethroughOffset() - metrics[1].getStrikethroughOffset(); 134 double du1 = metrics[2].getUnderlineThickness() - metrics[1].getUnderlineThickness(); 135 double ds2 = metrics[3].getStrikethroughOffset() - metrics[2].getStrikethroughOffset(); 136 double du2 = metrics[3].getUnderlineThickness() - metrics[2].getUnderlineThickness(); 137 if (ds2 != ds1 * 2 || du2 != du1 * 2) { 138 throw new IllegalStateException("non-linear scale: " + ds1 + " / " + ds2 + ", " + 139 du1 + " / " + du2); 140 } 141 142 JFrame jf = new JFrame("Fonts"); 143 jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 144 jf.add(new JScrollPane(new FontsPanel(fonts))); 145 jf.pack(); 146 jf.setVisible(true); 147 } 148 149 static void dumpMetrics(String header, LineMetrics lm) { 150 if (header != null) { 151 System.out.println(header); 152 } 153 System.out.println("asc: " + lm.getAscent()); 154 System.out.println("dsc: " + lm.getDescent()); 155 System.out.println("ulo: " + lm.getUnderlineOffset()); 156 System.out.println("ult: " + lm.getUnderlineThickness()); 157 System.out.println("sto: " + lm.getStrikethroughOffset()); 158 System.out.println("stt: " + lm.getStrikethroughThickness()); 159 } 160 } 161