From 107e7a2ed25087e8bd6d34239bae075389fc7618 Mon Sep 17 00:00:00 2001 From: benfry Date: Sat, 9 Oct 2004 19:19:59 +0000 Subject: [PATCH] lots of fixes to the font code --- core/PApplet.java | 4 +- core/PFont.java | 179 ++++++++++++++++++++++++++++++-------------- core/PGraphics.java | 31 +++++++- core/PMethods.java | 2 +- core/todo.txt | 5 +- 5 files changed, 158 insertions(+), 63 deletions(-) diff --git a/core/PApplet.java b/core/PApplet.java index c96f2d67f..df6e31bb7 100644 --- a/core/PApplet.java +++ b/core/PApplet.java @@ -4546,8 +4546,8 @@ public class PApplet extends Applet } - public void text(String s, float x, float y, float z, float w, float h) { - g.text(s, x, y, z, w, h); + public void text(String s, float x1, float y1, float z, float x2, float y2) { + g.text(s, x1, y1, z, x2, y2); } diff --git a/core/PFont.java b/core/PFont.java index bae934dea..efba90fbe 100644 --- a/core/PFont.java +++ b/core/PFont.java @@ -35,7 +35,7 @@ import java.util.*; | height is the full used height of the image | | ..XX.. } - | ..XX.. } + | ..XX.. } | ...... } | XXXX.. } topExtent (top y is baseline - topExtent) | ..XX.. } @@ -155,7 +155,7 @@ public class PFont implements PConstants { if (value[i] < 128) ascii[value[i]] = i; // the values for getAscent() and getDescent() from FontMetrics - // seem to be way too large.. perhaps they're the max? + // seem to be way too large.. perhaps they're the max? // as such, use a more traditional marker for ascent/descent if (value[i] == 'd') { if (ascent == 0) ascent = topExtent[i]; @@ -170,7 +170,7 @@ public class PFont implements PConstants { if ((ascent == 0) && (descent == 0)) { throw new RuntimeException("Please use \"Create Font\" to " + "re-create this font."); - } + } images = new PImage[charCount]; for (int i = 0; i < charCount; i++) { @@ -534,8 +534,8 @@ public class PFont implements PConstants { } - private void textLine(int start, int stop, - float x, float y, float z, + private void textLine(int start, int stop, + float x, float y, float z, PGraphics parent) { //float startX = x; //int index = 0; @@ -565,44 +565,111 @@ public class PFont implements PConstants { /** - * Draw text in a box that is constrained to a - * particular size. The current rectMode() determines - * what the coordinates mean (whether x1y1-x2y2 or x/y/w/h). + * Draw text in a box that is constrained to a particular size. + * The current rectMode() determines what the coordinates mean + * (whether x1/y1/x2/y2 or x/y/w/h). * - * Note that the x,y coords of the start of the box - * will align with the *ascent* of the text, - * not the baseline, as is the case for the other - * text() functions. + * Note that the x,y coords of the start of the box + * will align with the *ascent* of the text, not the baseline, + * as is the case for the other text() functions. */ - public void text(String str, float x, float y, float z, - float w, float h, PGraphics parent) { - float space = width(' '); - float xx = x; - float yy = y; - float right = x + w; + public void text(String str, float boxX1, float boxY1, float boxZ, + float boxX2, float boxY2, PGraphics parent) { + float spaceWidth = width(' '); + float runningX = boxX1; + float currentY = boxY1; + float boxWidth = boxX2 - boxX1; + //float right = x + w; - yy += ascent(); + float lineX = boxX1; + if (align == ALIGN_CENTER) { + lineX = lineX + boxWidth/2f; + } else if (align == ALIGN_RIGHT) { + lineX = boxX2; + } - String paragraphs[] = PApplet.split(str, '\n'); - for (int i = 0; i < paragraphs.length; i++) { - String words[] = PApplet.split(paragraphs[i], ' '); - float wide = 0; - for (int j = 0; j < words.length; j++) { - float size = width(words[j]); - if (xx + size > right) { - // this goes on the next line - xx = x; - yy += leading; - //yy += ascent() * 1.2f; - if (yy > y + h) return; // too big for box + // ala illustrator, the text itself must fit inside the box + currentY += ascent(); + // if the box is already too small, tell em to f off + if (currentY > boxY2) return; + + int length = str.length(); + if (length > textBuffer.length) { + textBuffer = new char[length + 10]; + } + str.getChars(0, length, textBuffer, 0); + + int wordStart = 0; + int wordStop = 0; + int lineStart = 0; + int index = 0; + while (index < length) { + if ((textBuffer[index] == ' ') || + (index == length-1)) { + // boundary of a word + float wordWidth = calcWidth(textBuffer, wordStart, index); + if (runningX + wordWidth > boxX2) { + if ((runningX == boxX1) && + (wordWidth > boxWidth)) { + // if this is the first word, and its width is + // greater than the width of the text box, + // then break the word where at the max width, + // and send the rest of the word to the next line. + do { + index--; + if (index == wordStart) { + // not a single char will fit on this line. screw 'em. + return; + } + wordWidth = calcWidth(textBuffer, wordStart, index); + } while (wordWidth > boxWidth); + textLine(lineStart, index, lineX, currentY, boxZ, parent); + + } else { + // next word is too big, output current line + // and advance to the next line + textLine(lineStart, wordStop, lineX, currentY, boxZ, parent); + // only increment index if a word wasn't broken inside the + // do/while loop above.. also, this is a while() loop too, + // because multiple spaces don't count for shit when they're + // at the end of a line like this. + + //index = wordStop + 1; // back that ass up + while ((index < length) && + (textBuffer[index] == ' ')) { + index++; + } + } + lineStart = index; + wordStart = index; + wordStop = index; + runningX = boxX1; + currentY += leading; + if (currentY > boxY2) return; // box is now full + + } else { + runningX += wordWidth + spaceWidth; + // on to the next word + wordStop = index; + wordStart = index + 1; } - text(words[j], xx, yy, z, parent); - xx += size + space; + + } else if (textBuffer[index] == '\n') { + if (lineStart != index) { // if line is not empty + textLine(lineStart, index, lineX, currentY, boxZ, parent); + } + lineStart = index + 1; + wordStart = lineStart; + currentY += leading; + if (currentY > boxY2) return; // box is now full } - // end of paragraph, move to left and increment leading - xx = 0; - yy += leading; - if (yy > h) return; // too big for box + index++; + } + if ((lineStart < length) && + (lineStart != index)) { // if line is not empty + //System.out.println("line not empty " + + // new String(textBuffer, lineStart, index)); + textLine(lineStart, index, lineX, currentY, boxZ, parent); } } @@ -627,15 +694,15 @@ public class PFont implements PConstants { while (index < length) { if (textBuffer[index] == '\n') { - y = startY; - x += leading; + y = startY; + x += leading; previous = 0; } else { ltext(textBuffer[index], x, y, parent); - y -= width(textBuffer[index]); + y -= width(textBuffer[index]); if (previous != 0) - y -= kern(previous, textBuffer[index]); + y -= kern(previous, textBuffer[index]); previous = textBuffer[index]; } index++; @@ -664,7 +731,7 @@ public class PFont implements PConstants { // if the character is off the screen if ((sx >= parent.width) || // top of letter past width (sy - pw >= parent.height) || - (sy + pw < 0) || + (sy + pw < 0) || (sx + ph < 0)) return; if (sx < 0) { // if starting x is off screen @@ -704,16 +771,16 @@ public class PFont implements PConstants { // (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]; + 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 | + pixels2[index] = + (0xff000000 | (((a1 * fr + a2 * ((p2 >> 16) & 0xff)) & 0xff00) << 8) | (( a1 * fg + a2 * ((p2 >> 8) & 0xff)) & 0xff00) | (( a1 * fb + a2 * ( p2 & 0xff)) >> 8)); @@ -745,15 +812,15 @@ public class PFont implements PConstants { while (index < length) { if (textBuffer[index] == '\n') { - y = startY; - x += leading; + y = startY; + x += leading; previous = 0; } else { rtext(textBuffer[index], x, y, parent); - y += width(textBuffer[index]); + y += width(textBuffer[index]); if (previous != 0) - y += kern(previous, textBuffer[index]); + y += kern(previous, textBuffer[index]); previous = textBuffer[index]; } index++; @@ -825,9 +892,9 @@ public class PFont implements PConstants { // (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]; + 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); @@ -836,8 +903,8 @@ public class PFont implements PConstants { int p2 = spixels[index]; // x coord is backwards - spixels[index] = - (0xff000000 | + spixels[index] = + (0xff000000 | (((a1 * fr + a2 * ((p2 >> 16) & 0xff)) & 0xff00) << 8) | (( a1 * fg + a2 * ((p2 >> 8) & 0xff)) & 0xff00) | (( a1 * fb + a2 * ( p2 & 0xff)) >> 8)); diff --git a/core/PGraphics.java b/core/PGraphics.java index 4370042c8..d0afc8aa8 100644 --- a/core/PGraphics.java +++ b/core/PGraphics.java @@ -4280,9 +4280,36 @@ public class PGraphics extends PImage text(s, x, y, 0, w, h); } - public void text(String s, float x, float y, float z, float w, float h) { + public void text(String s, float x1, float y1, float z, float x2, float y2) { if (text_font != null) { - text_font.text(s, x, y, z, w, h, this); + float hradius, vradius; + switch (rect_mode) { + case CORNER: + x2 += x1; y2 += y1; + break; + case CENTER_RADIUS: + hradius = x2; + vradius = y2; + x2 = x1 + hradius; + y2 = y1 + vradius; + x1 -= hradius; + y1 -= vradius; + break; + case CENTER: + hradius = x2 / 2.0f; + vradius = y2 / 2.0f; + x2 = x1 + hradius; + y2 = y1 + vradius; + x1 -= hradius; + y1 -= vradius; + } + if (x2 < x1) { + float temp = x1; x1 = x2; x2 = temp; + } + if (y2 < y1) { + float temp = y1; y1 = y2; y2 = temp; + } + text_font.text(s, x1, y1, z, x2, y2, this); } else { System.err.println("text(): first set a font before drawing text"); diff --git a/core/PMethods.java b/core/PMethods.java index 19230d931..5428bf7b5 100755 --- a/core/PMethods.java +++ b/core/PMethods.java @@ -189,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 x, float y, float z, float w, float h); + public void text(String s, float x1, float y1, float z, float x2, float y2); public void text(int num, float x, float y); diff --git a/core/todo.txt b/core/todo.txt index cd4daceef..e1655eebc 100644 --- a/core/todo.txt +++ b/core/todo.txt @@ -14,13 +14,14 @@ X libraryCalls() not properly working for pre, post, or draw() _ y2 position of rectangles not same as y2 position of lines text fixes -_ make text rect use rectMode for placement +X make text rect use rectMode for placement +X if a word (no spaces) is too long to fit, insert a 'space' + _ need to resolve rotated text in SCREEN_SPACE _ SCREEN_SPACE is weird for text _ does the font or PApplet control the size? (the font, ala java) _ without setting the font, the values come out weird rotated text _ get rotated text into the screen space stuff -_ if a word (no spaces) is too long to fit, insert a 'space' _ move left/center/right aligning into the font class _ otherwise text with alignment has problems with returns _ could PFont2 be done entirely with reflection?