Skip to content

Commit 99acb0d

Browse files
committed
Add more metrics to text layout
1 parent 17ac521 commit 99acb0d

File tree

3 files changed

+122
-0
lines changed

3 files changed

+122
-0
lines changed

Telegram.Native/PlaceholderImageHelper.cpp

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,6 +1224,116 @@ namespace winrt::Telegram::Native::implementation
12241224
return { metrics.left, metrics.top, metrics.width, metrics.height };
12251225
}
12261226

1227+
MaxLinesMetrics PlaceholderImageHelper::MaxLines(hstring text, int32_t offset, int32_t length, IVector<TextEntity> entities, double fontSize, double width, bool rtl, int32_t maxLines)
1228+
{
1229+
std::lock_guard const guard(m_criticalSection);
1230+
HRESULT result;
1231+
1232+
//ReturnIfFailed(result, CreateTextFormat(fontSize));
1233+
//ReturnIfFailed(result, m_appleFormat->SetReadingDirection(rtl ? DWRITE_READING_DIRECTION_RIGHT_TO_LEFT : DWRITE_READING_DIRECTION_LEFT_TO_RIGHT));
1234+
1235+
winrt::com_ptr<IDWriteTextFormat> textFormat;
1236+
ReturnDefaultIfFailed(result, m_dwriteFactory->CreateTextFormat(
1237+
L"Segoe UI Emoji", // font family name
1238+
m_fontCollection.get(), // system font collection
1239+
DWRITE_FONT_WEIGHT_NORMAL, // font weight
1240+
DWRITE_FONT_STYLE_NORMAL, // font style
1241+
DWRITE_FONT_STRETCH_NORMAL, // default font stretch
1242+
fontSize, // font size
1243+
L"", // locale name
1244+
textFormat.put()
1245+
));
1246+
ReturnDefaultIfFailed(result, textFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING));
1247+
ReturnDefaultIfFailed(result, textFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_NEAR));
1248+
ReturnDefaultIfFailed(result, textFormat->SetReadingDirection(rtl ? DWRITE_READING_DIRECTION_RIGHT_TO_LEFT : DWRITE_READING_DIRECTION_LEFT_TO_RIGHT));
1249+
1250+
winrt::com_ptr<IDWriteTextLayout> textLayout;
1251+
ReturnDefaultIfFailed(result, m_dwriteFactory->CreateTextLayout(
1252+
text.data(), // The string to be laid out and formatted.
1253+
text.size(), // The length of the string.
1254+
textFormat.get(), // The text format to apply to the string (contains font information, etc).
1255+
width, // The width of the layout box.
1256+
INFINITY, // The height of the layout box.
1257+
textLayout.put() // The IDWriteTextLayout interface pointer.
1258+
));
1259+
1260+
for (const TextEntity& entity : entities)
1261+
{
1262+
UINT32 startPosition = entity.Offset();
1263+
UINT32 length = entity.Length();
1264+
auto name = winrt::get_class_name(entity.Type());
1265+
1266+
if (name == winrt::name_of<TextEntityTypeBold>())
1267+
{
1268+
ReturnDefaultIfFailed(result, textLayout->SetFontWeight(DWRITE_FONT_WEIGHT_SEMI_BOLD, { startPosition, length }));
1269+
}
1270+
else if (name == winrt::name_of<TextEntityTypeItalic>())
1271+
{
1272+
ReturnDefaultIfFailed(result, textLayout->SetFontStyle(DWRITE_FONT_STYLE_ITALIC, { startPosition, length }));
1273+
}
1274+
else if (name == winrt::name_of<TextEntityTypeStrikethrough>())
1275+
{
1276+
ReturnDefaultIfFailed(result, textLayout->SetStrikethrough(TRUE, { startPosition, length }));
1277+
}
1278+
else if (name == winrt::name_of<TextEntityTypeUnderline>())
1279+
{
1280+
ReturnDefaultIfFailed(result, textLayout->SetUnderline(TRUE, { startPosition, length }));
1281+
}
1282+
//else if (name == winrt::name_of<TextEntityTypeCustomEmoji>())
1283+
//{
1284+
// textLayout->SetInlineObject(m_customEmoji.get(), { startPosition, length });
1285+
//}
1286+
else if (name == winrt::name_of<TextEntityTypeCode>() || name == winrt::name_of<TextEntityTypePre>() || name == winrt::name_of<TextEntityTypePreCode>())
1287+
{
1288+
ReturnDefaultIfFailed(result, textLayout->SetFontCollection(m_systemCollection.get(), { startPosition, length }));
1289+
ReturnDefaultIfFailed(result, textLayout->SetFontFamilyName(L"Consolas", { startPosition, length }));
1290+
}
1291+
}
1292+
1293+
DWRITE_TEXT_METRICS metrics;
1294+
ReturnDefaultIfFailed(result, textLayout->GetMetrics(&metrics));
1295+
1296+
if (maxLines == 0)
1297+
{
1298+
return { metrics.left, metrics.top, metrics.width, metrics.height, metrics.height, length };
1299+
}
1300+
1301+
UINT32 actualLineCount;
1302+
DWRITE_LINE_METRICS* ranges = new DWRITE_LINE_METRICS[metrics.lineCount];
1303+
result = textLayout->GetLineMetrics(ranges, metrics.lineCount, &actualLineCount);
1304+
1305+
if (result == E_NOT_SUFFICIENT_BUFFER)
1306+
{
1307+
delete[] ranges;
1308+
1309+
ranges = new DWRITE_LINE_METRICS[actualLineCount];
1310+
result = textLayout->GetLineMetrics(ranges, actualLineCount, &actualLineCount);
1311+
}
1312+
1313+
ReturnDefaultIfFailed(result, result);
1314+
1315+
float truncateHeight = 0;
1316+
int32_t truncatePosition = 0;
1317+
1318+
// Calculate position where to truncate
1319+
for (UINT32 i = 0; i < maxLines && i < actualLineCount; ++i)
1320+
{
1321+
truncateHeight += ranges[i].height;
1322+
truncatePosition += ranges[i].length;
1323+
}
1324+
1325+
// Remove trailing whitespace from last included line
1326+
if (maxLines <= actualLineCount)
1327+
{
1328+
//truncateHeight += ranges[maxLines - 1].height;
1329+
truncatePosition -= ranges[maxLines - 1].trailingWhitespaceLength;
1330+
truncatePosition -= ranges[maxLines - 1].newlineLength;
1331+
}
1332+
1333+
delete[] ranges;
1334+
return { metrics.left, metrics.top, metrics.width, metrics.height, truncateHeight, truncatePosition };
1335+
}
1336+
12271337
HRESULT PlaceholderImageHelper::WriteBytes(IVector<byte> hash, IRandomAccessStream randomAccessStream) noexcept
12281338
{
12291339
HRESULT result;

Telegram.Native/PlaceholderImageHelper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ namespace winrt::Telegram::Native::implementation
135135
IVector<Windows::Foundation::Rect> LineMetrics(hstring text, IVector<TextEntity> entities, double fontSize, double width, bool rtl);
136136
IVector<Windows::Foundation::Rect> RangeMetrics(hstring text, int32_t offset, int32_t length, IVector<TextEntity> entities, double fontSize, double width, bool rtl, bool wrap);
137137
Windows::Foundation::Rect LayoutMetrics(hstring text, int32_t offset, int32_t length, IVector<TextEntity> entities, double fontSize, double width, bool rtl);
138+
MaxLinesMetrics MaxLines(hstring text, int32_t offset, int32_t length, IVector<TextEntity> entities, double fontSize, double width, bool rtl, int32_t maxLines);
138139
//IVector<Windows::Foundation::Rect> EntityMetrics(hstring text, IVector<TextEntity> entities, double fontSize, double width, bool rtl);
139140

140141
private:

Telegram.Native/PlaceholderImageHelper.idl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,16 @@ import "TextFormat.idl";
33

44
namespace Telegram.Native
55
{
6+
struct MaxLinesMetrics
7+
{
8+
Double X;
9+
Double Y;
10+
Double Width;
11+
Double Height;
12+
Double TruncatedHeight;
13+
Int32 TruncatedOffset;
14+
};
15+
616
[default_interface]
717
runtimeclass PlaceholderImageHelper
818
{
@@ -39,6 +49,7 @@ namespace Telegram.Native
3949
Windows.Foundation.Collections.IVector<Windows.Foundation.Rect> LineMetrics(String text, Windows.Foundation.Collections.IVector<Telegram.Td.Api.TextEntity> entities, Double fontSize, Double width, Boolean rtl);
4050
Windows.Foundation.Collections.IVector<Windows.Foundation.Rect> RangeMetrics(String text, Int32 offset, Int32 length, Windows.Foundation.Collections.IVector<Telegram.Td.Api.TextEntity> entities, Double fontSize, Double width, Boolean rtl, Boolean wrap);
4151
Windows.Foundation.Rect LayoutMetrics(String text, Int32 offset, Int32 length, Windows.Foundation.Collections.IVector<Telegram.Td.Api.TextEntity> entities, Double fontSize, Double width, Boolean rtl);
52+
MaxLinesMetrics MaxLines(String text, Int32 offset, Int32 length, Windows.Foundation.Collections.IVector<Telegram.Td.Api.TextEntity> entities, Double fontSize, Double width, Boolean rtl, Int32 maxLines);
4253
//Windows.Foundation.Collections.IVector<Windows.Foundation.Rect> EntityMetrics(String text, Windows.Foundation.Collections.IVector<Telegram.Td.Api.TextEntity> entities, Double fontSize, Double width, Boolean rtl);
4354
}
4455
} // namespace Telegram.Native

0 commit comments

Comments
 (0)