# HG changeset patch # User lana # Date 1375930367 25200 # Node ID 821c274ea5d9845d9700ff980d07e64623fb19d0 # Parent 14d41f09941b6efe46392e47d98a30443483224f# Parent eacfab66b0680eb3bbedd90a65736a846a0bcd20 Merge diff -r 14d41f09941b -r 821c274ea5d9 jdk/src/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java --- a/jdk/src/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java Wed Aug 07 18:24:17 2013 -0700 +++ b/jdk/src/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java Wed Aug 07 19:52:47 2013 -0700 @@ -1856,7 +1856,10 @@ // If we're not valid that means we will shortly be validated and // painted, which means we don't have to do anything here. if (!isRunsDirty && index >= 0 && index < tabPane.getTabCount()) { - tabPane.repaint(getTabBounds(tabPane, index)); + Rectangle rect = getTabBounds(tabPane, index); + if (rect != null) { + tabPane.repaint(rect); + } } } diff -r 14d41f09941b -r 821c274ea5d9 jdk/src/macosx/classes/com/apple/laf/AquaTabbedPaneUI.java --- a/jdk/src/macosx/classes/com/apple/laf/AquaTabbedPaneUI.java Wed Aug 07 18:24:17 2013 -0700 +++ b/jdk/src/macosx/classes/com/apple/laf/AquaTabbedPaneUI.java Wed Aug 07 19:52:47 2013 -0700 @@ -702,6 +702,20 @@ } /** + * Returns the bounds of the specified tab index. The bounds are + * with respect to the JTabbedPane's coordinate space. If the tab at this + * index is not currently visible in the UI, then returns null. + */ + @Override + public Rectangle getTabBounds(final JTabbedPane pane, final int i) { + if (visibleTabState.needsScrollTabs() + && (visibleTabState.isBefore(i) || visibleTabState.isAfter(i))) { + return null; + } + return super.getTabBounds(pane, i); + } + + /** * Returns the tab index which intersects the specified point * in the JTabbedPane's coordinate space. */ diff -r 14d41f09941b -r 821c274ea5d9 jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Wed Aug 07 18:24:17 2013 -0700 +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Wed Aug 07 19:52:47 2013 -0700 @@ -830,18 +830,19 @@ // UTILITY METHODS // ---------------------------------------------------------------------- - /* - * Find image to install into Title or into Application icon. - * First try icons installed for toplevel. If there is no icon - * use default Duke image. - * This method shouldn't return null. + /** + * Find image to install into Title or into Application icon. First try + * icons installed for toplevel. Null is returned, if there is no icon and + * default Duke image should be used. */ private CImage getImageForTarget() { - List icons = target.getIconImages(); - if (icons == null || icons.size() == 0) { - return null; + CImage icon = null; + try { + icon = CImage.getCreator().createFromImages(target.getIconImages()); + } catch (Exception ignored) { + // Perhaps the icon passed into Java is broken. Skipping this icon. } - return CImage.getCreator().createFromImages(icons); + return icon; } /* diff -r 14d41f09941b -r 821c274ea5d9 jdk/src/share/classes/java/awt/event/ContainerListener.java --- a/jdk/src/share/classes/java/awt/event/ContainerListener.java Wed Aug 07 18:24:17 2013 -0700 +++ b/jdk/src/share/classes/java/awt/event/ContainerListener.java Wed Aug 07 19:52:47 2013 -0700 @@ -42,7 +42,7 @@ * Container events are provided for notification purposes ONLY; * The AWT will automatically handle add and remove operations * internally so the program works properly regardless of - * whether the program registers a ComponentListener or not. + * whether the program registers a {@code ContainerListener} or not. * * @see ContainerAdapter * @see ContainerEvent diff -r 14d41f09941b -r 821c274ea5d9 jdk/src/share/classes/javax/swing/text/GlyphView.java --- a/jdk/src/share/classes/javax/swing/text/GlyphView.java Wed Aug 07 18:24:17 2013 -0700 +++ b/jdk/src/share/classes/javax/swing/text/GlyphView.java Wed Aug 07 19:52:47 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -514,7 +514,7 @@ int x1 = x0 + (int) painter.getSpan(this, p0, p1, getTabExpander(), x0); // calculate y coordinate - int y = alloc.y + alloc.height - (int) painter.getDescent(this); + int y = alloc.y + (int)(painter.getHeight(this) - painter.getDescent(this)); if (underline) { int yTmp = y + 1; g.drawLine(x0, yTmp, x1, yTmp); diff -r 14d41f09941b -r 821c274ea5d9 jdk/src/share/classes/sun/awt/AppContext.java --- a/jdk/src/share/classes/sun/awt/AppContext.java Wed Aug 07 18:24:17 2013 -0700 +++ b/jdk/src/share/classes/sun/awt/AppContext.java Wed Aug 07 19:52:47 2013 -0700 @@ -310,11 +310,13 @@ // and excludes applets because by the time applet starts // a number of contexts have already been created by the plugin. if (numAppContexts.get() == 0) { - // This check is not necessary, its purpose is to help - // Plugin devs to catch all the cases of main AC creation. if (System.getProperty("javaplugin.version") == null && System.getProperty("javawebstart.version") == null) { initMainAppContext(); + } else if (System.getProperty("javafx.version") != null && + threadGroup.getParent() != null) { + // Swing inside JavaFX case + SunToolkit.createNewAppContext(); } } diff -r 14d41f09941b -r 821c274ea5d9 jdk/src/solaris/native/sun/awt/gtk2_interface.c --- a/jdk/src/solaris/native/sun/awt/gtk2_interface.c Wed Aug 07 18:24:17 2013 -0700 +++ b/jdk/src/solaris/native/sun/awt/gtk2_interface.c Wed Aug 07 19:52:47 2013 -0700 @@ -794,6 +794,7 @@ } putenv (new_env); free (new_env); + free (tmp_env); } } diff -r 14d41f09941b -r 821c274ea5d9 jdk/src/windows/native/sun/windows/awt_Component.cpp --- a/jdk/src/windows/native/sun/windows/awt_Component.cpp Wed Aug 07 18:24:17 2013 -0700 +++ b/jdk/src/windows/native/sun/windows/awt_Component.cpp Wed Aug 07 19:52:47 2013 -0700 @@ -3528,8 +3528,12 @@ if (ops == SAVE) { transTable.put(reinterpret_cast(static_cast(wkey)), reinterpret_cast(static_cast(translation))); - deadKeyFlagTable.put(reinterpret_cast(static_cast(wkey)), - reinterpret_cast(static_cast(deadKeyFlag))); + if (deadKeyFlag) { + deadKeyFlagTable.put(reinterpret_cast(static_cast(wkey)), + reinterpret_cast(static_cast(deadKeyFlag))); + } else { + deadKeyFlagTable.remove(reinterpret_cast(static_cast(wkey))); + } } isDeadKey = deadKeyFlag; diff -r 14d41f09941b -r 821c274ea5d9 jdk/test/com/apple/eawt/DefaultMenuBar/DefaultMenuBarTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/com/apple/eawt/DefaultMenuBar/DefaultMenuBarTest.java Wed Aug 07 19:52:47 2013 -0700 @@ -0,0 +1,108 @@ +/* + * Copyright (c) 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. + * + * 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 8007267 + * @summary [macosx] com.apple.eawt.Application.setDefaultMenuBar is not working + * @author leonid.romanov@oracle.com + * @run main DefaultMenuBarTest + */ + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import sun.awt.*; +import java.lang.reflect.Method; + + +public class DefaultMenuBarTest { + static KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.META_MASK); + + static volatile int listenerCallCounter = 0; + public static void main(String[] args) throws Exception { + if (sun.awt.OSInfo.getOSType() != sun.awt.OSInfo.OSType.MACOSX) { + System.out.println("This test is for MacOS only. Automatically passed on other platforms."); + return; + } + + System.setProperty("apple.laf.useScreenMenuBar", "true"); + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + createAndShowGUI(); + } + }); + + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + Robot robot = new Robot(); + robot.setAutoDelay(100); + + robot.keyPress(KeyEvent.VK_META); + robot.keyPress(ks.getKeyCode()); + robot.keyRelease(ks.getKeyCode()); + robot.keyRelease(KeyEvent.VK_META); + + toolkit.realSync(); + + if (listenerCallCounter != 1) { + throw new Exception("Test failed: ActionListener either wasn't called or was called more than once"); + } + } + + private static void createAndShowGUI() { + JMenu menu = new JMenu("File"); + JMenuItem newItem = new JMenuItem("Open"); + + newItem.setAccelerator(ks); + newItem.addActionListener( + new ActionListener(){ + public void actionPerformed(ActionEvent e) { + listenerCallCounter++; + } + } + ); + menu.add(newItem); + + JMenuBar defaultMenu = new JMenuBar(); + defaultMenu.add(menu); + + // Application.getApplication().setDefaultMenuBar(defaultMenu); + try { + Class appClass = Class.forName("com.apple.eawt.Application"); + if (appClass != null) { + Method method = appClass.getMethod("getApplication"); + if (method != null) { + Object app = method.invoke(null, new Object[]{}); + if (app != null) { + method = appClass.getMethod("setDefaultMenuBar", new Class[]{JMenuBar.class}); + if (method != null) { + method.invoke(app, new Object[]{defaultMenu}); + } + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff -r 14d41f09941b -r 821c274ea5d9 jdk/test/java/awt/EventDispatchThread/LoopRobustness/LoopRobustness.java --- a/jdk/test/java/awt/EventDispatchThread/LoopRobustness/LoopRobustness.java Wed Aug 07 18:24:17 2013 -0700 +++ b/jdk/test/java/awt/EventDispatchThread/LoopRobustness/LoopRobustness.java Wed Aug 07 19:52:47 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -49,6 +49,8 @@ public static volatile boolean otherExceptionsCaught = false; public static void main(String [] args) throws Exception { + SunToolkit.createNewAppContext(); + ThreadGroup mainThreadGroup = Thread.currentThread().getThreadGroup(); long at; diff -r 14d41f09941b -r 821c274ea5d9 jdk/test/java/awt/event/KeyEvent/DeadKey/DeadKeySystemAssertionDialog.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/event/KeyEvent/DeadKey/DeadKeySystemAssertionDialog.java Wed Aug 07 19:52:47 2013 -0700 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2012, 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. + */ + +import java.awt.Frame; +import java.awt.Robot; +import java.awt.TextField; +import java.awt.Toolkit; +import java.awt.event.KeyEvent; +import sun.awt.SunToolkit; +/* + * @test + * @bug 8013849 + * @summary Awt assert on Hashtable.cpp:124 + * @author alexandr.scherbatiy area=awt.event + * @run main/timeout=5 DeadKeySystemAssertionDialog + */ + +public class DeadKeySystemAssertionDialog { + + public static void main(String[] args) throws Exception { + + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + Frame frame = new Frame(); + frame.setSize(300, 200); + + TextField textField = new TextField(); + frame.add(textField); + + frame.setVisible(true); + toolkit.realSync(); + + textField.requestFocus(); + toolkit.realSync(); + + // Check that the system assertion dialog does not block Java + Robot robot = new Robot(); + robot.setAutoDelay(50); + robot.keyPress(KeyEvent.VK_A); + robot.keyRelease(KeyEvent.VK_A); + toolkit.realSync(); + + frame.setVisible(false); + frame.dispose(); + } +} diff -r 14d41f09941b -r 821c274ea5d9 jdk/test/javax/swing/JTabbedPane/4361477/bug4361477.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/JTabbedPane/4361477/bug4361477.java Wed Aug 07 19:52:47 2013 -0700 @@ -0,0 +1,100 @@ +/* + * Copyright (c) 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. + * + * 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. + */ + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.event.*; +import sun.awt.SunToolkit; + +/* + * @test + * @bug 4361477 + * @summary JTabbedPane throws ArrayOutOfBoundsException + * @author Oleg Mokhovikov + * @run main bug4361477 + */ +public class bug4361477 { + + static JTabbedPane tabbedPane; + volatile static boolean bStateChanged = false; + volatile static Rectangle bounds; + + public static void main(String args[]) throws Exception { + + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + Robot robot = new Robot(); + robot.setAutoDelay(50); + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + createAndShowUI(); + } + }); + + toolkit.realSync(); + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + bounds = tabbedPane.getUI().getTabBounds(tabbedPane, 0); + } + }); + + Point location = bounds.getLocation(); + SwingUtilities.convertPointToScreen(location, tabbedPane); + robot.mouseMove(location.x + 1, location.y + 1); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + + if (!bStateChanged) { + throw new RuntimeException("Tabbed pane state is not changed"); + } + } + + static void createAndShowUI() { + + final JFrame frame = new JFrame(); + tabbedPane = new JTabbedPane(); + tabbedPane.add("Tab0", new JPanel()); + tabbedPane.add("Tab1", new JPanel()); + tabbedPane.add("Tab2", new JPanel()); + tabbedPane.setSelectedIndex(2); + tabbedPane.addChangeListener(new ChangeListener() { + + public void stateChanged(final ChangeEvent pick) { + bStateChanged = true; + if (tabbedPane.getTabCount() == 3) { + tabbedPane.remove(2); + } + } + }); + + frame.getContentPane().add(tabbedPane); + frame.setSize(300, 200); + frame.setVisible(true); + } +} diff -r 14d41f09941b -r 821c274ea5d9 jdk/test/javax/swing/JTabbedPane/6495408/bug6495408.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/JTabbedPane/6495408/bug6495408.java Wed Aug 07 19:52:47 2013 -0700 @@ -0,0 +1,81 @@ +/* + * Copyright (c) 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. + * + * 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. + */ + +import javax.swing.*; +import java.awt.*; +import sun.awt.SunToolkit; +/* + * @test + * @bug 6495408 + * @summary REGRESSION: JTabbedPane throws ArrayIndexOutOfBoundsException + * @author Alexander Potochkin + * @run main bug6495408 + */ + +public class bug6495408 { + + static JTabbedPane tabbedPane; + + public static void main(String[] args) throws Exception { + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + final Robot robot = new Robot(); + robot.setAutoDelay(50); + + SwingUtilities.invokeAndWait(new Runnable() { + + public void run() { + final JFrame frame = new JFrame(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + tabbedPane = new JTabbedPane(); + tabbedPane.setTabPlacement(JTabbedPane.LEFT); + tabbedPane.addTab("Hello", null); + frame.add(tabbedPane); + frame.setSize(400, 400); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + }); + + toolkit.realSync(); + + final Rectangle d = new Rectangle(); + final Point p = new Point(); + + for (int i = 0; i < 7; i++) { + SwingUtilities.invokeLater(new Runnable() { + + public void run() { + int tab = tabbedPane.getTabCount() - 1; + Rectangle bounds = tabbedPane.getBoundsAt(tab); + if (bounds != null) { + d.setBounds(bounds); + p.setLocation(d.x + d.width / 2, d.y + d.height / 2); + SwingUtilities.convertPointToScreen(p, tabbedPane); + robot.mouseMove(p.x, p.y + d.height); + tabbedPane.addTab("Hello", null); + } + } + }); + } + } +} diff -r 14d41f09941b -r 821c274ea5d9 jdk/test/javax/swing/JTabbedPane/7161568/bug7161568.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/JTabbedPane/7161568/bug7161568.java Wed Aug 07 19:52:47 2013 -0700 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 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. + * + * 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. + */ +import java.awt.*; +import javax.swing.*; +import java.awt.event.*; +import sun.awt.SunToolkit; + +/** + * @test + * @bug 7161568 + * @author Alexander Scherbatiy + * @summary Tests that navigating tabs in the JTAbbedPane does not throw NPE + * @run main bug7161568 + */ +public class bug7161568 { + + private static final int N = 50; + private static JTabbedPane tabbedPane; + + public static void main(String[] args) throws Exception { + UIManager.put("TabbedPane.selectionFollowsFocus", Boolean.FALSE); + + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + Robot robot = new Robot(); + robot.setAutoDelay(50); + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + createAndShowUI(); + } + }); + + toolkit.realSync(); + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + tabbedPane.requestFocus(); + } + }); + + toolkit.realSync(); + + for (int i = 0; i < N; i++) { + robot.keyPress(KeyEvent.VK_LEFT); + robot.keyRelease(KeyEvent.VK_LEFT); + toolkit.realSync(); + } + } + + static void createAndShowUI() { + JFrame frame = new JFrame("Test"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setSize(100, 100); + + tabbedPane = new JTabbedPane(); + + for (int i = 0; i < N; i++) { + tabbedPane.addTab("Tab: " + i, new JLabel("Test")); + } + + tabbedPane.setSelectedIndex(0); + + frame.getContentPane().add(tabbedPane); + frame.setVisible(true); + } +} diff -r 14d41f09941b -r 821c274ea5d9 jdk/test/javax/swing/text/StyledEditorKit/8016833/bug8016833.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/text/StyledEditorKit/8016833/bug8016833.java Wed Aug 07 19:52:47 2013 -0700 @@ -0,0 +1,270 @@ +/* + * Copyright (c) 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. + * + * 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 8016833 + @summary underlines and strikethroughs should be painted at the correct + positions for different kind of text styles: normal, superscript and subscript + @author Anton Nashatyrev + @run main bug8016833 +*/ +import javax.swing.*; +import javax.swing.text.BadLocationException; +import javax.swing.text.Style; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyledDocument; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.lang.reflect.InvocationTargetException; + +public class bug8016833 { + + void drawText(final Graphics g, final boolean underline, final boolean strikethrough, final boolean background) { + drawText(g, "mama", underline, strikethrough, background); + } + + void drawText(final Graphics g, final String text, final boolean underline, final boolean strikethrough, final boolean background) { + try { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + final JTextPane comp = new JTextPane(); + final StyledDocument doc = comp.getStyledDocument(); + + Style style = comp.addStyle("superscript", null); + setNormalStyle(style); + + if (underline) { + StyleConstants.setUnderline(style, true); + } + if (strikethrough) { + StyleConstants.setStrikeThrough(style, true); + } + if (background) { + StyleConstants.setBackground(style, Color.BLUE); + } + try { + doc.insertString(doc.getLength(), "mama", style); + } catch (BadLocationException e) { + throw new RuntimeException(e); + } + + comp.setSize(200, 100); + comp.paint(g); + } + }); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + void setNormalStyle(Style style) { + StyleConstants.setSuperscript(style, true); + } + + int getEmptyPixel() { + return 0xFFFFFFFF; + } + + boolean isPixelEmpty(int argb) { + return (argb & 0x00FFFFFF) == (getEmptyPixel() & 0x00FFFFFF); + } + + boolean isLineEmpty(BufferedImage img, int coord, boolean isHorizontal) { + int len = isHorizontal ? img.getWidth() : img.getHeight(); + for (int i = 0; i < len; i++) { + int pixel = isHorizontal ? img.getRGB(i, coord) : img.getRGB(coord, i); + if (!isPixelEmpty(pixel)) { + return false; + } + } + return true; + } + + Rectangle getPixelsOutline(BufferedImage img) { + int x1 = 0; + while (x1 < img.getWidth() && isLineEmpty(img, x1, false)) { + x1++; + } + int x2 = img.getWidth() - 1; + while (x2 >= 0 && isLineEmpty(img, x2, false)) { + x2--; + } + int y1 = 0; + while (y1 < img.getHeight() && isLineEmpty(img, y1, true)) { + y1++; + } + int y2 = img.getHeight() - 1; + while (y2 >= 0 && isLineEmpty(img, y2, true)) { + y2--; + } + + return new Rectangle(x1, y1, x2 - x1 + 1, y2 - y1 + 1); + } + + BufferedImage createImage() { + final BufferedImage img = new BufferedImage(200, 100, BufferedImage.TYPE_INT_ARGB); + try { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + Graphics g = img.getGraphics(); + g.setColor(new Color(getEmptyPixel())); + g.fillRect(0, 0, 10000, 10000); + } + }); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } + return img; + } + + int subPixels(int pix1, int pix2) { + if (pix1 == pix2) { + return getEmptyPixel(); + } + return pix1; + } + + /** + * Subtracts img2 from img1 + */ + BufferedImage subImages(BufferedImage img1, BufferedImage img2) { + if (img1.getHeight() != img2.getHeight() || + img1.getWidth() != img2.getWidth()) { + throw new RuntimeException("Different sizes"); + } + BufferedImage ret = new BufferedImage(img1.getWidth(), img1.getHeight(), img1.getType()); + + for (int x = 0; x < ret.getWidth(); x++) { + for (int y = 0; y < ret.getHeight(); y++) { + ret.setRGB(x, y, subPixels(img1.getRGB(x, y), img2.getRGB(x, y))); + } + } + return ret; + } + + void testUnderline() { + System.out.println(" testUnderline()"); + + final BufferedImage img1 = createImage(); + drawText(img1.getGraphics(), true, false, false); + final Rectangle out1 = getPixelsOutline(img1); + System.out.println(" Underlined: " + out1); + + final BufferedImage img2 = createImage(); + drawText(img2.getGraphics(), false, false, false); + final Rectangle out2 = getPixelsOutline(img2); + System.out.println(" Normal: " + out2); + + final BufferedImage img3 = subImages(img1, img2); + final Rectangle out3 = getPixelsOutline(img3); + System.out.println(" Sub: " + out3); + + // underline is not too thick + assertTrue(out3.getHeight() <= 2); + // not too wide + assertTrue(out3.getWidth() * 0.8 < out2.getWidth()); + // not too low + assertTrue(out3.getY() - (out1.getY() + out2.getHeight()) < 3); + // not too high + assertTrue(out3.getY() - (out1.getY() + out2.getHeight()) > 0); + } + + void testStrikthrough() { + System.out.println(" testStrikthrough()"); + + final BufferedImage img1 = createImage(); + drawText(img1.getGraphics(), false, true, false); + final Rectangle out1 = getPixelsOutline(img1); + System.out.println(" Striked: " + out1); + + final BufferedImage img2 = createImage(); + drawText(img2.getGraphics(), false, false, false); + final Rectangle out2 = getPixelsOutline(img2); + System.out.println(" Normal: " + out2); + + final BufferedImage img3 = subImages(img1, img2); + final Rectangle out3 = getPixelsOutline(img3); + System.out.println(" Sub: " + out3); + + // strikethrough is not too thick + assertTrue(out3.getHeight() <= 2); + // not too wide + assertTrue(out3.getWidth() * 0.8 < out2.getWidth()); + // not too low + assertTrue(out3.getY() - (out1.getY() + out2.getHeight()) < 0); + // not too high + assertTrue(out3.getY() - out1.getY() > 1); + } + void assertTrue(boolean b) { + if (!b) { + throw new RuntimeException("Assertion failed"); + } + } + + static void testSuperScript() { + System.out.println("testSuperScript()"); + bug8016833 b = new bug8016833() { + @Override + void setNormalStyle(Style style) { + StyleConstants.setSuperscript(style, true); + } + }; + b.testUnderline(); + b.testStrikthrough(); + } + + static void testSubScript() { + System.out.println("testSubScript()"); + bug8016833 b = new bug8016833() { + @Override + void setNormalStyle(Style style) { + StyleConstants.setSubscript(style, true); + } + }; + b.testUnderline(); + b.testStrikthrough(); + } + + static void testNormalScript() { + System.out.println("testNormalScript()"); + bug8016833 b = new bug8016833() { + @Override + void setNormalStyle(Style style) { + } + }; + b.testUnderline(); + b.testStrikthrough(); + } + + public static void main(String[] args) { + testSubScript(); + testSuperScript(); + testNormalScript(); + } +}