1   /*
2    * SPDX-License-Identifier: Apache-2.0
3    *
4    * Copyright 2015-2022 Andres Almiray
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.kordamp.ikonli.swing;
19  
20  import org.kordamp.ikonli.Ikon;
21  import org.kordamp.ikonli.IkonHandler;
22  
23  import javax.swing.*;
24  import java.awt.*;
25  import java.awt.image.BufferedImage;
26  
27  import static java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment;
28  import static java.util.Objects.requireNonNull;
29  
30  /**
31   * @author Andres Almiray
32   */
33  public class FontIcon implements Icon {
34      private static final Object LOCK = new Object[0];
35  
36      private Font font;
37      private int width = 8;
38      private int height = 8;
39  
40      private int iconSize = 8;
41      private Color iconColor = Color.BLACK;
42      private Ikon ikon;
43  
44      public void paintIcon(Component c, Graphics g, int x, int y) {
45          int w = getIconWidth();
46          int h = getIconHeight();
47          if (w <= 0 || h <= 0) return;
48  
49          g.translate(x, y);
50          Color previousColor = g.getColor();
51          Font previousFont = g.getFont();
52  
53          try {
54              Graphics2D g2 = (Graphics2D) g;
55              g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
56                  RenderingHints.VALUE_ANTIALIAS_ON);
57  
58              g2.setFont(font);
59              g2.setColor(iconColor);
60  
61              int sy = g2.getFontMetrics().getAscent();
62              int code = ikon.getCode();
63  
64              if (code <= '\uFFFF') {
65                  g2.drawString(String.valueOf((char) code), 0, sy);
66              } else {
67                  char[] charPair = Character.toChars(code);
68                  String symbol = new String(charPair);
69                  g2.drawString(symbol, 0, sy);
70              }
71          } finally {
72              g.translate(-x, -y);
73              g.setColor(previousColor);
74              g.setFont(previousFont);
75          }
76      }
77  
78      public ImageIcon toImageIcon() {
79          return toImageIcon(this);
80      }
81  
82      public ImageIcon toImageIcon(Icon icon) {
83          BufferedImage image = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
84          icon.paintIcon(null, image.getGraphics(), 0, 0);
85          return new ImageIcon(image);
86      }
87  
88      public Ikon getIkon() {
89          return ikon;
90      }
91  
92      public void setIkon(Ikon ikon) {
93          requireNonNull(iconColor, "Argument 'iconFont' must not be null");
94          this.ikon = ikon;
95          synchronized (LOCK) {
96              IkonHandler ikonHandler = org.kordamp.ikonli.swing.IkonResolver.getInstance().resolve(ikon.getDescription());
97              font = ((Font) ikonHandler.getFont()).deriveFont(Font.PLAIN, iconSize);
98              setProperties();
99          }
100     }
101 
102     public int getIconSize() {
103         return iconSize;
104     }
105 
106     public void setIconSize(int iconSize) {
107         if (iconSize > 0) {
108             this.iconSize = iconSize;
109             if (null != font) {
110                 font = font.deriveFont(Font.PLAIN, iconSize);
111                 setProperties();
112             }
113         }
114     }
115 
116     protected void setProperties() {
117         BufferedImage tmp = new BufferedImage(iconSize, iconSize,
118             BufferedImage.TYPE_INT_ARGB);
119         Graphics2D g2 = getLocalGraphicsEnvironment().createGraphics(tmp);
120         g2.setFont(font);
121         this.width = g2.getFontMetrics().charWidth(ikon.getCode());
122         this.height = g2.getFontMetrics().getHeight();
123 
124         g2.dispose();
125     }
126 
127     public Color getIconColor() {
128         return iconColor;
129     }
130 
131     public void setIconColor(Color iconColor) {
132         requireNonNull(iconColor, "Argument 'iconColor' must not be null");
133         this.iconColor = iconColor;
134     }
135 
136     public int getIconHeight() {
137         return height;
138     }
139 
140     public int getIconWidth() {
141         return width;
142     }
143 
144     public static FontIcon of(Ikon ikon) {
145         return of(ikon, 8, Color.BLACK);
146     }
147 
148     public static FontIcon of(Ikon ikon, int iconSize) {
149         return of(ikon, iconSize, Color.BLACK);
150     }
151 
152     public static FontIcon of(Ikon ikon, Color iconColor) {
153         return of(ikon, 8, iconColor);
154     }
155 
156     public static FontIcon of(Ikon ikon, int iconSize, Color iconColor) {
157         FontIcontIcon.html#FontIcon">FontIcon icon = new FontIcon();
158         icon.setIkon(ikon);
159         icon.setIconSize(iconSize);
160         icon.setIconColor(iconColor);
161         return icon;
162     }
163 }