summaryrefslogtreecommitdiff
path: root/vcl/source/text/ImplLayoutRuns.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/source/text/ImplLayoutRuns.cxx')
-rw-r--r--vcl/source/text/ImplLayoutRuns.cxx95
1 files changed, 79 insertions, 16 deletions
diff --git a/vcl/source/text/ImplLayoutRuns.cxx b/vcl/source/text/ImplLayoutRuns.cxx
index ab1597b56449..f7bbd161650a 100644
--- a/vcl/source/text/ImplLayoutRuns.cxx
+++ b/vcl/source/text/ImplLayoutRuns.cxx
@@ -19,18 +19,7 @@
#include <ImplLayoutRuns.hxx>
#include <algorithm>
-
-ImplLayoutRuns::Run::Run(int nMinRunPos, int nEndRunPos, bool bRTL)
- : m_nMinRunPos(nMinRunPos)
- , m_nEndRunPos(nEndRunPos)
- , m_bRTL(bRTL)
-{
-}
-
-bool ImplLayoutRuns::Run::Contains(int nCharPos) const
-{
- return (m_nMinRunPos <= nCharPos) && (nCharPos < m_nEndRunPos);
-}
+#include <tuple>
void ImplLayoutRuns::AddPos( int nCharPos, bool bRTL )
{
@@ -38,12 +27,21 @@ void ImplLayoutRuns::AddPos( int nCharPos, bool bRTL )
if (!maRuns.empty())
{
auto& rLastRun = maRuns.back();
- if (bRTL == rLastRun.m_bRTL && nCharPos == rLastRun.m_nEndRunPos)
+ if (bRTL == rLastRun.m_bRTL)
{
- // extend current run by new charpos
- ++rLastRun.m_nEndRunPos;
- return;
+ if (nCharPos + 1 == rLastRun.m_nMinRunPos)
+ {
+ // extend current run by new charpos
+ rLastRun.m_nMinRunPos = nCharPos;
+ }
+
+ if (nCharPos == rLastRun.m_nEndRunPos)
+ {
+ // extend current run by new charpos
+ ++rLastRun.m_nEndRunPos;
+ }
}
+
// ignore new charpos when it is in current run
if ((rLastRun.m_nMinRunPos <= nCharPos) && (nCharPos < rLastRun.m_nEndRunPos))
{
@@ -79,6 +77,29 @@ void ImplLayoutRuns::AddRun( int nCharPos0, int nCharPos1, bool bRTL )
maRuns.emplace_back(nOrderedCharPos0, nOrderedCharPos1, bRTL);
}
+void ImplLayoutRuns::Normalize()
+{
+ boost::container::small_vector<Run, 8> aOldRuns;
+ std::swap(aOldRuns, maRuns);
+
+ std::sort(aOldRuns.begin(), aOldRuns.end(),
+ [](const Run& rA, const Run& rB)
+ {
+ return std::tie(rA.m_nMinRunPos, rA.m_nEndRunPos)
+ < std::tie(rB.m_nMinRunPos, rB.m_nEndRunPos);
+ });
+
+ for (const auto& rRun : aOldRuns)
+ {
+ AddRun(rRun.m_nMinRunPos, rRun.m_nEndRunPos, false);
+ }
+}
+
+void ImplLayoutRuns::ReverseTail(size_t nTailIndex)
+{
+ std::reverse(maRuns.begin() + nTailIndex, maRuns.end());
+}
+
bool ImplLayoutRuns::PosIsInRun( int nCharPos ) const
{
if( mnRunIndex >= static_cast<int>(maRuns.size()) )
@@ -145,4 +166,46 @@ bool ImplLayoutRuns::GetRun( int* nMinRunPos, int* nEndRunPos, bool* bRightToLef
return true;
}
+void ImplLayoutRuns::PrepareFallbackRuns(ImplLayoutRuns* paRuns, ImplLayoutRuns* paFallbackRuns)
+{
+ // Normalize the input fallback runs. This is required for efficient lookup.
+ paFallbackRuns->Normalize();
+
+ // Adjust fallback runs to have the same order and limits of the original runs.
+ ImplLayoutRuns aNewRuns;
+ for (const auto& rRun : *paRuns)
+ {
+ auto nTailIndex = aNewRuns.size();
+
+ // Search for the first fallback run intersecting this run
+ auto it = std::lower_bound(paFallbackRuns->begin(), paFallbackRuns->end(),
+ rRun.m_nMinRunPos, [](const auto& rCompRun, int nValue)
+ { return rCompRun.m_nEndRunPos < nValue; });
+ for (; it != paFallbackRuns->end(); ++it)
+ {
+ if (rRun.m_nEndRunPos <= it->m_nMinRunPos)
+ {
+ break;
+ }
+
+ int nSubMin = std::max(rRun.m_nMinRunPos, it->m_nMinRunPos);
+ int nSubMax = std::min(rRun.m_nEndRunPos, it->m_nEndRunPos);
+
+ aNewRuns.AddRun(nSubMin, nSubMax, rRun.m_bRTL);
+ }
+
+ // RTL subruns must be added in reverse order
+ if (rRun.m_bRTL)
+ {
+ aNewRuns.ReverseTail(nTailIndex);
+ }
+ }
+
+ *paRuns = aNewRuns;
+ paRuns->ResetPos();
+
+ paFallbackRuns->Clear();
+ paFallbackRuns->ResetPos();
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */