Convert text to PShape?

Hi out there :wave:

i was wondering if it s possible to put a text with a specific size and font into a PShape object.

i am working on a sketch, that has some text elements, floating and bouncing around. i am not happy with the textWidth() function as it is not exactly correct, same with the text height.

so i thought it would be nice to have it as a shape object to get the specific width and height of it.
like converting text to paths as in illustrator. i know that i could load a svg file from the text but i was looking for a more elegant way.

do you have any ideas? :thought_balloon:

2 Likes

Hello,

https://processing.org/reference/PShape.html
https://processing.org/reference/PImage.html
https://processing.org/reference/texture_.html
https://processing.org/reference/textureMode_.html

From the references above I was able to:

// https://processing.org/reference/PGraphics.html
// https://processing.org/reference/texture_.html

PGraphics pg;
PImage pi;

public void settings()
  {  
  size(400, 400, P3D); 
  }

public void setup() 
  { 
  pg = createGraphics(100, 100);
  
  pg.beginDraw();
  pg.background(100);
  pg.fill(255, 255, 0);
  pg.textAlign(CENTER, CENTER);
  pg.textSize(18);
  pg.text("0", 0+10, 0+10);
  pg.text("1", 100-10, 0+10);
  pg.text("2", 100-10, 100-10);
  pg.text("3", 0+10, 100-10);
  pg.save("image.png");
  pg.endDraw();
  
  pi = loadImage("image.png");
  }

public void draw() 
  {
  image(pi, 200, 200);
  
  noStroke();
  beginShape();
  textureMode(IMAGE);
  texture(pi);
  vertex(0, 0, 0, 0); 
  vertex(100, 0, 100, 0);
  vertex(100, 100, 100, 100);
  vertex(0, 100, 0, 100);
  endShape();  
  }

image

:slight_smile:

1 Like

Hi @glv,

thanks for your reply!
unfortunately i dont understand your code example. might there be something missing in the beginning / setup ?

1 Like

Hello,

I updated it!

I also learned a lot doing this!

:slight_smile:

1 Like

I accidentally came across a solution for this one.
So in case someone has a similar problem, here it goes:

There is processing library called ‘geomerative’ which cut the letter/font into very small vertexes.
A good example with code can be seen here:
http://www.generative-gestaltung.de/1/P_3_2_3_01

With this library you can also read the x/y-position of the vertex points. So i was able to read the exact dimensions of the font to make it perfectly bouncing in a specific frame.
You can also make a PShape out of this but I wasn’t that happy with the resolution. Thats why I draw the text with the text()-function and use the geomerative-text as a hidden mask.

2 Likes

here is a smaller sketch with letters

// https : // forum.processing.org/two/discussion/comment/79932/#Comment_79932

ArrayList<PVector[]> list = new ArrayList(); 

PGraphics pg=new PGraphics();
PFont f, f1;

String word = "A";
boolean cursorOn=false;
boolean fly=false;

// -------------------------------------------------------------------------

void setup() {

  size(1960, 1000);
  background(0);

  f1 = createFont("Arial", 300); // "AR BERKLEY", 300 ) ; //
  f = createFont("AR BERKLEY", 300);
  textFont(f);
  fill(0);

  makeAlphabet(); 
  //
}//func

void draw() {
  //
  background(60, 60, 60); // clear screen
  textFont(f);
  fill(0, 0, 0);
  noStroke(); 
  float xpos=-10;

  // for loop over word 
  for (int i = 0; i < word.length(); i++) {
    char letter = word.charAt(i);
    xpos = i * 210 + 66;
    showOneLetter(letter, xpos, 210);
  }//for 

  // increase for cursor
  xpos += 140;

  // The curosor Image (the vertical red line | )
  manageCursorImage(xpos);

  // help text 
  textFont(f1);
  fill(255); // white
  textSize(20);
  text("Type key A-Z and test with mouseY. F2 to fly.", 18, 18);
}//func

// ------------------------------------------------------------------------------------

void makeAlphabet() {
  // Init 
  // make entire Alphabet A-Z
  // make pg
  pg = createGraphics(400, 400);
  pg.smooth(16);// noSmooth 

  for (int i='A'; i<='Z'; i++) {

    makeLetter(char(i));

    PVector[] pvList = new PVector[0]; 

    // analyze pg 
    for (int x=0; x < pg.width; x+=2) {
      for (int y=0; y < pg.height; y+=3) {
        if (pg.get(x, y) < color(1)) 
          //point(x, y) ;
          pvList = (PVector[])append(pvList, new PVector(x, y));
      }//for
    }//for

    list.add(pvList);
  }//for
}//func 

void showOneLetter(char letter, 
  float x, float y) {

  letter=str(letter).toUpperCase().charAt(0); 

  // check against <0
  if (letter-65<0)
    return; 

  PVector[] pvector_Array = list.get(letter-65);

  pushMatrix();
  translate(x, y);
  for (PVector pv : pvector_Array) {
    // point(pv.x, pv.y) ;
    noStroke(); 
    fill(0, 255, 0);
    float sizeEllipse; 
    //sizeEllipse=mouseY/16; // OR use 
    sizeEllipse=map(mouseY, 
      0, height, 
      1, 111); // or 1,500
    ellipse(pv.x, pv.y, sizeEllipse, sizeEllipse); // use
    if (fly) {
      pv.x  += 3;  
      pv.y  += 2;
    }
    // ellipse(pv.x, pv.y*mouseX/26, sizeEllipse, sizeEllipse); // use
  }
  popMatrix();
}//func

void makeLetter (char letter) {
  // for init
  pg.beginDraw();
  pg.background(255);
  pg.textFont(f);
  pg.fill(0);
  pg.text(letter, 4, 223);
  pg.endDraw();
}

void keyPressed() {
  if (key==CODED) {
    fly = !fly;
  } else {
    println(keyCode); 
    if (keyCode!=8&&key!=SHIFT) {
      word = word + key;
    }//if
  }//else
}//func 

void manageCursorImage( float xpos ) {
  // The curosor Image (the vertical red line | )  
  if (cursorOn) {
    xpos+=100;
    stroke(255, 0, 0); // red  
    line(xpos, 170, xpos, 450);
  }

  if (frameCount%13==0) {
    cursorOn = !cursorOn;
  }
}
//
3 Likes

True. That’s another way I haven’t thought about, thanks!!

But in this one the letters are not kerned so it looks very unbalanced overall.
I think fixing that would be a lot of effort.

Another reason geomerative works best in this case so far as it keeps the kerning information of the font.
Sorry for my crabbing, i’m very picky in case of type :smiley:

3 Likes