Jaggedy motion of text moving inside circle (PROCESSING)

Seeing as you need to use floats as position, which for some reason the default renderer seems to dislike specifically regarding text, you can switch to another rendered.

Of course, this max tax your machine a little bit more. There's a cost to this kind of maneuver.

size(500, 500, P3D);

You'll notice that the move is significantly smoother, and appears slightly different. That's because processing will be using your graphic card to process some of the math involved in drawing your sketch. Theoretically, your sketch should run smoother and faster, but some people see their CPU usage goes up while doing this, or sometimes the sketch takes slightly more time to load. People with issues with P3D should be the minority, though.

Hope this helps. I think this issue is freaky.


This doesn't seem possible to overcome with the text() method at least.

What's seemingly happening in each renderer (except P3D) is that text is being drawn at integer intervals (no sub-pixel positioning), jumping between pixels every additional +=0.5 in either axis and this causes the jagged motion.

In Java2D mode for example (PGraphicsJava2D) text/character position is explicitly cast to an integer:

g2.drawChars(buffer, start, length, (int) (x + 0.5f), (int) (y + 0.5f));

I don't see the coordinates being cast to integers in the FX2D and P2D renderers so the rounding must lie with the renderer itself (glyphs are drawn/stamped individually as PImages so perhaps that is why).


Perhaps the simplest workaround is to render the text as a PShape (vector graphic). To do this we first load a font (as a PFont) then use the .charAt() method to get a vector shape for each character. Characters can be arranged into a single PShape and finally drawn as a vector using the shape() method. Thankfully, shape() allows sub-pixel positioning so we avoid the jaggedness present in text().

The getVectorText() method below does this for you.

Code

import processing.javafx.*;

PFont font;

void setup() {
  size(500, 500, FX2D);
  font = createFont("Arial", 24);
  textFont(font);
}

float x = 250, y = 250;

void draw() {
  background(255);
  x += 0.1;
  y += 0.1;
  fill(120, 120, 120);
  ellipse(x, y, 50, 50);
  fill(0);
  text("hello", x, y);
  shape(getVectorText("hello"), x + 60, y);
}

PShape getVectorText(String text) {
  PShape textShape = createShape(GROUP);
  textShape.setStroke(false);

  float translationX = 0;
  for (int i = 0; i < text.length(); i++) {
    char c = text.charAt(i);
    PShape character = font.getShape(c);

    character.translate(translationX, 0); // offset each character
    character.disableStyle(); // parent shape should override style
    textShape.addChild(character);

    translationX += font.width(c) * font.getSize(); // width() returns width with size 1, so scale up
  }

  return textShape;
}

Outcome

A comparison between the text drawn using text() (jagged) vs shape() (smooth).

enter image description here