/******************************************************************************* * Copyright 2011 See AUTHORS file. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package com.badlogic.gdx.tools.bmfont; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.graphics.PixmapIO; import com.badlogic.gdx.graphics.g2d.BitmapFont.BitmapFontData; import com.badlogic.gdx.graphics.g2d.BitmapFont.Glyph; import com.badlogic.gdx.graphics.g2d.PixmapPacker.Page; import com.badlogic.gdx.tools.hiero.Hiero; import com.badlogic.gdx.utils.Array; /** A utility to output BitmapFontData to a FNT file. This can be useful for caching the result from TrueTypeFont, for faster load * times. *
* The font file format is from the AngelCodeFont BMFont tool. *
* Output is nearly identical to the FreeType settting in the {@link Hiero} tool. BitmapFontWriter gives more flexibility, eg
* borders and shadows can be used. Hiero is able to avoid outputting the same glyph image more than once if multiple character
* codes have the exact same glyph.
* @author mattdesl AKA davedes */
public class BitmapFontWriter {
/** The output format. */
public static enum OutputFormat {
/** AngelCodeFont text format */
Text,
/** AngelCodeFont XML format */
XML;
}
/** The output format */
private static OutputFormat format = OutputFormat.Text;
/** Sets the AngelCodeFont output format for subsequent writes; can be text (for LibGDX) or XML (for other engines, like
* Pixi.js).
*
* @param fmt the output format to use */
public static void setOutputFormat (OutputFormat fmt) {
if (fmt == null) throw new NullPointerException("format cannot be null");
format = fmt;
}
/** Returns the currently used output format.
* @return the output format */
public static OutputFormat getOutputFormat () {
return format;
}
/** The Padding parameter for FontInfo. */
public static class Padding {
public int up, down, left, right;
public Padding () {
}
public Padding (int up, int down, int left, int right) {
this.up = up;
this.down = down;
this.left = left;
this.right = right;
}
}
/** The spacing parameter for FontInfo. */
public static class Spacing {
public int horizontal, vertical;
}
/** The font "info" line; everything except padding is ignored by LibGDX's BitmapFont reader, it is otherwise just useful for
* clean and organized output. */
public static class FontInfo {
/** Face name */
public String face;
/** Font size (pt) */
public int size = 12;
/** Whether the font is bold */
public boolean bold;
/** Whether the font is italic */
public boolean italic;
/** The charset; or null/empty for default */
public String charset;
/** Whether the font uses unicode glyphs */
public boolean unicode = true;
/** Stretch for height; default to 100% */
public int stretchH = 100;
/** Whether smoothing is applied */
public boolean smooth = true;
/** Amount of anti-aliasing that was applied to the font */
public int aa = 2;
/** Padding that was applied to the font */
public Padding padding = new Padding();
/** Horizontal/vertical spacing that was applied to font */
public Spacing spacing = new Spacing();
public int outline = 0;
public FontInfo () {
}
public FontInfo (String face, int size) {
this.face = face;
this.size = size;
}
}
private static String quote (Object params) {
return quote(params, false);
}
private static String quote (Object params, boolean spaceAfter) {
if (BitmapFontWriter.getOutputFormat() == OutputFormat.XML)
return "\"" + params.toString().trim() + "\"" + (spaceAfter ? " " : "");
else
return params.toString();
}
/** Writes the given BitmapFontData to a file, using the specified pageRefs strings as the image paths for each
* texture page. The glyphs in BitmapFontData have a "page" id, which references the index of the pageRef you specify here.
*
* The FontInfo parameter is useful for cleaner output; such as including a size and font face name hint. However, it can be
* null to use default values. LibGDX ignores most of the "info" line when reading back fonts, only padding is used. Padding
* also affects the size, location, and offset of the glyphs that are output.
*
* Likewise, the scaleW and scaleH are only for cleaner output. They are currently ignored by LibGDX's reader. For maximum
* compatibility with other BMFont tools, you should use the width and height of your texture pages (each page should be the
* same size).
*
* @param fontData the bitmap font
* @param pageRefs the references to each texture page image file, generally in the same folder as outFntFile
* @param outFntFile the font file to save to (typically ends with '.fnt')
* @param info the optional info for the file header; can be null
* @param scaleW the width of your texture pages
* @param scaleH the height of your texture pages */
public static void writeFont (BitmapFontData fontData, String[] pageRefs, FileHandle outFntFile, FontInfo info, int scaleW,
int scaleH) {
if (info == null) {
info = new FontInfo();
info.face = outFntFile.nameWithoutExtension();
}
int lineHeight = (int)fontData.lineHeight;
int pages = pageRefs.length;
int packed = 0;
int base = (int)((fontData.capHeight) + (fontData.flipped ? -fontData.ascent : fontData.ascent));
OutputFormat fmt = BitmapFontWriter.getOutputFormat();
boolean xml = fmt == OutputFormat.XML;
StringBuilder buf = new StringBuilder();
if (xml) {
buf.append("\n");
}
String xmlOpen = xml ? "\t<" : "";
String xmlCloseSelf = xml ? "/>" : "";
String xmlTab = xml ? "\t" : "";
String xmlClose = xml ? ">" : "";
String xmlQuote = xml ? "\"" : "";
String alphaChnlParams = xml ? " alphaChnl=\"0\" redChnl=\"0\" greenChnl=\"0\" blueChnl=\"0\""
: " alphaChnl=0 redChnl=0 greenChnl=0 blueChnl=0";
// INFO LINE
buf.append(xmlOpen).append("info face=\"").append(info.face == null ? "" : info.face.replaceAll("\"", "'"))
.append("\" size=").append(quote(info.size)).append(" bold=").append(quote(info.bold ? 1 : 0)).append(" italic=")
.append(quote(info.italic ? 1 : 0)).append(" charset=\"").append(info.charset == null ? "" : info.charset)
.append("\" unicode=").append(quote(info.unicode ? 1 : 0)).append(" stretchH=").append(quote(info.stretchH))
.append(" smooth=").append(quote(info.smooth ? 1 : 0)).append(" aa=").append(quote(info.aa)).append(" padding=")
.append(xmlQuote).append(info.padding.up).append(",").append(info.padding.down).append(",").append(info.padding.left)
.append(",").append(info.padding.right).append(xmlQuote).append(" spacing=").append(xmlQuote)
.append(info.spacing.horizontal).append(",").append(info.spacing.vertical).append(xmlQuote).append(xmlCloseSelf)
.append("\n");
// COMMON line
buf.append(xmlOpen).append("common lineHeight=").append(quote(lineHeight)).append(" base=").append(quote(base))
.append(" scaleW=").append(quote(scaleW)).append(" scaleH=").append(quote(scaleH)).append(" pages=").append(quote(pages))
.append(" packed=").append(quote(packed)).append(alphaChnlParams).append(xmlCloseSelf).append("\n");
if (xml) buf.append("\t
* BitmapFontWriter.writeFont(myFontData, myFontPixmaps, Gdx.files.external("fonts/output.fnt"), new FontInfo("Arial", 16)); ** * @param fontData the font data * @param pages the pixmaps to write as PNGs * @param outFntFile the output file for the font definition * @param info the optional font info for the header file, can be null */ public static void writeFont (BitmapFontData fontData, Pixmap[] pages, FileHandle outFntFile, FontInfo info) { String[] pageRefs = writePixmaps(pages, outFntFile.parent(), outFntFile.nameWithoutExtension()); // write the font data writeFont(fontData, pageRefs, outFntFile, info, pages[0].getWidth(), pages[0].getHeight()); } /** A utility method to write the given array of pixmaps to the given output directory, with the specified file name. If the * pages array is of length 1, then the resulting file ref will look like: "fileName.png". * * If the pages array is greater than length 1, the resulting file refs will be appended with "_N", such as "fileName_0.png", * "fileName_1.png", "fileName_2.png" etc. * * The returned string array can then be passed to the writeFont method. * * Note: None of the pixmaps will be disposed. * * @param pages the pages of pixmap data to write * @param outputDir the output directory * @param fileName the file names for the output images * @return the array of string references to be used with writeFont */ public static String[] writePixmaps (Pixmap[] pages, FileHandle outputDir, String fileName) { if (pages == null || pages.length == 0) throw new IllegalArgumentException("no pixmaps supplied to BitmapFontWriter.write"); String[] pageRefs = new String[pages.length]; for (int i = 0; i < pages.length; i++) { String ref = pages.length == 1 ? (fileName + ".png") : (fileName + "_" + i + ".png"); // the ref for this image pageRefs[i] = ref; // write the PNG in that directory PixmapIO.writePNG(outputDir.child(ref), pages[i]); } return pageRefs; } /** A convenience method to write pixmaps by page; typically returned from a PixmapPacker when used alongside * FreeTypeFontGenerator. * * @param pages the pages containing the Pixmaps * @param outputDir the output directory * @param fileName the file name * @return the file refs */ public static String[] writePixmaps (Array