changeset 13233:fa51d35102f1

8081411: Add an API for painting an icon with a SynthContext Reviewed-by: serb, azvegint
author alexsch
date Wed, 18 Nov 2015 19:13:42 +0400
parents b86b6b023ae2
children e8e7a00c1bff
files src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKIconFactory.java src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java src/java.desktop/share/classes/javax/swing/plaf/nimbus/NimbusIcon.java src/java.desktop/share/classes/javax/swing/plaf/nimbus/NimbusLookAndFeel.java src/java.desktop/share/classes/javax/swing/plaf/synth/SynthGraphicsUtils.java src/java.desktop/share/classes/javax/swing/plaf/synth/SynthIcon.java src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java src/java.desktop/share/classes/javax/swing/plaf/synth/SynthMenuItemLayoutHelper.java src/java.desktop/share/classes/javax/swing/plaf/synth/SynthToolBarUI.java src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTreeUI.java src/java.desktop/share/classes/sun/swing/plaf/synth/SynthIcon.java test/javax/swing/plaf/synth/8081411/bug8081411.java
diffstat 12 files changed, 326 insertions(+), 166 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKIconFactory.java	Tue Nov 17 13:24:06 2015 -0800
+++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKIconFactory.java	Wed Nov 18 19:13:42 2015 +0400
@@ -24,6 +24,7 @@
  */
 package com.sun.java.swing.plaf.gtk;
 
+import javax.swing.plaf.synth.SynthIcon;
 import java.util.*;
 import javax.swing.plaf.synth.*;
 import java.awt.*;
--- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java	Tue Nov 17 13:24:06 2015 -0800
+++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java	Wed Nov 18 19:13:42 2015 +0400
@@ -36,7 +36,7 @@
 import sun.awt.AppContext;
 import sun.awt.UNIXToolkit;
 import sun.swing.SwingUtilities2;
-import sun.swing.plaf.synth.SynthIcon;
+import javax.swing.plaf.synth.SynthIcon;
 
 import com.sun.java.swing.plaf.gtk.GTKEngine.WidgetType;
 import static java.awt.RenderingHints.KEY_TEXT_ANTIALIASING;
--- a/src/java.desktop/share/classes/javax/swing/plaf/nimbus/NimbusIcon.java	Tue Nov 17 13:24:06 2015 -0800
+++ b/src/java.desktop/share/classes/javax/swing/plaf/nimbus/NimbusIcon.java	Wed Nov 18 19:13:42 2015 +0400
@@ -25,7 +25,7 @@
 package javax.swing.plaf.nimbus;
 
 import javax.swing.Painter;
-import sun.swing.plaf.synth.SynthIcon;
+import javax.swing.plaf.synth.SynthIcon;
 
 import javax.swing.plaf.synth.SynthContext;
 import javax.swing.*;
@@ -37,7 +37,7 @@
  * An icon that delegates to a painter.
  * @author rbair
  */
-class NimbusIcon extends SynthIcon {
+class NimbusIcon implements SynthIcon {
     private int width;
     private int height;
     private String prefix;
--- a/src/java.desktop/share/classes/javax/swing/plaf/nimbus/NimbusLookAndFeel.java	Tue Nov 17 13:24:06 2015 -0800
+++ b/src/java.desktop/share/classes/javax/swing/plaf/nimbus/NimbusLookAndFeel.java	Wed Nov 18 19:13:42 2015 +0400
@@ -50,7 +50,7 @@
 import javax.swing.plaf.BorderUIResource;
 import javax.swing.plaf.ColorUIResource;
 import sun.swing.ImageIconUIResource;
-import sun.swing.plaf.synth.SynthIcon;
+import javax.swing.plaf.synth.SynthIcon;
 import sun.swing.plaf.GTKKeybindings;
 import sun.swing.plaf.WindowsKeybindings;
 import sun.security.action.GetPropertyAction;
--- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthGraphicsUtils.java	Tue Nov 17 13:24:06 2015 -0800
+++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthGraphicsUtils.java	Wed Nov 18 19:13:42 2015 +0400
@@ -31,7 +31,6 @@
 import javax.swing.*;
 import javax.swing.plaf.basic.BasicHTML;
 import javax.swing.text.*;
-import sun.swing.plaf.synth.*;
 
 /**
  * Wrapper for primitive graphics calls.
@@ -287,8 +286,8 @@
             return new Dimension(dx, dy);
         }
         else if ((text == null) || ((icon != null) && (font == null))) {
-            return new Dimension(SynthIcon.getIconWidth(icon, ss) + dx,
-                                 SynthIcon.getIconHeight(icon, ss) + dy);
+            return new Dimension(getIconWidth(icon, ss) + dx,
+                                 getIconHeight(icon, ss) + dy);
         }
         else {
             FontMetrics fm = c.getFontMetrics(font);
@@ -404,7 +403,7 @@
                 paintIconR.x += textOffset;
             }
             paintIconR.y += textOffset;
-            SynthIcon.paintIcon(icon, ss, g, paintIconR.x, paintIconR.y,
+            paintIcon(icon, ss, g, paintIconR.x, paintIconR.y,
                                 paintIconR.width, paintIconR.height);
             g.setColor(color);
         }
@@ -423,6 +422,62 @@
         }
     }
 
+    /**
+     * Returns the icon's width.
+     * The {@code getIconWidth(context)} method is called for {@code SynthIcon}.
+     *
+     * @param icon the icon
+     * @param context {@code SynthContext} requesting the icon, may be null.
+     * @return an int specifying the width of the icon.
+     */
+    public static int getIconWidth(Icon icon, SynthContext context) {
+        if (icon == null) {
+            return 0;
+        }
+        if (icon instanceof SynthIcon) {
+            return ((SynthIcon) icon).getIconWidth(context);
+        }
+        return icon.getIconWidth();
+    }
+
+    /**
+     * Returns the icon's height.
+     * The {@code getIconHeight(context)} method is called for {@code SynthIcon}.
+     *
+     * @param icon the icon
+     * @param context {@code SynthContext} requesting the icon, may be null.
+     * @return an int specifying the height of the icon.
+     */
+    public static int getIconHeight(Icon icon, SynthContext context) {
+        if (icon == null) {
+            return 0;
+        }
+        if (icon instanceof SynthIcon) {
+            return ((SynthIcon) icon).getIconHeight(context);
+        }
+        return icon.getIconHeight();
+    }
+
+    /**
+     * Paints the icon. The {@code paintIcon(context, g, x, y, width, height)}
+     * method is called for {@code SynthIcon}.
+     *
+     * @param icon the icon
+     * @param context identifies hosting region, may be null.
+     * @param g the graphics context
+     * @param x the x location to paint to
+     * @param y the y location to paint to
+     * @param width the width of the region to paint to, may be 0
+     * @param height the height of the region to paint to, may be 0
+     */
+    public static void paintIcon(Icon icon, SynthContext context, Graphics g,
+            int x, int y, int width, int height) {
+        if (icon instanceof SynthIcon) {
+            ((SynthIcon) icon).paintIcon(context, g, x, y, width, height);
+        } else if (icon != null) {
+            icon.paintIcon(context.getComponent(), g, x, y);
+        }
+    }
 
      /**
       * A quick note about how preferred sizes are calculated... Generally
@@ -561,7 +616,7 @@
 
             if (icon != null) {
                 Rectangle iconRect = lr.getIconRect();
-                SynthIcon.paintIcon(icon, lh.getContext(), g, iconRect.x,
+                paintIcon(icon, lh.getContext(), g, iconRect.x,
                         iconRect.y, iconRect.width, iconRect.height);
             }
         }
@@ -571,7 +626,7 @@
                                MenuItemLayoutHelper.LayoutResult lr) {
         if (lh.getCheckIcon() != null) {
             Rectangle checkRect = lr.getCheckRect();
-            SynthIcon.paintIcon(lh.getCheckIcon(), lh.getContext(), g,
+            paintIcon(lh.getCheckIcon(), lh.getContext(), g,
                     checkRect.x, checkRect.y, checkRect.width, checkRect.height);
         }
     }
@@ -610,7 +665,7 @@
                                MenuItemLayoutHelper.LayoutResult lr) {
         if (lh.getArrowIcon() != null) {
             Rectangle arrowRect = lr.getArrowRect();
-            SynthIcon.paintIcon(lh.getArrowIcon(), lh.getContext(), g,
+            paintIcon(lh.getArrowIcon(), lh.getContext(), g,
                     arrowRect.x, arrowRect.y, arrowRect.width, arrowRect.height);
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthIcon.java	Wed Nov 18 19:13:42 2015 +0400
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2002, 2015, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package javax.swing.plaf.synth;
+
+import java.awt.*;
+import javax.swing.*;
+
+/**
+ * An icon that is passed a {@code SynthContext}. Subclasses need only implement
+ * the variants that take a {@code SynthContext}, but must be prepared for the
+ * {@code SynthContext} to be null.
+ *
+ * @author Scott Violet
+ */
+public interface SynthIcon extends Icon {
+
+    /**
+     * Paints the icon at the specified location for the given synth context.
+     *
+     * @param context identifies hosting region, may be null.
+     * @param g the graphics context
+     * @param x the x location to paint to
+     * @param y the y location to paint to
+     * @param width the width of the region to paint to, may be 0
+     * @param height the height of the region to paint to, may be 0
+     */
+    void paintIcon(SynthContext context, Graphics g, int x, int y,
+            int width, int height);
+
+    /**
+     * Returns the icon's width for the given synth context.
+     *
+     * @param context {@code SynthContext} requesting the Icon, may be null.
+     * @return an int specifying the width of the icon.
+     */
+    int getIconWidth(SynthContext context);
+
+    /**
+     * Returns the icon's height for the given synth context.
+     *
+     * @param context {@code SynthContext} requesting the Icon, may be null.
+     * @return an int specifying the height of the icon.
+     */
+    int getIconHeight(SynthContext context);
+
+    @Override
+    default void paintIcon(Component c, Graphics g, int x, int y) {
+        paintIcon(null, g, x, y, getIconWidth(), getIconHeight());
+    }
+
+    @Override
+    default int getIconWidth() {
+        return getIconWidth(null);
+    }
+
+    @Override
+    default int getIconHeight() {
+        return getIconHeight(null);
+    }
+}
--- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java	Tue Nov 17 13:24:06 2015 -0800
+++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java	Wed Nov 18 19:13:42 2015 +0400
@@ -53,6 +53,10 @@
  * an example of providing your own <code>SynthStyleFactory</code> to
  * <code>setStyleFactory</code>.
  * <p>
+ * {@link SynthIcon} interface provides
+ * {@code paintIcon(synthContext, graphics, x, y, width, height)} method that
+ * allows to draw the icon with the given {@code SynthContext}.
+ * <p>
  * <strong>Warning:</strong>
  * This class implements {@link Serializable} as a side effect of it
  * extending {@link BasicLookAndFeel}. It is not intended to be serialized.
--- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthMenuItemLayoutHelper.java	Tue Nov 17 13:24:06 2015 -0800
+++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthMenuItemLayoutHelper.java	Wed Nov 18 19:13:42 2015 +0400
@@ -27,7 +27,6 @@
 
 import sun.swing.StringUIClientPropertyKey;
 import sun.swing.MenuItemLayoutHelper;
-import sun.swing.plaf.synth.SynthIcon;
 
 import javax.swing.*;
 import javax.swing.text.View;
@@ -130,8 +129,8 @@
     protected void calcWidthsAndHeights() {
         // iconRect
         if (getIcon() != null) {
-            getIconSize().setWidth(SynthIcon.getIconWidth(getIcon(), context));
-            getIconSize().setHeight(SynthIcon.getIconHeight(getIcon(), context));
+            getIconSize().setWidth(SynthGraphicsUtils.getIconWidth(getIcon(), context));
+            getIconSize().setHeight(SynthGraphicsUtils.getIconHeight(getIcon(), context));
         }
 
         // accRect
@@ -165,16 +164,16 @@
             // checkIcon
             if (getCheckIcon() != null) {
                 getCheckSize().setWidth(
-                        SynthIcon.getIconWidth(getCheckIcon(), context));
+                        SynthGraphicsUtils.getIconWidth(getCheckIcon(), context));
                 getCheckSize().setHeight(
-                        SynthIcon.getIconHeight(getCheckIcon(), context));
+                        SynthGraphicsUtils.getIconHeight(getCheckIcon(), context));
             }
             // arrowRect
             if (getArrowIcon() != null) {
                 getArrowSize().setWidth(
-                        SynthIcon.getIconWidth(getArrowIcon(), context));
+                        SynthGraphicsUtils.getIconWidth(getArrowIcon(), context));
                 getArrowSize().setHeight(
-                        SynthIcon.getIconHeight(getArrowIcon(), context));
+                        SynthGraphicsUtils.getIconHeight(getArrowIcon(), context));
             }
         }
 
--- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthToolBarUI.java	Tue Nov 17 13:24:06 2015 -0800
+++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthToolBarUI.java	Wed Nov 18 19:13:42 2015 +0400
@@ -41,7 +41,6 @@
 import javax.swing.JToolBar;
 import javax.swing.plaf.ComponentUI;
 import javax.swing.plaf.basic.BasicToolBarUI;
-import sun.swing.plaf.synth.SynthIcon;
 
 /**
  * Provides the Synth L&amp;F UI delegate for
@@ -281,10 +280,10 @@
         if (handleIcon != null && toolBar.isFloatable()) {
             int startX = toolBar.getComponentOrientation().isLeftToRight() ?
                 0 : toolBar.getWidth() -
-                    SynthIcon.getIconWidth(handleIcon, context);
-            SynthIcon.paintIcon(handleIcon, context, g, startX, 0,
-                    SynthIcon.getIconWidth(handleIcon, context),
-                    SynthIcon.getIconHeight(handleIcon, context));
+                    SynthGraphicsUtils.getIconWidth(handleIcon, context);
+            SynthGraphicsUtils.paintIcon(handleIcon, context, g, startX, 0,
+                    SynthGraphicsUtils.getIconWidth(handleIcon, context),
+                    SynthGraphicsUtils.getIconHeight(handleIcon, context));
         }
 
         SynthContext subcontext = getContext(
@@ -358,7 +357,7 @@
 
             if (tb.getOrientation() == JToolBar.HORIZONTAL) {
                 dim.width = tb.isFloatable() ?
-                    SynthIcon.getIconWidth(handleIcon, context) : 0;
+                    SynthGraphicsUtils.getIconWidth(handleIcon, context) : 0;
                 Dimension compDim;
                 for (int i = 0; i < tb.getComponentCount(); i++) {
                     Component component = tb.getComponent(i);
@@ -370,7 +369,7 @@
                 }
             } else {
                 dim.height = tb.isFloatable() ?
-                    SynthIcon.getIconHeight(handleIcon, context) : 0;
+                    SynthGraphicsUtils.getIconHeight(handleIcon, context) : 0;
                 Dimension compDim;
                 for (int i = 0; i < tb.getComponentCount(); i++) {
                     Component component = tb.getComponent(i);
@@ -396,7 +395,7 @@
 
             if (tb.getOrientation() == JToolBar.HORIZONTAL) {
                 dim.width = tb.isFloatable() ?
-                    SynthIcon.getIconWidth(handleIcon, context) : 0;
+                    SynthGraphicsUtils.getIconWidth(handleIcon, context) : 0;
                 Dimension compDim;
                 for (int i = 0; i < tb.getComponentCount(); i++) {
                     Component component = tb.getComponent(i);
@@ -408,7 +407,7 @@
                 }
             } else {
                 dim.height = tb.isFloatable() ?
-                    SynthIcon.getIconHeight(handleIcon, context) : 0;
+                    SynthGraphicsUtils.getIconHeight(handleIcon, context) : 0;
                 Dimension compDim;
                 for (int i = 0; i < tb.getComponentCount(); i++) {
                     Component component = tb.getComponent(i);
@@ -449,7 +448,7 @@
 
             if (tb.getOrientation() == JToolBar.HORIZONTAL) {
                 int handleWidth = tb.isFloatable() ?
-                    SynthIcon.getIconWidth(handleIcon, context) : 0;
+                    SynthGraphicsUtils.getIconWidth(handleIcon, context) : 0;
 
                 // Note: contentRect does not take insets into account
                 // since it is used for determining the bounds that are
@@ -500,7 +499,7 @@
                 }
             } else {
                 int handleHeight = tb.isFloatable() ?
-                    SynthIcon.getIconHeight(handleIcon, context) : 0;
+                    SynthGraphicsUtils.getIconHeight(handleIcon, context) : 0;
 
                 // See notes above regarding the use of insets
                 contentRect.x = 0;
--- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTreeUI.java	Tue Nov 17 13:24:06 2015 -0800
+++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTreeUI.java	Wed Nov 18 19:13:42 2015 +0400
@@ -47,7 +47,6 @@
 import javax.swing.tree.TreeCellRenderer;
 import javax.swing.tree.TreeModel;
 import javax.swing.tree.TreePath;
-import sun.swing.plaf.synth.SynthIcon;
 
 /**
  * Provides the Synth L&amp;F UI delegate for
@@ -610,10 +609,10 @@
     @Override
     protected void drawCentered(Component c, Graphics graphics, Icon icon,
                                 int x, int y) {
-        int w = SynthIcon.getIconWidth(icon, paintContext);
-        int h = SynthIcon.getIconHeight(icon, paintContext);
+        int w = SynthGraphicsUtils.getIconWidth(icon, paintContext);
+        int h = SynthGraphicsUtils.getIconHeight(icon, paintContext);
 
-        SynthIcon.paintIcon(icon, paintContext, graphics,
+        SynthGraphicsUtils.paintIcon(icon, paintContext, graphics,
                             findCenteredX(x, w),
                             y - h/2, w, h);
     }
@@ -780,16 +779,16 @@
     // To get the correct context we return an instance of this that fetches
     // the SynthContext as needed.
     //
-    private class ExpandedIconWrapper extends SynthIcon {
+    private class ExpandedIconWrapper implements SynthIcon {
         public void paintIcon(SynthContext context, Graphics g, int x,
                               int y, int w, int h) {
             if (context == null) {
                 context = getContext(tree);
-                SynthIcon.paintIcon(expandedIcon, context, g, x, y, w, h);
+                SynthGraphicsUtils.paintIcon(expandedIcon, context, g, x, y, w, h);
                 context.dispose();
             }
             else {
-                SynthIcon.paintIcon(expandedIcon, context, g, x, y, w, h);
+                SynthGraphicsUtils.paintIcon(expandedIcon, context, g, x, y, w, h);
             }
         }
 
@@ -797,11 +796,11 @@
             int width;
             if (context == null) {
                 context = getContext(tree);
-                width = SynthIcon.getIconWidth(expandedIcon, context);
+                width = SynthGraphicsUtils.getIconWidth(expandedIcon, context);
                 context.dispose();
             }
             else {
-                width = SynthIcon.getIconWidth(expandedIcon, context);
+                width = SynthGraphicsUtils.getIconWidth(expandedIcon, context);
             }
             return width;
         }
@@ -810,11 +809,11 @@
             int height;
             if (context == null) {
                 context = getContext(tree);
-                height = SynthIcon.getIconHeight(expandedIcon, context);
+                height = SynthGraphicsUtils.getIconHeight(expandedIcon, context);
                 context.dispose();
             }
             else {
-                height = SynthIcon.getIconHeight(expandedIcon, context);
+                height = SynthGraphicsUtils.getIconHeight(expandedIcon, context);
             }
             return height;
         }
--- a/src/java.desktop/share/classes/sun/swing/plaf/synth/SynthIcon.java	Tue Nov 17 13:24:06 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +0,0 @@
-/*
- * Copyright (c) 2002, 2003, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-package sun.swing.plaf.synth;
-
-import javax.swing.plaf.synth.*;
-import java.awt.*;
-import javax.swing.*;
-import javax.swing.border.Border;
-import javax.swing.plaf.UIResource;
-
-/**
- * An icon that is passed a SynthContext. Subclasses need only implement
- * the variants that take a SynthContext, but must be prepared for the
- * SynthContext to be null.
- *
- * @author Scott Violet
- */
-public abstract class SynthIcon implements Icon {
-    public static int getIconWidth(Icon icon, SynthContext context) {
-        if (icon == null) {
-            return 0;
-        }
-        if (icon instanceof SynthIcon) {
-            return ((SynthIcon)icon).getIconWidth(context);
-        }
-        return icon.getIconWidth();
-    }
-
-    public static int getIconHeight(Icon icon, SynthContext context) {
-        if (icon == null) {
-            return 0;
-        }
-        if (icon instanceof SynthIcon) {
-            return ((SynthIcon)icon).getIconHeight(context);
-        }
-        return icon.getIconHeight();
-    }
-
-    public static void paintIcon(Icon icon, SynthContext context, Graphics g,
-                                 int x, int y, int w, int h) {
-        if (icon instanceof SynthIcon) {
-            ((SynthIcon)icon).paintIcon(context, g, x, y, w, h);
-        }
-        else if (icon != null) {
-            icon.paintIcon(context.getComponent(), g, x, y);
-        }
-    }
-
-    /**
-     * Paints the icon at the specified location.
-     *
-     * @param context Identifies hosting region, may be null.
-     * @param x x location to paint to
-     * @param y y location to paint to
-     * @param w Width of the region to paint to, may be 0
-     * @param h Height of the region to paint to, may be 0
-     */
-    public abstract void paintIcon(SynthContext context, Graphics g, int x,
-                                   int y, int w, int h);
-
-    /**
-     * Returns the desired width of the Icon.
-     *
-     * @param context SynthContext requesting the Icon, may be null.
-     * @return Desired width of the icon.
-     */
-    public abstract int getIconWidth(SynthContext context);
-
-    /**
-     * Returns the desired height of the Icon.
-     *
-     * @param context SynthContext requesting the Icon, may be null.
-     * @return Desired height of the icon.
-     */
-    public abstract int getIconHeight(SynthContext context);
-
-    /**
-     * Paints the icon. This is a cover method for
-     * <code>paintIcon(null, g, x, y, 0, 0)</code>
-     */
-    public void paintIcon(Component c, Graphics g, int x, int y) {
-        paintIcon(null, g, x, y, 0, 0);
-    }
-
-    /**
-     * Returns the icon's width. This is a cover methods for
-     * <code>getIconWidth(null)</code>.
-     *
-     * @return an int specifying the fixed width of the icon.
-     */
-    public int getIconWidth() {
-        return getIconWidth(null);
-    }
-
-    /**
-     * Returns the icon's height. This is a cover method for
-     * <code>getIconHeight(null)</code>.
-     *
-     * @return an int specifying the fixed height of the icon.
-     */
-    public int getIconHeight() {
-        return getIconHeight(null);
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/swing/plaf/synth/8081411/bug8081411.java	Wed Nov 18 19:13:42 2015 +0400
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2015, 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.Color;
+import java.awt.Graphics;
+import java.awt.image.BufferedImage;
+import javax.swing.Icon;
+import javax.swing.JMenuItem;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.UIManager.LookAndFeelInfo;
+import javax.swing.plaf.synth.Region;
+import javax.swing.plaf.synth.SynthConstants;
+import javax.swing.plaf.synth.SynthContext;
+import javax.swing.plaf.synth.SynthGraphicsUtils;
+import javax.swing.plaf.synth.SynthIcon;
+import javax.swing.plaf.synth.SynthLookAndFeel;
+import javax.swing.plaf.synth.SynthStyle;
+
+/*
+ * @test
+ * @bug 8081411
+ * @summary Add an API for painting an icon with a SynthContext
+ * @author Alexander Scherbatiy
+ */
+public class bug8081411 {
+
+    private static final Color TEST_COLOR = new Color(71, 71, 72);
+
+    public static void main(String[] args) throws Exception {
+        SwingUtilities.invokeAndWait(bug8081411::testSynthIcon);
+    }
+
+    private static void testSynthIcon() {
+
+        if (!checkAndSetNimbusLookAndFeel()) {
+            return;
+        }
+
+        JMenuItem menu = new JMenuItem();
+        Icon subMenuIcon = UIManager.getIcon("Menu.arrowIcon");
+
+        if (!(subMenuIcon instanceof SynthIcon)) {
+            throw new RuntimeException("Icon is not a SynthIcon!");
+        }
+
+        Region region = SynthLookAndFeel.getRegion(menu);
+        SynthStyle style = SynthLookAndFeel.getStyle(menu, region);
+        SynthContext synthContext = new SynthContext(menu, region, style, SynthConstants.ENABLED);
+
+        int width = SynthGraphicsUtils.getIconWidth(subMenuIcon, synthContext);
+        int height = SynthGraphicsUtils.getIconHeight(subMenuIcon, synthContext);
+        paintAndCheckIcon(subMenuIcon, synthContext, width, height);
+
+        int newWidth = width * 17;
+        int newHeight = height * 37;
+        Icon centeredIcon = new CenteredSynthIcon((SynthIcon) subMenuIcon,
+                newWidth, newHeight);
+        paintAndCheckIcon(centeredIcon, synthContext, newWidth, newHeight);
+    }
+
+    private static void paintAndCheckIcon(Icon icon, SynthContext synthContext,
+            int width, int height) {
+
+        BufferedImage buffImage = new BufferedImage(width, height,
+                BufferedImage.TYPE_INT_RGB);
+        Graphics g = buffImage.createGraphics();
+        g.setColor(Color.RED);
+        g.fillRect(0, 0, width, height);
+        SynthGraphicsUtils.paintIcon(icon, synthContext, g, 0, 0, width, height);
+        g.dispose();
+
+        Color iconCenterColor = new Color(buffImage.getRGB(width / 2, height / 2));
+
+        if (!TEST_COLOR.equals(iconCenterColor)) {
+            throw new RuntimeException("Icon is painted incorrectly!");
+        }
+    }
+
+    private static boolean checkAndSetNimbusLookAndFeel() {
+        try {
+            for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
+                if ("Nimbus".equals(info.getName())) {
+                    UIManager.setLookAndFeel(info.getClassName());
+                    return true;
+                }
+            }
+            return false;
+        } catch (Exception ignore) {
+            return false;
+        }
+    }
+
+    private static class CenteredSynthIcon implements SynthIcon {
+
+        private final SynthIcon icon;
+        private final int width;
+        private final int height;
+
+        public CenteredSynthIcon(SynthIcon icon, int width, int height) {
+            this.icon = icon;
+            this.width = width;
+            this.height = height;
+        }
+
+        @Override
+        public void paintIcon(SynthContext syntContext, Graphics g, int x, int y,
+                int w, int h) {
+            int dw = icon.getIconWidth(syntContext);
+            int dh = icon.getIconHeight(syntContext);
+            int dx = width - dw;
+            int dy = height - dh;
+            icon.paintIcon(syntContext, g, x + dx / 2, y + dy / 2,
+                    dw + 2, dh + 2);
+        }
+
+        @Override
+        public int getIconWidth(SynthContext sc) {
+            return width;
+        }
+
+        @Override
+        public int getIconHeight(SynthContext sc) {
+            return height;
+        }
+    }
+}