summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenneth Russel <[email protected]>2007-11-03 01:00:36 +0000
committerKenneth Russel <[email protected]>2007-11-03 01:00:36 +0000
commit12461ad95b421694706e39ff15eba3bf15e9790b (patch)
treef007e03aecce0985a159f0fda336bf597d240f3e
parentf58b77c498cd00273fdc4b9fb26a0df55c804476 (diff)
Fixes from John Burkey:
1) Add segmenting for runs of glyphs that are going to blow the cache (we track upload size) a) upload handling b) glyph run segmenting 2) Fix incorrect assumption that the glyph cached didn't change size. git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/svn-server-sync/jogl/trunk@1423 232f8b59-042b-4e1e-8c03-345bb8c30851
-rwxr-xr-xsrc/classes/com/sun/opengl/util/j2d/TextRenderer.java170
1 files changed, 117 insertions, 53 deletions
diff --git a/src/classes/com/sun/opengl/util/j2d/TextRenderer.java b/src/classes/com/sun/opengl/util/j2d/TextRenderer.java
index 312c99c13..78b193fb7 100755
--- a/src/classes/com/sun/opengl/util/j2d/TextRenderer.java
+++ b/src/classes/com/sun/opengl/util/j2d/TextRenderer.java
@@ -816,17 +816,21 @@ public class TextRenderer {
}
}
- //----------------------------------------------------------------------
- // Glyph-by-glyph rendering support
- //
private void internal_draw3D(CharSequence str, float x, float y, float z,
float scaleFactor) {
- GlyphsList glyphs = mGlyphProducer.getGlyphs(str);
-
- if (glyphs != null) {
- drawGlyphs(glyphs, x, y, z, scaleFactor);
- } else {
- this.draw3D_ROBUST(str, x, y, z, scaleFactor);
+ int drawingState = DrawingState.fast;
+
+ while (drawingState != DrawingState.finished) {
+ GlyphsList glyphs = mGlyphProducer.getGlyphs(str);
+
+ if (drawingState == DrawingState.fast) {
+ x += drawGlyphs(glyphs, x, y, z, scaleFactor);
+ str = glyphs.remaining;
+ drawingState = glyphs.nextState;
+ } else if (drawingState == DrawingState.robust) {
+ this.draw3D_ROBUST(str, x, y, z, scaleFactor);
+ drawingState = DrawingState.finished;
+ }
}
}
@@ -836,19 +840,19 @@ public class TextRenderer {
}
}
- private void drawGlyphs(GlyphsList inGlyphs, float inX, float inY, float z,
- float scaleFactor) {
+ private float drawGlyphs(GlyphsList inGlyphs, float inX, float inY,
+ float z, float scaleFactor) {
+ float xOffset = 0;
+
try {
if (mPipelinedQuadRenderer == null) {
mPipelinedQuadRenderer = new Pipelined_QuadRenderer();
}
TextureRenderer renderer = getBackingStore();
- float xOffset = 0;
for (int i = 0; i < inGlyphs.length; i++) {
Rect rect = inGlyphs.textureSourceRect[i];
-
TextData data = (TextData) rect.getUserData();
data.markUsed();
@@ -860,11 +864,12 @@ public class TextRenderer {
int width = rect.w();
int height = rect.h();
- float tx1 = (float) texturex / (float) kSize;
- float ty1 = 1.0f - ((float) texturey / (float) kSize);
- float tx2 = (float) (texturex + width) / (float) kSize;
+ float tx1 = (float) texturex / (float) renderer.getWidth();
+ float ty1 = 1.0f -
+ ((float) texturey / (float) renderer.getHeight());
+ float tx2 = (float) (texturex + width) / (float) renderer.getWidth();
float ty2 = 1.0f -
- ((float) (texturey + height) / (float) kSize);
+ ((float) (texturey + height) / (float) renderer.getHeight());
mPipelinedQuadRenderer.glTexCoord2f(tx1, ty1);
mPipelinedQuadRenderer.glVertex3f(x, y, z);
@@ -883,15 +888,16 @@ public class TextRenderer {
} catch (Exception e) {
e.printStackTrace();
}
- }
- private void drawGlyphsSIMPLE(GlyphsList inGlyphs, float x, float y,
- float z, float scaleFactor) { // unused, for reference, debugging
+ return xOffset;
+ }
+ private float drawGlyphsSIMPLE(GlyphsList inGlyphs, float x, float y,
+ float z, float scaleFactor) // unused, for reference, debugging
+ {
TextureRenderer renderer = getBackingStore();
- int xOffset = 0;
- GL gl = GLU.getCurrentGL();
+ int xOffset = 0;
for (int i = 0; i < inGlyphs.length; i++) {
Rect rect = inGlyphs.textureSourceRect[i];
@@ -910,6 +916,8 @@ public class TextRenderer {
0.5f); // note the advances.. I had to use this to get proper kerning.
}
}
+
+ return xOffset;
}
private void draw3D_ROBUST(CharSequence str, float x, float y, float z,
@@ -929,8 +937,7 @@ public class TextRenderer {
if (rect == null) {
// Rasterize this string and place it on the backing store
Graphics2D g = getGraphics2D();
- Rectangle2D bbox = normalize(renderDelegate.getBounds(
- curStr, font, getFontRenderContext()));
+ Rectangle2D bbox = normalize(renderDelegate.getBounds(curStr, font, getFontRenderContext()));
Point origin = new Point((int) -bbox.getMinX(),
(int) -bbox.getMinY());
rect = new Rect(0, 0, (int) bbox.getWidth(),
@@ -1254,6 +1261,7 @@ public class TextRenderer {
// Heavy hammer -- might consider doing something different
packer.clear();
stringLocations.clear();
+ mGlyphProducer.clearAllCacheEntries();
if (DEBUG) {
System.err.println(
@@ -1264,6 +1272,9 @@ public class TextRenderer {
public void beginMovement(Object oldBackingStore, Object newBackingStore) {
// Exit the begin / end pair if necessary
if (inBeginEndPair) {
+ // Draw any outstanding glyphs
+ flush();
+
GL gl = GLU.getCurrentGL();
// Pop client attrib bits used by the pipelined quad renderer
@@ -1373,6 +1384,15 @@ public class TextRenderer {
}
}
+ //----------------------------------------------------------------------
+ // Glyph-by-glyph rendering support
+ //
+ private static class DrawingState {
+ public static final int fast = 1;
+ public static final int robust = 2;
+ public static final int finished = 3;
+ }
+
class GlyphsUploadList {
int numberOfNewGlyphs;
GlyphVector[] glyphVector;
@@ -1437,6 +1457,8 @@ public class TextRenderer {
outList.textureSourceRect[this.renderIndex[i]] = mapper.glyphRectForTextureMapping[this.newGlyphs[i]];
}
}
+
+ this.numberOfNewGlyphs = 0;
}
public void allocateSpace(int inLength) {
@@ -1453,7 +1475,10 @@ public class TextRenderer {
}
static class GlyphsList {
+ int /* DrawingState */ nextState;
+ CharSequence remaining;
float[] advances;
+ float totalAdvance;
Rect[] textureSourceRect;
int length;
@@ -1489,10 +1514,7 @@ public class TextRenderer {
glyphRectForTextureMapping = new Rect[fontLengthInGlyphs];
unicodes2Glyphs = new int[512];
singleUnicode = new char[1];
-
- for (int i = 0; i < unicodes2Glyphs.length; i++) {
- unicodes2Glyphs[i] = undefined;
- }
+ clearAllCacheEntries();
}
}
@@ -1500,6 +1522,12 @@ public class TextRenderer {
unicodes2Glyphs[unicodeID] = undefined;
}
+ public void clearAllCacheEntries() {
+ for (int i = 0; i < unicodes2Glyphs.length; i++) {
+ unicodes2Glyphs[i] = undefined;
+ }
+ }
+
public void allocateSpace(int length) {
length = Math.max(length, 100);
@@ -1514,27 +1542,40 @@ public class TextRenderer {
float getGlyphPixelWidth(char unicodeID) {
int glyphID = undefined;
- if (unicodeID < unicodes2Glyphs.length) { // <--- could support the rare high unicode better later
- glyphID = unicodes2Glyphs[unicodeID]; // Check to see if we have already encountered this unicode
- }
-
- if (glyphID != undefined) { // if we haven't, we must get some its attributes, and prep for upload
+ if (unicodeID < unicodes2Glyphs.length) // <--- could support the rare high unicode better later
+ {
+ glyphID = unicodes2Glyphs[unicodeID]; // Check to see if we have already encountered this unicode
+ }
- return advances[glyphID];
- } else {
- tempChars[0] = unicodeID;
+ if (glyphID != undefined) // if we haven't, we must get some its attributes, and prep for upload
+ {
+ return advances[glyphID];
+ } else {
+ tempChars[0] = unicodeID;
- GlyphVector fullRunGlyphVector = font.createGlyphVector(fontRenderContext,
- tempChars);
+ GlyphVector fullRunGlyphVector = font.createGlyphVector(fontRenderContext,
+ tempChars);
- return fullRunGlyphVector.getGlyphMetrics(0).getAdvance();
- }
+ return fullRunGlyphVector.getGlyphMetrics(0).getAdvance();
+ }
// return -1;
}
+ GlyphsList puntToRobust(CharSequence inString) {
+ glyphsOutput.nextState = DrawingState.robust;
+ glyphsOutput.remaining = inString;
+
+ return glyphsOutput;
+ }
+
GlyphsList getGlyphs(CharSequence inString) {
- glyphsToUpload.numberOfNewGlyphs = 0;
+ float fontSize = font.getSize();
+
+ if (fontSize > 128) {
+ glyphsOutput.nextState = DrawingState.robust;
+ glyphsOutput.remaining = inString;
+ }
int length = inString.length();
allocateSpace(length);
@@ -1547,43 +1588,66 @@ public class TextRenderer {
int lengthInGlyphs = fullRunGlyphVector.getNumGlyphs();
if (complex) {
- return null;
+ return puntToRobust(inString);
}
+ TextureRenderer renderer = getBackingStore();
+
+ float totalAdvanceUploaded = 0;
+ float cacheSize = renderer.getWidth() * renderer.getHeight();
+
for (int i = 0; i < lengthInGlyphs; i++) {
+ float advance;
+
char unicodeID = inString.charAt(i);
if (unicodeID >= unicodes2Glyphs.length) { // <-- -could support these better
-
- return null;
+ return puntToRobust(inString);
}
int glyphID = unicodes2Glyphs[unicodeID]; // Check to see if we have already encountered this unicode
if (glyphID == undefined) { // if we haven't, we must get some its attributes, and prep for upload
-
GlyphMetrics metrics = fullRunGlyphVector.getGlyphMetrics(i);
singleUnicode[0] = unicodeID;
GlyphVector gv = font.createGlyphVector(fontRenderContext,
singleUnicode); // need this to get single bitmaps
glyphID = gv.getGlyphCode(0);
+ advance = metrics.getAdvance();
+ advances[glyphID] = advance;
- glyphsToUpload.prepGlyphForUpload(unicodeID,
- gv.getGlyphCode(0),
- gv.getPixelBounds(fontRenderContext, 0, 0), i, gv);
+ glyphsToUpload.prepGlyphForUpload(unicodeID, glyphID,
+ gv.getVisualBounds(), i, gv);
- advances[glyphID] = metrics.getAdvance();
+ totalAdvanceUploaded += advance;
} else {
- glyphsOutput.textureSourceRect[i] = glyphRectForTextureMapping[glyphID];
+ Rect r = glyphRectForTextureMapping[glyphID];
+ glyphsOutput.textureSourceRect[i] = r;
+
+ TextData data = (TextData) r.getUserData();
+ data.markUsed();
+
+ advance = advances[glyphID];
}
- glyphsOutput.advances[i] = advances[glyphID];
- }
+ glyphsOutput.advances[i] = advance;
+ glyphsOutput.totalAdvance += advance;
- glyphsOutput.length = length;
+ if ((totalAdvanceUploaded * fontSize) > (0.25f * cacheSize)) // note -- if the incoming string is bigger than 1/4 the total font cache, start segmenting glyph stream into bite sized pieces
+ {
+ glyphsToUpload.uploadAnyNewGlyphs(glyphsOutput, this);
+ glyphsOutput.length = i + 1;
+ glyphsOutput.remaining = inString.subSequence(i + 1, length);
+ glyphsOutput.nextState = DrawingState.fast;
+
+ return glyphsOutput;
+ }
+ }
+ glyphsOutput.length = lengthInGlyphs;
glyphsToUpload.uploadAnyNewGlyphs(glyphsOutput, this);
+ glyphsOutput.nextState = DrawingState.finished;
return glyphsOutput;
}