I’m currently in the same position he was, trying to create a TTF label (cocos2d-x v3) using Label::createWithTTF() function, and I was wondering if there is an efficient way to create my label so it fits a boundingbox (automatically adjusting the size of the font, based on the string of the label).
This, or any other way to make sure (and not using a BMfont) my label fits a defined size (so I can create my label in all languages at runtime).
is it possible with current base class, or is there a way to achieve this otherwise?
I noticed there is no setFontSize for the cocos2d::Label class, so I can’t even iterate and try to find a fitting font without recreating the object everytime.
Here is the code I use (cocos2d-x v2.2, you can probably achieve the same in 3.0).
delegate is the actual CCLabelTTF
realDimensions is the size you want your label to fit in
fitType is an enum with NoResize (do nothing, especially for large labels which can go over the texture limit size), CutEnd (to cut the end of the label to fit in without changing the font size) and ResizeFont (that’s probably what you are looking for)
I didn’t touch that code in over 6 months, feel free to ask questions if something non-obvious isn’t explained by the comments (I did a binary search for cutEnd because I runned into performance issues. Note that I use a modified v2.2 version for Android, with speed optimizations in the native CCLabelTTF generation).
if(realDimensions.width != 0 && realDimensions.height != 0 && fitType != NoResize)
{
bool wasChanged = false;
float scale = this->getScale();
CCSize size = delegate->getContentSize();
//Add a 5% margin for fitInside comparison since the algorithm underneath is not exact …
bool fitInside = size.height * scale <= realDimensions.height * 1.05 && size.width * scale <= realDimensions.width * 1.05;
//Used by CutEnd to perform a binary search (optimization because CCLabelTTF::updateTexture is slow on Android)
//If you run into performance issues, you should also cache the CutEnd results
std::string original = delegate->getString();
int end = utf8_len(original);
int start = fitInside || fitType != CutEnd ? end : 0; //If it already fit, bypass the while
while((fitType != CutEnd && !fitInside)
|| end - start > 1) //There is one character precision (it may cut one more character than necessary)
{
wasChanged = true;
I thought about using a Node->setScale() call to adjust the size of the label to fit inside my box, but I feared it might not be visualy good. I’ll try your solution (realy faster than having to recreate a texture with the new font size), even if I prefer not having to scale the label.
Here’s my solution, I’m using cocos2d-x 3.4. basically I start with a big font size and iterate by dividing the font size by two each time until it fits the box, then sizing it up to fit.
Unfortunately, there’s no setFontsize method for the Label class, so I need to recreate a label for the iterations, so there could be performance improvement.