[Solved] Fonts & PGraphics in Processing 3

edited February 2017 in Questions about Code

The short form of my question is: How do I set a custom font for a PGraphics object in processing 3? I'm trying to migrate a complex sketch from 2 to 3, I recreated the issue in a much simpler program so we can isolate it and focus on it.

Processing 2 has no issues with PGraphics.textFont( PFont ) to set the font of a PGraphics object. Processing 3 throws a generic "NULL ptr exception" ( mind you neither the pg object nor the myfont object are null and the ttf font is correctly loaded from the data directory as it works perfectly in the main frame ( line 8 simply works ) ).

Am I missing some sort of initialization for my pg object? the textfont memeber of PGraphics is set to null and pg.textFont = myfont; creates more issues than it solves.

If you want to test this code simply use any ttf font place it in the data directory and change myfont = createFont("small_pixel.ttf", 10); from "small_pixel.ttf" to your file name.

PGraphics pg;
PFont myfont;

void setup() {
  size(640, 360);
  pg = createGraphics(400, 200);
  myfont = createFont("small_pixel.ttf", 10);
  textFont(myfont);
  // The next line is the issue
  pg.textFont(myfont);

}

void draw() {
  fill(0, 12);
  rect(0, 0, width, height);
  fill(255);
  noStroke();
  text("Hello main frame", 20, 20);
  pg.beginDraw();
  pg.background(150,150,150);
  pg.fill(255,255,255);
  pg.textSize(12);
  pg.text("Hello pGraphics", pg.width/2, pg.height/2);
  pg.textAlign(CENTER,CENTER);
  pg.noFill();
  pg.stroke(255);
  pg.endDraw();
  
  // Draw the offscreen buffer to the screen with image() 
  image(pg, 120, 60); 
}

Answers

  • Have you tried moving the pg.textFont() call to after pg.beginDraw() in draw()? It's possible you need to beginDraw on the PGraphics before you can set the font!? At least, that's the only difference I can see from code I have that's working.

  • edited February 2017

    Yep that was it, I would suggest adding this behavior change to the processing.core javadoc for the textFont() method. Just a final note I wanted to keep my textfont in the setup so instead of moving the pg.textFont(myfont); line I did this and everything seems to work:

    PGraphics pg;
    PFont myfont;
    
    void setup() {
      size(640, 360);
      pg = createGraphics(400, 200);
      myfont = createFont("small_pixel.ttf", 10);
      textFont(myfont);
      // This now works
      pg.beginDraw();
      pg.textFont(myfont);
      pg.endDraw();
    
    }
    
    void draw() {
      fill(0, 12);
      rect(0, 0, width, height);
      fill(255);
      noStroke();
      text("Hello main frame", 20, 20);
      pg.beginDraw();
      pg.background(150,150,150);
      pg.fill(255,255,255);
      pg.textSize(12);
      pg.text("Hello pGraphics", pg.width/2, pg.height/2);
      pg.textAlign(CENTER,CENTER);
      pg.noFill();
      pg.stroke(255);
      pg.endDraw();
      
      // Draw the offscreen buffer to the screen with image() 
      image(pg, 120, 60); 
    }
  • I would suggest adding this behavior change to the processing.core javadoc for the textFont() method.

    Do you mean that in Processing 2 PGraphics.textFont() did not require PGraphics.beginDraw() to be called first and in Processing 3 it is required?

    If you would please report this to the Processing Docs github repo, Issues:

  • edited February 2017

    In order:

    1. Yes, processing 2 did not require that, ( this stricter approach might be "better" but it's not documented, so... not great.. )

    2. Done: https://github.com/processing/processing-docs/issues/521

  • edited February 2017

    just a clarification: this also works in processing3:

    
      pg.beginDraw();
      pg.endDraw();
    
      pg.textFont(myfont);
    

    it just seems like it should be initialized with createGraphics not beginDraw, different responsibility...

  • it just seems like it should be initialized with createGraphics not beginDraw

    Why!? beginDraw() is documented to set up the default properties of a PGraphics object. While the documentation might be clarified, I think you were relying on an undocumented quirk in Processing 2.x and this is now behaving as intended and documented.

  • I kind of replied to that here: https://github.com/processing/processing-docs/issues/521

    But basically it seems arbitrary as a behavior, the error it throws is very generic, and given the name of the method it does not make sense for textFont() to be inside the beginDraw() endDraw() block. On top of it, it can be outside as long as it's after the beginDraw() call.

    It's a set property method, it could check to see if the property has been initialized and if not at least throw an exception a bit more meaningful than "null pointer exception". That's really all I'm suggesting.

    The behavior is not obvious, it's not documented in the textFont() docs and there is no way to know that I need to look for the beginDraw() to do the initializing as it's main responsibility should be to populate the PGraphics object with content. ( at least in how I understood it, i now know it also sets the properties )

    I'm not arguing we should change anything( i understand it's a core object ) , just perhaps that error message.

  • I also find this counterintuitive -- or at least inconsistent with the general narrative of begin/end commands for beginners.

    I would instead have expected that an operation would either only work inside a draw "begin/end" block or work both inside and outside a draw block.

    I wouldn't expect something to:

    1. Not work before createGraphics
    2. Not work before beginDraw
    3. Work after beginDraw
    4. Work after endDraw < - - this would surprise me - I would expect 2 & 4 to both work or both not-work.
Sign In or Register to comment.