X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Forg%2Fxwt%2FFont.java;h=bd11c4f0c0b7c91ee5a4b4a4bb5562785fdff90d;hb=7e9239a7088d4cd772a31a76e1a53e1c681638bc;hp=b1d9230b8a36a0d6ad8af0956483fe6e2ab3356f;hpb=b205a30ca1e66d49676d807969dd73da999c26f0;p=org.ibex.core.git diff --git a/src/org/xwt/Font.java b/src/org/xwt/Font.java index b1d9230..bd11c4f 100644 --- a/src/org/xwt/Font.java +++ b/src/org/xwt/Font.java @@ -1,93 +1,129 @@ -// Copyright 2003 Adam Megacz, see the COPYING file for licensing [GPL] +// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL] package org.xwt; import org.xwt.translators.*; import org.xwt.util.*; import org.xwt.js.*; import java.util.*; +import java.io.*; +/** encapsulates a single font (a set of Glyphs) */ public class Font { - public final int pointsize; - public final Res res; - public int max_ascent; - public int max_descent; - public Glyph[] glyphs = new Glyph[65535]; - boolean used = false; + private Font(Stream res, int pointsize) { this.res = res; this.pointsize = pointsize; } - private Font(Res res, int pointsize) { - this.res = res; - this.pointsize = pointsize; + private static boolean glyphRenderingTaskIsScheduled = false; + + public final int pointsize; ///< the size of the font + public final Stream res; ///< the resource from which this font was loaded + public int max_ascent; ///< the maximum ascent, in pixels + public int max_descent; ///< the maximum descent, in pixels + boolean latinCharsPreloaded = false; ///< true if a request to preload ASCII 32-127 has begun + Glyph[] glyphs = new Glyph[65535]; ///< the glyphs that comprise this font + + public abstract static class Glyph { + protected Glyph(Font font, char c) { this.font = font; this.c = c; } + public final Font font; + public final char c; + public int baseline; ///< within the alphamask, this is the y-coordinate of the baseline + public int advance; ///< amount to increment the x-coordinate + public boolean isLoaded = false; ///< true iff the glyph is loaded + public byte[] alphaChannel = null; + public int width = -1; ///< the width of the glyph + public int height = -1; ///< the height of the glyph + public byte[] data = null; } - private static Cache fontCache = new Cache(); - public static Font getFont(Res res, int pointsize) { + + // Statics ////////////////////////////////////////////////////////////////////// + + private static final Freetype freetype = new Freetype(); + static final Queue glyphsToBeRendered = new Queue(255); + private static Cache fontCache = new Cache(100); + public static Font getFont(Stream res, int pointsize) { Font ret = (Font)fontCache.get(res, new Integer(pointsize)); if (ret == null) fontCache.put(res, new Integer(pointsize), ret = new Font(res, pointsize)); return ret; } + + // Methods ////////////////////////////////////////////////////////////////////// + /** - * If the glyphs of text are not yet loaded, spawn a - * Task to load them and invoke callback. + * Rasterize the glyphs of text. + * + * If all the glyphs of text are not yet loaded, + * spawn a Task to load them and then invoke callback. If all + * the glyphs are loaded, rasterize them to the + * PixelBuffer (if non-null). * - * returns the width (in the high-order int) and height (in the - * low-order int) of the string's rasterization, or -1 if some - * glyphs are not loaded. + * @returns (width<<32)|height if all glyphs are loaded; else -1 */ public long rasterizeGlyphs(final String text, PixelBuffer pb, int textcolor, int x, int y, int cx1, int cy1, int cx2, int cy2, final Scheduler.Task callback) { boolean encounteredUnrenderedGlyph = false; - int width = 0; - int height = 0; + int width = 0, height = 0; for(int i=0; i>> 32) & 0xffffffff); } + public int textheight(String s) { return (int)(textsize(s) & 0xffffffffL); } + public long textsize(String s) { + Long l = (Long)sizeCache.get(s); + if (l != null) return ((Long)l).longValue(); + long ret = rasterizeGlyphs(s, null, 0, 0, 0, 0, 0, 0, 0, null); + if (ret != -1) sizeCache.put(s, new Long(ret)); + return ret == -1 ? 0 : ret; } - private static final Freetype freetype = new Freetype(); - static final Queue glyphsToBeRendered = new Queue(255); static final Scheduler.Task glyphRenderingTask = new Scheduler.Task() { public void perform() { Glyph g = (Glyph)glyphsToBeRendered.remove(false); - if (g == null || g.p != null) return; - Log.log(Glyph.class, "rendering glyph " + g.c); - freetype.renderGlyph(g); - Scheduler.add(this); + if (g == null) { glyphRenderingTaskIsScheduled = false; return; } + if (g.isLoaded) { perform(); /* tailcall to the next glyph */ return; } + //Log.info(Glyph.class, "rendering glyph " + g.c); + try { freetype.renderGlyph(g); } catch (IOException e) { Log.info(Freetype.class, e); } + g.isLoaded = true; + Scheduler.add(this); // keep ourselves in the queue until there are no glyphs to render + glyphRenderingTaskIsScheduled = true; } }; }