Skip to content

Add geode::Label - #2144

Draft
prevter wants to merge 3 commits into
mainfrom
geode-label
Draft

Add geode::Label#2144
prevter wants to merge 3 commits into
mainfrom
geode-label

Conversation

@prevter

@prevter prevter commented Aug 1, 2026

Copy link
Copy Markdown
Member

Adds a complete CCLabelBMFont drop-in replacement that offers improved performance and support for fallback fonts, emojis and embedded nodes.

Main features:

  • Custom font cache that parses things ~20 times faster than cocos2d
  • VBO based rendering compared to spawning a CCSprite for each character, which is both faster and requires less memory
  • Improved performance and caching at every step possible
  • Supports Left, Center, Right and Justify (!!) text alignment options
  • Dirty flag system which only re-evaluates changes when it's time to render the label.
  • Fallback fonts support, which allows splitting your font files and support multiple languages.
  • Emoji system for embedding custom sprites or even dynamic nodes such as buttons.
  • setLabelLimitWidth/Height/Size as opposed to CCLabelBMFont::limitLabelWidth, which automatically rescale on any text change.
  • setFitBox (which i like to call limitLabelWidth on steroids) which enables line wrap and attempts to match the given aspect ratio as close as possible (scaling down extends the line wrap width, perfect for comment cells and similar places with limited space)
  • Technically supports up to 16M characters, unlike 16K supported by cocos2d batches (please don't try this at home anyways).

Some benchmarks against CCLabelBMFont and my older AdvancedLabel implementation:

Benchmark Name cocos2d-x AdvancedLabel geode::Label vs cocos2d avg Notes
.fnt parsing 116.81 ms (114.08 ms) [89.80-273.76 ms] 3.10 ms (2.95 ms) [2.81-9.94 ms] 5.61 ms (5.48 ms) [5.27-16.65 ms] x20.82 faster geode::Label does content scale premultiplication during parsing
simple create() 16.61 μs (12.20 μs) [6.70 μs - 1.66 ms] 18.04 μs (13.80 μs) [7.30 μs - 3.77 ms] 4.18 μs (3.00 μs) [2.00-84.80 μs] x3.97 faster
setString() [32 chars] 11.57 μs (11.00 μs) [10.50-19.80 μs] 3.55 μs (3.40 μs) [3.10-8.30 μs] 1.22 μs (1.20 μs) [1.00-5.50 μs] x9.46 faster this includes calling validate() for geode::Label
setString() [256 chars] 111.05 μs (109.40 μs) [107.80-179.20 μs] 23.37 μs (23.20 μs) [22.30-55.60 μs] 7.94 μs (7.90 μs) [7.40-39.80 μs] x13.99 faster
setString() [256 chars + newlines] 107.80 μs (106.80 μs) [104.00-234.80 μs] 24.34 μs (24.20 μs) [22.90-30.70 μs] 7.92 μs (7.90 μs) [7.30-18.20 μs] x13.61 faster
setString() [256 chars + autowrap] 183.51 μs (183.60 μs) [176.20-253.50 μs] 29.81 μs (29.70 μs) [25.00-62.90 μs] 8.02 μs (8.00 μs) [7.40-13.80 μs] x22.88 faster
re-layout (alignment) 56.63 μs (56.80 μs) [51.10-98.00 μs] 20.37 μs (20.30 μs) [17.20-32.70 μs] 2.56 μs (2.50 μs) [2.50-8.10 μs] x22.12 faster all used a randomly generated string with 256 chars with newlines put around
re-paint (color) 4.22 μs (4.20 μs) [4.10-9.60 μs] 4.04 μs (4.00 μs) [3.90-9.70 μs] 256.20 ns (300.00 ns) [200.00 ns - 4.40 μs] x16.48 faster
visit() call [256 chars] 2.19 μs (2.20 μs) [2.10-12.30 μs] 2.30 μs (2.30 μs) [2.20-9.70 μs] 1.23 μs (1.20 μs) [1.10-10.00 μs] x1.78 faster

format: average time (median time) [min - max]

TODO:

  • Some way to handle string contents for embedded nodes
  • Add rich-text / color tag support
  • Fix fonts without uppercase letters
  • Add more create() overloads?
  • Label shadows
  • Test everything one more time on all platforms

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant