IconFactory

This forum is used by users to request and discuss new product features. Please do not use this forum for technical support including bug reports.

Moderator: JIDE Support

Forum rules
Product suggestions only. Please do not use this forum for technical support including bug reports.

IconFactory

Postby heartburn » Mon Feb 13, 2006 4:53 pm

Hi.

Maybe this is far fetched, but here goes...

I have a need to create icons from font glyphs, so I was thinking it would be cool if there was a method in the IconFactory class like:

ImageIcon getIcon(Font f, Character c, Color stroke, Color, fill, Color background);

that would of course cache already generated instances.

Thanks!

- mark
heartburn
 
Posts: 5
Joined: Sat Oct 11, 2003 10:20 pm

Postby JIDE Support » Mon Feb 13, 2006 5:07 pm

Do you already have the code to create icon from font glyphs? If so, you can send me the code and I will include it in IconsFactory.

Thanks,
JIDE Software Technical Support Team
JIDE Support
Site Admin
 
Posts: 37219
Joined: Sun Sep 14, 2003 10:49 am

Postby heartburn » Mon Feb 13, 2006 5:12 pm

In progress :)
heartburn
 
Posts: 5
Joined: Sat Oct 11, 2003 10:20 pm

Postby heartburn » Mon Feb 13, 2006 7:54 pm

I wrote this real quick just now. It almost kinda' works. Let me know if you have any problems with it.

Code: Select all
import javax.swing.*;
import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.geom.PathIterator;
import java.awt.geom.GeneralPath;
import java.awt.image.BufferedImage;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.font.LineMetrics;
import java.util.Vector;



public class GlyphDemo extends JFrame {
  private static GlyphDemo _frame;

  public GlyphDemo(String title) throws HeadlessException {
    super(title);
  }

  public static void main(String[] args) {
    _frame = new GlyphDemo("GlyphDemo");
    _frame.setDefaultCloseOperation(EXIT_ON_CLOSE);

    final GlyphPanel glyphPanel = new GlyphPanel();

    glyphPanel.addComponentListener(new ComponentAdapter(){
      public void componentResized(ComponentEvent e) {
          Graphics2D g2 = (Graphics2D)glyphPanel.getGraphics();
          float fontSize = 5.0f;
          Font font = glyphPanel.getFont().deriveFont(fontSize);
          LineMetrics metrics = font.getLineMetrics("O", g2.getFontRenderContext());
          while (metrics.getHeight() < glyphPanel.getHeight() - 2) {
            glyphPanel.setFont(font);
            font = glyphPanel.getFont().deriveFont(fontSize++);
            metrics = font.getLineMetrics("O", g2.getFontRenderContext());
          }
        super.componentResized(e);
      }
    });

    _frame.getContentPane().setLayout(new BorderLayout());
    _frame.getContentPane().add(glyphPanel);

    _frame.pack();
    _frame.setVisible(true);
    _frame.toFront();
  }

  public static class GlyphPanel extends JPanel {
    public void paint(Graphics g) {
      Graphics2D g2 = (Graphics2D)g;
      ImageIcon image = getGlyphAsIcon(getFont(), "O", Color.black, Color.white, Color.BLUE);
      g2.drawImage(image.getImage(), 0, 0, null);
    }

    public ImageIcon getGlyphAsIcon(Font font, String text, Color stroke, Color fill, Color back) {
      Shape[] mask;
      Shape strokedGlyph;
      FontRenderContext frc = new FontRenderContext(null, true, true);
      GlyphVector gv = font.createGlyphVector(frc, text);
      Shape glyph = gv.getOutline();

      int strokeWidth = (int)Math.round(font.getSize()/24.0f);
      if (strokeWidth > 0) {
        Stroke str = new BasicStroke(strokeWidth);
        strokedGlyph = str.createStrokedShape(glyph);
        mask = getMask(strokedGlyph, true);
      }
      else {
        mask = getMask(strokedGlyph = glyph, true);
      }

      Rectangle glyphBounds = glyph.getBounds();
      int width = (glyphBounds.width <= 0) ? 1 : glyphBounds.width;
      int height = (glyphBounds.height <= 0) ? 1 : glyphBounds.height;

      BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
      Graphics2D g = bi.createGraphics();

      g.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,   RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
      g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,         RenderingHints.VALUE_ANTIALIAS_ON);
      g.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,      RenderingHints.VALUE_COLOR_RENDER_QUALITY);
      g.setRenderingHint(RenderingHints.KEY_DITHERING,         RenderingHints.VALUE_DITHER_ENABLE);
      g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,   RenderingHints.VALUE_FRACTIONALMETRICS_ON);
      g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,      RenderingHints.VALUE_INTERPOLATION_BICUBIC);
      g.setRenderingHint(RenderingHints.KEY_RENDERING,         RenderingHints.VALUE_RENDER_QUALITY);
      g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,      RenderingHints.VALUE_STROKE_DEFAULT);
      g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,   RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

      int xoff = glyphBounds.x - strokeWidth;
      int yoff = glyphBounds.y - strokeWidth;

      g.translate(-xoff, -yoff);

      g.setPaint(back);
      for (int i = 0; i < mask.length; i++) {
        g.fill(mask[i]);
      }

      g.setPaint(fill);
      g.fill(glyph);

      g.setStroke(new BasicStroke(font.getSize()/24.0f));
      g.setPaint(stroke);
      g.draw(glyph);


      return new ImageIcon(bi);
    }


    public Shape[] getMask(Shape shape, boolean outline)
    {
      Vector result = new Vector();

      float[] coords = new float[6];
      PathIterator pi = shape.getPathIterator(null);
      GeneralPath current = new GeneralPath(pi.getWindingRule());
      while (!pi.isDone()) {
        int type = pi.currentSegment(coords);
        switch (type) {
        case PathIterator.SEG_CLOSE:
          current.closePath();
          result.add(current);
          current = new GeneralPath(pi.getWindingRule());
          break;
        case PathIterator.SEG_CUBICTO:
          current.curveTo(coords[0],coords[1],coords[2],coords[3],coords[4],coords[5]);
          break;
        case PathIterator.SEG_LINETO:
          current.lineTo(coords[0],coords[1]);
          break;
        case PathIterator.SEG_MOVETO:
          current.moveTo(coords[0],coords[1]);
          break;
        case PathIterator.SEG_QUADTO:
          current.quadTo(coords[0],coords[1],coords[2],coords[3]);
          break;
        }
        pi.next();
      }

      if (current.getCurrentPoint()!=null)
        result.add(current);

      if (outline)
        for (int i=result.size()-1; i>=1; i--) {
          Shape a = (Shape)result.get(i);
          for (int j=0; j<i; j++) {
            Shape b = (Shape)result.get(j);
            if (a.getBounds2D().contains(b.getBounds2D())) {
              result.remove(i);
              break;
            }
          }
        }

      Shape[] shapes = new Shape[result.size()];
      result.toArray(shapes);
      return shapes;
    }
  }


}
Last edited by heartburn on Mon Feb 13, 2006 8:27 pm, edited 1 time in total.
heartburn
 
Posts: 5
Joined: Sat Oct 11, 2003 10:20 pm

Postby heartburn » Mon Feb 13, 2006 8:23 pm

I forgot to set the background translucent and call super.paint(). This version works better.

Code: Select all
import javax.swing.*;
import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.geom.PathIterator;
import java.awt.geom.GeneralPath;
import java.awt.image.BufferedImage;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.font.LineMetrics;
import java.util.Vector;



public class GlyphDemo extends JFrame {
  private static GlyphDemo _frame;

  public GlyphDemo(String title) throws HeadlessException {
    super(title);
  }

  public static void main(String[] args) {
    _frame = new GlyphDemo("GlyphDemo");
    _frame.setDefaultCloseOperation(EXIT_ON_CLOSE);

    final GlyphPanel glyphPanel = new GlyphPanel();
    glyphPanel.setBackground(Color.cyan);


    glyphPanel.addComponentListener(new ComponentAdapter(){
      public void componentResized(ComponentEvent e) {
          Graphics2D g2 = (Graphics2D)glyphPanel.getGraphics();
          float fontSize = 5.0f;
          Font font = glyphPanel.getFont().deriveFont(fontSize);
          LineMetrics metrics = font.getLineMetrics("O", g2.getFontRenderContext());
          while (metrics.getHeight() < glyphPanel.getHeight() - 2) {
            glyphPanel.setFont(font);
            font = glyphPanel.getFont().deriveFont(fontSize++);
            metrics = font.getLineMetrics("O", g2.getFontRenderContext());
          }
        super.componentResized(e);
      }
    });

    _frame.getContentPane().setLayout(new BorderLayout());
    _frame.getContentPane().add(glyphPanel);

    _frame.pack();
    _frame.setVisible(true);
    _frame.toFront();
  }

  public static class GlyphPanel extends JPanel {
    public void paint(Graphics g) {
      super.paint(g);
      Graphics2D g2 = (Graphics2D)g;
      ImageIcon image = getGlyphAsIcon(getFont(), "O", Color.black, Color.white, Color.BLUE);
      g2.drawImage(image.getImage(), 0, 0, null);
    }

    public ImageIcon getGlyphAsIcon(Font font, String text, Color stroke, Color fill, Color back) {
      Shape[] mask;
      Shape strokedGlyph;
      FontRenderContext frc = new FontRenderContext(null, true, true);
      GlyphVector gv = font.createGlyphVector(frc, text);
      Shape glyph = gv.getOutline();

      int strokeWidth = (int)Math.round(font.getSize()/24.0f);
      if (strokeWidth > 0) {
        Stroke str = new BasicStroke(strokeWidth);
        strokedGlyph = str.createStrokedShape(glyph);
        mask = getMask(strokedGlyph, true);
      }
      else {
        mask = getMask(strokedGlyph = glyph, true);
      }

      Rectangle glyphBounds = glyph.getBounds();
      int width = (glyphBounds.width <= 0) ? 1 : glyphBounds.width;
      int height = (glyphBounds.height <= 0) ? 1 : glyphBounds.height;

      BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
      Graphics2D g = bi.createGraphics();

      g.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,   RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
      g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,         RenderingHints.VALUE_ANTIALIAS_ON);
      g.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,      RenderingHints.VALUE_COLOR_RENDER_QUALITY);
      g.setRenderingHint(RenderingHints.KEY_DITHERING,         RenderingHints.VALUE_DITHER_ENABLE);
      g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,   RenderingHints.VALUE_FRACTIONALMETRICS_ON);
      g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,      RenderingHints.VALUE_INTERPOLATION_BICUBIC);
      g.setRenderingHint(RenderingHints.KEY_RENDERING,         RenderingHints.VALUE_RENDER_QUALITY);
      g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,      RenderingHints.VALUE_STROKE_DEFAULT);
      g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,   RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

      int xoff = glyphBounds.x - strokeWidth;
      int yoff = glyphBounds.y - strokeWidth;

      g.translate(-xoff, -yoff);

      g.setColor(new Color(0,0,0,0));
      g.fillRect(xoff, yoff, width, height);

      g.setPaint(back);
      for (int i = 0; i < mask.length; i++) {
        g.fill(mask[i]);
      }

      g.setPaint(fill);
      g.fill(glyph);

      g.setStroke(new BasicStroke(font.getSize()/24.0f));
      g.setPaint(stroke);
      g.draw(glyph);


      return new ImageIcon(bi);
    }


    public Shape[] getMask(Shape shape, boolean outline)
    {
      Vector result = new Vector();

      float[] coords = new float[6];
      PathIterator pi = shape.getPathIterator(null);
      GeneralPath current = new GeneralPath(pi.getWindingRule());
      while (!pi.isDone()) {
        int type = pi.currentSegment(coords);
        switch (type) {
        case PathIterator.SEG_CLOSE:
          current.closePath();
          result.add(current);
          current = new GeneralPath(pi.getWindingRule());
          break;
        case PathIterator.SEG_CUBICTO:
          current.curveTo(coords[0],coords[1],coords[2],coords[3],coords[4],coords[5]);
          break;
        case PathIterator.SEG_LINETO:
          current.lineTo(coords[0],coords[1]);
          break;
        case PathIterator.SEG_MOVETO:
          current.moveTo(coords[0],coords[1]);
          break;
        case PathIterator.SEG_QUADTO:
          current.quadTo(coords[0],coords[1],coords[2],coords[3]);
          break;
        }
        pi.next();
      }

      if (current.getCurrentPoint()!=null)
        result.add(current);

      if (outline)
        for (int i=result.size()-1; i>=1; i--) {
          Shape a = (Shape)result.get(i);
          for (int j=0; j<i; j++) {
            Shape b = (Shape)result.get(j);
            if (a.getBounds2D().contains(b.getBounds2D())) {
              result.remove(i);
              break;
            }
          }
        }

      Shape[] shapes = new Shape[result.size()];
      result.toArray(shapes);
      return shapes;
    }
  }


}
heartburn
 
Posts: 5
Joined: Sat Oct 11, 2003 10:20 pm

Postby JIDE Support » Tue Feb 14, 2006 9:41 am

I noticed it is slightly cut off at bottom and right side. Did you see it too?

Thanks,
JIDE Software Technical Support Team
JIDE Support
Site Admin
 
Posts: 37219
Joined: Sun Sep 14, 2003 10:49 am

Postby heartburn » Tue Feb 14, 2006 9:51 am

Yeah. There's something wrong with my measuring. I wrote it real quick late last night, so it's pretty rough. I'll try to fix it up.
heartburn
 
Posts: 5
Joined: Sat Oct 11, 2003 10:20 pm


Return to Product Suggestions

Who is online

Users browsing this forum: No registered users and 47 guests