-// Copyright 2003 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.*;
-
-public class Glyph {
- public char c;
- public int max_ascent; // same value for every glyph in font; the max ascent of all chars
- public int max_descent; // same value for every glyph in font; the max descent of all chars
- public int baseline; // within the picture, this is the y-coordinate of the baseline
- public int advance; // amount to increment the x-coordinate
- public int pointsize;
- public Picture p;
- public Res res;
- public boolean rendered = false;
-
- // k1=font.res k2=(c << 16 | pointsize)
- private static Cache glyphCache = new Cache();
-
- private static Queue glyphsToBeRendered = new Queue(255);
- private static Freetype freetype = new Freetype();
-
- private static Scheduler.Task glyphRenderingTask = new Scheduler.Task() {
- public Object call(Object arg) {
- Glyph g = (Glyph)glyphsToBeRendered.remove(false);
- if (g == null) return null;
- if (g.p != null) return null;
- Log.log(Glyph.class, "rendering glyph " + g.c);
- freetype.renderGlyph(g.res, g);
- g.rendered = true;
- Scheduler.add(this);
- return null;
- }
- };
-
- /**
-
- * If the glyphs of <code>text</code> are not yet loaded, spawn a
- * Task to load them and invoke callback.
- *
-
- * 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.
-
- */
- public static long rasterizeGlyphs(final Res res, final int pointsize, final String text, PixelBuffer pb, int textcolor,
- int x, int y, int cx1, int cy1, int cx2, int cy2, final Callback callback) {
- boolean ret = true;
- int width = 0;
- int height = 0;
- for(int i=0; i<text.length(); i++) {
- final char c = text.charAt(i);
- Glyph g = (Glyph)glyphCache.get(res, new Integer((((int)c) << 16) | pointsize));
- if (g == null) {
- g = new Glyph();
- g.c = c;
- g.pointsize = pointsize;
- g.res = res;
- glyphCache.put(res, new Integer((((int)c) << 16) | pointsize), g);
- glyphsToBeRendered.prepend(g);
- }
- if (g.rendered && ret) {
- if (pb != null && g.p != null)
- pb.drawPictureAlphaOnly(g.p, x, y + g.max_ascent - g.baseline, cx1, cy1, cx2, cy2, textcolor);
- x += g.advance;
- width += g.advance;
- height = java.lang.Math.max(height, g.max_ascent + g.max_descent);
- } else {
- glyphsToBeRendered.prepend(g);
- Scheduler.add(glyphRenderingTask);
- ret = false;
- }
- }
- if (!ret) Scheduler.add(new Scheduler.Task() { public Object call(Object arg) {
- for(int i=0; i<text.length(); i++) {
- Glyph g = (Glyph)glyphCache.get(res, new Integer((((int)text.charAt(i)) << 16) | pointsize));
- if (g == null || !g.rendered) {
- Scheduler.add(this);
- return null;
- }
- }
- callback.call(null);
- return null;
- }});
-
- if (ret) return ((long)width << 16) | (long)height;
- for(int i=32; i<128; i++) {
- Glyph g = (Glyph)glyphCache.get(res, new Integer((i << 16) | pointsize));
- if (g == null) {
- g = new Glyph();
- g.c = (char)i;
- g.pointsize = pointsize;
- g.res = res;
- glyphCache.put(res, new Integer((i << 16) | pointsize), g);
- glyphsToBeRendered.append(g);
- }
- }
- return -1;
- }
-}