/*
* This file is part of the Haven & Hearth game client.
* Copyright (C) 2009 Fredrik Tolf <fredrik@dolda2000.com>, and
* Björn Johannessen <johannessen.bjorn@gmail.com>
*
* Redistribution and/or modification of this file is subject to the
* terms of the GNU Lesser General Public License, version 3, 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 for more details.
*
* Other parts of this source tree adhere to other copying
* rights. Please see the file `COPYING' in the root directory of the
* source tree for details.
*
* A copy the GNU Lesser General Public License is distributed along
* with the source tree of which this file is a part in the file
* `doc/LPGL-3'. If it is missing for any reason, please see the Free
* Software Foundation's website at <http://www.fsf.org/>, or write
* to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307 USA
*/
package haven;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
public class Text {
public static final Foundry std;
public BufferedImage img;
public final String text;
private Tex tex;
public static final Color black = Color.BLACK;
public static final Color white = Color.WHITE;
static {
std = new Foundry(new Font("SansSerif", Font.PLAIN, 10));
}
public static class Line extends Text {
private FontMetrics m;
private Line(String text) {
super(text);
}
public Coord base() {
return (new Coord(0, m.getAscent()));
}
public int advance(int pos) {
return (m.stringWidth(text.substring(0, pos)));
}
public int charat(int x) {
int l = 0, r = text.length() + 1;
while (true) {
int p = (l + r) / 2;
int a = advance(p);
if ((a < x) && (l < p)) {
l = p;
} else if ((a > x) && (r > p)) {
r = p;
} else {
return (p);
}
}
}
}
public static int[] findspaces(String text) {
java.util.List<Integer> l = new ArrayList<Integer>();
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
if (Character.isWhitespace(c))
l.add(i);
}
int[] ret = new int[l.size()];
for (int i = 0; i < ret.length; i++)
ret[i] = l.get(i);
return (ret);
}
public static class Foundry {
private FontMetrics m;
Font font;
Color defcol;
public boolean aa = false;
private RichText.Foundry wfnd = null;
public Foundry(Font f, Color defcol) {
font = f;
this.defcol = defcol;
BufferedImage junk = TexI.mkbuf(new Coord(10, 10));
Graphics tmpl = junk.getGraphics();
tmpl.setFont(f);
m = tmpl.getFontMetrics();
}
public Foundry(Font f) {
this(f, Color.WHITE);
}
public Foundry(String font, int psz) {
this(new Font(font, Font.PLAIN, psz));
}
public int height() {
/*
* XXX: Should leading go into this, when it's mostly supposed to be
* used for one-liners?
*/
return (m.getAscent() + m.getDescent());
}
private Coord strsize(String text) {
return (new Coord(m.stringWidth(text), height()));
}
public Text renderwrap(String text, Color c, int width) {
if (wfnd == null)
wfnd = new RichText.Foundry(font, defcol);
wfnd.aa = aa;
text = RichText.Parser.quote(text);
if (c != null)
text = String.format("$col[%d,%d,%d,%d]{%s}", c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha(), text);
return (wfnd.render(text, width));
}
public Text renderwrap(String text, int width) {
return (renderwrap(text, null, width));
}
public Line render(String text, Color fg) {
Line t = new Line(text);
Coord sz = strsize(text);
if (sz.x < 1)
sz = sz.add(1, 0);
t.img = TexI.mkbuf(sz);
Graphics g = t.img.createGraphics();
if (aa)
Utils.AA(g);
g.setFont(font);
g.setColor(fg);
t.m = g.getFontMetrics();
g.drawString(text, 0, t.m.getAscent());
g.dispose();
return (t);
}
public Line render(String text, Color fg, Color bg) {
Line t = new Line(text);
Coord sz = strsize(text);
if (sz.x < 1)
sz = sz.add(1, 0);
t.img = TexI.mkbuf(sz);
Graphics g = t.img.createGraphics();
if (aa)
Utils.AA(g);
g.setFont(font);
t.m = g.getFontMetrics();
Rectangle2D rect = t.m.getStringBounds(text, g);
g.setColor(bg);
g.fillRect(0, t.m.getAscent() - (int) rect.getHeight(), (int) rect.getWidth(), (int) rect.getHeight() * 2);
g.setColor(fg);
g.drawString(text, 0, t.m.getAscent());
g.dispose();
return (t);
}
public Line render(String text) {
return (render(text, defcol));
}
public Line renderf(String fmt, Object... args) {
return (render(String.format(fmt, args)));
}
}
protected Text(String text) {
this.text = text;
}
public Coord sz() {
return (Utils.imgsz(img));
}
public static Line render(String text, Color c) {
return (std.render(text, c));
}
public static Line renderf(Color c, String text, Object... args) {
return (std.render(String.format(text, args), c));
}
public static Line render(String text) {
return (render(text, Color.WHITE));
}
public Tex tex() {
if (tex == null)
tex = new TexI(img);
return (tex);
}
public static void main(String[] args) throws Exception {
String cmd = args[0].intern();
if (cmd == "render") {
PosixArgs opt = PosixArgs.getopt(args, 1, "aw:f:s:");
boolean aa = false;
String font = "SansSerif";
int width = 100, size = 10;
for (char c : opt.parsed()) {
if (c == 'a') {
aa = true;
} else if (c == 'f') {
font = opt.arg;
} else if (c == 'w') {
width = Integer.parseInt(opt.arg);
} else if (c == 's') {
size = Integer.parseInt(opt.arg);
}
}
Foundry f = new Foundry(font, size);
f.aa = aa;
Text t = f.renderwrap(opt.rest[0], width);
java.io.OutputStream out = new java.io.FileOutputStream(opt.rest[1]);
javax.imageio.ImageIO.write(t.img, "PNG", out);
out.close();
}
}
}