# Vertical and horizontal center glyphs

**URL:** https://discourse.processing.org/t/vertical-and-horizontal-center-glyphs/860
**Category:** Coding Questions
**Created:** [June 11, 2018, 2:28am UTC](https://discourse.processing.org/t/vertical-and-horizontal-center-glyphs/860 "2018-06-11T02:28:22Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![Leo\_Aguiar](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/leo_aguiar/32/18942_2.png) [@Leo\_Aguiar](https://discourse.processing.org/u/Leo_Aguiar)
#### Post date: [June 11, 2018, 2:28am UTC](https://discourse.processing.org/t/vertical-and-horizontal-center-glyphs/860/1 "2018-06-11T02:28:23Z")

</div>

Hi guys,

I’m a noob and I’ve made a sketch where by clicking you can shuffle through an alphabet’s glyphs and they get vertically and horizontally centered according to their size and the size of the sketch. I was stuck for a bit but I stumbled along untill I found some logic that works.

The sketch has an array that stores the different glyphs and I shuffle through them. Since I wanted to vertically center the glyphs and type glyphs have different heights, I figured I would need some code that could determine the height of each glyph. So I searched online and used some of the last code shared in this thread: [https://forum.processing.org/two/discussion/19869/is-it-really-not-possible-to-determine-the-precise-height-of-a-text](https://forum.processing.org/two/discussion/19869/is-it-really-not-possible-to-determine-the-precise-height-of-a-text)

With the height and width data being determined for each different glyph I then “position their midpoints” on the sketch’s midpoints by doing some simple math. Arriving at this solution took me a while. I worked casually on this over the weekend as an exercise.

Now I’m curious if there are better and simpler ways to making this work because along the way I got lost/confused and was missing some important info about the nuts and bolts of how the type glyphs and Processing work.

Could anyone share any other approaches?

Thanks

```auto
int i = 0; //change value to start at a different letter

char [] alphabet = {
  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 
  'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
}; 

void setup(){
 size(600,600);
}

void draw(){
  
  int xPos = width/2; //horizontal position where you want the glyphs to be centered 
  int yPos = height/2; //vertical position where you want the glyphs to be centered
  
  int textSize = 400;
  PFont typeface;
  typeface = createFont("Arial",textSize);
  PFont.Glyph glyph = typeface.getGlyph(alphabet[i]);
  int t = glyph.topExtent;
  int h = glyph.height;
  int l = glyph.leftExtent;
  int w = glyph.width;
  int yMove = height/2-((yPos-t)+h/2);
  int xMove = width/2-((xPos+l)+w/2);
  
  background(255);
  fill(0);
  
  textFont(typeface);
  textSize(textSize);
  textLeading(0);
  text(alphabet[i], width/2+xMove, height/2+yMove);
  
  
  ////////////////// lines for showing top limit and bottom limit of glyph
  stroke(255,0,0);
  line(0,(yPos-t)+yMove,width,(yPos-t)+yMove); //red line top of glyph 
  strokeWeight(5);
  point((xPos+l)+xMove, (yPos-t)+yMove);
  strokeWeight(1);
  stroke(0,255,0);
  line(0,((yPos-t)+h+yMove),width,((yPos-t)+h)+yMove); //green line height of glyph
  
  //light blue line middle of glyph (helped during coding) comment out blue line (below) to see this one
  stroke(0,255,255);
  line(0,(((yPos-t)+h/2))+yMove,width,((yPos-t)+h/2)+yMove); 

  
  //////////////// line and point for showing center of "canvas"
  strokeWeight(1);
  stroke(0,0,255);
  line(0,yPos,width,yPos); //blue line at vertical midpoint of canvas
  strokeWeight(5);
  point(width/2, height/2);
  strokeWeight(1);

  //////////////// glyph bounding box
  noFill();
  stroke(0,255,0);
  rect((xPos+l)+xMove, (yPos-t)+yMove, w, h);
  
  
   println(alphabet[i]+" "+"t:"+t+" "+" "+"h:"+h+" "+" "+"mouseY:"+mouseY);
   println("yMove:"+yMove);
}

void mousePressed() {
      
  ////////////////// shuffle through glyphs in array
  if(mouseX > width/2){
    i = i+1;
  } else {
    i = i-1;
  }
  
  //////////////// ifs for controlling end behaviors when stepping through array
  if(i == 26){
   i = 0; 
  }
  
  if(i < 0){
   i = 25; 
  }
   
}

```

---

<div class="post-metadata">

### Author: ![dan850](https://avatars.discourse-cdn.com/v4/letter/d/e9c0ed/32.png) [@dan850](https://discourse.processing.org/u/dan850)
#### Post date: [June 11, 2018, 5:51am UTC](https://discourse.processing.org/t/vertical-and-horizontal-center-glyphs/860/2 "2018-06-11T05:51:10Z")

</div>

very cool program to demonstrate typography glyphs. A different way to code this would be to create a function for each glyph. For example, you have `strokeWeight()` being used multiple times with 1 parameter. Hope this answers your question. Good luck on your project! Hope to see 2.0 😃

---

<div class="post-metadata">

### Author: ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)
#### Post date: [June 19, 2018, 4:26pm UTC](https://discourse.processing.org/t/vertical-and-horizontal-center-glyphs/860/3 "2018-06-19T16:26:47Z")

</div>

Interesting – thank you for sharing!

Yes, this definitely aligns the glyph differently than if you centered it using `textMode(CENTER,CENTER)`.

Your code has width/2 and height/2 (and many other terms) cancelling out everywhere. You should factor that out. For example:

1. `yPos = height/2` … so:
2. `yMove = height/2 - yPos + t + h/2` is actually…  
`yMove = height/2 - height/2 + t + h/2`  
`yMove = t + h/2`
3. Now look at this line:  
`line(0,((yPos-t)+h+yMove),width,((yPos-t)+h)+yMove);`  
[made an error when quickly unpacking, but I think you see the point – t cancels, et cetera]

---

<div class="post-metadata">

### Author: ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)
#### Post date: [June 20, 2018, 2:36am UTC](https://discourse.processing.org/t/vertical-and-horizontal-center-glyphs/860/4 "2018-06-20T02:36:00Z")

</div>

Followup – I tried wrapping your approaches to glyph bounding boxes up in a class.

```auto
/**
 * GlyphBoxes
 * 2018-06 Processing 3.3.6 
 */

PFont.Glyph glyph;
GlyphBox glyphbox;

int i = 0; // letter index
char [] alphabet = {
  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 
  'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
};

void setup() {
  size(600, 600);
  textLeading(0);
  textFont(createFont("Arial", 400), 400);
  glyphbox = new GlyphBox("Arial", 400, alphabet[i]);
  glyphbox.align("CENTER"); // CENTER / BASELINE / NONE
}

void draw() {
  background(255);
  stroke(0);

  // screen crosshairs
  line(0, height/2.0, width, height/2.0);
  line(width/2.0, 0, width/2.0, height);

  // center the screen coordinates
  translate(width/2, height/2);

  // draw letter
  fill(0);
  glyphbox.text(0, 0);

  // draw some glyph lines
  noFill();
  stroke(0, 0, 255);
  glyphbox.boxbaseline();
  stroke(255, 0, 0);
  glyphbox.box();
  stroke(0, 255, 0);
  glyphbox.reticule();
}

class GlyphBox {
  String fontName;
  float textSize;
  PFont typeface;
  PFont.Glyph glyph;
  char character;
  String alignment = "";
  float x = 0; // x offset based on extent
  float y = 0; // y offset based on extent

  GlyphBox (String fontName, float textSize, char c) {
    this.fontName = fontName;
    this.textSize = textSize;
    this.typeface = createFont(fontName, textSize);
    this.character = c;
    this.glyph = typeface.getGlyph(c);
    this.alignUpdate();
  }
  
  void align(String s) {
    alignment = s;
    alignUpdate();
  }
  
  void alignUpdate() {
    if (alignment.equals("CENTER")) {
      // adjust center by glyph width/height
      x = -glyph.width/2.0;
      y = -glyph.height/2.0;
      // adjust center by glyph extent
      x -= glyph.leftExtent;
      y += glyph.topExtent;
    } else if (alignment.equals("BASELINE")) {
      y = 0;
      // adjust center by glyph width/height
      x = -glyph.width/2.0;
      // adjust center by glyph extent
      x -= glyph.leftExtent;
    } else if (alignment.equals("NONE")) {
      x = 0;
      y = 0;
    } else {
      x = 0;
      y = 0;
    }
  }
  
  void setChar(char c) {
    character = c;
    glyph = typeface.getGlyph(c);
    alignUpdate();
  }
  
  void text() {
    this.text(0, 0);
  }
  
  void text(float tx, float ty) {
    pushMatrix();
    translate(x, y);
    translate(0, 0);
    pushStyle();
    textFont(typeface);
    textSize(400);
    g.text(character, tx, ty);
    popStyle();
    popMatrix();
  }
  
  void box() {
    rect(x + glyph.leftExtent, y + -glyph.topExtent, glyph.width, glyph.height);
  }
  
  void boxbaseline() {
    topline();
    baseline();
    leftbaseline();
    rightbaseline();
  }
  
  void reticule() {
    midline();
    centerline();
  }
  
  void reticulebaseline() {
    midline();
    centerbaseline();
  }
  
  void topline() {
    line(x + glyph.leftExtent, y + -glyph.topExtent, 
      x + glyph.leftExtent + glyph.width, y + -glyph.topExtent);
  }
  
  void midline() {
    line(x + glyph.leftExtent, y + -glyph.topExtent + glyph.height/2.0, 
      x + glyph.leftExtent + glyph.width, y + -glyph.topExtent + glyph.height/2.0);
  }
  
  void baseline() {
    line(x + glyph.leftExtent, y, 
      x + glyph.leftExtent + glyph.width, y);
  }
  
  void bottomline() {
    line(x + glyph.leftExtent, y + glyph.height-glyph.topExtent, 
      x + glyph.leftExtent + glyph.width, y + glyph.height-glyph.topExtent);
  }
  
  void leftbaseline() {
    line(x + glyph.leftExtent, y + -glyph.topExtent, 
      x + glyph.leftExtent, y);
  }
  
  void leftline() {
    line(x + glyph.leftExtent, y + -glyph.topExtent, 
      x + glyph.leftExtent, y + -glyph.topExtent + glyph.height);
  }
  
  void centerline() {
    line(x + glyph.leftExtent + glyph.width/2.0, y + -glyph.topExtent, 
      x + glyph.leftExtent + glyph.width/2.0, y + -glyph.topExtent + glyph.height);
  }
  
  void centerbaseline() {
    line(x + glyph.leftExtent + glyph.width/2.0, y + -glyph.topExtent, 
      x + glyph.leftExtent + glyph.width/2.0, y);
  }
  
  void rightbaseline() {
    line(x + glyph.leftExtent + glyph.width, y + -glyph.topExtent, 
      x + glyph.leftExtent + glyph.width, y);
  }
  
  void rightline() {
    line(x + glyph.leftExtent + glyph.width, y + -glyph.topExtent, 
      x + glyph.leftExtent + glyph.width, y + -glyph.topExtent + glyph.height);
  }
}

void mousePressed() {
  // shuffle through glyphs in array
  if (mouseX > width/2) {
    i = (i+1) % 26;
  } else {
    i = i-1;
    if (i < 0) {
      i = 25;
    }
  }
  glyphbox.setChar(alphabet[i]);
}

```

 ![GlyphBoxes--screenshot2](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/1X/118c80d8c3e22da86ad2ce38f222a9f420dce300.png)

RE: textAlign – Note that I believe your approach (centering the glyph on its height) is not compatible with setting `textAlign(CENTER, CENTER)` in the main sketch. If you wanted to make the glyph boxes responsive to the global textAlign style you could actually use g.textAlign / textAlignY to detect the current mode – e.g. `if (g.textAlignY==CENTER)` – but I’m not actually sure how you would then alter GlyphBox.align to make assign correct offsets to a textAlign centered glyph so that the bounding box would line up.
