Strange text-displacement within grid-spaced typography

Hello,

The idea for a project I’m working on rests on the use of typography in a grid. I wanted to put one letter in the center (x) of every cell of this grid. The size of the letter would be determined/altered by an underlying image, noise or some other input. I want to export the result to a .pdf file.

In principle I thought this would mean simply setting up a grid, setting the typeAlign-mode to (CENTER, BASELINE) and using small correction-calculations to sort out the correct placement for each letter. It’s seems however I was wrong about this. In my current results the x-position of every letter appears to be displaced slightly, and in varying degrees (in this case: depending on the brightness values of the underlying image (a simple gradient going from white to black diagonally) sometimes the displacement is shifted to the left, sometimes to the right), and I can’t work out what’s causing it. It seems however that all the letters in a column get aligned on their left side.

I have experimented with different sizes of typography. The displacement seems to be there regardless of the size of the type, it simply becomes more visible/obvious with smaller sizes - which is unfortunately what I’m working with.

What could be the cause of this displacement? Might it have to do with the inbuilt margins within the types’ .ttf file? And what would be the ‘smartest’ way to work around it? Considering this is the size I have to work with simply making everything bigger wouldn’t be an option.

This screenshot might give a good depiction of what I mean. The blue squares indicate the middle of each cell (visible by the white outline). You can see how the letters aren’t matching it’s position, but are displaced around them. I added a guideline at the letter ‘m’ so you can see how they all seem to match up to their left side.

You’ll be able to find my code below.

import processing.pdf.*;

//GRID VARIABLES
float cols, rows, total, w, h, scl, mW, mH;

//TYPESIZE VARIABLES
float tW, tH;

//FONTS
PFont suis, helv;

//CHARACTER SETUP
String sentence = "adamsdramatised";
char[] letters = sentence.toCharArray();

//SPACING ARRAYS
float[] spacingW = { 1, 1, 1, 1.2, .94, 1, .8, 1, 1.2, 1, .84, .75, .94, 1, 1 };

//TRIGONOMETRIC AMPERS
float woSt, woMp, wIncr;
float yoSt, yoMp, yIncr;

//IMAGES
PImage img;

//COLOURS
color bg = #fde800;

void setup() {
  size(4800, 480, PDF, "GH_Alt.pdf");
  //size(2400, 240);
  textMode(SHAPE);

  //LOADING FONTS
  suis = createFont("SuisseIntlMono-Regular.otf",10);
  helv = createFont("HelveticaNeueLTW1G-Bd.otf",10);

  //GRID ELEMENTS SETUP
  cols = 600;
  rows = 60;
  total = cols * rows;
  w = width/cols;
  h = height/rows;
  mW = w/2;
  mH = h/2;
  tW = w;
  tH = h;

  //TRIGONOMETRIC AMPERS
  yoSt = 0;
  yIncr = .5;
  woSt = 0;
  wIncr = .4;

  //STYLE
  textFont(helv);

  //CONSOLE/TESTING


  //LOADING IMAGE
  img = loadImage("gradient.png");

  //PLAYBACK/PERFORMANCE
  noLoop();
}

void draw() {
  background(bg);

  //wMod determines which changing width the rectangles in the grid get multiplied by
  //It's the count for the widths[] array
  //sWk = spacingW k | k for count
  int sWk = 0;

  int k = 0;
  int j = 0;
  for (float y = mH; y < height; y += h) {
    j++;
    int i = 0;
    for (float x = mW; x < width; x += (w * spacingW[sWk])) {
      int index = int(j + i * (cols*rows));
      sWk = int(i % letters.length);

      float tx = (i * w) * spacingW[sWk];

      //IMAGE VALUES
      color c = img.get(int(x), int(y));
      //float imgAmper = map(brightness(c), 0, 255, .2, 2);
      float imgAmper = map(brightness(c), 0, 255, 1, 5);
      float rowAmper = map(sin(yoSt), -1, 1, .9, 1.3);      

      //TYPOGRAPHY
      fill(0);
      textSize((imgAmper));
      textAlign(CENTER, BASELINE);
      int l = i % letters.length;
      //pushMatrix();
      //translate(x,y);
      //rotate(radians((i*4)+(j*4)));
      text(letters[l], (x), y);
      //popMatrix();

      ////GUIDING RECTANGLES
      rectMode(CORNER);
      noFill();
      stroke(-1);
      strokeWeight(.1);
      rect(x-mW, y, (w*spacingW[sWk]), h);

      fill(255, 0, 0);
      noStroke();
      rect(x-mW, y, 1, 1);

      fill(0, 0, 255);
      rectMode(CENTER);
      noStroke();
      rect((x-mW)+((w*spacingW[sWk])/2), y, 1, 1);

      woSt += wIncr;    
      i++;
      k++;
      println(k);
    }
    yoSt += yIncr;
  }

  println("finished");
  exit();
}

The code is a bit messy, apologies for that.

Thanks a lot in advance. I’m really curious to see if someone is able to help me with this.

Try offsetting each letter’s x position using textWidth(…) (0.5 * textWidth(“m”)).