package org.geogebra.desktop.gui.util; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Polygon; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.font.FontRenderContext; import java.awt.font.GlyphVector; import java.awt.geom.Ellipse2D; import java.awt.geom.GeneralPath; import java.awt.geom.Line2D; import java.awt.image.BufferedImage; import javax.swing.ImageIcon; import org.geogebra.common.euclidian.EuclidianStatic; import org.geogebra.common.euclidian.draw.DrawText; import org.geogebra.common.factories.AwtFactory; import org.geogebra.common.kernel.geos.GeoText; import org.geogebra.common.plugin.EuclidianStyleConstants; import org.geogebra.common.util.lang.Unicode; import org.geogebra.desktop.awt.GColorD; import org.geogebra.desktop.awt.GFontD; import org.geogebra.desktop.awt.GGraphics2DD; import org.geogebra.desktop.awt.GRectangleD; import org.geogebra.desktop.factories.AwtFactoryD; import org.geogebra.desktop.main.AppD; import org.geogebra.desktop.util.ImageManagerD; import org.geogebra.desktop.util.ImageResourceD; import com.himamis.retex.renderer.desktop.graphics.ColorD; import com.himamis.retex.renderer.share.TeXConstants; import com.himamis.retex.renderer.share.TeXFormula; /** * Creates various ImageIcons for use in lists and tables. * * @author G. Sturr * */ @SuppressWarnings("javadoc") public class GeoGebraIconD { private static final int HGRID_MARGIN = 4; private static final int VGRID_MARGIN = 4; public static ImageIcon createEmptyIcon(int width, int height) { BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); ImageIcon ic = new ImageIcon(image); return ic; } public static ImageIcon createNullSymbolIcon(int width, int height) { BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = createGraphics(image); g2.setPaint(Color.GRAY); // draw a rectangle with an x inside g2.drawRect(3, 3, width - 6, height - 6); int k = 7; g2.drawLine(k, k, width - k, height - k); g2.drawLine(k, height - k, width - k, k); ImageIcon ic = new ImageIcon(image); return ic; } public static ImageIcon createFileImageIcon(AppD app, ImageResourceD res) { Image im = app.getImageManager().getImageResource(res); ImageIcon ic = im == null ? null : new ImageIcon(ImageManagerD.toBufferedImage(im)); // ensureIconSize(ic, iconSize); return ic; } public static ImageIcon createHGridIcon(Dimension iconSize) { int h = iconSize.height; int w = iconSize.width; BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = createGraphics(image); // draw 3 horizontal lines g2.setPaint(Color.GRAY); int gap = h / 4; int margin = (h - 2 * gap) / 2; for (int i = 0; i < 3; i++) { int y = margin + i * gap; g2.drawLine(HGRID_MARGIN, y, h - HGRID_MARGIN, y); } ImageIcon ic = new ImageIcon(image); // ensureIconSize(ic, iconSize); return ic; } public static ImageIcon createVGridIcon(Dimension iconSize) { int h = iconSize.height; int w = iconSize.width; BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = createGraphics(image); // draw 3 horizontal lines g2.setPaint(Color.GRAY); int gap = w / 4; int margin = (w - 2 * gap) / 2; for (int i = 0; i < 3; i++) { int x = margin + i * gap; g2.drawLine(x, VGRID_MARGIN, x, h - VGRID_MARGIN); } ImageIcon ic = new ImageIcon(image); // ensureIconSize(ic, iconSize); return ic; } private static Graphics2D createGraphics(BufferedImage image) { Graphics2D g2 = image.createGraphics(); GGraphics2DD.setAntialiasing(g2); return g2; } /** * Creates a 16x16 pixel icon representing a tree display of data */ public static ImageIcon createTreeIcon() { BufferedImage image = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = createGraphics(image); g2.setPaint(Color.DARK_GRAY); for (int i = 3; i < 12; i = i + 2) { g2.drawLine(6, i, 12, i); if (i % 3 == 0) { g2.fillRect(2, i - 1, 3, 3); g2.drawLine(2, i, 12, i); } } ImageIcon ic = new ImageIcon(image); // ensureIconSize(ic, iconSize); return ic; } /** * Creates a 16x16 pixel icon to represent rightward opening/closing a list * display of data */ public static ImageIcon listRightIcon() { BufferedImage image = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = createGraphics(image); g2.setPaint(Color.DARK_GRAY); for (int i = 3; i <= 12; i = i + 2) { g2.drawLine(1, i, 6, i); } g2.setPaint(Color.GRAY); g2.drawLine(10, 5, 10, 9); g2.drawLine(9, 5, 9, 9); g2.drawLine(8, 5, 8, 9); for (int i = 0; i <= 4; i++) { g2.drawLine(11 + i, 3 + i, 11 + i, 11 - i); } ImageIcon ic = new ImageIcon(image); return ic; } /** * Creates a 16x16 pixel icon to represent leftward opening/closing a list * display of data */ public static ImageIcon listLeftIcon() { BufferedImage image = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = createGraphics(image); g2.setPaint(Color.DARK_GRAY); for (int i = 3; i <= 12; i = i + 2) { g2.drawLine(10, i, 15, i); } g2.setPaint(Color.GRAY); g2.drawLine(8, 5, 8, 9); g2.drawLine(7, 5, 7, 9); g2.drawLine(6, 5, 6, 9); for (int i = 0; i <= 4; i++) { g2.drawLine(5 - i, 11 - i, 5 - i, 3 + i); } ImageIcon ic = new ImageIcon(image); return ic; } public static ImageIcon createDownTriangleIcon(int height) { int width = 8; BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = createGraphics(image); g2.setColor(Color.BLACK); int x = 1; int y = height / 2 - 1; g2.drawLine(x, y, x + 6, y); g2.drawLine(x + 1, y + 1, x + 5, y + 1); g2.drawLine(x + 2, y + 2, x + 4, y + 2); g2.drawLine(x + 3, y + 3, x + 3, y + 3); ImageIcon ic = new ImageIcon(image); return ic; } public static ImageIcon createDownTriangleIconRollOver(int height) { int width = 8; BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = createGraphics(image); g2.setColor(Color.LIGHT_GRAY); g2.fillOval(0, 0, width, height); g2.setColor(Color.BLACK); int x = 1; int y = height / 2 - 1; g2.drawLine(x, y, x + 6, y); g2.drawLine(x + 1, y + 1, x + 5, y + 1); g2.drawLine(x + 2, y + 2, x + 4, y + 2); g2.drawLine(x + 3, y + 3, x + 3, y + 3); ImageIcon ic = new ImageIcon(image); return ic; } public static ImageIcon createSymbolTableIcon(Font font0) { int s = 14; String alpha = Unicode.alpha + ""; BufferedImage image = new BufferedImage(s, s, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = createGraphics(image); g2.setPaint(Color.DARK_GRAY); Font font = font0.deriveFont(Font.BOLD, s); g2.setFont(font); g2.setColor(Color.DARK_GRAY); drawCenteredText(g2, alpha, s / 2 - 1, s / 2); g2.setColor(Color.GRAY); g2.drawRect(0, 0, s - 2, s - 2); g2.setColor(Color.LIGHT_GRAY); g2.drawLine(s - 1, 1, s - 1, s - 1); g2.drawLine(1, s - 1, s - 1, s - 1); ImageIcon ic = new ImageIcon(image); return ic; } private static void drawCenteredText(Graphics2D graphics, String text, int centerX, int centerY) { // get the visual center of the component. // int centerX = getWidth()/2; // int centerY = getHeight()/2; // get the bounds of the string to draw. FontMetrics fontMetrics = graphics.getFontMetrics(); Rectangle stringBounds = fontMetrics.getStringBounds(text, graphics) .getBounds(); // get the visual bounds of the text using a GlyphVector. Font font = graphics.getFont(); FontRenderContext renderContext = graphics.getFontRenderContext(); GlyphVector glyphVector = font.createGlyphVector(renderContext, text); Rectangle visualBounds = glyphVector.getVisualBounds().getBounds(); // calculate the lower left point at which to draw the string. note that // this we // give the graphics context the y coordinate at which we want the // baseline to // be placed. use the visual bounds height to center on in conjunction // with the // position returned in the visual bounds. the vertical position given // back in the // visualBounds is a negative offset from the baseline of the text. int textX = centerX - stringBounds.width / 2; int textY = centerY - visualBounds.height / 2 - visualBounds.y; graphics.drawString(text, textX, textY); } /** * Creates an icon for a popup list --- two triangles pointing up and down */ public static ImageIcon createUpDownTriangleIcon(boolean isRollOver, boolean isEnabled) { int h = 18; int w = 12; BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = createGraphics(image); if (!isEnabled) { ImageIcon ic = new ImageIcon(image); return ic; } if (isRollOver) { g2.setColor(Color.LIGHT_GRAY); g2.fillRect(0, 0, w - 1, h - 1); } g2.setColor(Color.GRAY); // g2.drawRect(0, 0, w-1, h-1); // g2.setColor(Color.LIGHT_GRAY); // g2.drawLine(w-1,1, w-1, h-1); // g2.drawLine(1,h-1, w-1, h-1); if (isRollOver) { g2.setColor(Color.BLACK); } else { g2.setColor(Color.DARK_GRAY); } int midx = w / 2; int midy = h / 2; Polygon p = new Polygon(); // make a triangle. p.addPoint(midx - 3, midy - 1); p.addPoint(midx + 3, midy - 1); p.addPoint(midx, midy - 6); g2.fillPolygon(p); // make a triangle. p = new Polygon(); p.addPoint(midx - 3, midy + 1); p.addPoint(midx + 3, midy + 1); p.addPoint(midx, midy + 6); g2.fillPolygon(p); /* * g2.drawLine(x, y, x+6, y); g2.drawLine(x+1, y+1, x+5, y+1); * g2.drawLine(x+2, y+2, x+4, y+2); g2.drawLine(x+3, y+3, x+3, y+3); */ ImageIcon ic = new ImageIcon(image); return ic; } public static ImageIcon createColorSwatchIcon(double alpha, Dimension iconSize, Color fgColor0, Color bgColor) { int h = iconSize.height; int w = iconSize.width; int offset = 2; double thickness = 3; // if fgColor is null then make it a transparent white Color fgColor = fgColor0; if (fgColor0 == null) { fgColor = new Color(255, 255, 255, 1); } BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = createGraphics(image); --h; --w; if (bgColor != null) { g2.setPaint(bgColor); g2.fillRect(0, 0, w, h); } // interior fill color using alpha level float[] rgb = new float[3]; fgColor.getRGBColorComponents(rgb); g2.setPaint(new Color(rgb[0], rgb[1], rgb[2], (float) alpha)); g2.fillRect(offset, offset, w - 2 * offset, h - 2 * offset); // border color with alpha = 1 g2.setPaint(fgColor); g2.setStroke(new BasicStroke((float) thickness)); g2.drawRect(offset, offset, w - 2 * offset, h - 2 * offset); ImageIcon ic = new ImageIcon(image); // ensureIconSize(ic, iconSize); return ic; } public static ImageIcon createLineStyleIcon(int dashStyle, int thickness, Dimension iconSize, Color fgColor, Color bgColor) { int h = iconSize.height; int w = iconSize.width; BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = createGraphics(image); if (bgColor != null) { g2.setPaint(bgColor); g2.fillRect(0, 0, w, h); } // draw dashed line g2.setPaint(fgColor); g2.setStroke(((AwtFactoryD) AwtFactory.getPrototype()) .getAwtStroke(EuclidianStatic.getStroke(thickness, dashStyle))); int mid = h / 2; g2.drawLine(4, mid, w - 4, mid); ImageIcon ic = new ImageIcon(image); // ensureIconSize(ic, iconSize); return ic; } public static ImageIcon createTextSymbolIcon(String symbol, Font font, Dimension iconSize, Color fgColor, Color bgColor) { int h = iconSize.height; int w = iconSize.width; BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = createGraphics(image); if (bgColor != null) { g2.setBackground(bgColor); } g2.setColor(fgColor); g2.setFont(new Font(font.getFamily(), Font.PLAIN, h - 9)); FontMetrics fm = g2.getFontMetrics(); int symbolWidth = fm.stringWidth(symbol); int ascent = fm.getMaxAscent(); int descent = fm.getMaxDescent(); int msg_x = w / 2 - symbolWidth / 2; int msg_y = h / 2 - descent / 2 + ascent / 2; g2.drawString(symbol, msg_x, msg_y - 2); g2.fillRect(1, h - 5, w - 1, 3); ImageIcon ic = new ImageIcon(image); // ensureIconSize(ic, iconSize); return ic; } /** * Creates a 16x16 icon to represent a cell grid background color */ public static ImageIcon createCellGridIcon(Color fgColor, Color bgColor) { int h = 16; int w = 16; BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = createGraphics(image); // fill rectangle with bgColor (the selected color) g2.setPaint(bgColor); g2.fillRect(0, 3, 15, 9); // draw border around the colored rectangle g2.setColor(fgColor); g2.drawRect(0, 3, 15, 9); ImageIcon ic = new ImageIcon(image); // ensureIconSize(ic, iconSize); return ic; } public static ImageIcon createStringIcon(String str, Font font, Dimension iconSize) { return createStringIcon(str, font, false, false, true, iconSize, Color.BLACK, null); } public static ImageIcon createStringIcon(String str, Font font0, boolean isBold, boolean isItalic, boolean isCentered, Dimension iconSize, Color fgColor, Color bgColor) { int h = iconSize.height; int w = iconSize.width; BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = createGraphics(image); if (bgColor != null) { g2.setBackground(bgColor); } g2.setColor(fgColor); // font = font.deriveFont((h-6)*1.0f); Font font = font0; if (isBold) { font = font.deriveFont(Font.BOLD); } if (isItalic) { font = font.deriveFont(Font.ITALIC); } g2.setFont(font); FontMetrics fm = g2.getFontMetrics(); int symbolWidth = fm.stringWidth(str); int ascent = fm.getMaxAscent(); int descent = fm.getMaxDescent(); int x = (isCentered) ? w / 2 - symbolWidth / 2 : 1; int mid_y = h / 2 - descent / 2 + ascent / 2 - 1; g2.drawString(str, x, mid_y); return new ImageIcon(image); } public static ImageIcon createBracketIcon(String[] brackets, Font font0, Dimension iconSize, Color fgColor, Color bgColor) { /* * String latex = "\\left" + brackets[0] + "\\equiv" + "\\right" + * brackets[1]; ImageIcon icon = createLatexIcon(app, latex, font, * false, fgColor, null); icon = GeoGebraIcon.ensureIconSize(icon, * iconSize); */ int h = iconSize.height; int w = iconSize.width; BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = createGraphics(image); if (bgColor != null) { g2.setBackground(bgColor); } g2.setColor(fgColor); Font font = font0.deriveFont((h - 4) * 1.0f); g2.setFont(font); FontMetrics fm = g2.getFontMetrics(); // int symbolWidth = fm.stringWidth (c); // int msg_x = w/2 - symbolWidth/2; int ascent = fm.getMaxAscent(); int descent = fm.getMaxDescent(); int mid_y = h / 2 - descent / 2 + ascent / 2; int x = 2; g2.drawString(brackets[0] + "::" + brackets[1], x, mid_y); return new ImageIcon(image); } /** * Draw a LaTeX image in the icon. */ public static ImageIcon createLatexIcon(AppD app, String latex, Font font, Color fgColor, Color bgColor) { app.getDrawEquation().checkFirstCall(app); return new ImageIcon((BufferedImage) TeXFormula.createBufferedImage( latex, TeXConstants.STYLE_DISPLAY, font.getSize() + 3, ColorD.get(fgColor), ColorD.get(bgColor))); } public static ImageIcon createLatexIcon(AppD app, String latex, Color fgColor, Color bgColor, int height) { app.getDrawEquation().checkFirstCall(app); ImageIcon ic = new ImageIcon( (BufferedImage) TeXFormula.createBufferedImage(latex, TeXConstants.STYLE_DISPLAY, height - 6, ColorD.get(fgColor), ColorD.get(bgColor))); ensureIconSize(ic, new Dimension(ic.getIconWidth(), height)); return ic; } public static ImageIcon createPointStyleIcon(int pointStyle, int pointSize, Dimension iconSize, Color fgColor, Color bgColor) { // TODO: PointStyleIcon as a stand alone class PointStyleImage image = new PointStyleImage(iconSize, pointStyle, pointSize, fgColor, bgColor); ImageIcon ic = new ImageIcon(image); // ensureIconSize(ic, iconSize); return ic; } public static class PointStyleImage extends BufferedImage { private int pointStyle = -1; // for drawing private int pointSize = 4; private Ellipse2D.Double circle = new Ellipse2D.Double(); private Line2D.Double line1, line2, line3, line4; private GeneralPath gp = null; private BasicStroke borderStroke = AwtFactoryD.getDefaultStrokeAwt(); private BasicStroke[] crossStrokes = new BasicStroke[10]; private int h, w; public PointStyleImage(Dimension d, int pointStyle, int pointSize, Color fgColor, Color bgColor) { super(d.width, d.height, BufferedImage.TYPE_INT_ARGB); this.h = d.height; this.w = d.width; this.pointStyle = pointStyle; this.pointSize = pointSize; drawPointStyle(fgColor, bgColor); } public void drawPointStyle(Color fgColor, Color bgColor) { Graphics2D g2 = createGraphics(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // set background if (bgColor != null) { g2.setBackground(bgColor); } // draw point using routine from euclidian.DrawPoint g2.setPaint(fgColor); getPath(); switch (pointStyle) { case EuclidianStyleConstants.POINT_STYLE_PLUS: case EuclidianStyleConstants.POINT_STYLE_CROSS: // draw cross like: X or + g2.setStroke(crossStrokes[pointSize]); g2.draw(line1); g2.draw(line2); break; case EuclidianStyleConstants.POINT_STYLE_EMPTY_DIAMOND: // draw diamond g2.setStroke(crossStrokes[pointSize]); g2.draw(line1); g2.draw(line2); g2.draw(line3); g2.draw(line4); break; case EuclidianStyleConstants.POINT_STYLE_FILLED_DIAMOND: case EuclidianStyleConstants.POINT_STYLE_TRIANGLE_NORTH: case EuclidianStyleConstants.POINT_STYLE_TRIANGLE_SOUTH: case EuclidianStyleConstants.POINT_STYLE_TRIANGLE_EAST: case EuclidianStyleConstants.POINT_STYLE_TRIANGLE_WEST: // draw diamond g2.setStroke(crossStrokes[pointSize]); g2.draw(gp); g2.fill(gp); break; case EuclidianStyleConstants.POINT_STYLE_CIRCLE: // draw a circle g2.setStroke(crossStrokes[pointSize]); g2.draw(circle); break; // case EuclidianStyleConstants.POINT_STYLE_CIRCLE: default: // draw a dot g2.fill(circle); g2.setStroke(borderStroke); g2.draw(circle); } } public void getPath() { // clear old path if (gp != null) { gp.reset(); } // set point size // pointSize = 4; int diameter = 2 * pointSize; // set coords = center of cell double[] coords = new double[2]; coords[0] = w / 2.0; coords[1] = h / 2.0; // get draw path using routine from euclidian.DrawPoint double xUL = coords[0] - pointSize; double yUL = coords[1] - pointSize; double root3over2 = Math.sqrt(3.0) / 2.0; switch (pointStyle) { default: // do nothing break; case EuclidianStyleConstants.POINT_STYLE_FILLED_DIAMOND: double xR = coords[0] + pointSize; double yB = coords[1] + pointSize; if (gp == null) { gp = new GeneralPath(); } gp.moveTo((float) (xUL + xR) / 2, (float) yUL); gp.lineTo((float) xUL, (float) (yB + yUL) / 2); gp.lineTo((float) (xUL + xR) / 2, (float) yB); gp.lineTo((float) xR, (float) (yB + yUL) / 2); gp.closePath(); if (crossStrokes[pointSize] == null) { crossStrokes[pointSize] = new BasicStroke(pointSize / 2f); } break; case EuclidianStyleConstants.POINT_STYLE_TRIANGLE_SOUTH: case EuclidianStyleConstants.POINT_STYLE_TRIANGLE_NORTH: double direction = 1.0; if (pointStyle == EuclidianStyleConstants.POINT_STYLE_TRIANGLE_NORTH) { direction = -1.0; } if (gp == null) { gp = new GeneralPath(); } gp.moveTo((float) coords[0], (float) (coords[1] + direction * pointSize)); gp.lineTo((float) (coords[0] + pointSize * root3over2), (float) (coords[1] - direction * pointSize / 2)); gp.lineTo((float) (coords[0] - pointSize * root3over2), (float) (coords[1] - direction * pointSize / 2)); gp.lineTo((float) coords[0], (float) (coords[1] + direction * pointSize)); gp.closePath(); if (crossStrokes[pointSize] == null) { crossStrokes[pointSize] = new BasicStroke(pointSize / 2f); } break; case EuclidianStyleConstants.POINT_STYLE_TRIANGLE_EAST: case EuclidianStyleConstants.POINT_STYLE_TRIANGLE_WEST: direction = 1.0; if (pointStyle == EuclidianStyleConstants.POINT_STYLE_TRIANGLE_WEST) { direction = -1.0; } if (gp == null) { gp = new GeneralPath(); } gp.moveTo((float) (coords[0] + direction * pointSize), (float) coords[1]); gp.lineTo((float) (coords[0] - direction * pointSize / 2), (float) (coords[1] + pointSize * root3over2)); gp.lineTo((float) (coords[0] - direction * pointSize / 2), (float) (coords[1] - pointSize * root3over2)); gp.lineTo((float) (coords[0] + direction * pointSize), (float) coords[1]); gp.closePath(); if (crossStrokes[pointSize] == null) { crossStrokes[pointSize] = new BasicStroke(pointSize / 2f); } break; case EuclidianStyleConstants.POINT_STYLE_EMPTY_DIAMOND: xR = coords[0] + pointSize; yB = coords[1] + pointSize; if (line1 == null) { line1 = new Line2D.Double(); line2 = new Line2D.Double(); } if (line3 == null) { line3 = new Line2D.Double(); line4 = new Line2D.Double(); } line1.setLine((xUL + xR) / 2, yUL, xUL, (yB + yUL) / 2); line2.setLine(xUL, (yB + yUL) / 2, (xUL + xR) / 2, yB); line3.setLine((xUL + xR) / 2, yB, xR, (yB + yUL) / 2); line4.setLine(xR, (yB + yUL) / 2, (xUL + xR) / 2, yUL); if (crossStrokes[pointSize] == null) { crossStrokes[pointSize] = new BasicStroke(pointSize / 2f); } break; case EuclidianStyleConstants.POINT_STYLE_PLUS: xR = coords[0] + pointSize; yB = coords[1] + pointSize; if (line1 == null) { line1 = new Line2D.Double(); line2 = new Line2D.Double(); } line1.setLine((xUL + xR) / 2, yUL, (xUL + xR) / 2, yB); line2.setLine(xUL, (yB + yUL) / 2, xR, (yB + yUL) / 2); if (crossStrokes[pointSize] == null) { crossStrokes[pointSize] = new BasicStroke(pointSize / 2f); } break; case EuclidianStyleConstants.POINT_STYLE_CROSS: xR = coords[0] + pointSize; yB = coords[1] + pointSize; if (line1 == null) { line1 = new Line2D.Double(); line2 = new Line2D.Double(); } line1.setLine(xUL, yUL, xR, yB); line2.setLine(xUL, yB, xR, yUL); if (crossStrokes[pointSize] == null) { crossStrokes[pointSize] = new BasicStroke(pointSize / 2f); } break; case EuclidianStyleConstants.POINT_STYLE_CIRCLE: if (crossStrokes[pointSize] == null) { crossStrokes[pointSize] = new BasicStroke(pointSize / 2f); } break; } // for circle points circle.setFrame(xUL, yUL, diameter, diameter); } } public static ImageIcon ensureIconSize(ImageIcon icon, Dimension iconSize) { int h = iconSize.height; int w = iconSize.width; int h2 = icon.getIconHeight(); int w2 = icon.getIconWidth(); if (h2 == h && w2 == w) { return icon; } int wInset = (w - w2) > 0 ? (w - w2) / 2 : 0; int hInset = (h - h2) > 0 ? (h - h2) / 2 : 0; BufferedImage newImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = createGraphics(newImage); try { Image currentImage = icon.getImage(); if (currentImage != null) { g2.drawImage(currentImage, wInset, hInset, null); icon.setImage(newImage); } } catch (Exception e) { e.printStackTrace(); } return icon; } /** * Draws a LaTeX image in the given ImageIcon. Drawing is done twice. First * draw gives the needed size of the image. Second draw renders the image * with the correct dimensions. */ public static final void drawLatexImageIcon(AppD app, ImageIcon latexIcon, String latex, Font font, boolean serif, Color fgColor, Color bgColor) { // Create image with dummy size, then draw into it to get the correct // size GeoText geo = new GeoText(app.getKernel().getConstruction(), latex); geo.setSerifFont(serif); DrawText draw = new DrawText(app.getActiveEuclidianView(), geo); draw.drawMultilineLaTeX( app.getActiveEuclidianView() .getTempGraphics2D(new GFontD(font)), new GFontD(font), GColorD.newColor(fgColor), GColorD.newColor(bgColor)); Rectangle d = GRectangleD.getAWTRectangle(draw.getBounds()); // Now use this size and draw again to get the final image if (d == null || d.width == -1 || d.height == -1) { return; } BufferedImage image = new BufferedImage(d.width, d.height, BufferedImage.TYPE_INT_ARGB); Graphics2D g2image = createGraphics(image); g2image.setBackground(bgColor); g2image.clearRect(0, 0, image.getWidth(), image.getHeight()); draw.drawMultilineLaTeX(new GGraphics2DD(g2image), new GFontD(font), GColorD.newColor(fgColor), GColorD.newColor(bgColor)); latexIcon.setImage(image); } /** * Creates a new ImageIcon by joining them together (leftIcon to rightIcon). */ public static final ImageIcon joinIcons(ImageIcon leftIcon, ImageIcon rightIcon) { int w1 = leftIcon.getIconWidth(); int w2 = rightIcon.getIconWidth(); int h1 = leftIcon.getIconHeight(); int h2 = rightIcon.getIconHeight(); int h = Math.max(h1, h2); int mid = h / 2; BufferedImage image = new BufferedImage(w1 + w2, h, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = (Graphics2D) image.getGraphics(); g2.drawImage(leftIcon.getImage(), 0, mid - h1 / 2, null); g2.drawImage(rightIcon.getImage(), w1, mid - h2 / 2, null); g2.dispose(); ImageIcon ic = new ImageIcon(image); return ic; } }