diff options
author | Neil <nyamatongwe@gmail.com> | 2022-08-02 11:46:31 +1000 |
---|---|---|
committer | Neil <nyamatongwe@gmail.com> | 2022-08-02 11:46:31 +1000 |
commit | 189d5f4e766ba6864d7557111397e000776d6841 (patch) | |
tree | df9b3c6f2e2a2a3b7b6db604f08e9075fb13ab70 /win32 | |
parent | a91e4af5c5fbbe464093e24ae39f980b56598847 (diff) | |
download | scintilla-mirror-189d5f4e766ba6864d7557111397e000776d6841.tar.gz |
Hoist common DirectWrite position measuring code into MeasurePositions function.
Ensure works on text longer than stackBufferLength.
Diffstat (limited to 'win32')
-rw-r--r-- | win32/PlatWin.cxx | 75 |
1 files changed, 32 insertions, 43 deletions
diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index 761c00193..f33b1fcd3 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -2361,31 +2361,33 @@ void SurfaceD2D::DrawTextTransparent(PRectangle rc, const Font *font_, XYPOSITIO } } -void SurfaceD2D::MeasureWidths(const Font *font_, std::string_view text, XYPOSITION *positions) { - const FontDirectWrite *pfm = FontDirectWrite::Cast(font_); - if (!pfm->pTextFormat) { - // SetFont failed or no access to DirectWrite so give up. - return; +namespace { + +HRESULT MeasurePositions(TextPositions &poses, const TextWide &tbuf, IDWriteTextFormat *pTextFormat) { + if (!pTextFormat) { + // Unexpected failure like no access to DirectWrite so give up. + return E_FAIL; } - const int codePageText = pfm->CodePageText(mode.codePage); - const TextWide tbuf(text, codePageText); - TextPositions poses(tbuf.tlen); + // Initialize poses for safety. std::fill(poses.buffer, poses.buffer + tbuf.tlen, 0.0f); // Create a layout IDWriteTextLayout *pTextLayout = nullptr; - const HRESULT hrCreate = pIDWriteFactory->CreateTextLayout(tbuf.buffer, tbuf.tlen, pfm->pTextFormat, 10000.0, 1000.0, &pTextLayout); - if (!SUCCEEDED(hrCreate) || !pTextLayout) { - return; + const HRESULT hrCreate = pIDWriteFactory->CreateTextLayout(tbuf.buffer, tbuf.tlen, pTextFormat, 10000.0, 1000.0, &pTextLayout); + if (!SUCCEEDED(hrCreate)) { + return hrCreate; } - constexpr int clusters = stackBufferLength; - DWRITE_CLUSTER_METRICS clusterMetrics[clusters]; + if (!pTextLayout) { + return E_FAIL; + } + VarBuffer<DWRITE_CLUSTER_METRICS, stackBufferLength> cm(tbuf.tlen); UINT32 count = 0; - const HRESULT hrGetCluster = pTextLayout->GetClusterMetrics(clusterMetrics, clusters, &count); + const HRESULT hrGetCluster = pTextLayout->GetClusterMetrics(cm.buffer, tbuf.tlen, &count); ReleaseUnknown(pTextLayout); if (!SUCCEEDED(hrGetCluster)) { - return; + return hrGetCluster; } + const DWRITE_CLUSTER_METRICS * const clusterMetrics = cm.buffer; // A cluster may be more than one WCHAR, such as for "ffi" which is a ligature in the Candara font XYPOSITION position = 0.0; int ti=0; @@ -2396,6 +2398,19 @@ void SurfaceD2D::MeasureWidths(const Font *font_, std::string_view text, XYPOSIT position += clusterMetrics[ci].width; } PLATFORM_ASSERT(ti == tbuf.tlen); + return S_OK; +} + +} + +void SurfaceD2D::MeasureWidths(const Font *font_, std::string_view text, XYPOSITION *positions) { + const FontDirectWrite *pfm = FontDirectWrite::Cast(font_); + const int codePageText = pfm->CodePageText(mode.codePage); + const TextWide tbuf(text, codePageText); + TextPositions poses(tbuf.tlen); + if (FAILED(MeasurePositions(poses, tbuf, pfm->pTextFormat))) { + return; + } if (codePageText == CpUtf8) { // Map the widths given for UTF-16 characters back onto the UTF-8 input string size_t i = 0; @@ -2491,37 +2506,11 @@ void SurfaceD2D::DrawTextTransparentUTF8(PRectangle rc, const Font *font_, XYPOS void SurfaceD2D::MeasureWidthsUTF8(const Font *font_, std::string_view text, XYPOSITION *positions) { const FontDirectWrite *pfm = FontDirectWrite::Cast(font_); - if (!pfm->pTextFormat) { - return; - } const TextWide tbuf(text, CpUtf8); TextPositions poses(tbuf.tlen); - // Initialize poses for safety. - std::fill(poses.buffer, poses.buffer + tbuf.tlen, 0.0f); - // Create a layout - IDWriteTextLayout *pTextLayout = nullptr; - const HRESULT hrCreate = pIDWriteFactory->CreateTextLayout(tbuf.buffer, tbuf.tlen, pfm->pTextFormat, 10000.0, 1000.0, &pTextLayout); - if (!SUCCEEDED(hrCreate) || !pTextLayout) { - return; - } - constexpr int clusters = stackBufferLength; - DWRITE_CLUSTER_METRICS clusterMetrics[clusters]; - UINT32 count = 0; - const HRESULT hrGetCluster = pTextLayout->GetClusterMetrics(clusterMetrics, clusters, &count); - ReleaseUnknown(pTextLayout); - if (!SUCCEEDED(hrGetCluster)) { + if (FAILED(MeasurePositions(poses, tbuf, pfm->pTextFormat))) { return; } - // A cluster may be more than one WCHAR, such as for "ffi" which is a ligature in the Candara font - XYPOSITION position = 0.0; - int ti = 0; - for (unsigned int ci = 0; ci < count; ci++) { - for (unsigned int inCluster = 0; inCluster < clusterMetrics[ci].length; inCluster++) { - poses.buffer[ti++] = position + clusterMetrics[ci].width * (inCluster + 1) / clusterMetrics[ci].length; - } - position += clusterMetrics[ci].width; - } - PLATFORM_ASSERT(ti == tbuf.tlen); // Map the widths given for UTF-16 characters back onto the UTF-8 input string size_t i = 0; for (int ui = 0; ui < tbuf.tlen; ui++) { @@ -2529,7 +2518,7 @@ void SurfaceD2D::MeasureWidthsUTF8(const Font *font_, std::string_view text, XYP const unsigned int byteCount = UTF8BytesOfLead[uch]; if (byteCount == 4) { // Non-BMP ui++; - PLATFORM_ASSERT(ui < ti); + PLATFORM_ASSERT(ui < tbuf.tlen); } for (unsigned int bytePos=0; (bytePos<byteCount) && (i<text.length()) && (ui < tbuf.tlen); bytePos++) { positions[i++] = poses.buffer[ui]; |