gt:             centerRowHeight = totalHeight - metrics.nCut - metrics.sCut;
context: /*
   * Copyright (c) 2011, 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 com.apple.laf;
  
  import java.awt.*;
  import java.awt.image.BufferedImage;
  import java.security.PrivilegedAction;
  
  import javax.swing.*;
  import javax.swing.plaf.*;
  
  import sun.lwawt.macosx.LWCToolkit;
  import apple.laf.JRSUIConstants.AlignmentHorizontal;
  import apple.laf.JRSUIConstants.AlignmentVertical;
  import apple.laf.JRSUIConstants.Direction;
  import apple.laf.JRSUIConstants.State;
  import apple.laf.JRSUIConstants.Widget;
  import apple.laf.*;
  
  import com.apple.eio.FileManager;
  import com.apple.laf.AquaIcon.InvertableIcon;
  import com.apple.laf.AquaIcon.JRSUIControlSpec;
  import com.apple.laf.AquaIcon.SystemIcon;
  import com.apple.laf.AquaUtils.RecyclableObject;
  import com.apple.laf.AquaUtils.RecyclableSingleton;
  
  public class AquaImageFactory {
      public static IconUIResource getConfirmImageIcon() {
          // public, because UIDefaults.ProxyLazyValue uses reflection to get this value
  
          return new IconUIResource(new AquaIcon.CachingScalingIcon(kAlertIconSize, kAlertIconSize) {
              Image createImage() {
                  return getThisApplicationsIcon(kAlertIconSize, kAlertIconSize);
              }
          });
      }
  
      public static IconUIResource getCautionImageIcon() {
          // public, because UIDefaults.ProxyLazyValue uses reflection to get this value
          return getAppIconCompositedOn(AquaIcon.SystemIcon.getCautionIcon());
      }
  
      public static IconUIResource getStopImageIcon() {
          // public, because UIDefaults.ProxyLazyValue uses reflection to get this value
          return getAppIconCompositedOn(AquaIcon.SystemIcon.getStopIcon());
      }
  
      public static IconUIResource getLockImageIcon() {
          // public, because UIDefaults.ProxyLazyValue uses reflection to get this value
          if (JRSUIUtils.Images.shouldUseLegacySecurityUIPath()) {
              final Image lockIcon = AquaUtils.getCImageCreator().createImageFromFile("/System/Library/CoreServices/SecurityAgent.app/Contents/Resources/Security.icns", kAlertIconSize, kAlertIconSize);
              return getAppIconCompositedOn(lockIcon);
          }
  
          final Image lockIcon = Toolkit.getDefaultToolkit().getImage("NSImage://NSSecurity");
          return getAppIconCompositedOn(lockIcon);
      }
  
      static Image getThisApplicationsIcon(final int width, final int height) {
          final String path = getPathToThisApplication();
  
          if (path == null) {
              return getGenericJavaIcon();
          }
  
          if (path.endsWith("/Home/bin")) {
              return getGenericJavaIcon();
          }
  
          if (path.startsWith("/usr/bin")) {
              return getGenericJavaIcon();
          }
  
          return AquaUtils.getCImageCreator().createImageOfFile(path, height, width);
      }
  
      static Image getGenericJavaIcon() {
          return java.security.AccessController.doPrivileged(new PrivilegedAction<Image>() {
              public Image run() {
                  return com.apple.eawt.Application.getApplication().getDockIconImage();
              }
          });
      }
  
      static String getPathToThisApplication() {
          return java.security.AccessController.doPrivileged(new PrivilegedAction<String>() {
              public String run() {
                  return FileManager.getPathToApplicationBundle();
              }
          });
      }
  
      static IconUIResource getAppIconCompositedOn(final SystemIcon systemIcon) {
          systemIcon.setSize(kAlertIconSize, kAlertIconSize);
          return getAppIconCompositedOn(systemIcon.createImage());
      }
  
      private static final int kAlertIconSize = 64;
      static IconUIResource getAppIconCompositedOn(final Image background) {
          final double scaleFactor = 1.0; // revise for HiDPI
  
          final int kAlertSubIconSize = (int)(kAlertIconSize * 0.5 * scaleFactor);
          final int kAlertSubIconInset = (int)(kAlertIconSize * scaleFactor) - kAlertSubIconSize;
          final Icon smallAppIconScaled = new AquaIcon.CachingScalingIcon(kAlertSubIconSize, kAlertSubIconSize) {
              Image createImage() {
                  return getThisApplicationsIcon(kAlertSubIconSize, kAlertSubIconSize);
              }
          };
  
          final BufferedImage image = new BufferedImage(kAlertIconSize, kAlertIconSize, BufferedImage.TYPE_INT_ARGB);
          final Graphics g = image.getGraphics();
          g.drawImage(background, 0, 0, (int)(kAlertIconSize * scaleFactor), (int)(kAlertIconSize * scaleFactor), null);
          if (g instanceof Graphics2D) {
              // improves icon rendering quality in Quartz
              ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
          }
  
          smallAppIconScaled.paintIcon(null, g, kAlertSubIconInset, kAlertSubIconInset);
          g.dispose();
  
          return new IconUIResource(new ImageIcon(image));
      }
  
      public static IconUIResource getTreeFolderIcon() {
          // public, because UIDefaults.ProxyLazyValue uses reflection to get this value
          return AquaIcon.SystemIcon.getFolderIconUIResource();
      }
  
      public static IconUIResource getTreeOpenFolderIcon() {
          // public, because UIDefaults.ProxyLazyValue uses reflection to get this value
          return AquaIcon.SystemIcon.getOpenFolderIconUIResource();
      }
  
      public static IconUIResource getTreeDocumentIcon() {
          // public, because UIDefaults.ProxyLazyValue uses reflection to get this value
          return AquaIcon.SystemIcon.getDocumentIconUIResource();
      }
  
      public static UIResource getTreeExpandedIcon() {
          // public, because UIDefaults.ProxyLazyValue uses reflection to get this value
          return AquaIcon.getIconFor(new JRSUIControlSpec() {
              public void initIconPainter(final AquaPainter<? extends JRSUIState> painter) {
                  painter.state.set(Widget.DISCLOSURE_TRIANGLE);
                  painter.state.set(State.ACTIVE);
                  painter.state.set(Direction.DOWN);
                  painter.state.set(AlignmentHorizontal.CENTER);
                  painter.state.set(AlignmentVertical.CENTER);
              }
          }, 20, 20);
      }
  
      public static UIResource getTreeCollapsedIcon() {
          // public, because UIDefaults.ProxyLazyValue uses reflection to get this value
          return AquaIcon.getIconFor(new JRSUIControlSpec() {
              public void initIconPainter(final AquaPainter<? extends JRSUIState> painter) {
                  painter.state.set(Widget.DISCLOSURE_TRIANGLE);
                  painter.state.set(State.ACTIVE);
                  painter.state.set(Direction.RIGHT);
                  painter.state.set(AlignmentHorizontal.CENTER);
                  painter.state.set(AlignmentVertical.CENTER);
              }
          }, 20, 20);
      }
  
      public static UIResource getTreeRightToLeftCollapsedIcon() {
          // public, because UIDefaults.ProxyLazyValue uses reflection to get this value
          return AquaIcon.getIconFor(new JRSUIControlSpec() {
              public void initIconPainter(final AquaPainter<? extends JRSUIState> painter) {
                  painter.state.set(Widget.DISCLOSURE_TRIANGLE);
                  painter.state.set(State.ACTIVE);
                  painter.state.set(Direction.LEFT);
                  painter.state.set(AlignmentHorizontal.CENTER);
                  painter.state.set(AlignmentVertical.CENTER);
              }
          }, 20, 20);
      }
  
      static class NamedImageSingleton extends RecyclableSingleton<Image> {
          final String namedImage;
  
          NamedImageSingleton(final String namedImage) {
              this.namedImage = namedImage;
          }
  
          @Override
          protected Image getInstance() {
              return Toolkit.getDefaultToolkit().getImage("NSImage://" + namedImage);
          }
      }
  
      static class IconUIResourceSingleton extends RecyclableSingleton<IconUIResource> {
          final NamedImageSingleton holder;
  
          public IconUIResourceSingleton(final NamedImageSingleton holder) {
              this.holder = holder;
          }
  
          @Override
          protected IconUIResource getInstance() {
              return new IconUIResource(new ImageIcon(holder.get()));
          }
      }
  
      static class InvertableImageIcon extends ImageIcon implements InvertableIcon, UIResource {
          Icon invertedImage;
          public InvertableImageIcon(final Image image) {
              super(image);
          }
  
          @Override
          public Icon getInvertedIcon() {
              if (invertedImage != null) return invertedImage;
              return invertedImage = new IconUIResource(new ImageIcon(AquaUtils.generateLightenedImage(getImage(), 100)));
          }
      }
  
      protected static final NamedImageSingleton northArrow = new NamedImageSingleton("NSMenuScrollUp");
      protected static final IconUIResourceSingleton northArrowIcon = new IconUIResourceSingleton(northArrow);
      protected static final NamedImageSingleton southArrow = new NamedImageSingleton("NSMenuScrollDown");
      protected static final IconUIResourceSingleton southArrowIcon = new IconUIResourceSingleton(southArrow);
      protected static final NamedImageSingleton westArrow = new NamedImageSingleton("NSMenuSubmenuLeft");
      protected static final IconUIResourceSingleton westArrowIcon = new IconUIResourceSingleton(westArrow);
      protected static final NamedImageSingleton eastArrow = new NamedImageSingleton("NSMenuSubmenu");
      protected static final IconUIResourceSingleton eastArrowIcon = new IconUIResourceSingleton(eastArrow);
  
      static Image getArrowImageForDirection(final int direction) {
          switch(direction) {
              case SwingConstants.NORTH: return northArrow.get();
              case SwingConstants.SOUTH: return southArrow.get();
              case SwingConstants.EAST: return eastArrow.get();
              case SwingConstants.WEST: return westArrow.get();
          }
          return null;
      }
  
      static Icon getArrowIconForDirection(int direction) {
          switch(direction) {
              case SwingConstants.NORTH: return northArrowIcon.get();
              case SwingConstants.SOUTH: return southArrowIcon.get();
              case SwingConstants.EAST: return eastArrowIcon.get();
              case SwingConstants.WEST: return westArrowIcon.get();
          }
          return null;
      }
  
      public static Icon getMenuArrowIcon() {
          return new InvertableImageIcon(AquaUtils.generateLightenedImage(eastArrow.get(), 25));
      }
  
      public static Icon getMenuItemCheckIcon() {
          return new InvertableImageIcon(AquaUtils.generateLightenedImage(Toolkit.getDefaultToolkit().getImage("NSImage://NSMenuItemSelection"), 25));
      }
  
      public static Icon getMenuItemDashIcon() {
          return new InvertableImageIcon(AquaUtils.generateLightenedImage(Toolkit.getDefaultToolkit().getImage("NSImage://NSMenuMixedState"), 25));
      }
  
      public static class NineSliceMetrics {
          public final int wCut, eCut, nCut, sCut;
          public final int minW, minH;
          public final boolean showMiddle, stretchH, stretchV;
  
          public NineSliceMetrics(final int minWidth, final int minHeight, final int westCut, final int eastCut, final int northCut, final int southCut) {
              this(minWidth, minHeight, westCut, eastCut, northCut, southCut, true);
          }
  
          public NineSliceMetrics(final int minWidth, final int minHeight, final int westCut, final int eastCut, final int northCut, final int southCut, final boolean showMiddle) {
              this(minWidth, minHeight, westCut, eastCut, northCut, southCut, showMiddle, true, true);
          }
  
          public NineSliceMetrics(final int minWidth, final int minHeight, final int westCut, final int eastCut, final int northCut, final int southCut, final boolean showMiddle, final boolean stretchHorizontally, final boolean stretchVertically) {
              this.wCut = westCut; this.eCut = eastCut; this.nCut = northCut; this.sCut = southCut;
              this.minW = minWidth; this.minH = minHeight;
              this.showMiddle = showMiddle; this.stretchH = stretchHorizontally; this.stretchV = stretchVertically;
          }
      }
  
      /*
       * A "paintable" which holds nine images, which represent a sliced up initial
       * image that can be streched from its middles.
       */
      public static class SlicedImageControl {
          final BufferedImage NW, N, NE;
          final BufferedImage W, C, E;
          final BufferedImage SW, S, SE;
  
          final NineSliceMetrics metrics;
  
          final int totalWidth, totalHeight;
          final int centerColWidth, centerRowHeight;
  
          public SlicedImageControl(final Image img, final int westCut, final int eastCut, final int northCut, final int southCut) {
              this(img, westCut, eastCut, northCut, southCut, true);
          }
  
          public SlicedImageControl(final Image img, final int westCut, final int eastCut, final int northCut, final int southCut, final boolean useMiddle) {
              this(img, westCut, eastCut, northCut, southCut, useMiddle, true, true);
          }
  
          public SlicedImageControl(final Image img, final int westCut, final int eastCut, final int northCut, final int southCut, final boolean useMiddle, final boolean stretchHorizontally, final boolean stretchVertically) {
              this(img, new NineSliceMetrics(img.getWidth(null), img.getHeight(null), westCut, eastCut, northCut, southCut, useMiddle, stretchHorizontally, stretchVertically));
          }
  
          public SlicedImageControl(final Image img, final NineSliceMetrics metrics) {
              this.metrics = metrics;
  
              if (img.getWidth(null) != metrics.minW || img.getHeight(null) != metrics.minH) {
                  throw new IllegalArgumentException("SlicedImageControl: template image and NineSliceMetrics don't agree on minimum dimensions");
              }
  
              totalWidth = metrics.minW;
              totalHeight = metrics.minH;
              centerColWidth = totalWidth - metrics.wCut - metrics.eCut;
  