Skip to content

Commit cae9640

Browse files
authored
Calculate correct positions for underline and strikethrough (#2398)
* Calculate positions for underline and strikethrough when label uses SHRINK setting for overflow * Reduce strikethrough and underlin thickness to 12% of font size * Fix line position calculation to factor in contentScaleFactor * Fix line positioning due to line spacing * Add underline and strikethrough to label tests * Make line thickness multiple of 2 to avoid flickering during movement
1 parent 10a9904 commit cae9640

File tree

3 files changed

+91
-43
lines changed

3 files changed

+91
-43
lines changed

core/2d/Label.cpp

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1753,28 +1753,33 @@ void Label::updateContent()
17531753

17541754
_lineDrawNode->clear();
17551755

1756-
if (_numberOfLines && _currentLabelType != LabelType::STRING_TEXTURE)
1756+
if (_numberOfLines > 0 && _currentLabelType != LabelType::STRING_TEXTURE)
17571757
{
17581758
// This is the logic for TTF fonts
1759-
const float charheight = (_textDesiredHeight / _numberOfLines);
1760-
float thickness = charheight / 6;
1759+
float thickness = std::max(std::ceil(_lineHeight * _fontScale * 0.12f * 2) / 2.f, 2.f);
1760+
float nextY = _letterOffsetY;
1761+
auto contentScaleFactor = AX_CONTENT_SCALE_FACTOR();
1762+
float lineSpacing = _lineSpacing;
1763+
float lineHeight = _lineHeight * _fontScale / contentScaleFactor;
17611764

17621765
// atlas font
17631766
for (int i = 0; i < _numberOfLines; ++i)
17641767
{
17651768
if (_strikethroughEnabled)
17661769
{
1767-
float y = (_numberOfLines - i - 1) * charheight + charheight / 2;
1770+
auto y = nextY - lineHeight / 2;
17681771
_lineDrawNode->drawLine(Vec2(_linesOffsetX[i], y), Vec2(_linesWidth[i] + _linesOffsetX[i], y),
17691772
Color4F(lineColor), thickness);
17701773
}
17711774

17721775
if (_underlineEnabled)
17731776
{
1774-
float y = (_numberOfLines - i - 1) * charheight;
1777+
auto y = nextY - lineHeight;
17751778
_lineDrawNode->drawLine(Vec2(_linesOffsetX[i], y), Vec2(_linesWidth[i] + _linesOffsetX[i], y),
17761779
Color4F(lineColor), thickness);
17771780
}
1781+
1782+
nextY -= lineHeight + lineSpacing;
17781783
}
17791784
}
17801785
else if (_textSprite) // ...and is the logic for System fonts
@@ -1784,24 +1789,26 @@ void Label::updateContent()
17841789

17851790
// FIXME: system fonts don't report the height of the font correctly. only the size of the texture, which is POT
17861791
// FIXME: Might not work with different vertical alignments
1787-
float offsety = spriteSize.height / _numberOfLines;
1788-
float thickness = spriteSize.height / 6 / _numberOfLines;
1789-
1792+
const auto lineSize = spriteSize.height / static_cast<float>(_numberOfLines);
1793+
const auto thickness = std::max(std::ceil(lineSize * 0.12f * 2) / 2.f, 2.f);
1794+
17901795
if (_underlineEnabled)
1791-
{
1796+
{
1797+
const auto baseY = spriteSize.height / (static_cast<float>(_numberOfLines) * lineSize);
17921798
for (int i = 0; i < _numberOfLines; ++i)
17931799
{
1794-
float y = offsety * i;
1800+
float y = baseY + lineSize * i;
17951801
_lineDrawNode->drawLine(Vec2(0.0f, y), Vec2(spriteSize.width, y), Color4F(lineColor), thickness);
17961802
}
17971803
}
17981804

17991805
if (_strikethroughEnabled)
18001806
{
1801-
float _of = spriteSize.height / _numberOfLines / 2;
1807+
const auto baseY = lineSize - lineSize / 2;
1808+
18021809
for (int i = 0; i < _numberOfLines; ++i)
18031810
{
1804-
float y = _of + offsety * i;
1811+
float y = baseY + lineSize * i;
18051812
_lineDrawNode->drawLine(Vec2(0.0f, y), Vec2(spriteSize.width, y), Color4F(lineColor), thickness);
18061813
}
18071814
}

tests/cpp-tests/Source/LabelTest/LabelTestNew.cpp

Lines changed: 68 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2282,6 +2282,8 @@ LabelLayoutBaseTest::LabelLayoutBaseTest()
22822282

22832283
this->initAlignmentOption(size);
22842284

2285+
this->initUnderlineStrikethroughOption(size);
2286+
22852287
this->initDrawNode(size);
22862288

22872289
this->initSliders(size);
@@ -2394,6 +2396,41 @@ void LabelLayoutBaseTest::initAlignmentOption(const ax::Size& size)
23942396
this->addChild(menu);
23952397
}
23962398

2399+
void LabelLayoutBaseTest::initUnderlineStrikethroughOption(const ax::Size& size)
2400+
{
2401+
// add text alignment settings
2402+
MenuItemFont::setFontSize(12);
2403+
auto menu = Menu::create(MenuItemFont::create("Toggle Underline",
2404+
[this](Object*) {
2405+
if (_underline)
2406+
{
2407+
_label->disableEffect(LabelEffect::UNDERLINE);
2408+
}
2409+
else
2410+
{
2411+
_label->enableUnderline();
2412+
}
2413+
_underline = !_underline;
2414+
}
2415+
),
2416+
MenuItemFont::create("Toggle Strikethrough",
2417+
[this](Object*) {
2418+
if (_strikethrough)
2419+
{
2420+
_label->disableEffect(LabelEffect::STRIKETHROUGH);
2421+
}
2422+
else
2423+
{
2424+
_label->enableStrikethrough();
2425+
}
2426+
_strikethrough = !_strikethrough;
2427+
}
2428+
), nullptr);
2429+
menu->alignItemsVerticallyWithPadding(4);
2430+
menu->setPosition(Vec2(size.width - 60, 60));
2431+
this->addChild(menu);
2432+
}
2433+
23972434
void LabelLayoutBaseTest::initSliders(const ax::Size& size)
23982435
{
23992436
auto slider = ui::Slider::create();
@@ -3325,61 +3362,61 @@ LabelUnderlineStrikethroughMultiline::LabelUnderlineStrikethroughMultiline()
33253362
ttfConfig.strikethrough = true;
33263363

33273364
const int count = 7;
3328-
Label* label[count];
3365+
Label* labels[count];
33293366

3330-
label[0] = Label::createWithSystemFont("SystemFont TextVAlignment::TOP\nusing setTextColor(255, 0, 255, 100)", font, 14, Vec2::ZERO, TextHAlignment::LEFT, TextVAlignment::TOP);
3331-
label[0]->setTextColor(Color4B(255, 0, 255, 100));
3332-
label[0]->enableGlow(Color4B::BLUE);
3367+
labels[0] = Label::createWithSystemFont("SystemFont TextVAlignment::TOP\nusing setTextColor(255, 0, 255, 100)", font, 14, Vec2::ZERO, TextHAlignment::LEFT, TextVAlignment::TOP);
3368+
labels[0]->setTextColor(Color4B(255, 0, 255, 100));
3369+
labels[0]->enableGlow(Color4B::BLUE);
33333370

3334-
label[1] = Label::createWithSystemFont("SystemFont TextVAlignment::CENTER\nusing setColor(*RED*)", font, 14, Vec2::ZERO, TextHAlignment::RIGHT, TextVAlignment::CENTER);
3335-
label[1]->setColor(Color3B::RED);
3371+
labels[1] = Label::createWithSystemFont("SystemFont TextVAlignment::CENTER\nusing setColor(*RED*)", font, 14, Vec2::ZERO, TextHAlignment::RIGHT, TextVAlignment::CENTER);
3372+
labels[1]->setColor(Color3B::RED);
33363373

3337-
label[2] = Label::createWithSystemFont("SystemFont TextVAlignment::BOTTOM\nusingsetTextColor(*YELLOW)", font, 14,
3374+
labels[2] = Label::createWithSystemFont("SystemFont TextVAlignment::BOTTOM\nusingsetTextColor(*YELLOW)", font, 14,
33383375
Vec2::ZERO, TextHAlignment::CENTER, TextVAlignment::BOTTOM);
3339-
label[2]->setTextColor(Color4B::YELLOW);
3376+
labels[2]->setTextColor(Color4B::YELLOW);
33403377

3341-
label[3] = Label::createWithBMFont("fonts/bitmapFontTest5.fnt", "BMFont\nwith default color", TextHAlignment::CENTER, s.width);
3378+
labels[3] = Label::createWithBMFont("fonts/bitmapFontTest5.fnt", "BMFont\nwith default color", TextHAlignment::CENTER, s.width);
33423379

3343-
label[4] = Label::createWithBMFont("fonts/bitmapFontTest5.fnt", "BMFont\nusing setTextColor(0, 255, 0, 100)",
3380+
labels[4] = Label::createWithBMFont("fonts/bitmapFontTest5.fnt", "BMFont\nusing setTextColor(0, 255, 0, 100)",
33443381
TextHAlignment::CENTER, s.width);
3345-
label[4]->setTextColor(Color4B(0, 255, 0, 100));
3382+
labels[4]->setTextColor(Color4B(0, 255, 0, 100));
33463383

3347-
label[5] = Label::createWithTTF(ttfConfig, "TTF setColor(*BLUE*)\nwith multiline 1\nand a much more longer multiline 2",
3384+
labels[5] = Label::createWithTTF(ttfConfig, "TTF setColor(*BLUE*)\nwith multiline 1\nand a much more longer multiline 2",
33483385
TextHAlignment::LEFT, s.width);
3349-
label[5]->setColor(Color3B::BLUE);
3386+
labels[5]->setColor(Color3B::BLUE);
33503387

3351-
label[6] = Label::createWithTTF("TTF setTextColor(*RED*)\nwith multiline 1\nand a much more longer multiline 2",
3388+
labels[6] = Label::createWithTTF("TTF setTextColor(*RED*)\nwith multiline 1\nand a much more longer multiline 2",
33523389
font, 14);
3353-
label[6]->setTextColor(Color4B::RED);
3390+
labels[6]->setTextColor(Color4B::RED);
33543391

33553392
for (int i = 0; i < count; i++)
33563393
{
3357-
label[i]->setPosition(Vec2(label[i]->getBoundingBox().getMaxX() +10, s.height * 0.13f * (i + 1)));
3358-
label[i]->enableUnderline();
3359-
label[i]->enableStrikethrough();
3360-
addChild(label[i]);
3394+
labels[i]->setPosition(Vec2(labels[i]->getBoundingBox().getMaxX() +10, s.height * 0.13f * (i + 1)));
3395+
labels[i]->enableUnderline();
3396+
labels[i]->enableStrikethrough();
3397+
addChild(labels[i]);
33613398
}
33623399

33633400
Label* labelSize[10];
33643401
float y = 0;
33653402
for (int i = 0; i < 10; i++)
33663403
{
33673404
float fs = (i + 1) * 3;
3368-
labelSize[i] = Label::createWithTTF("UNTERLINE", "fonts/arial.ttf", fs);
3405+
labelSize[i] = Label::createWithTTF("UNDERLINE", "fonts/arial.ttf", fs);
33693406
labelSize[i]->setPosition(s.width / 1.3, s.height -50 - y);
33703407
y += (i + 2) * 3;
33713408
labelSize[i]->enableUnderline();
33723409
addChild(labelSize[i]);
33733410
}
33743411

3375-
auto menuItemU = MenuItemFont::create("disable/enable underline", [=](ax::Object* sender) {
3412+
auto menuItemU = MenuItemFont::create("toggle underline", [=](ax::Object* sender) {
33763413
static bool isEnabled = true;
33773414
for (int i = 0; i < count; i++)
33783415
{
33793416
if (isEnabled)
3380-
label[i]->disableEffect(LabelEffect::UNDERLINE);
3417+
labels[i]->disableEffect(LabelEffect::UNDERLINE);
33813418
else
3382-
label[i]->enableUnderline();
3419+
labels[i]->enableUnderline();
33833420
}
33843421
for (int i = 0; i < 10; i++)
33853422
{
@@ -3388,21 +3425,22 @@ LabelUnderlineStrikethroughMultiline::LabelUnderlineStrikethroughMultiline()
33883425
else
33893426
labelSize[i]->enableUnderline();
33903427
}
3391-
isEnabled = (isEnabled) ? false : true;
3428+
isEnabled = !isEnabled;
33923429
});
33933430
menuItemU->setFontSizeObj(12);
3394-
auto menuItemS = MenuItemFont::create("disable/enable strikethrough", [=](ax::Object* sender) {
3431+
auto menuItemS = MenuItemFont::create("toggle strikethrough", [=](ax::Object* sender) {
33953432
static bool isEnabled = true;
33963433
for (int i = 0; i < count; i++)
33973434
{
33983435
if (isEnabled)
3399-
label[i]->disableEffect(LabelEffect::STRIKETHROUGH);
3436+
labels[i]->disableEffect(LabelEffect::STRIKETHROUGH);
34003437
else
3401-
label[i]->enableStrikethrough();
3438+
labels[i]->enableStrikethrough();
34023439
}
3403-
isEnabled = (isEnabled) ? false : true;
3440+
isEnabled = !isEnabled;
34043441
});
34053442
menuItemS->setFontSizeObj(12);
3443+
34063444
auto menu = Menu::create(menuItemU, menuItemS, NULL);
34073445
addChild(menu);
34083446

@@ -3442,15 +3480,15 @@ LabelStrikethrough::LabelStrikethrough()
34423480
addChild(_label2a, 0, kTagBitmapAtlas2);
34433481
_label2a->setPosition(Vec2(s.width / 2, s.height * 1 / 3));
34443482

3445-
auto menuItem = MenuItemFont::create("disable underline", [&](ax::Object* sender) {
3483+
auto menuItem = MenuItemFont::create("disable strikethrough", [&](ax::Object* sender) {
34463484
_label2a->disableEffect(LabelEffect::STRIKETHROUGH);
34473485
_label1a->disableEffect(LabelEffect::STRIKETHROUGH);
34483486
});
34493487
menuItem->setFontSizeObj(12);
34503488
auto menu = Menu::createWithItem(menuItem);
34513489
addChild(menu);
34523490
auto winSize = Director::getInstance()->getWinSize();
3453-
menu->setPosition(winSize.width * 0.9, winSize.height * 0.25f);
3491+
menu->setPosition(winSize.width * 0.86, winSize.height * 0.25f);
34543492
}
34553493

34563494
std::string LabelStrikethrough::title() const

tests/cpp-tests/Source/LabelTest/LabelTestNew.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -715,17 +715,20 @@ class LabelLayoutBaseTest : public AtlasDemoNew
715715
void setAlignmentTop(ax::Object* sender);
716716
void setAlignmentMiddle(ax::Object* sender);
717717
void setAlignmentBottom(ax::Object* sender);
718-
718+
719719
void initWrapOption(const ax::Size& size);
720720
void initToggleLabelTypeOption(const ax::Size& size);
721721
void initAlignmentOption(const ax::Size& size);
722+
void initUnderlineStrikethroughOption(const ax::Size& size);
722723
void initFontSizeChange(const ax::Size& size);
723724
void initSliders(const ax::Size& size);
724725
void initTestLabel(const ax::Size& size);
725726
void initDrawNode(const ax::Size& size);
726727
ax::DrawNode* _drawNode;
727728
ax::Label* _label;
728729
int _labelType;
730+
bool _underline{};
731+
bool _strikethrough{};
729732
};
730733

731734
class LabelWrapByWordTest : public LabelLayoutBaseTest

0 commit comments

Comments
 (0)