fixing and finalizing fonts

This commit is contained in:
benfry
2005-03-01 13:43:46 +00:00
parent 95d4e144c5
commit 17ca7a3326
5 changed files with 256 additions and 302 deletions
+39 -11
View File
@@ -275,6 +275,10 @@ public class PApplet extends Applet
public void depth() {
if (g.textFont != null) {
die("textFont() cannot be used before calling depth()");
}
// OPT if PGraphics already exists, pass in its pixels[]
// buffer so as not to re-allocate all that memory again
if (g.width != 0) {
@@ -1265,8 +1269,7 @@ public class PApplet extends Applet
*/
public void die(String what) {
stop();
throw new RuntimeException("died: " + what);
throw new RuntimeException(what);
/*
if (online) {
System.err.println("i'm dead.. " + what);
@@ -2077,6 +2080,10 @@ public class PApplet extends Applet
public PFont loadFont(String filename) {
//if (g == null) { // just for good measure
//die("loadFont() only be used inside setup() or draw()");
//}
try {
String lower = filename.toLowerCase();
InputStream input = openStream(filename);
@@ -2085,6 +2092,7 @@ public class PApplet extends Applet
input = new GZIPInputStream(input);
} else if (!lower.endsWith(".vlw")) {
// this gets thrown down below
throw new IOException("I don't know how to load a font named " +
filename);
}
@@ -4880,18 +4888,18 @@ v PApplet.this.stop();
}
public void textFont(PFont which) {
if (recorder != null) recorder.textFont(which);
g.textFont(which);
}
public void textFont(PFont which, float size) {
if (recorder != null) recorder.textFont(which, size);
g.textFont(which, size);
}
public void textFont(PFont which) {
if (recorder != null) recorder.textFont(which);
g.textFont(which);
}
public void textSize(float size) {
if (recorder != null) recorder.textSize(size);
g.textSize(size);
@@ -4916,6 +4924,26 @@ v PApplet.this.stop();
}
public float textAscent() {
return g.textAscent();
}
public float textDescent() {
return g.textDescent();
}
public float textWidth(char c) {
return g.textWidth(c);
}
public float textWidth(String s) {
return g.textWidth(s);
}
public void text(char c, float x, float y) {
if (recorder != null) recorder.text(c, x, y);
g.text(c, x, y);
@@ -4946,9 +4974,9 @@ v PApplet.this.stop();
}
public void text(String s, float x1, float y1, float z, float x2, float y2) {
if (recorder != null) recorder.text(s, x1, y1, z, x2, y2);
g.text(s, x1, y1, z, x2, y2);
public void text(String s, float x1, float y1, float x2, float y2, float z) {
if (recorder != null) recorder.text(s, x1, y1, x2, y2, z);
g.text(s, x1, y1, x2, y2, z);
}
+6
View File
@@ -174,6 +174,12 @@ public interface PConstants {
static final int IMAGE_SPACE = 1;
// hrmm, can i avoid these?
//static final int DEFAULT_SIZE = Float.NaN;
//static final int DEFAULT_LEADING = Float.NaN;
// text placement modes
static final int SCREEN_SPACE = 2;
+95 -276
View File
@@ -4,7 +4,7 @@
PFont - font object for text rendering
Part of the Processing project - http://processing.org
Copyright (c) 2004 Ben Fry & Casey Reas
Copyright (c) 2004-05 Ben Fry & Casey Reas
Portions Copyright (c) 2001-04 Massachusetts Institute of Technology
This library is free software; you can redistribute it and/or
@@ -81,18 +81,19 @@ public class PFont implements PConstants {
public int descent;
// scaling, for convenience
public float size;
public float leading;
public int align;
public int space;
//public float size;
//public float leading;
//public int align;
//public int space;
int ascii[]; // quick lookup for the ascii chars
//boolean cached;
// used by the text() functions to avoid over-allocation of memory
private char textBuffer[] = new char[8 * 1024];
private char widthBuffer[] = new char[8 * 1024];
// shared by the text() functions to avoid incessant allocation of memory
protected char textBuffer[] = new char[8 * 1024];
protected char widthBuffer[] = new char[8 * 1024];
//public PGraphics parent;
public PFont() { } // for PFontAI subclass and font builder
@@ -194,9 +195,8 @@ public class PFont implements PConstants {
int valu = temp[y*w + x] & 0xff;
//images[i].pixels[y * twidth + x] = valu;
images[i].pixels[y * twidth + x] =
//valu;
(valu << 24) | 0xFFFFFF; // windows
images[i].pixels[y * twidth + x] = valu;
//(valu << 24) | 0xFFFFFF; // windows
//0xFFFFFF00 | valu; // macosx
//(valu << 24) | (valu << 16) | (valu << 8) | valu;
@@ -210,10 +210,9 @@ public class PFont implements PConstants {
}
///cached = false;
resetSize();
//resetLeading(); // ??
space = OBJECT_SPACE;
align = ALIGN_LEFT;
//resetSize();
//space = OBJECT_SPACE;
//align = ALIGN_LEFT;
}
//static boolean isSpace(int c) {
@@ -282,7 +281,7 @@ public class PFont implements PConstants {
// whups, this used the p5 charset rather than what was inside the font
// meaning that old fonts would crash.. fixed for 0069
private int index_hunt(int c, int start, int stop) {
protected int index_hunt(int c, int start, int stop) {
//System.err.println("checking between " + start + " and " + stop);
int pivot = (start + stop) / 2;
@@ -301,6 +300,7 @@ public class PFont implements PConstants {
}
/*
public void space(int which) {
this.space = which;
if (space == SCREEN_SPACE) {
@@ -313,13 +313,19 @@ public class PFont implements PConstants {
public void align(int which) {
this.align = which;
}
*/
/**
* Currently un-implemented for .vlw fonts,
* but honored for layout in case subclasses use it.
*/
public float kern(char a, char b) {
return 0; // * size, but since zero..
}
/*
public void resetSize() {
//size = 12;
size = mbox; // default size for the font
@@ -341,28 +347,45 @@ public class PFont implements PConstants {
public void leading(float ileading) {
leading = ileading;
}
*/
/**
* Returns the ascent of this font from the baseline.
* The value is based on a font of size 1.
*/
public float ascent() {
return ((float)ascent / fheight) * size;
return ((float)ascent / fheight); // * size;
}
/**
* Returns how far this font descends from the baseline.
* The value is based on a font size of 1.
*/
public float descent() {
return ((float)descent / fheight) * size;
return ((float)descent / fheight); // * size;
}
/**
* Width of this character for a font of size 1.
*/
public float width(char c) {
if (c == 32) return width('i');
int cc = index(c);
if (cc == -1) return 0;
return ((float)setWidth[cc] / fwidth) * size;
//return ((float)setWidth[cc] / fwidth) * size;
return ((float)setWidth[cc] / fwidth); // * size;
}
/**
* Return the width of a line of text of size 1. If the text has
* multiple lines, this returns the length of the longest line.
*/
public float width(String str) {
int length = str.length();
if (length > widthBuffer.length) {
@@ -399,12 +422,31 @@ public class PFont implements PConstants {
}
/**
* Draw a character at an x, y position.
*/
public void text(char c, float x, float y, PGraphics parent) {
text(c, x, y, 0, parent);
}
public void text(char c, float x, float y, float z, PGraphics parent) {
if (parent.textMode == ALIGN_CENTER) {
x -= parent.textSize * width(c) / 2f;
} else if (parent.textMode == ALIGN_RIGHT) {
x -= parent.textSize * width(c);
}
textImpl(c, x, y, z, parent);
}
/**
* Draw a character at an x, y, z position.
*/
//public void text(char c, float x, float y, float z, PGraphics parent) {
protected void textImpl(char c, float x, float y, float z, PGraphics parent) {
//if (!valid) return;
//if (!exists(c)) return;
@@ -422,21 +464,31 @@ public class PFont implements PConstants {
}
*/
if (space == OBJECT_SPACE) {
if (parent.textSpace == OBJECT_SPACE) {
float high = (float) height[glyph] / fheight;
float bwidth = (float) width[glyph] / fwidth;
float lextent = (float) leftExtent[glyph] / fwidth;
float textent = (float) topExtent[glyph] / fheight;
float x1 = x + lextent * size;
float y1 = y - textent * size;
float x2 = x1 + bwidth * size;
float y2 = y1 + high * size;
float x1 = x + lextent * parent.textSize;
float y1 = y - textent * parent.textSize;
float x2 = x1 + bwidth * parent.textSize;
float y2 = y1 + high * parent.textSize;
//parent.rectImpl(x1, y1, x2, y2);
//boolean savedTint = parent.tint;
//int savedTintColor = parent.tintColor;
//parent.tint = true;
//parent.tintColor = parent.fillColor;
parent.imageImpl(images[glyph],
x1, y1, x2-x1, y2-y1,
0, 0, width[glyph], height[glyph]);
//parent.tint = savedTint;
//parent.tintColor = savedTintColor;
/*
// this code was moved here (instead of using parent.image)
// because now images use tint() for their coloring, which
@@ -547,7 +599,7 @@ public class PFont implements PConstants {
if (textBuffer[index] == '\n') {
textLine(start, index, x, y, z, parent);
start = index + 1;
y += leading;
y += parent.textLeading;
}
index++;
}
@@ -564,15 +616,15 @@ public class PFont implements PConstants {
//int index = 0;
//char previous = 0;
if (align == ALIGN_CENTER) {
x -= calcWidth(textBuffer, start, stop) / 2f;
if (parent.textMode == ALIGN_CENTER) {
x -= parent.textSize * calcWidth(textBuffer, start, stop) / 2f;
} else if (align == ALIGN_RIGHT) {
x -= calcWidth(textBuffer, start, stop);
} else if (parent.textMode == ALIGN_RIGHT) {
x -= parent.textSize * calcWidth(textBuffer, start, stop);
}
for (int index = start; index < stop; index++) {
text(textBuffer[index], x, y, z, parent);
textImpl(textBuffer[index], x, y, z, parent);
x += width(textBuffer[index]);
}
}
@@ -605,9 +657,9 @@ public class PFont implements PConstants {
//float right = x + w;
float lineX = boxX1;
if (align == ALIGN_CENTER) {
if (parent.textMode == ALIGN_CENTER) {
lineX = lineX + boxWidth/2f;
} else if (align == ALIGN_RIGHT) {
} else if (parent.textMode == ALIGN_RIGHT) {
lineX = boxX2;
}
@@ -666,7 +718,7 @@ public class PFont implements PConstants {
wordStart = index;
wordStop = index;
runningX = boxX1;
currentY += leading;
currentY += parent.textLeading;
if (currentY > boxY2) return; // box is now full
} else {
@@ -682,7 +734,7 @@ public class PFont implements PConstants {
}
lineStart = index + 1;
wordStart = lineStart;
currentY += leading;
currentY += parent.textLeading;
if (currentY > boxY2) return; // box is now full
}
index++;
@@ -696,248 +748,6 @@ public class PFont implements PConstants {
}
// .................................................................
/**
* Draw SCREEN_SPACE text on its left edge.
* This method is incomplete and should not be used.
*/
public void ltext(String str, float x, float y, PGraphics parent) {
float startY = y;
int index = 0;
char previous = 0;
int length = str.length();
if (length > textBuffer.length) {
textBuffer = new char[length + 10];
}
str.getChars(0, length, textBuffer, 0);
while (index < length) {
if (textBuffer[index] == '\n') {
y = startY;
x += leading;
previous = 0;
} else {
ltext(textBuffer[index], x, y, parent);
y -= width(textBuffer[index]);
if (previous != 0)
y -= kern(previous, textBuffer[index]);
previous = textBuffer[index];
}
index++;
}
}
/**
* Draw SCREEN_SPACE text on its left edge.
* This method is incomplete and should not be used.
*/
public void ltext(char c, float x, float y, PGraphics parent) {
int glyph = index(c);
if (glyph == -1) return;
// top-lefthand corner of the char
int sx = (int) x - topExtent[glyph];
int sy = (int) y - leftExtent[glyph];
// boundary of the character's pixel buffer to copy
int px = 0;
int py = 0;
int pw = width[glyph];
int ph = height[glyph];
// if the character is off the screen
if ((sx >= parent.width) || // top of letter past width
(sy - pw >= parent.height) ||
(sy + pw < 0) ||
(sx + ph < 0)) return;
if (sx < 0) { // if starting x is off screen
py -= sx;
ph += sx;
sx = 0;
}
if (sx + ph >= parent.width) {
ph -= ((sx + ph) - parent.width);
}
if (sy < pw) {
//int extra = pw - sy;
pw -= -1 + pw - sy;
//px -= sy;
//pw += sy;
//sy = 0;
}
if (sy >= parent.height) { // off bottom edge
int extra = 1 + sy - parent.height;
pw -= extra;
px += extra;
sy -= extra;
//pw -= ((sy + pw) - parent.height);
}
int fr = parent.fillRi;
int fg = parent.fillGi;
int fb = parent.fillBi;
int fa = parent.fillAi;
int pixels1[] = images[glyph].pixels;
int pixels2[] = parent.pixels;
// loop over the source pixels in the character image
// row & col is the row and column of the source image
// (but they become col & row in the target image)
for (int row = py; row < py + ph; row++) {
for (int col = px; col < px + pw; col++) {
int a1 = (fa * pixels1[row * twidth + col]) >> 8;
int a2 = a1 ^ 0xff;
int p1 = pixels1[row * width[glyph] + col];
try {
int index = (sy + px-col)*parent.width + (sx+row-py);
int p2 = pixels2[index];
pixels2[index] =
(0xff000000 |
(((a1 * fr + a2 * ((p2 >> 16) & 0xff)) & 0xff00) << 8) |
(( a1 * fg + a2 * ((p2 >> 8) & 0xff)) & 0xff00) |
(( a1 * fb + a2 * ( p2 & 0xff)) >> 8));
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("out of bounds " + sy + " " + px + " " + col);
}
}
}
}
// .................................................................
/**
* Draw SCREEN_SPACE text on its right edge.
* This method is incomplete and should not be used.
*/
public void rtext(String str, float x, float y, PGraphics parent) {
float startY = y;
int index = 0;
char previous = 0;
int length = str.length();
if (length > textBuffer.length) {
textBuffer = new char[length + 10];
}
str.getChars(0, length, textBuffer, 0);
while (index < length) {
if (textBuffer[index] == '\n') {
y = startY;
x += leading;
previous = 0;
} else {
rtext(textBuffer[index], x, y, parent);
y += width(textBuffer[index]);
if (previous != 0)
y += kern(previous, textBuffer[index]);
previous = textBuffer[index];
}
index++;
}
}
/**
* Draw SCREEN_SPACE text on its right edge.
* This method is incomplete and should not be used.
*/
public void rtext(char c, float x, float y, PGraphics parent) {
int glyph = index(c);
if (glyph == -1) return;
// starting point on the screen
int sx = (int) x + topExtent[glyph];
int sy = (int) y + leftExtent[glyph];
// boundary of the character's pixel buffer to copy
int px = 0;
int py = 0;
int pw = width[glyph];
int ph = height[glyph];
// if the character is off the screen
if ((sx - ph >= parent.width) || (sy >= parent.height) ||
(sy + pw < 0) || (sx < 0)) return;
// off the left of screen, cut off bottom of letter
if (sx < ph) {
//x0 -= xx; // chop that amount off of the image area to be copied
//w0 += xx; // and reduce the width by that (negative) amount
//py0 -= xx; // if x = -3, cut off 3 pixels from the bottom
//ph0 += xx;
ph -= (ph - sx) - 1;
//sx = 0;
}
// off the right of the screen, cut off top of the letter
if (sx >= parent.width) {
int extra = sx - (parent.width-1);
py += extra;
ph -= extra;
//sx = parent.width-1;
}
// off the top, cut off left edge of letter
if (sy < 0) {
int extra = -sy;
px += extra;
pw -= extra;
sy = 0;
}
// off the bottom, cut off right edge of letter
if (sy + pw >= parent.height-1) {
int extra = (sy + pw) - parent.height;
pw -= extra;
}
int fr = parent.fillRi;
int fg = parent.fillGi;
int fb = parent.fillBi;
int fa = parent.fillAi;
int fpixels[] = images[glyph].pixels;
int spixels[] = parent.pixels;
// loop over the source pixels in the character image
// row & col is the row and column of the source image
// (but they become col & row in the target image)
for (int row = py; row < py + ph; row++) {
for (int col = px; col < px + pw; col++) {
int a1 = (fa * fpixels[row * twidth + col]) >> 8;
int a2 = a1 ^ 0xff;
int p1 = fpixels[row * width[glyph] + col];
try {
//int index = (yy + x0-col)*parent.width + (xx+row-y0);
//int index = (sy + px-col)*parent.width + (sx+row-py);
int index = (sy + px+col)*parent.width + (sx-row);
int p2 = spixels[index];
// x coord is backwards
spixels[index] =
(0xff000000 |
(((a1 * fr + a2 * ((p2 >> 16) & 0xff)) & 0xff00) << 8) |
(( a1 * fg + a2 * ((p2 >> 8) & 0xff)) & 0xff00) |
(( a1 * fb + a2 * ( p2 & 0xff)) >> 8));
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("out of bounds " + sy + " " + px + " " + col);
}
}
}
}
// ....................................................................
@@ -1006,6 +816,15 @@ public class PFont implements PConstants {
this(new Font(name, Font.PLAIN, size), false, smooth);
}
/**
* Use reflection to create a new .vlw font on the fly.
* This only works with Java 1.3 and higher.
*
* @param Font the font object to create from
* @param all true to include all available characters in the font
* @param smooth true to enable smoothing/anti-aliasing
*/
public PFont(Font font, boolean all, boolean smooth) {
try {
this.charCount = all ? 65536 : charset.length;
+107 -14
View File
@@ -385,6 +385,10 @@ public class PGraphics extends PImage implements PConstants {
// no current font
textFont = null;
textSize = 12;
textLeading = 14;
textMode = ALIGN_LEFT;
textSpace = OBJECT_SPACE;
//text_mode = ALIGN_LEFT;
//text_space = OBJECT_SPACE;
}
@@ -1411,11 +1415,17 @@ public class PGraphics extends PImage implements PConstants {
// TEXT/FONTS
public void textFont(PFont which, float size) {
textFont(which);
textSize(size);
}
public void textFont(PFont which) {
if (which != null) {
textFont = which;
textFont.resetSize();
textFont.resetLeading();
//textFont.resetSize();
//textFont.resetLeading();
} else {
throw new RuntimeException("a null PFont was passed to textFont()");
@@ -1423,16 +1433,10 @@ public class PGraphics extends PImage implements PConstants {
}
public void textFont(PFont which, float size) {
textFont(which);
textSize(size);
}
public void textSize(float size) {
if (textFont != null) {
//textFont.size(size);
textSize = size;
resetLeading();
} else {
throw new RuntimeException("use textFont() before textSize()");
@@ -1440,33 +1444,91 @@ public class PGraphics extends PImage implements PConstants {
}
protected void resetLeading() {
textLeading = (textFont.ascent() + textFont.descent()) * 1.275f;
}
public void textLeading(float leading) {
textLeading = leading;
/*
if (textFont != null) {
textFont.leading(leading);
} else {
throw new RuntimeException("use textFont() before textLeading()");
}
*/
}
public void textMode(int mode) {
textMode = mode;
/*
if (textFont != null) {
textFont.align(mode);
} else {
throw new RuntimeException("use textFont() before textMode()");
}
*/
}
public void textSpace(int space) {
textSpace = space;
/*
if (textFont != null) {
textFont.space(space);
} else {
throw new RuntimeException("use textFont() before textSpace()");
}
*/
}
public float textAscent() {
if (textFont != null) {
return textFont.ascent() * textSize;
} else {
throw new RuntimeException("use textFont() before textAscent()");
}
}
public float textDescent() {
if (textFont != null) {
return textFont.descent() * textSize;
} else {
throw new RuntimeException("use textFont() before textDescent()");
}
}
public float textWidth(char c) {
if (textFont != null) {
return textFont.width(c) * textSize;
} else {
throw new RuntimeException("use textFont() before textWidth()");
}
}
/**
* Return the width of a line of text. If the text has multiple
* lines, this returns the length of the longest line.
*/
public float textWidth(String s) {
if (textFont != null) {
return textFont.width(s) * textSize;
} else {
throw new RuntimeException("use textFont() before textWidth()");
}
}
@@ -1481,7 +1543,21 @@ public class PGraphics extends PImage implements PConstants {
public void text(char c, float x, float y, float z) {
// not supported in 2D
if ((z != 0) && (textSpace == SCREEN_SPACE)) {
String msg = "textSpace(SCREEN_SPACE) cannot have a z coordinate";
throw new RuntimeException(msg);
}
// this just has to pass through.. if z is not zero when
// drawing to non-depth(), the PFont will have to throw an error.
if (textFont != null) {
textFont.text(c, x, y, z, this);
} else {
throw new RuntimeException("use textFont() before text()");
}
//throw new RuntimeException("text() with a z coordinate is " +
// "only supported when depth() is used");
}
@@ -1496,7 +1572,21 @@ public class PGraphics extends PImage implements PConstants {
public void text(String s, float x, float y, float z) {
// not supported in 2D
if ((z != 0) && (textSpace == SCREEN_SPACE)) {
String msg = "textSpace(SCREEN_SPACE) cannot have a z coordinate";
throw new RuntimeException(msg);
}
// this just has to pass through.. if z is not zero when
// drawing to non-depth(), the PFont will have to throw an error.
if (textFont != null) {
textFont.text(s, x, y, z, this);
} else {
throw new RuntimeException("use textFont() before text()");
}
//throw new RuntimeException("text() with a z coordinate is " +
// "only supported when depth() is used");
}
@@ -1537,8 +1627,9 @@ public class PGraphics extends PImage implements PConstants {
}
public void text(String s, float x1, float y1, float z, float x2, float y2) {
// not supported in 2D
public void text(String s, float x1, float y1, float x2, float y2, float z) {
throw new RuntimeException("text() with a z coordinate is " +
"only supported when depth() is used");
}
@@ -1548,7 +1639,9 @@ public class PGraphics extends PImage implements PConstants {
public void text(int num, float x, float y, float z) {
// not supported in 2D
text(String.valueOf(num), x, y, z);
//throw new RuntimeException("text() with a z coordinate is " +
// "only supported when depth() is used");
}
+9 -1
View File
@@ -171,6 +171,14 @@ public interface PMethods {
public void textSpace(int space);
public float textAscent();
public float textDescent();
public float textWidth(char c);
public float textWidth(String s);
public void text(char c, float x, float y);
public void text(char c, float x, float y, float z);
@@ -181,7 +189,7 @@ public interface PMethods {
public void text(String s, float x, float y, float w, float h);
public void text(String s, float x1, float y1, float z, float x2, float y2);
public void text(String s, float x1, float y1, float x2, float y2, float z);
public void text(int num, float x, float y);