Skip to content

Drawing Text

SpiDrone edited this page Jul 22, 2026 · 5 revisions

Drawing Text

This assumes you've already registered a font from the Adding Fonts page. All examples below use a ResourceLocation font ID like mymod:myfont, but every method also has a String overload ("mymod:myfont") and a no-font overload that just falls back to Minecraft's vanilla font.

Basics

UIGraphicsHelper.drawCustomFont(graphics, myFont, "Hello World", x, y, 0xFFFFFFFF, false);
Param Meaning
graphics The GuiGraphics from your render call
myFont The font's registered ID
x, y Anchor position, meaning depends on align (below)
color ARGB int, e.g. 0xFFFFFFFF for opaque white
dropShadow Whether to render vanilla's text drop shadow

Shorter overloads exist that drop the trailing params:

UIGraphicsHelper.drawCustomFont(graphics, myFont, "Hello", x, y, color);      // no drop shadow
UIGraphicsHelper.drawCustomFont(graphics, myFont, "Hello", x, y);             // + white text
UIGraphicsHelper.drawCustomFont(graphics, "Hello", x, y);                     // + vanilla font

Alignment

public enum TextAlign { LEFT, CENTER, RIGHT }

Add align as the last argument. It changes what x means:

  • LEFT (default) - x is the left edge of the text
  • CENTER - x is the horizontal center point
  • RIGHT - x is the right edge of the text
// Title, centered on screen
UIGraphicsHelper.drawCustomFont(graphics, myFont, "Title", w / 2, 20, 0xFFFFFFFF, false, TextAlign.CENTER);

// Numbers pinned to the right edge UIGraphicsHelper.drawCustomFont(graphics, myFont, "42", w - 10, 40, 0xFFFFFFFF, false, TextAlign.RIGHT);

// Names pinned to the left edge, same as leaving align out UIGraphicsHelper.drawCustomFont(graphics, myFont, "Player Name", 10, 40, 0xFFFFFFFF, false, TextAlign.LEFT);

Good for HUD rows where numbers and labels need to stay lined up on opposite edges no matter how long the text is.

Color Effects

Instead of a flat int color you can pass a ComponentEffects.TextEffect for per character coloring. Check ComponentEffects for the full list, currently:

ComponentEffects.solid(int color)                       // flat color, same as passing color directly
ComponentEffects.gradient(int colorStart, int colorEnd)  // smooth blend across the string
ComponentEffects.rainbow()                                // animated hue cycle
ComponentEffects.rainbow(float speed)                     // faster/slower cycle
ComponentEffects.holographic(int color1, int color2)      // animated shimmer between two colors
UIGraphicsHelper.drawCustomFont(graphics, myFont, "Legendary", x, y,
    ComponentEffects.gradient(0xFFFFD700, 0xFFFF4500), false);

UIGraphicsHelper.drawCustomFont(graphics, myFont, "Rainbow Title", x, y, ComponentEffects.rainbow(), false, TextAlign.CENTER);

Combining color effects

ComponentEffects.combine(...) blends multiple color effects together, averaged per character:

TextEffect blended = ComponentEffects.combine(
    ComponentEffects.rainbow(),
    ComponentEffects.gradient(0xFFFFFFFF, 0xFF000000)
);
UIGraphicsHelper.drawCustomFont(graphics, myFont, "Blended", x, y, blended, false);

Motion Effects

Motion effects move each character on its own. Pass one alongside a color effect using ComponentEffects.TextOffset:

ComponentEffects.wave()                                              // gentle up/down bob per character
ComponentEffects.wave(float amplitude, float speed)                   // custom height/speed
ComponentEffects.typewriterBounce()                                   // one letter bounces up at a time, left to right
ComponentEffects.typewriterBounce(float amplitude, long msPerChar)    // custom height/timing
// Plain white text with a wave
UIGraphicsHelper.drawCustomFont(graphics, myFont, "Wavy Text", x, y,
    ComponentEffects.solid(0xFFFFFFFF), ComponentEffects.wave(), false);

// Rainbow color plus wave motion UIGraphicsHelper.drawCustomFont(graphics, myFont, "Rainbow Wave", x, y, ComponentEffects.rainbow(), ComponentEffects.wave(), false);

// Typewriter style bounce UIGraphicsHelper.drawCustomFont(graphics, myFont, "Typewriter", x, y, ComponentEffects.solid(0xFFFFFFFF), ComponentEffects.typewriterBounce(), false);

Combining motion effects

ComponentEffects.combine(...) works for offset effects too, summed per character this time:

TextOffset busy = ComponentEffects.combine(ComponentEffects.wave(), ComponentEffects.typewriterBounce());

Stacking multiple motion effects gets messy fast. Try lower amplitudes first if you go this route.

Note: motion effects draw one character at a time instead of the whole string in a single call, since each glyph needs its own position. Fine for titles and short labels, not something you want to use on a full paragraph.

Wrapped Text in a Bounding Box

drawCustomFontBound auto wraps text to fit inside a box, with an optional manual split character for forced line breaks. Anything that would overflow the box gets clipped instead of drawn outside it.

int linesDrawn = UIGraphicsHelper.drawCustomFontBound(
    graphics, myFont, "Some long description$New paragraph here",
    '$',                    // manual split character, forces a break wherever it appears
    x1, y1, x2, y2,          // box bounds
    0xFFFFFFFF, false,       // color, drop shadow
    TextAlign.LEFT            // aligns each wrapped line within the box width
);

The $ splits the string into segments first, then each segment gets auto wrapped to fit the box width. Useful for translations, where a translator needs some control over line breaks that auto wrapping alone can't guarantee.

Returns the number of lines actually drawn, useful if you want to size a panel around the text afterward.

Measuring Text

Before drawing into a layout you can measure how wide text will render in a given font:

int width = UIGraphicsHelper.measureCustomFontWidth(myFont, "Hello World");
# Drawing Text

This assumes you've already registered a font from the [Adding Fonts](Adding-Fonts) page. All examples below use a ResourceLocation font ID like mymod:myfont, but every method also has a String overload ("mymod:myfont") and a no-font overload that just falls back to Minecraft's vanilla font.

Basics

UIGraphicsHelper.drawCustomFont(graphics, myFont, "Hello World", x, y, 0xFFFFFFFF, false);
Param Meaning
graphics The GuiGraphics from your render call
myFont The font's registered ID
x, y Anchor position, meaning depends on align (below)
color ARGB int, e.g. 0xFFFFFFFF for opaque white
dropShadow Whether to render vanilla's text drop shadow

Shorter overloads exist that drop the trailing params:

UIGraphicsHelper.drawCustomFont(graphics, myFont, "Hello", x, y, color);      // no drop shadow
UIGraphicsHelper.drawCustomFont(graphics, myFont, "Hello", x, y);             // + white text
UIGraphicsHelper.drawCustomFont(graphics, "Hello", x, y);                     // + vanilla font

Alignment

public enum TextAlign { LEFT, CENTER, RIGHT }

Add align as the last argument. It changes what x means:

  • LEFT (default) - x is the left edge of the text
  • CENTER - x is the horizontal center point
  • RIGHT - x is the right edge of the text
// Title, centered on screen
UIGraphicsHelper.drawCustomFont(graphics, myFont, "Title", w / 2, 20, 0xFFFFFFFF, false, TextAlign.CENTER);

// Numbers pinned to the right edge
UIGraphicsHelper.drawCustomFont(graphics, myFont, "42", w - 10, 40, 0xFFFFFFFF, false, TextAlign.RIGHT);

// Names pinned to the left edge, same as leaving align out
UIGraphicsHelper.drawCustomFont(graphics, myFont, "Player Name", 10, 40, 0xFFFFFFFF, false, TextAlign.LEFT);

Good for HUD rows where numbers and labels need to stay lined up on opposite edges no matter how long the text is.

Color Effects

Instead of a flat int color you can pass a ComponentEffects.TextEffect for per character coloring. Check ComponentEffects for the full list, currently:

ComponentEffects.solid(int color)                       // flat color, same as passing color directly
ComponentEffects.gradient(int colorStart, int colorEnd)  // smooth blend across the string
ComponentEffects.rainbow()                                // animated hue cycle
ComponentEffects.rainbow(float speed)                     // faster/slower cycle
ComponentEffects.holographic(int color1, int color2)      // animated shimmer between two colors
UIGraphicsHelper.drawCustomFont(graphics, myFont, "Legendary", x, y,
    ComponentEffects.gradient(0xFFFFD700, 0xFFFF4500), false);

UIGraphicsHelper.drawCustomFont(graphics, myFont, "Rainbow Title", x, y,
    ComponentEffects.rainbow(), false, TextAlign.CENTER);

Combining color effects

ComponentEffects.combine(...) blends multiple color effects together, averaged per character:

TextEffect blended = ComponentEffects.combine(
    ComponentEffects.rainbow(),
    ComponentEffects.gradient(0xFFFFFFFF, 0xFF000000)
);
UIGraphicsHelper.drawCustomFont(graphics, myFont, "Blended", x, y, blended, false);

Motion Effects

Motion effects move each character on its own. Pass one alongside a color effect using ComponentEffects.TextOffset:

ComponentEffects.wave()                                              // gentle up/down bob per character
ComponentEffects.wave(float amplitude, float speed)                   // custom height/speed
ComponentEffects.typewriterBounce()                                   // one letter bounces up at a time, left to right
ComponentEffects.typewriterBounce(float amplitude, long msPerChar)    // custom height/timing
// Plain white text with a wave
UIGraphicsHelper.drawCustomFont(graphics, myFont, "Wavy Text", x, y,
    ComponentEffects.solid(0xFFFFFFFF), ComponentEffects.wave(), false);

// Rainbow color plus wave motion
UIGraphicsHelper.drawCustomFont(graphics, myFont, "Rainbow Wave", x, y,
    ComponentEffects.rainbow(), ComponentEffects.wave(), false);

// Typewriter style bounce
UIGraphicsHelper.drawCustomFont(graphics, myFont, "Typewriter", x, y,
    ComponentEffects.solid(0xFFFFFFFF), ComponentEffects.typewriterBounce(), false);

Combining motion effects

ComponentEffects.combine(...) works for offset effects too, summed per character this time:

TextOffset busy = ComponentEffects.combine(ComponentEffects.wave(), ComponentEffects.typewriterBounce());

Stacking multiple motion effects gets messy fast. Try lower amplitudes first if you go this route.

Note: motion effects draw one character at a time instead of the whole string in a single call, since each glyph needs its own position. Fine for titles and short labels, not something you want to use on a full paragraph.

Wrapped Text in a Bounding Box

drawCustomFontBound auto wraps text to fit inside a box, with an optional manual split character for forced line breaks. Anything that would overflow the box gets clipped instead of drawn outside it.

int linesDrawn = UIGraphicsHelper.drawCustomFontBound(
    graphics, myFont, "Some long description$New paragraph here",
    '$',                    // manual split character, forces a break wherever it appears
    x1, y1, x2, y2,          // box bounds
    0xFFFFFFFF, false,       // color, drop shadow
    TextAlign.LEFT            // aligns each wrapped line within the box width
);

The $ splits the string into segments first, then each segment gets auto wrapped to fit the box width. Useful for translations, where a translator needs some control over line breaks that auto wrapping alone can't guarantee.

Returns the number of lines actually drawn, useful if you want to size a panel around the text afterward.

Measuring Text

Before drawing into a layout you can measure how wide text will render in a given font:

int width = UIGraphicsHelper.measureCustomFontWidth(myFont, "Hello World");

Clone this wiki locally