Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit f333bab

Browse files
Fix chat message word wrapping after scale change (#4425) (#4437)
adding scale change detection and cache invalidation.
1 parent 24de732 commit f333bab

File tree

2 files changed

+141
-98
lines changed

2 files changed

+141
-98
lines changed

‎Client/core/CChat.cpp‎

Lines changed: 121 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ CChat::CChat(CGUI* pManager, const CVector2D& vecPosition)
2727
// Calculate relative position (assuming a 800x600 native resolution for our defined CCHAT_* values)
2828
CVector2D vecResolution = m_pManager->GetResolution();
2929
m_vecScale = CVector2D(vecResolution.fX / 800.0f, vecResolution.fY / 600.0f);
30+
m_previousScale = m_vecScale;
3031
m_vecBackgroundPosition = vecPosition * vecResolution;
3132

3233
// Initialize variables
@@ -914,6 +915,13 @@ void CChat::SetDxFont(LPD3DXFONT pDXFont)
914915

915916
void CChat::UpdateGUI()
916917
{
918+
// Check if scale has changed and invalidate cached widths if so
919+
if (m_vecScale != m_previousScale)
920+
{
921+
InvalidateAllCachedWidths();
922+
m_previousScale = m_vecScale;
923+
}
924+
917925
m_vecBackgroundSize = CVector2D(m_fNativeWidth * m_vecScale.fX, CChat::GetFontHeight(m_vecScale.fY) * (float(m_uiNumLines) + 0.5f));
918926
m_vecBackgroundSize.fX = Round(m_vecBackgroundSize.fX);
919927
m_vecBackgroundSize.fY = Round(m_vecBackgroundSize.fY);
@@ -935,6 +943,15 @@ void CChat::UpdateGUI()
935943
UpdatePosition();
936944
}
937945

946+
void CChat::InvalidateAllCachedWidths()
947+
{
948+
for (int i = 0; i < CHAT_MAX_LINES; i++)
949+
{
950+
m_Lines[i].InvalidateCache();
951+
}
952+
m_InputLine.InvalidateCache();
953+
}
954+
938955
void CChat::UpdatePosition()
939956
{
940957
CVector2D vecResolution = m_pManager->GetResolution();
@@ -1166,78 +1183,78 @@ const char* CalcAnsiPtr(const char* szStringAnsi, const wchar_t* szPosition)
11661183
return szStringAnsi + iOffset;
11671184
}
11681185

1169-
const char* CChatLine::Format(const char* szStringAnsi, float fWidth, CColor& color, bool bColorCoded)
1186+
const char* CChatLine::Format(const char* text, float width, CColor& color, bool colorCoded)
11701187
{
1171-
std::wstring wString = MbUTF8ToUTF16(szStringAnsi);
1188+
std::wstring wString = MbUTF8ToUTF16(text);
11721189
const wchar_t* szString = wString.c_str();
11731190

1174-
float fPrevSectionsWidth = 0.0f;
1191+
float prevSectionsWidth = 0.0f;
11751192
m_Sections.clear();
11761193

1177-
const wchar_t* szSectionStart = szString;
1178-
const wchar_t* szSectionEnd = szString;
1179-
const wchar_t* szLastWrapPoint = szString;
1180-
bool bLastSection = false;
1181-
while (!bLastSection) // iterate over sections
1194+
const wchar_t* sectionStart = szString;
1195+
const wchar_t* sectionEnd = szString;
1196+
const wchar_t* lastWrapPoint = szString;
1197+
bool lastSection = false;
1198+
while (!lastSection) // iterate over sections
11821199
{
11831200
m_Sections.resize(m_Sections.size() + 1);
11841201
CChatLineSection& section = *(m_Sections.end() - 1);
11851202
section.SetColor(color);
11861203

1187-
if (m_Sections.size() > 1 && bColorCoded) // If we've processed sections before
1188-
szSectionEnd += 7; // skip the color code
1204+
if (m_Sections.size() > 1 && colorCoded) // If we've processed sections before
1205+
sectionEnd += 7; // skip the color code
11891206

1190-
szSectionStart = szSectionEnd;
1191-
szLastWrapPoint = szSectionStart;
1192-
unsigned int uiSeekPos = 0;
1193-
std::wstring strSectionStart = szSectionStart;
1207+
sectionStart = sectionEnd;
1208+
lastWrapPoint = sectionStart;
1209+
unsigned int seekPos = 0;
1210+
std::wstring strSectionStart = sectionStart;
11941211

11951212
while (true) // find end of this section
11961213
{
1197-
float fSectionWidth = CChat::GetTextExtent(UTF16ToMbUTF8(strSectionStart.substr(0, uiSeekPos)).c_str(), g_pChat->m_vecScale.fX);
1214+
float sectionWidth = CChat::GetTextExtent(UTF16ToMbUTF8(strSectionStart.substr(0, seekPos)).c_str(), g_pChat->m_vecScale.fX);
11981215

1199-
if (*szSectionEnd == '0円' || *szSectionEnd == '\n' || std::ceil(fPrevSectionsWidth + fSectionWidth) > fWidth)
1216+
if (*sectionEnd == '0円' || *sectionEnd == '\n' || std::ceil(prevSectionsWidth + sectionWidth) > width)
12001217
{
1201-
bLastSection = true;
1218+
lastSection = true;
12021219
break;
12031220
}
1204-
if (bColorCoded && IsColorCode(UTF16ToMbUTF8(szSectionEnd).c_str()))
1221+
if (colorCoded && IsColorCode(UTF16ToMbUTF8(sectionEnd).c_str()))
12051222
{
1206-
unsigned long ulColor = 0;
1207-
sscanf(UTF16ToMbUTF8(szSectionEnd).c_str() + 1, "%06x", &ulColor);
1208-
color = ulColor;
1209-
fPrevSectionsWidth += fSectionWidth;
1223+
unsigned long colorValue = 0;
1224+
sscanf(UTF16ToMbUTF8(sectionEnd).c_str() + 1, "%06x", &colorValue);
1225+
color = colorValue;
1226+
prevSectionsWidth += sectionWidth;
12101227
break;
12111228
}
1212-
if (isspace((unsigned char)*szSectionEnd) || ispunct((unsigned char)*szSectionEnd))
1229+
if (isspace((unsigned char)*sectionEnd) || ispunct((unsigned char)*sectionEnd))
12131230
{
1214-
szLastWrapPoint = szSectionEnd;
1231+
lastWrapPoint = sectionEnd;
12151232
}
1216-
szSectionEnd++;
1217-
uiSeekPos++;
1233+
sectionEnd++;
1234+
seekPos++;
12181235
}
1219-
section.m_strText = UTF16ToMbUTF8(strSectionStart.substr(0, uiSeekPos));
1236+
section.m_text = UTF16ToMbUTF8(strSectionStart.substr(0, seekPos));
12201237
}
12211238

1222-
if (*szSectionEnd == '0円')
1239+
if (*sectionEnd == '0円')
12231240
{
1224-
return NULL;
1241+
return nullptr;
12251242
}
1226-
else if (*szSectionEnd == '\n')
1243+
else if (*sectionEnd == '\n')
12271244
{
1228-
return CalcAnsiPtr(szStringAnsi, szSectionEnd + 1);
1245+
return CalcAnsiPtr(text, sectionEnd + 1);
12291246
}
12301247
else
12311248
{
12321249
// Do word wrap
1233-
if (szLastWrapPoint == szSectionStart)
1250+
if (lastWrapPoint == sectionStart)
12341251
{
12351252
// Wrapping point coincides with the start of a section.
1236-
if (szLastWrapPoint == szString)
1253+
if (lastWrapPoint == szString)
12371254
{
12381255
// The line consists of one huge word. Leave the one section we created as it
1239-
// is (with the huge word cut off) and return szRemaining as the rest of the word
1240-
return CalcAnsiPtr(szStringAnsi, szSectionEnd);
1256+
// is (with the huge word cut off) and return remaining as the rest of the word
1257+
return CalcAnsiPtr(text, sectionEnd);
12411258
}
12421259
else
12431260
{
@@ -1249,56 +1266,61 @@ const char* CChatLine::Format(const char* szStringAnsi, float fWidth, CColor& co
12491266
{
12501267
// Wrapping point is in the middle of a section, truncate
12511268
CChatLineSection& last = *(m_Sections.end() - 1);
1252-
std::wstring wstrTemp = MbUTF8ToUTF16(last.m_strText);
1253-
wstrTemp.resize(szLastWrapPoint - szSectionStart);
1254-
last.m_strText = UTF16ToMbUTF8(wstrTemp);
1269+
std::wstring wstrTemp = MbUTF8ToUTF16(last.m_text);
1270+
wstrTemp.resize(lastWrapPoint - sectionStart);
1271+
last.m_text = UTF16ToMbUTF8(wstrTemp);
12551272
}
1256-
return CalcAnsiPtr(szStringAnsi, szLastWrapPoint);
1273+
return CalcAnsiPtr(text, lastWrapPoint);
1274+
}
1275+
}
1276+
1277+
void CChatLine::Draw(const CVector2D& position, unsigned char alpha, bool shadow, bool outline, const CRect2D& renderBounds)
1278+
{
1279+
float currentX = position.fX;
1280+
for (auto& section : m_Sections)
1281+
{
1282+
section.Draw(CVector2D(currentX, position.fY), alpha, shadow, outline, renderBounds);
1283+
currentX += section.GetWidth();
12571284
}
12581285
}
12591286

1260-
void CChatLine::Draw(const CVector2D& vecPosition, unsignedchar ucAlpha, bool bShadow, bool bOutline, const CRect2D& RenderBounds)
1287+
float CChatLine::GetWidth() const
12611288
{
1262-
float fCurrentX = vecPosition.fX;
1263-
std::vector<CChatLineSection>::iterator iter = m_Sections.begin();
1264-
for (; iter != m_Sections.end(); iter++)
1289+
float width = 0.0f;
1290+
for (const auto& section : m_Sections)
12651291
{
1266-
(*iter).Draw(CVector2D(fCurrentX, vecPosition.fY), ucAlpha, bShadow, bOutline, RenderBounds);
1267-
fCurrentX += (*iter).GetWidth();
1292+
width += section.GetWidth();
12681293
}
1294+
return width;
12691295
}
12701296

1271-
float CChatLine::GetWidth()
1297+
void CChatLine::InvalidateCache()
12721298
{
1273-
float fWidth = 0.0f;
1274-
std::vector<CChatLineSection>::iterator it;
1275-
for (it = m_Sections.begin(); it != m_Sections.end(); it++)
1299+
for (auto& section : m_Sections)
12761300
{
1277-
fWidth += (*it).GetWidth();
1301+
section.InvalidateCache();
12781302
}
1279-
return fWidth;
12801303
}
12811304

1282-
void CChatInputLine::Draw(CVector2D& vecPosition, unsigned char ucAlpha, bool bShadow, bool bOutline)
1305+
void CChatInputLine::Draw(CVector2D& position, unsigned char alpha, bool shadow, bool outline)
12831306
{
1284-
CRect2D RenderBounds(0, 0, 9999, 9999);
1307+
CRect2D renderBounds(0, 0, 9999, 9999);
12851308

1286-
CColor colPrefix;
1287-
m_Prefix.GetColor(colPrefix);
1288-
if (colPrefix.A > 0)
1289-
m_Prefix.Draw(vecPosition, colPrefix.A, bShadow, bOutline, RenderBounds);
1309+
CColor prefixColor;
1310+
m_Prefix.GetColor(prefixColor);
1311+
if (prefixColor.A > 0)
1312+
m_Prefix.Draw(position, prefixColor.A, shadow, outline, renderBounds);
12901313

12911314
if (g_pChat->m_InputTextColor.A > 0 && m_Sections.size() > 0)
12921315
{
1293-
m_Sections[0].Draw(CVector2D(vecPosition.fX + m_Prefix.GetWidth(), vecPosition.fY), g_pChat->m_InputTextColor.A, bShadow, bOutline, RenderBounds);
1316+
m_Sections[0].Draw(CVector2D(position.fX + m_Prefix.GetWidth(), position.fY), g_pChat->m_InputTextColor.A, shadow, outline, renderBounds);
12941317

1295-
float fLineDifference = CChat::GetFontHeight(g_pChat->m_vecScale.fY);
1318+
float lineDifference = CChat::GetFontHeight(g_pChat->m_vecScale.fY);
12961319

1297-
vector<CChatLine>::iterator iter = m_ExtraLines.begin();
1298-
for (; iter != m_ExtraLines.end(); iter++)
1320+
for (auto& line : m_ExtraLines)
12991321
{
1300-
vecPosition.fY += fLineDifference;
1301-
(*iter).Draw(vecPosition, g_pChat->m_InputTextColor.A, bShadow, bOutline, RenderBounds);
1322+
position.fY += lineDifference;
1323+
line.Draw(position, g_pChat->m_InputTextColor.A, shadow, outline, renderBounds);
13021324
}
13031325
}
13041326
}
@@ -1309,10 +1331,20 @@ void CChatInputLine::Clear()
13091331
m_ExtraLines.clear();
13101332
}
13111333

1334+
void CChatInputLine::InvalidateCache()
1335+
{
1336+
CChatLine::InvalidateCache();
1337+
m_Prefix.InvalidateCache();
1338+
for (auto& line : m_ExtraLines)
1339+
{
1340+
line.InvalidateCache();
1341+
}
1342+
}
1343+
13121344
CChatLineSection::CChatLineSection()
13131345
{
1314-
m_fCachedWidth = -1.0f;
1315-
m_uiCachedLength = 0;
1346+
m_cachedWidth = -1.0f;
1347+
m_cachedLength = 0;
13161348
}
13171349

13181350
CChatLineSection::CChatLineSection(const CChatLineSection& other)
@@ -1322,35 +1354,41 @@ CChatLineSection::CChatLineSection(const CChatLineSection& other)
13221354

13231355
CChatLineSection& CChatLineSection::operator=(const CChatLineSection& other)
13241356
{
1325-
m_strText = other.m_strText;
1326-
m_Color = other.m_Color;
1327-
m_fCachedWidth = other.m_fCachedWidth;
1328-
m_uiCachedLength = other.m_uiCachedLength;
1357+
m_text = other.m_text;
1358+
m_color = other.m_color;
1359+
m_cachedWidth = other.m_cachedWidth;
1360+
m_cachedLength = other.m_cachedLength;
13291361
return *this;
13301362
}
13311363

1332-
void CChatLineSection::Draw(const CVector2D& vecPosition, unsigned char ucAlpha, bool bShadow, bool bOutline, const CRect2D& RenderBounds)
1364+
void CChatLineSection::Draw(const CVector2D& position, unsigned char alpha, bool shadow, bool outline, const CRect2D& renderBounds)
13331365
{
1334-
if (!m_strText.empty() && ucAlpha > 0)
1366+
if (!m_text.empty() && alpha > 0)
13351367
{
1336-
if (bShadow)
1368+
if (shadow)
13371369
{
1338-
CRect2D drawShadowAt(vecPosition.fX + 1.0f, vecPosition.fY + 1.0f, vecPosition.fX + 1000.0f, vecPosition.fY + 1000.0f);
1339-
CChat::DrawTextString(m_strText.c_str(), drawShadowAt, 0.0f, drawShadowAt, 0, COLOR_ARGB(ucAlpha, 0, 0, 0), g_pChat->m_vecScale.fX,
1340-
g_pChat->m_vecScale.fY, bOutline, RenderBounds);
1370+
CRect2D drawShadowAt(position.fX + 1.0f, position.fY + 1.0f, position.fX + 1000.0f, position.fY + 1000.0f);
1371+
CChat::DrawTextString(m_text.c_str(), drawShadowAt, 0.0f, drawShadowAt, 0, COLOR_ARGB(alpha, 0, 0, 0), g_pChat->m_vecScale.fX,
1372+
g_pChat->m_vecScale.fY, outline, renderBounds);
13411373
}
1342-
CRect2D drawAt(vecPosition.fX, vecPosition.fY, vecPosition.fX + 1000.0f, vecPosition.fY + 1000.0f);
1343-
CChat::DrawTextString(m_strText.c_str(), drawAt, 0.0f, drawAt, 0, COLOR_ARGB(ucAlpha, m_Color.R, m_Color.G, m_Color.B), g_pChat->m_vecScale.fX,
1344-
g_pChat->m_vecScale.fY, bOutline, RenderBounds);
1374+
CRect2D drawAt(position.fX, position.fY, position.fX + 1000.0f, position.fY + 1000.0f);
1375+
CChat::DrawTextString(m_text.c_str(), drawAt, 0.0f, drawAt, 0, COLOR_ARGB(alpha, m_color.R, m_color.G, m_color.B), g_pChat->m_vecScale.fX,
1376+
g_pChat->m_vecScale.fY, outline, renderBounds);
13451377
}
13461378
}
13471379

1348-
float CChatLineSection::GetWidth()
1380+
float CChatLineSection::GetWidth()const
13491381
{
1350-
if (m_fCachedWidth < 0.0f || m_strText.size() != m_uiCachedLength)
1382+
if (m_cachedWidth < 0.0f || m_text.size() != m_cachedLength)
13511383
{
1352-
m_fCachedWidth = std::ceil(CChat::GetTextExtent(m_strText.c_str(), g_pChat->m_vecScale.fX) / std::max(0.01f, g_pChat->m_vecScale.fX));
1353-
m_uiCachedLength = m_strText.size();
1384+
m_cachedWidth = std::ceil(CChat::GetTextExtent(m_text.c_str(), g_pChat->m_vecScale.fX) / std::max(0.01f, g_pChat->m_vecScale.fX));
1385+
m_cachedLength = m_text.size();
13541386
}
1355-
return m_fCachedWidth * g_pChat->m_vecScale.fX;
1387+
return m_cachedWidth * g_pChat->m_vecScale.fX;
1388+
}
1389+
1390+
void CChatLineSection::InvalidateCache()
1391+
{
1392+
m_cachedWidth = -1.0f;
1393+
m_cachedLength = 0;
13561394
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /