/* * * * Copyright 1990-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program 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 program 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 at /legal/license.txt). * * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. */ package buildtimefontgenerator; import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Image; import java.awt.image.BufferedImage; import java.util.Vector; public class Main { private static final String COPYRIGHT = "# Copyright 1990-2009 Sun Microsystems, Inc. All Rights Reserved.\n" + "# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER\n" + "# \n" + "# This program is free software; you can redistribute it and/or\n" + "# modify it under the terms of the GNU General Public License version\n" + "# 2 only, as published by the Free Software Foundation.\n" + "# \n" + "# This program is distributed in the hope that it will be useful, but\n" + "# WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" + "# General Public License version 2 for more details (a copy is\n" + "# included at /legal/license.txt).\n" + "# \n" + "# You should have received a copy of the GNU General Public License\n" + "# version 2 along with this work; if not, write to the Free Software\n" + "# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA\n" + "# 02110-1301 USA\n" + "# \n" + "# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa\n" + "# Clara, CA 95054 or visit www.sun.com if you need additional\n" + "# information or have any questions.\n"; private static final int WHITE_RGB = Color.WHITE.getRGB(); private static final int BLACK_RGB = Color.BLACK.getRGB(); private static boolean failed = false; private static String fontName; private static int fontStyle; private static int fontSize; private static int overrideWidth; private static Vector<Integer> ranges = new Vector<Integer>(2); private static void fail(String string) { System.err.println("Error: " + string); System.exit(1); } /** * @param args the command line arguments */ public static void main(String[] args) { if (args.length == 0) { System.err.println("Arguments are:\n" + "font-name: <font-name> {font-style: italic|bold} font-size: <font-size> {range: <start> <end>} [override-width: <width>]"); return; } for (int i = 0; i < args.length; i++) { String arg = args[i]; if (i == args.length - 1) { fail(""); break; } if (arg.equals("font-name:")) { fontName = args[++i].replace('+', ' '); } else if (arg.equals("font-style:")) { String style = args[++i]; if (style.equals("bold")) fontStyle |= Font.BOLD; else if (style.equals("italic")) fontStyle |= Font.ITALIC; else fail("Invalid value for font-style"); } else if (arg.equals("font-size:")) { try { fontSize = Integer.decode(args[++i]); } catch (NumberFormatException ex) { fail("Invalid value provided for font-size"); } } else if (arg.equals("override-width:")) { try { overrideWidth = Integer.decode(args[++i]); } catch (NumberFormatException ex) { fail("Invalid value provided for font-size"); } } else if (arg.equals("range:")) { try { int start, end; start = Integer.decode(args[++i]); if (i == args.length) { fail("No value provided for range end"); } else { end = Integer.decode(args[++i]); if ((start & 0xff00) != (end & 0xff00)) fail("Chameleon does not support ranges rolling over code page boundary"); if (start > 0xffff || start < 0) fail("Invalid range specified. Note that surrogates are not supported"); if ((start & 0xf800) == 0xd800) fail("Invalid range specified. Note that surrogates are not supported"); ranges.add(start); ranges.add(end); } } catch (NumberFormatException ex) { fail("Invalid value provided for range"); } } else fail("Unrecognized option name " + arg); } if (fontName == null || ranges.size() < 2 || fontSize == 0) { fail("font name, size and range are mandatory arguments"); } generate(); } private static void generate() { Font font = new Font(fontName, fontStyle, fontSize); BufferedImage glyphBitmap = new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_BINARY); FontMetrics fm = glyphBitmap.getGraphics().getFontMetrics(font); int bitmapWidth = overrideWidth == 0 ? fm.getMaxAdvance() : overrideWidth; int bitmapHeight = fm.getHeight(); int baseline = fm.getAscent(); char[] charToRender = new char[1]; glyphBitmap = new BufferedImage(bitmapWidth, bitmapHeight, BufferedImage.TYPE_BYTE_BINARY); Graphics gr = glyphBitmap.getGraphics(); gr.setFont(font); System.out.println(COPYRIGHT); System.out.println("# Font parameters:\n \n# width height ascent descent leading"); System.out.println("@ " + bitmapWidth + ' ' + bitmapHeight + ' ' + fm.getAscent() + ' ' + fm.getDescent() + ' ' + fm.getLeading()); System.out.println("# high_byte first_code_low_byte last_code_low_byte"); for (int i = 0; i < ranges.size(); i += 2) { int start = ranges.get(i); int end = ranges.get(i + 1); System.out.println("% " + Integer.toHexString(start >> 8) + ' ' + Integer.toHexString(start & 0xff) + ' ' + Integer.toHexString(end & 0xff)); for (int ch = (char)start; ch <= end; ch++) { charToRender[0] = (char)ch; gr.setColor(Color.WHITE); gr.fillRect(0, 0, bitmapWidth, bitmapHeight); gr.setColor(Color.BLACK); gr.drawChars(charToRender, 0, 1, 0, baseline); dumpCharGlyph(ch, glyphBitmap); } } } private static void dumpCharGlyph(int ch, BufferedImage glyphBitmap) { int width = glyphBitmap.getWidth(); int height = glyphBitmap.getHeight(); drawHR(width); System.out.println(": " + Integer.toHexString(ch)); drawHR(width); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { char code; int color = glyphBitmap.getRGB(x, y); if (color == WHITE_RGB) code = ' '; else if (color == BLACK_RGB) code = '*'; else code = 'x'; System.out.print(code); } System.out.println("."); } drawHR(width); } private static void drawHR(int width) { System.out.print("#"); for (int i = 0; i < width; i++) { System.out.print('-'); } System.out.println(); } }