From 745980f6fefe2dfc4a3216c248880df543b17d32 Mon Sep 17 00:00:00 2001 From: benfry Date: Wed, 22 Jun 2005 18:28:01 +0000 Subject: [PATCH] lots of new stuff with native fonts and debugging em, threading stuff, and more --- core/PApplet.java | 174 +++++++++++++++++++++++++++++-------------- core/PGraphics.java | 37 ++++++++- core/PGraphics2.java | 9 ++- core/todo.txt | 8 ++ 4 files changed, 165 insertions(+), 63 deletions(-) diff --git a/core/PApplet.java b/core/PApplet.java index cd11596e0..8f6f5ecfb 100644 --- a/core/PApplet.java +++ b/core/PApplet.java @@ -671,10 +671,10 @@ public class PApplet extends Applet /** - * Starts up and creates a two-dimensional drawing surface. + * Starts up and creates a two-dimensional drawing surface, + * or resizes the current drawing surface. *

- * To ensure no strangeness, this should be the first thing - * called inside of setup(). + * This should be the first thing called inside of setup(). *

* If using Java 1.3 or later, this will default to using * PGraphics2, the Java2D-based renderer. If using Java 1.1, @@ -708,8 +708,9 @@ public class PApplet extends Applet * Creates a new PGraphics object and sets it to the specified size. *

* Note that you cannot change the renderer once outside of setup(). - * You can call size() to give it a new size, but you need to always - * ask for the same renderer, otherwise you're gonna run into trouble. + * In most cases, you can call size() to give it a new size, + * but you need to always ask for the same renderer, otherwise + * you're gonna run into trouble. *

* Also note that this calls defaults(), which will reset any * settings for colorMode or lights or whatever. @@ -720,13 +721,18 @@ public class PApplet extends Applet if (currentRenderer != null) { if (currentRenderer.equals(renderer)) { if ((iwidth == g.width) && (iheight == g.height)) { - // all set, the renderer was queued up last time - // before throwing the exception - //System.out.println("ignoring additional size()"); - // but this time set the defaults - //g.defaults(); - //System.out.println("defaults set"); + // in this case, size() is being called a second time because + // setup() is being called a second time, since the first time + // that setup was called, the renderer was changed so an + // exception was thrown and setup() didn't complete. but this + // time around, g is the proper size and the proper class, so + // all that needs to be done is to set the defaults (clear the + // background, set default strokeWeight, etc). g.defaults(); + // this will happen when P3D or OPENGL are used with size() + // inside of setup. it's also safe to call defaults() now, + // because it's happening inside setup, which is just frame 0, + // meaning that the graphics context is proper and visible. return; } } else { @@ -742,10 +748,6 @@ public class PApplet extends Applet "Import Library > opengl from the Sketch menu."; try { - //if (renderer.equals(OPENGL)) { - //g = new processing.opengl.PGraphicsGL(iwidth, iheight, this); - //} else { - Class rendererClass = Class.forName(renderer); Class constructorParams[] = new Class[] { Integer.TYPE, @@ -759,19 +761,13 @@ public class PApplet extends Applet this }; // create the actual PGraphics object for rendering //System.out.println("creating new PGraphics " + constructor); - g = (PGraphics) - constructor.newInstance(constructorValues); + g = (PGraphics) constructor.newInstance(constructorValues); this.width = iwidth; this.height = iheight; - // can't do this here because of gl - //g.defaults(); - //width = g.width; - //height = g.height; - //pixels = g.pixels; // this may be null - - // make the applet itself larger + // make the applet itself larger.. it's a subclass of Component, + // so this is important for when it's embedded inside another app. setSize(width, height); // probably needs to mess with the parent frame here? @@ -816,39 +812,68 @@ public class PApplet extends Applet // restore it to its default values g.defaults(); - /* - if (g == null) return; - g.resize(iwidth, iheight); - - this.pixels = g.pixels; - this.width = g.width; - this.height = g.height; - - if (frame != null) { - Insets insets = frame.getInsets(); - - // msft windows has a limited minimum size for frames - int minW = 120; - int minH = 120; - int winW = Math.max(width, minW) + insets.left + insets.right; - int winH = Math.max(height, minH) + insets.top + insets.bottom; - frame.setSize(winW, winH); - - setBounds((winW - width)/2, - insets.top + ((winH - insets.top - insets.bottom) - height)/2, - winW, winH); - //} else { - //System.out.println("frame was null"); - //setBounds(0, 0, width, height); - } - */ - Object methodArgs[] = new Object[] { new Integer(width), new Integer(height) }; sizeMethods.handle(methodArgs); } + public PGraphics createGraphics(String renderer) { + return createGraphics(width, height, renderer); + } + + + public PGraphics createGraphics(int iwidth, int iheight) { + return createGraphics(iwidth, iheight, g.getClass().getName()); + } + + + public PGraphics createGraphics(int iwidth, int iheight, String renderer) { + if (renderer.equals(OPENGL)) { + throw new RuntimeException("createGraphics() with OPENGL is not " + + "supported. Use P3D instead."); + } + + PGraphics outgoing; + try { + Class rendererClass = Class.forName(renderer); + Class constructorParams[] = + new Class[] { Integer.TYPE, + Integer.TYPE, + PApplet.class }; + Constructor constructor = + rendererClass.getConstructor(constructorParams); + Object constructorValues[] = + new Object[] { new Integer(iwidth), + new Integer(iheight), + this }; + // create the actual PGraphics object for rendering + //System.out.println("creating new PGraphics " + constructor); + outgoing = (PGraphics) constructor.newInstance(constructorValues); + + } catch (InvocationTargetException ite) { + //Throwable target = ((InvocationTargetException) t).getTargetException(); + throw new RuntimeException(ite.getTargetException()); + //ite.getTargetException().printStackTrace(); + + } catch (ClassNotFoundException cnfe) { + throw new RuntimeException("You need to use \"Import Library\" " + + "to add " + renderer + " to your sketch."); + + } catch (Exception e) { + throw new RuntimeException(e); + //e.printStackTrace(); + //die("Could not start because of a problem with size()", e); + } + + // clear things out to get started + outgoing.defaults(); + + // and send 'em off + return outgoing; + } + + public void update(Graphics screen) { //System.out.println("PApplet.update()"); if (THREAD_DEBUG) println(Thread.currentThread().getName() + @@ -972,7 +997,7 @@ public class PApplet extends Applet // have a feeling that some platforms aren't gonna like that // if !looping, sleeps for a nice long time, // or until interrupted - int nap = looping ? 1 : 10000; + int nap = (looping || finished) ? 1 : 10000; // don't nap after setup, because if noLoop() is called this // will make the first draw wait 10 seconds before showing up if (frameCount == 1) nap = 1; @@ -1014,6 +1039,13 @@ public class PApplet extends Applet } if (THREAD_DEBUG) println(Thread.currentThread().getName() + " thread finished"); + + // this may not be safe? this will get triggered with exit() + // but need to see if this is it + if ((leechErr == null) && !online) { + System.exit(0); + } + //System.out.println("exiting run " + finished); stop(); // call to shutdown libs? } @@ -1837,10 +1869,6 @@ public class PApplet extends Applet public void exit() { stop(); finished = true; - - if ((leechErr == null) && !online) { - System.exit(0); - } } @@ -5533,8 +5561,28 @@ v PApplet.this.stop(); public void recordFrame(PGraphics recorder) { + recordFrame(recorder, "frame-" + nf(frameCount, 4)); + } + + + public void recordFrame(PGraphics recorder, String filename) { + int first = filename.indexOf('#'); + int last = filename.lastIndexOf('#'); + + if (first != -1) { + String prefix = filename.substring(0, first); + int count = last - first + 1; + String suffix = filename.substring(last + 1); + filename = prefix + nf(frameCount, count) + suffix; + } + recordFrame(recorder, savePath(filename)); + } + + + public void recordFrame(PGraphics recorder, File file) { this.recorder = recorder; - recorder.beginFrame(); + //recorder.record(frameCount, file); + recorder.beginFrame(); //frameCount, file); } @@ -6057,6 +6105,12 @@ v PApplet.this.stop(); } + public void text(char c) { + if (recorder != null) recorder.text(c); + g.text(c); + } + + public void text(char c, float x, float y) { if (recorder != null) recorder.text(c, x, y); g.text(c, x, y); @@ -6069,6 +6123,12 @@ v PApplet.this.stop(); } + public void text(String str) { + if (recorder != null) recorder.text(str); + g.text(str); + } + + public void text(String str, float x, float y) { if (recorder != null) recorder.text(str, x, y); g.text(str, x, y); diff --git a/core/PGraphics.java b/core/PGraphics.java index a106a754f..d9aed0166 100644 --- a/core/PGraphics.java +++ b/core/PGraphics.java @@ -265,10 +265,10 @@ public class PGraphics extends PImage implements PConstants { public PFont textFont; /** The current font if a Java version of it is installed */ - protected Font textFontNative; + public Font textFontNative; /** Metrics for the current native Java font */ - protected FontMetrics textFontNativeMetrics; + public FontMetrics textFontNativeMetrics; /** The current text align (read-only) */ public int textAlign; @@ -282,6 +282,9 @@ public class PGraphics extends PImage implements PConstants { /** The current text leading (read-only) */ public float textLeading; + /** Last text position, because text often mixed on lines together */ + public float textX, textY, textZ; + /** * Internal buffer used by the text() functions * because the String object is slow @@ -567,10 +570,14 @@ public class PGraphics extends PImage implements PConstants { /** - * set engine's default values + * Set engine's default values. This has to be called by PApplet, + * somewhere inside setup() or draw() because it talks to the + * graphics buffer, meaning that for subclasses like OpenGL, there + * needs to be a valid graphics context to mess with otherwise + * you'll get some good crashing action. */ public void defaults() { // ignore - //System.out.println("PGraphics.defaults()"); + //System.out.println("PGraphics.defaults() " + width + " " + height); colorMode(RGB, TFF); fill(TFF); stroke(0); @@ -1813,6 +1820,14 @@ public class PGraphics extends PImage implements PConstants { // ........................................................ + /** + * Write text where we just left off. + */ + public void text(char c) { + text(c, textX, textY, textZ); + } + + /** * Draw a single character on screen. * Extremely slow when used with textMode(SCREEN) and Java 2D, @@ -1844,11 +1859,20 @@ public class PGraphics extends PImage implements PConstants { if (z != 0) translate(0, 0, z); // slowness, badness text(c, x, y); + textZ = z; if (z != 0) translate(0, 0, -z); } + /** + * Write text where we just left off. + */ + public void text(String str) { + text(str, textX, textY, textZ); + } + + /** * Draw a chunk of text. * Newlines that are \n (Unix newline or linefeed char, ascii 10) @@ -1893,6 +1917,7 @@ public class PGraphics extends PImage implements PConstants { if (z != 0) translate(0, 0, z); // slow! text(str, x, y); + textZ = z; if (z != 0) translate(0, 0, -z); } @@ -1922,6 +1947,9 @@ public class PGraphics extends PImage implements PConstants { // this doesn't account for kerning x += textWidth(buffer[index]); } + textX = x; + textY = y; + textZ = 0; // this will get set by the caller if non-zero } @@ -2083,6 +2111,7 @@ public class PGraphics extends PImage implements PConstants { if (z != 0) translate(0, 0, z); // slowness, badness text(s, x1, y1, x2, y2); + textZ = z; if (z != 0) translate(0, 0, -z); // TEMPORARY HACK! SLOW! } diff --git a/core/PGraphics2.java b/core/PGraphics2.java index 6b8a6a4f7..3312a8092 100644 --- a/core/PGraphics2.java +++ b/core/PGraphics2.java @@ -696,7 +696,8 @@ public class PGraphics2 extends PGraphics { return super.textWidthImpl(buffer, start, stop); } // maybe should use one of the newer/fancier functions for this? - return textFontNativeMetrics.charsWidth(buffer, start, stop); + int length = stop - start; + return textFontNativeMetrics.charsWidth(buffer, start, length); } @@ -719,7 +720,8 @@ public class PGraphics2 extends PGraphics { g2.setColor(fillColorObject); // better to use drawString(float, float)? - g2.drawChars(buffer, start, stop, (int) (x + 0.5f), (int) (y + 0.5f)); + int length = stop - start; + g2.drawChars(buffer, start, length, (int) (x + 0.5f), (int) (y + 0.5f)); // return to previous smoothing state if it was changed if (textFont.smooth != savedSmooth) { @@ -729,6 +731,9 @@ public class PGraphics2 extends PGraphics { noSmooth(); } } + textX = x + textWidthImpl(buffer, start, stop); + textY = y; + textZ = 0; // this will get set by the caller if non-zero } diff --git a/core/todo.txt b/core/todo.txt index ef1f3a213..536134605 100644 --- a/core/todo.txt +++ b/core/todo.txt @@ -32,9 +32,17 @@ X and when smooth field is set, make sure JAVA2D enables smoothing X since otherwise smooth() has to be called for the whole g2 X rob saunders contributed a fix for a bug in PImage.copy() X the wrong boundaries were being copied in the code +X fix bug where noLoop() was waiting 10 secs to call exit() +X add ability to draw text from the current text position +_ need to add this to the documentation + +_ leading looks too big, at least in PGraphics2 with news gothic +_ though it may be the converted version of the .ttf? _ when using things like PGraphicsPDF, need to not resize window _ if it doesn't display to the screen, needs to never show a window +_ basically if the main gfx context isn't viewable, close the window +_ since it may have already been opened at 100x100 _ how to deal with triangles/lines and triangleCount and lineCount _ maybe just need a triangleImpl and lineImpl