Skip to content

Commit 6ffe0bd

Browse files
committed
Improve text SDF rendering content dirty strategy
Also correct indent and add hints comments
1 parent 763b6af commit 6ffe0bd

4 files changed

Lines changed: 117 additions & 81 deletions

File tree

core/2d/Label.cpp

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -778,15 +778,15 @@ void Label::updateUniformLocations()
778778
_effectTypeLocation = _programState->getUniformLocation(backend::Uniform::EFFECT_TYPE);
779779
}
780780

781-
void Label::setFontAtlas(FontAtlas* atlas, bool distanceFieldEnabled /* = false */, bool useA8Shader /* = false */)
781+
bool Label::setFontAtlas(FontAtlas* atlas, bool distanceFieldEnabled /* = false */, bool useA8Shader /* = false */)
782782
{
783783
if (atlas)
784784
{
785785
_systemFontDirty = false;
786786
}
787787

788788
if (atlas == _fontAtlas)
789-
return;
789+
return false;
790790

791791
AX_SAFE_RETAIN(atlas);
792792
if (_fontAtlas)
@@ -818,6 +818,8 @@ void Label::setFontAtlas(FontAtlas* atlas, bool distanceFieldEnabled /* = false
818818
_currLabelEffect = LabelEffect::NORMAL;
819819
updateShaderProgram();
820820
}
821+
822+
return true;
821823
}
822824

823825
bool Label::setTTFConfig(const TTFConfig& ttfConfig)
@@ -1280,11 +1282,14 @@ bool Label::updateQuads()
12801282

12811283
bool Label::setTTFConfigInternal(const TTFConfig& ttfConfig)
12821284
{
1285+
unsigned int mods = 0;
1286+
mods |= (ttfConfig.fontSize != _fontConfig.fontSize);
1287+
mods |= (ttfConfig.outlineSize != _fontConfig.outlineSize);
12831288
_fontConfig = ttfConfig;
1284-
return updateTTFConfigInternal();
1289+
return updateTTFConfigInternal(mods);
12851290
}
12861291

1287-
bool Label::updateTTFConfigInternal()
1292+
bool Label::updateTTFConfigInternal(unsigned int mods)
12881293
{
12891294
FontAtlas* newAtlas = FontAtlasCache::getFontAtlasTTF(&_fontConfig);
12901295

@@ -1293,9 +1298,17 @@ bool Label::updateTTFConfigInternal()
12931298
reset();
12941299
return false;
12951300
}
1296-
_contentDirty = true;
1301+
12971302
_currentLabelType = LabelType::TTF;
1298-
setFontAtlas(newAtlas, _fontConfig.distanceFieldEnabled, true);
1303+
bool atlasUpdated = setFontAtlas(newAtlas, _fontConfig.distanceFieldEnabled, true);
1304+
1305+
/*
1306+
* In distance field text rendering, different font sizes share the same `fontAtlas`, so we need to additionally
1307+
* check if `fontSize` has changed in order to set `contentDirty`. The same applies to `outlineSize`. See
1308+
* `FontAtlasCache` for details.
1309+
*/
1310+
if (!atlasUpdated && mods && _fontConfig.distanceFieldEnabled)
1311+
_contentDirty = true;
12991312

13001313
if (_fontConfig.outlineSize > 0)
13011314
{
@@ -1305,7 +1318,8 @@ bool Label::updateTTFConfigInternal()
13051318
}
13061319
else
13071320
{
1308-
if(_currLabelEffect != LabelEffect::GLOW){
1321+
if (_currLabelEffect != LabelEffect::GLOW)
1322+
{
13091323
_currLabelEffect = LabelEffect::NORMAL;
13101324
updateShaderProgram();
13111325
}
@@ -1379,6 +1393,7 @@ void Label::enableGlow(const Color4B& glowColor)
13791393
config.outlineSize = 0;
13801394
++mods;
13811395
}
1396+
// Note: axmol only support Glow effect in SDF rendering mode
13821397
if (!_fontConfig.distanceFieldEnabled)
13831398
{
13841399
config.distanceFieldEnabled = true;

core/2d/Label.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -765,7 +765,7 @@ class AX_DLL Label : public Node, public LabelProtocol, public BlendProtocol
765765

766766
void clearTextures();
767767

768-
virtual void setFontAtlas(FontAtlas* atlas, bool distanceFieldEnabled = false, bool useA8Shader = false);
768+
virtual bool setFontAtlas(FontAtlas* atlas, bool distanceFieldEnabled = false, bool useA8Shader = false);
769769
bool getFontLetterDef(char32_t character, FontLetterDefinition& letterDef) const;
770770

771771
void computeStringNumLines();
@@ -805,7 +805,7 @@ class AX_DLL Label : public Node, public LabelProtocol, public BlendProtocol
805805
#endif
806806
void scaleFontSize(float fontSize);
807807
bool setTTFConfigInternal(const TTFConfig& ttfConfig);
808-
bool updateTTFConfigInternal();
808+
bool updateTTFConfigInternal(unsigned int mods = 0);
809809
void setBMFontSizeInternal(float fontSize);
810810
bool isLetterHorizontallyClamped(float letterPositionX, float letterWidth, int lineIndex, float offsetX);
811811
void restoreFontSize();

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

Lines changed: 92 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/****************************************************************************
22
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
3+
Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md).
34
45
https://axmol.dev/
56
@@ -1334,7 +1335,7 @@ std::string LabelTTFDistanceField::subtitle() const
13341335
LabelTitleButtonTTFDistanceField::LabelTitleButtonTTFDistanceField()
13351336
{
13361337
auto size = Director::getInstance()->getWinSize();
1337-
1338+
13381339
FontFreeType::setShareDistanceFieldEnabled(false);
13391340
auto button = ax::ui::Button::create();
13401341
button->setTitleText("Should be the same size");
@@ -1382,85 +1383,102 @@ std::string LabelTitleButtonTTFDistanceField::subtitle() const
13821383
LabelTTFSDF::LabelTTFSDF()
13831384
{
13841385
auto size = Director::getInstance()->getWinSize();
1385-
1386+
13861387
FontFreeType::setShareDistanceFieldEnabled(false);
13871388
Label* title = Label::createWithTTF("Normal", "fonts/Marker Felt.ttf", 20);
13881389
this->addChild(title);
1389-
title->setPosition(Vec2(size.width*3/4, size.height*0.75));
1390-
_labelNormal = Label::createWithTTF("Should be the same", "fonts/Marker Felt.ttf", 20);;
1390+
title->setPosition(Vec2(size.width * 3 / 4, size.height * 0.75));
1391+
_labelNormal = Label::createWithTTF("Should be the same", "fonts/Marker Felt.ttf", 20);
13911392
this->addChild(_labelNormal);
1392-
_labelNormal->setPosition(Vec2(size.width*3/4, size.height*0.65));
1393-
1393+
_labelNormal->setPosition(Vec2(size.width * 3 / 4, size.height * 0.65));
1394+
13941395
FontFreeType::setShareDistanceFieldEnabled(true);
13951396
title = Label::createWithTTF("SDF", "fonts/Marker Felt.ttf", 20);
13961397
this->addChild(title);
1397-
title->setPosition(Vec2(size.width/4, size.height*0.75));
1398-
_labelSDF= Label::createWithTTF("Should be the same", "fonts/Marker Felt.ttf", 20);
1398+
title->setPosition(Vec2(size.width / 4, size.height * 0.75));
1399+
_labelSDF = Label::createWithTTF("Should be the same", "fonts/Marker Felt.ttf", 20);
13991400
this->addChild(_labelSDF);
1400-
_labelSDF->setPosition(Vec2(size.width/4, size.height*0.65));
1401-
auto config = _labelSDF->getTTFConfig();
1401+
_labelSDF->setPosition(Vec2(size.width / 4, size.height * 0.65));
1402+
auto config = _labelSDF->getTTFConfig();
14021403
config.distanceFieldEnabled = true;
14031404
_labelSDF->setTTFConfig(config);
1404-
1405-
initToggleLabel("enableItalics", Vec2(size.width*0.15, size.height*0.25), [=, this](Object*obj, ax::ui::CheckBox::EventType type){
1406-
if(type == ax::ui::CheckBox::EventType::SELECTED){
1405+
1406+
initToggleLabel("enableItalics", Vec2(size.width * 0.15, size.height * 0.25),
1407+
[=, this](Object* obj, ax::ui::CheckBox::EventType type) {
1408+
if (type == ax::ui::CheckBox::EventType::SELECTED)
1409+
{
14071410
_labelSDF->enableItalics();
14081411
_labelNormal->enableItalics();
1409-
}else{
1412+
}
1413+
else
1414+
{
14101415
_labelSDF->disableEffect(ax::LabelEffect::ITALICS);
14111416
_labelNormal->disableEffect(ax::LabelEffect::ITALICS);
14121417
}
14131418
});
1414-
initToggleLabel("enableShadow", Vec2(size.width*0.15, size.height*0.35), [=, this](Object*obj, ax::ui::CheckBox::EventType type){
1415-
if(type == ax::ui::CheckBox::EventType::SELECTED){
1416-
_labelSDF->enableShadow(Color4B::YELLOW,Vec2(-1,-1));
1417-
_labelNormal->enableShadow(Color4B::YELLOW,Vec2(-1,-1));
1418-
}else{
1419+
initToggleLabel("enableShadow", Vec2(size.width * 0.15, size.height * 0.35),
1420+
[=, this](Object* obj, ax::ui::CheckBox::EventType type) {
1421+
if (type == ax::ui::CheckBox::EventType::SELECTED)
1422+
{
1423+
_labelSDF->enableShadow(Color4B::YELLOW, Vec2(-1, -1));
1424+
_labelNormal->enableShadow(Color4B::YELLOW, Vec2(-1, -1));
1425+
}
1426+
else
1427+
{
14191428
_labelSDF->disableEffect(ax::LabelEffect::SHADOW);
14201429
_labelNormal->disableEffect(ax::LabelEffect::SHADOW);
14211430
}
14221431
});
1423-
initToggleLabel("enableBold", Vec2(size.width*0.15, size.height*0.45), [=, this](Object*obj, ax::ui::CheckBox::EventType type){
1424-
if(type == ax::ui::CheckBox::EventType::SELECTED){
1432+
initToggleLabel("enableBold", Vec2(size.width * 0.15, size.height * 0.45),
1433+
[=, this](Object* obj, ax::ui::CheckBox::EventType type) {
1434+
if (type == ax::ui::CheckBox::EventType::SELECTED)
1435+
{
14251436
_labelSDF->enableBold();
14261437
_labelNormal->enableBold();
1427-
}else{
1438+
}
1439+
else
1440+
{
14281441
_labelSDF->disableEffect(ax::LabelEffect::BOLD);
14291442
_labelNormal->disableEffect(ax::LabelEffect::BOLD);
14301443
}
14311444
});
1432-
1433-
initSlider("Size", Vec2(size.width*0.5, size.height*0.20), [=, this](Object*obj, ax::ui::Slider::EventType type){
1434-
Slider* slider = (Slider*)obj;
1435-
float size = 20 + slider->getPercent()/5.f;
1445+
1446+
initSlider("Size", Vec2(size.width * 0.5, size.height * 0.20),
1447+
[=, this](Object* obj, ax::ui::Slider::EventType type) {
1448+
Slider* slider = (Slider*)obj;
1449+
float size = 20 + slider->getPercent() / 5.f;
14361450
TTFConfig config = _labelSDF->getTTFConfig();
14371451
config.fontSize = size;
14381452
_labelSDF->setTTFConfig(config);
1439-
config = _labelNormal->getTTFConfig();
1440-
config.fontSize = size;
1453+
config = _labelNormal->getTTFConfig();
1454+
config.fontSize = size;
14411455
_labelNormal->setTTFConfig(config);
1442-
14431456
});
1444-
initSlider("Scale", Vec2(size.width*0.5, size.height*0.25), [=, this](Object*obj, ax::ui::Slider::EventType type){
1445-
Slider* slider = (Slider*)obj;
1446-
float scale = 1 + slider->getPercent()/50.f;
1457+
initSlider("Scale", Vec2(size.width * 0.5, size.height * 0.25),
1458+
[=, this](Object* obj, ax::ui::Slider::EventType type) {
1459+
Slider* slider = (Slider*)obj;
1460+
float scale = 1 + slider->getPercent() / 50.f;
14471461
_labelSDF->setScale(scale);
14481462
_labelNormal->setScale(scale);
14491463
});
1450-
_sliderOutline = initSlider("Outline", Vec2(size.width*0.5, size.height*0.30),[=, this](Object*obj, ui::Slider::EventType type){
1451-
Slider* slider = (Slider*)obj;
1452-
float size = 1 + slider->getPercent()/10;
1453-
if(!slider->isEnabled()) return;
1454-
_labelSDF->enableOutline(Color4B::GREEN,size);
1455-
_labelNormal->enableOutline(Color4B::GREEN,size);
1456-
1464+
_sliderOutline = initSlider("Outline", Vec2(size.width * 0.5, size.height * 0.30),
1465+
[=, this](Object* obj, ui::Slider::EventType type) {
1466+
Slider* slider = (Slider*)obj;
1467+
float size = 1 + slider->getPercent() / 10;
1468+
if (!slider->isEnabled())
1469+
return;
1470+
_labelSDF->enableOutline(Color4B::GREEN, size);
1471+
_labelNormal->enableOutline(Color4B::GREEN, size);
14571472
});
14581473
initToggleCheckboxes();
14591474
_sliderOutline->setEnabled(false);
14601475
_sliderOutline->setOpacity(100);
14611476
}
1462-
ui::Slider* LabelTTFSDF::initSlider(std::string content,Vec2 pos,std::function<void(Object*, ui::Slider::EventType)> callback){
1463-
1477+
ui::Slider* LabelTTFSDF::initSlider(std::string content,
1478+
Vec2 pos,
1479+
std::function<void(Object*, ui::Slider::EventType)> callback)
1480+
{
1481+
14641482
auto slider2 = ui::Slider::create();
14651483
slider2->setTag(2);
14661484
slider2->setTouchEnabled(true);
@@ -1472,52 +1490,53 @@ ui::Slider* LabelTTFSDF::initSlider(std::string content,Vec2 pos,std::function<v
14721490
slider2->setScale(0.6);
14731491
slider2->addEventListener(callback);
14741492
addChild(slider2, 999);
1475-
1476-
auto label = Label::createWithSystemFont(content +": ","Arial",10);
1493+
1494+
auto label = Label::createWithSystemFont(content + ": ", "Arial", 10);
14771495
label->setColor(Color3B::WHITE);
1478-
label->setPosition(pos - Vec2(slider2->getContentSize().width*0.3,0));
1479-
label->setAnchorPoint(Vec2(1,0.5));
1496+
label->setPosition(pos - Vec2(slider2->getContentSize().width * 0.3, 0));
1497+
label->setAnchorPoint(Vec2(1, 0.5));
14801498
this->addChild(label);
1481-
1499+
14821500
return slider2;
14831501
}
14841502
void LabelTTFSDF::initToggleCheckboxes()
14851503
{
1486-
float startPosY = 0;
1487-
Size winSize = Director::getInstance()->getVisibleSize();
1504+
float startPosY = 0;
1505+
Size winSize = Director::getInstance()->getVisibleSize();
14881506

14891507
// Create a radio button group
14901508
auto radioButtonGroup = RadioButtonGroup::create();
14911509
this->addChild(radioButtonGroup);
14921510

14931511
// Create the radio buttons
14941512
static const int NUMBER_OF_BUTTONS = 3;
1495-
startPosY = winSize.height*0.25;
1513+
startPosY = winSize.height * 0.25;
14961514
std::vector<std::string> labelTypes = {"Normal", "Glow", "OutLine"};
14971515

14981516
for (int i = 0; i < NUMBER_OF_BUTTONS; ++i)
14991517
{
15001518

15011519
RadioButton* radioButton = RadioButton::create("cocosui/radio_button_off.png", "cocosui/radio_button_on.png");
1502-
float posY = startPosY + (radioButton->getContentSize().height +5) * i;
1503-
radioButton->setPosition(Vec2(winSize.width*0.8, posY));
1520+
float posY = startPosY + (radioButton->getContentSize().height + 5) * i;
1521+
radioButton->setPosition(Vec2(winSize.width * 0.8, posY));
15041522
radioButton->addEventListener(AX_CALLBACK_2(LabelTTFSDF::onChangedRadioButtonSelect, this));
15051523
radioButton->setTag(i);
15061524
radioButtonGroup->addRadioButton(radioButton);
15071525
this->addChild(radioButton);
15081526

15091527
auto label = Label::createWithSystemFont(labelTypes.at(i), "Arial", 15);
15101528
label->setPosition(radioButton->getPosition() + Vec2(radioButton->getContentSize().width + 1, 0.0f));
1511-
label->setAnchorPoint(Vec2(0,0.5));
1529+
label->setAnchorPoint(Vec2(0, 0.5));
15121530
this->addChild(label);
15131531
}
15141532
}
1515-
void LabelTTFSDF::onChangedRadioButtonSelect(RadioButton* radioButton, RadioButton::EventType type){
1533+
void LabelTTFSDF::onChangedRadioButtonSelect(RadioButton* radioButton, RadioButton::EventType type)
1534+
{
15161535
if (radioButton == nullptr)
15171536
{
15181537
return;
15191538
}
1520-
1539+
15211540
if (type != RadioButton::EventType::SELECTED)
15221541
return;
15231542
_labelNormal->disableEffect(LabelEffect::OUTLINE);
@@ -1529,29 +1548,30 @@ void LabelTTFSDF::onChangedRadioButtonSelect(RadioButton* radioButton, RadioButt
15291548
_sliderOutline->setPercent(0);
15301549
switch (radioButton->getTag())
15311550
{
1532-
case 0:
1533-
break;
1534-
case 1:
1535-
_labelNormal->enableGlow(Color4B::RED);
1536-
_labelSDF->enableGlow(Color4B::RED);
1537-
break;
1538-
case 2:
1539-
_labelSDF->enableOutline(Color4B::GREEN,1);
1540-
_labelNormal->enableOutline(Color4B::GREEN,1);
1541-
_sliderOutline->setEnabled(true);
1542-
_sliderOutline->setOpacity(255);
1543-
break;
1544-
default:
1545-
break;
1551+
case 0:
1552+
break;
1553+
case 1:
1554+
_labelNormal->enableGlow(Color4B::RED);
1555+
_labelSDF->enableGlow(Color4B::RED);
1556+
break;
1557+
case 2:
1558+
_labelSDF->enableOutline(Color4B::GREEN, 1);
1559+
_labelNormal->enableOutline(Color4B::GREEN, 1);
1560+
_sliderOutline->setEnabled(true);
1561+
_sliderOutline->setOpacity(255);
1562+
break;
1563+
default:
1564+
break;
15461565
}
1547-
15481566
}
1549-
void LabelTTFSDF::initToggleLabel(std::string content, ax::Vec2 pos, std::function<void(Object*, ax::ui::CheckBox::EventType)> callback)
1567+
void LabelTTFSDF::initToggleLabel(std::string content,
1568+
ax::Vec2 pos,
1569+
std::function<void(Object*, ax::ui::CheckBox::EventType)> callback)
15501570
{
15511571
auto label = Label::createWithSystemFont(content + ":", "Arial", 10);
15521572
label->setColor(Color3B::WHITE);
15531573
label->setPosition(pos);
1554-
label->setAnchorPoint(Vec2(1,0.5));
1574+
label->setAnchorPoint(Vec2(1, 0.5));
15551575
this->addChild(label);
15561576

15571577
CheckBox* checkBox = CheckBox::create("cocosui/check_box_normal.png", "cocosui/check_box_normal_press.png",
@@ -1562,7 +1582,7 @@ void LabelTTFSDF::initToggleLabel(std::string content, ax::Vec2 pos, std::functi
15621582
checkBox->setName("toggleType");
15631583
checkBox->setSelected(true);
15641584
checkBox->addEventListener(callback);
1565-
checkBox->setAnchorPoint(Vec2(0,0.5));
1585+
checkBox->setAnchorPoint(Vec2(0, 0.5));
15661586
checkBox->setSelected(false);
15671587
this->addChild(checkBox);
15681588
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/****************************************************************************
22
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
3+
Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md).
34
45
https://axmol.dev/
56

0 commit comments

Comments
 (0)