Fixed multifragment lines on Windows, again with the help of the PadWrite sample.

This commit is contained in:
Pietro Gagliardi 2017-01-21 09:39:53 -05:00
parent 4de8d4402f
commit f0b9ff9aba
1 changed files with 28 additions and 14 deletions

View File

@ -54,9 +54,9 @@ static void computeLineInfo(uiDrawTextLayout *tl)
{ {
DWRITE_LINE_METRICS *dlm; DWRITE_LINE_METRICS *dlm;
size_t nextStart; size_t nextStart;
UINT32 i; UINT32 i, j;
DWRITE_HIT_TEST_METRICS htm; DWRITE_HIT_TEST_METRICS *htm;
UINT32 unused; UINT32 nFragments, unused;
HRESULT hr; HRESULT hr;
// TODO make sure this is legal; if not, switch to GetMetrics() and use its line count field instead // TODO make sure this is legal; if not, switch to GetMetrics() and use its line count field instead
@ -83,20 +83,34 @@ static void computeLineInfo(uiDrawTextLayout *tl)
tl->lineInfo[i].newlineCount = dlm[i].newlineLength; tl->lineInfo[i].newlineCount = dlm[i].newlineLength;
nextStart = tl->lineInfo[i].endPos; nextStart = tl->lineInfo[i].endPos;
// a line can have multiple fragments; for example, if there's a bidirectional override in the middle of a line
hr = tl->layout->HitTestTextRange(tl->lineInfo[i].startPos, (tl->lineInfo[i].endPos - tl->lineInfo[i].newlineCount) - tl->lineInfo[i].startPos, hr = tl->layout->HitTestTextRange(tl->lineInfo[i].startPos, (tl->lineInfo[i].endPos - tl->lineInfo[i].newlineCount) - tl->lineInfo[i].startPos,
0, 0, 0, 0,
&htm, 1, &unused); NULL, 0, &nFragments);
// TODO this happens with the hit test string on the line with the RTL override (presumably the overridden part is its own separate result); see how it affects metrics if (hr != S_OK && hr != E_NOT_SUFFICIENT_BUFFER)
if (hr == E_NOT_SUFFICIENT_BUFFER) logHRESULT(L"error getting IDWriteTextLayout line fragment count", hr);
;else// logHRESULT(L"TODO CONTACT ANDLABS — IDWriteTextLayout::HitTestTextRange() can return multiple ranges for a single line", hr); htm = new DWRITE_HIT_TEST_METRICS[nFragments];
// TODO verify unused == nFragments?
hr = tl->layout->HitTestTextRange(tl->lineInfo[i].startPos, (tl->lineInfo[i].endPos - tl->lineInfo[i].newlineCount) - tl->lineInfo[i].startPos,
0, 0,
htm, nFragments, &unused);
// TODO can this return E_NOT_SUFFICIENT_BUFFER again?
if (hr != S_OK) if (hr != S_OK)
logHRESULT(L"error getting IDWriteTextLayout line rect", hr); logHRESULT(L"error getting IDWriteTextLayout line fragment metrics", hr);
// TODO verify htm.textPosition and htm.length? // TODO verify htm.textPosition and htm.length against dtm[i]/tl->lineInfo[i]?
tl->lineInfo[i].x = htm.left; tl->lineInfo[i].x = htm[0].left;
tl->lineInfo[i].y = htm.top; tl->lineInfo[i].y = htm[0].top;
tl->lineInfo[i].width = htm.width; tl->lineInfo[i].width = htm[0].width;
tl->lineInfo[i].height = htm.height; tl->lineInfo[i].height = htm[0].height;
// TODO verify dlm[i].height == htm.height for (j = 1; j < nFragments; j++) {
// this is correct even if the leftmost fragment on the line is RTL
if (tl->lineInfo[i].x > htm[j].left)
tl->lineInfo[i].x = htm[j].left;
tl->lineInfo[i].width += htm[j].width;
// TODO verify y and height haven't changed?
}
// TODO verify dlm[i].height == htm.height?
delete[] htm;
// TODO on Windows 8.1 and/or 10 we can use DWRITE_LINE_METRICS1 to get specific info about the ascent and descent; do we have an alternative? // TODO on Windows 8.1 and/or 10 we can use DWRITE_LINE_METRICS1 to get specific info about the ascent and descent; do we have an alternative?
// TODO and even on those platforms can we somehow split tyographic leading from spacing? // TODO and even on those platforms can we somehow split tyographic leading from spacing?