Using another text renderer

I was looking if it was possible to render text a different way.
For those who are interested:

Not made user friendly yet.

Unfortunately it needs PJOGL.profile = 1; so it’s kinda bad…

import java.awt.Font;
import com.jogamp.opengl.util.awt.TextRenderer;
import processing.core.PApplet;
import processing.opengl.PJOGL;


TextRenderer textRender;

public void settings() {
  PJOGL.profile = 1;
  size(800, 600, P2D);
  pixelDensity(2);
}


@Override
  public void setup() {

  boolean antialiased = true;
  boolean mipmap = true;
  textRender = new TextRenderer( new Font("SansSerif", Font.PLAIN, 20), antialiased, true, null, mipmap );

  createFont("SansSerif", 20);
}


public void draw() {

  background(255);

  textRender.beginRendering(width, height, true);
  textRender.setColor(0, 0, 0, 1);
  textRender.draw("The quick brown fox jumped over the lazy dog", 50, height-50);
  textRender.endRendering();
  textRender.flush();

  fill(0);
  textSize(20);
  text("The quick brown fox jumped over the lazy dog", 50, 70);
}
1 Like

I guess this is how to do proper font rendering in P2D.
(This will be slow)



PGraphics pg;

void setup() {
  size(200, 200, P2D);
  pixelDensity(2);
  
  textSize(120);

  
  pg = createGraphics(1200, 200);
  pg.beginDraw();
  pg.clear();
  pg.fill(255);
  pg.textSize(60);
  pg.textAlign(LEFT, TOP);
  pg.text("The quick brown fox", 0, 0);
  pg.endDraw();
  
}

void draw() {
  background(0);  
  
  
  float s = 0.16;
  image(pg, 10, 10, pg.width * s, pg.height * s);
  
  fill(255);
  textSize(9);
  textAlign(LEFT, TOP);
  text("The quick brown fox", 10, 25);
}
1 Like

test
Another way to do it

String s = "The quick brown fox";
PGraphics pg;

void setup() {
  size(200, 100, P2D);
  background(200, 255, 200);
  // P2D text
  textSize(12);
  fill(128, 0, 128);
  text(s, 0, 20);
  // Now for the alternative
  pg = createGraphics(200, 30, JAVA2D);
  pg.beginDraw();
  pg.clear();
  pg.textSize(12);
  pg.fill(128, 0, 128);
  pg.text(s, 0, 20);
  pg.endDraw();
  image(pg, 0, 24);
}
1 Like

Nice, I used your JAVA2D trick. Look how insane good the size 5 font is (retina).
Work in progress, but pretty far. I think I only have todo textAlignY and the text method where you define the width and height of the box.





void setup() {
  size(200, 500, P2D);
  pixelDensity(2);
  font = create_font("SansSerif", 64);
}





void draw() {

  background(255);

  fill(0);
  textAlign(LEFT);


  for (int i = 14; i > 4; i--) {
    textSize(i);
    text("The quick brown fox", 20, 20);
    translate(0, g.textLeading);
    text2("The quick brown fox", 20, 20);
    translate(0, g.textLeading * 2);
  }
}



public void text2(String txt, float x, float y) {

  float sx = x;

  String remainder = null;

  int new_line = txt.indexOf("\n", 0);
  if (new_line != -1) {
    remainder = txt.substring(new_line+1, txt.length());  
    txt = txt.substring(0, new_line);
  }

  if (g.textAlign == RIGHT) {
    x -= textWidth(txt);
  } else if (g.textAlign == CENTER) {
    x -= textWidth(txt) / 2;
  }


  float size = g.textSize;


  // backup tint
  boolean tint = g.tint;
  //float tintR = g.tintR;
  //float tintG = g.tintG;
  //float tintB = g.tintB;
  //float tintA = g.tintA;
  //float tintRi = g.tintRi;
  //float tintGi = g.tintGi;
  //float tintBi = g.tintBi;
  //float tintAi = g.tintAi;
  int tintColor = g.tintColor;
  //boolean tintAlpha = g.tintAlpha;
  
  tint(g.fillColor);


  for (int i = 0; i < txt.length(); i++) {
    char c = txt.charAt(i);
    if (c == '\r') continue;

    Glyph glyph = font.glyphs[(int)c];

    float x_pos = x + -font.offset_x * size / font.creation_size;
    float y_pos = y - (font.text_ascent * size);
    float width = glyph.g.width * size / font.creation_size;
    float height = glyph.g.height * size / font.creation_size;

    image(glyph.g, x_pos, y_pos, width, height);
    x += glyph.w * size;
  }

  if (remainder != null) {
    text2(remainder, sx, y + g.textLeading);
  }
  
  
  // restore tint
  g.tint = tint;
  //g.tintR = tintR;
  //g.tintG = tintG;
  //g.tintB = tintB;
  //g.tintA = tintA;
  //g.tintRi = tintRi;
  //g.tintGi = tintGi;
  //g.tintBi = tintBi;
  //g.tintAi = tintAi;
  g.tintColor = tintColor;
  //g.tintAlpha = tintAlpha;
  
}




Font font;


class Glyph {
  PGraphics g;
  float w;
}

class Font {
  String name;
  float creation_size;
  float text_ascent;
  float text_descent;
  //float text_leading;
  float offset_x;
  Glyph[] glyphs;
}






Font create_font(String font_name, float size) {

  Font font = new Font();
  font.name = font_name;
  font.creation_size = size;

  PFont pfont = createFont(font_name, size);
  textFont(pfont);
  textSize(size);

  font.text_ascent = textAscent() / size;
  font.text_descent = textDescent() / size;
  //font.text_leading = (font.text_ascent + font.text_descent) * 1.275;

  float tw = textWidth("X"); 
  int w = (int) (tw * 1.9);
  int h = (int) (tw * 2.1);

  float offset_x = w * 0.1; // prevent capping the left side of 'j' for example
  font.offset_x = offset_x;

  font.glyphs = new Glyph[128];

  for (int i = 1; i < 128; i++) {
    char c = (char)i;

    PGraphics pg = createGraphics(w, h, JAVA2D);
    pg.beginDraw();
    pg.clear();
    //pg.background(0,255,0);
    pg.textFont(pfont);
    pg.textSize(size);
    pg.fill(255);
    //pg.fill(0);
    pg.textAlign(LEFT, TOP);
    pg.text(""+c, offset_x, 0); 
    pg.endDraw();

    Glyph glyph = new Glyph();
    glyph.g = pg;
    glyph.w = textWidth(c) / size;

    font.glyphs[i] = glyph;
  }

  return font;
}

textAlignY support:


public void text2(String txt, float x, float y) {

  float sx = x;
  float size = g.textSize;


  // backup tint
  boolean tint = g.tint;
  //float tintR = g.tintR;
  //float tintG = g.tintG;
  //float tintB = g.tintB;
  //float tintA = g.tintA;
  //float tintRi = g.tintRi;
  //float tintGi = g.tintGi;
  //float tintBi = g.tintBi;
  //float tintAi = g.tintAi;
  int tintColor = g.tintColor;
  //boolean tintAlpha = g.tintAlpha;

  tint(g.fillColor);


  // deal with textAlignY
  // ---
  {
    float height = 0;
    for (int i = 0; i < txt.length(); i++) {
      if (txt.charAt(i) == '\n') {
        height += g.textLeading;
      }
    }

    if (g.textAlignY == CENTER) {
      y += (textAscent() - height)/2;
    } else if (g.textAlignY == TOP) {
      y += textAscent();
    } else if (g.textAlignY == BOTTOM) {
      y -= textDescent() + height;
    }
    
  }
  // ---


  while (txt.length() > 0) {

    String line;

    int index_of_new_line = txt.indexOf("\n", 0);
    if (index_of_new_line != -1) {
      line = txt.substring(0, index_of_new_line);
      txt = txt.substring(index_of_new_line+1, txt.length());
    } else {
      line = txt;
      txt = "";
    }


    if (g.textAlign == RIGHT) {
      x -= textWidth(line);
    } else if (g.textAlign == CENTER) {
      x -= textWidth(line) / 2;
    }


    for (int i = 0; i < line.length(); i++) {
      char c = line.charAt(i);
      if (c == '\r') continue;

      Glyph glyph = font.glyphs[(int)c];

      float x_pos = x + -font.offset_x * size / font.creation_size;
      float y_pos = y - (font.text_ascent * size);
      float width = glyph.g.width * size / font.creation_size;
      float height = glyph.g.height * size / font.creation_size;

      image(glyph.g, x_pos, y_pos, width, height);
      x += glyph.w * size;
    }


    y += g.textLeading;
    x = sx;
  }


  // restore tint
  g.tint = tint;
  //g.tintR = tintR;
  //g.tintG = tintG;
  //g.tintB = tintB;
  //g.tintA = tintA;
  //g.tintRi = tintRi;
  //g.tintGi = tintGi;
  //g.tintBi = tintBi;
  //g.tintAi = tintAi;
  g.tintColor = tintColor;
  //g.tintAlpha = tintAlpha;
}

1 Like