X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Forg%2Fxwt%2FFont.java;h=ae9a7d36ce528da1281d3c5d17d78963726793ee;hb=de378041d5ca2aca1a2b5a31ef15ae90a86c977f;hp=2eef1f1abd4d66b92c369534eed1ec033755678c;hpb=9d07963a45f2147a62d8897e9c4245c224d98ccb;p=org.ibex.core.git diff --git a/src/org/xwt/Font.java b/src/org/xwt/Font.java index 2eef1f1..ae9a7d3 100644 --- a/src/org/xwt/Font.java +++ b/src/org/xwt/Font.java @@ -1,4 +1,4 @@ -// 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.*; @@ -6,36 +6,42 @@ import org.xwt.js.*; import java.util.*; import java.io.*; +// FEATURE: this could be cleaner +/** encapsulates a single font (a set of Glyphs) */ public class Font { - private Font(Res res, int pointsize) { this.res = res; this.pointsize = pointsize; } + private Font(Stream stream, int pointsize) { this.stream = stream; this.pointsize = pointsize; } - public final int pointsize; - public final Res res; - public int max_ascent; - public int max_descent; + private static boolean glyphRenderingTaskIsScheduled = false; + + public final int pointsize; ///< the size of the font + public final Stream stream; ///< the stream 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]; - - public static class Glyph { - public Glyph(char c, Font f) { this.c = c; font = f; } - public char c; - public int baseline; // within the picture, this is the y-coordinate of the baseline - public int advance; // amount to increment the x-coordinate - public Picture p; + 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 int width = -1; ///< the width of the glyph + public int height = -1; ///< the height of the glyph + public byte[] data = null; ///< the alpha channel samples for this font } // Statics ////////////////////////////////////////////////////////////////////// private static final Freetype freetype = new Freetype(); - private static Cache sizeCache = new Cache(100); static final Queue glyphsToBeRendered = new Queue(255); private static Cache fontCache = new Cache(100); - public static Font getFont(Res 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)); + public static Font getFont(Stream stream, int pointsize) { + Font ret = (Font)fontCache.get(stream, new Integer(pointsize)); + if (ret == null) fontCache.put(stream, new Integer(pointsize), ret = new Font(stream, pointsize)); return ret; } @@ -43,49 +49,68 @@ public class Font { // 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>> 16L); } + // FEATURE do we really need to be caching sizes? + private static Cache sizeCache = new Cache(1000); + public int textwidth(String s) { return (int)((textsize(s) >>> 32) & 0xffffffff); } public int textheight(String s) { return (int)(textsize(s) & 0xffffffffL); } public long textsize(String s) { Long l = (Long)sizeCache.get(s); @@ -97,10 +122,12 @@ public class Font { static final Scheduler.Task glyphRenderingTask = new Scheduler.Task() { public void perform() { Glyph g = (Glyph)glyphsToBeRendered.remove(false); - if (g == null) return; - if (g.p != null) { perform(); return; } - Log.log(Glyph.class, "rendering glyph " + g.c); - try { freetype.renderGlyph(g); } catch (IOException e) { Log.log(Freetype.class, e); } - Scheduler.add(this); + if (g == null) { glyphRenderingTaskIsScheduled = false; return; } + Log.debug(Font.class, "glyphRenderingTask dequeued glyph " + g.c + " of font " + g.font); + if (g.isLoaded) { perform(); /* tailcall to the next glyph */ return; } + Log.debug(Glyph.class, "rendering glyph " + g.c); + try { freetype.renderGlyph(g); } catch (IOException e) { Log.info(Freetype.class, e); } + Scheduler.add(this); // keep ourselves in the queue until there are no glyphs to render + glyphRenderingTaskIsScheduled = true; } }; }