4#ifndef _Stroika_Frameworks_Led_PartitioningTextImager_h_
5#define _Stroika_Frameworks_Led_PartitioningTextImager_h_ 1
7#include "Stroika/Frameworks/StroikaPreComp.h"
9#include "Stroika/Foundation/Cache/LRUCache.h"
25#include "TextImager.h"
27namespace Stroika::Frameworks::Led {
33#ifndef qCacheTextMeasurementsForPM
34#define qCacheTextMeasurementsForPM 1
49 class Partition :
public virtual MarkerOwner {
51 using inherited = MarkerOwner;
54 Partition (TextStore& textStore);
55 virtual ~Partition ();
58 virtual void FinalConstruct ();
59#if qStroika_Foundation_Debug_AssertionsChecked
61 bool fFinalConstructCalled;
65 class PartitionMarker;
68 virtual TextStore* PeekAtTextStore ()
const override;
71 TextStore& fTextStore;
74 virtual void UpdatePartitions (PartitionMarker* pm,
const UpdateInfo& updateInfo)
noexcept = 0;
77 virtual PartitionMarker* GetPartitionMarkerContainingPosition (
size_t charPosition)
const;
80 mutable PartitionMarker* fFindContainingPMCache;
83 virtual PartitionMarker* MakeNewPartitionMarker (PartitionMarker* insertAfterMe);
86 class PartitionWatcher;
87 nonvirtual
void AddPartitionWatcher (PartitionWatcher* watcher);
88 nonvirtual
void RemovePartitionWatcher (PartitionWatcher* watcher);
91 vector<PartitionWatcher*> fPartitionWatchers;
94 virtual void Split (PartitionMarker* pm,
size_t at);
95 virtual void Coalece (PartitionMarker* pm);
97 nonvirtual
void DoAboutToSplitCalls (PartitionMarker* pm,
size_t at, vector<void*>* infos)
const noexcept;
98 nonvirtual
void DoDidSplitCalls (
const vector<void*>& infos)
const noexcept;
99 nonvirtual
void DoAboutToCoaleceCalls (PartitionMarker* pm, vector<void*>* infos)
const noexcept;
100 nonvirtual
void DoDidCoaleceCalls (
const vector<void*>& infos)
const noexcept;
103 nonvirtual
void AccumulateMarkerForDeletion (PartitionMarker* m);
104 MarkerMortuary<PartitionMarker> fMarkersToBeDeleted;
107 virtual void AboutToUpdateText (
const UpdateInfo& updateInfo)
override;
108 virtual void DidUpdateText (
const UpdateInfo& updateInfo)
noexcept override;
112 nonvirtual
size_t GetEnd ()
const;
113 nonvirtual
void CopyOut (
size_t from,
size_t count, Led_tChar* buffer)
const;
116 nonvirtual PartitionMarker* GetFirstPartitionMarker ()
const;
117 nonvirtual PartitionMarker* GetLastPartitionMarker ()
const;
120#if qStroika_Foundation_Debug_AssertionsChecked
121 size_t fPartitionMarkerCount;
123 PartitionMarker* fPartitionMarkerFirst;
124 PartitionMarker* fPartitionMarkerLast;
128 nonvirtual
void Invariant ()
const;
129#if qStroika_Foundation_Debug_AssertionsChecked
131 virtual void Invariant_ ()
const;
134 friend class PartitionMarker;
145 class Partition::PartitionMarker :
public Marker,
public Foundation::Memory::UseBlockAllocationIfAppropriate<PartitionMarker> {
147 using inherited = Marker;
150 PartitionMarker (Partition& owner, PartitionMarker* insertAfterMe);
154 virtual void DidUpdateText (
const UpdateInfo& updateInfo)
noexcept override;
158 virtual PartitionMarker* GetPrevious ()
const;
159 virtual PartitionMarker* GetNext ()
const;
162 PartitionMarker* fPrevious;
163 PartitionMarker* fNext;
166 nonvirtual Partition& GetOwner ()
const;
169 friend class Partition;
181 class Partition::PartitionWatcher {
183 virtual void AboutToSplit (PartitionMarker* pm,
size_t at,
void** infoRecord)
const noexcept = 0;
184 virtual void DidSplit (
void* infoRecord)
const noexcept = 0;
185 virtual void AboutToCoalece (PartitionMarker* pm,
void** infoRecord)
const noexcept = 0;
186 virtual void DidCoalece (
void* infoRecord)
const noexcept = 0;
189#if qStroika_Frameworks_Led_SupportGDI
197 class PartitioningTextImager :
public virtual TextImager {
199 using inherited = TextImager;
202 PartitioningTextImager ();
203 virtual ~PartitioningTextImager ();
206 using PartitionPtr = shared_ptr<Partition>;
207 nonvirtual PartitionPtr GetPartition ()
const;
210 virtual void SetPartition (
const PartitionPtr& partitionPtr);
213 PartitionPtr fPartition;
216 virtual PartitionPtr MakeDefaultPartition ()
const = 0;
218#if qCacheTextMeasurementsForPM
220 class MeasureTextCache;
221 unique_ptr<MeasureTextCache> fMeasureTextCache;
224 virtual void InvalidateAllCaches ()
override;
228 using PartitionMarker = Partition::PartitionMarker;
232 nonvirtual PartitionMarker* GetFirstPartitionMarker ()
const;
235 nonvirtual
size_t GetStartOfPartitionContainingPosition (
size_t charPosition)
const;
236 nonvirtual
size_t GetEndOfPartitionContainingPosition (
size_t charPosition)
const;
237 nonvirtual PartitionMarker* GetPartitionMarkerContainingPosition (
size_t charPosition)
const;
240 virtual TextDirection GetPrimaryPartitionTextDirection (
size_t rowContainingCharPosition)
const;
243 virtual TextLayoutBlock_Copy GetTextLayoutBlock (
size_t rowStart,
size_t rowEnd)
const override;
246 virtual TextDirection GetTextDirection (
size_t charPosition)
const override;
249 virtual DistanceType CalcSegmentSize (
size_t from,
size_t to)
const override;
252 virtual void GetRowRelativeCharLoc (
size_t charLoc, DistanceType* lhs, DistanceType* rhs)
const override;
253 virtual size_t GetRowRelativeCharAtLoc (CoordinateType hOffset,
size_t rowStart)
const override;
256 nonvirtual DistanceType CalcSegmentSize_REFERENCE (
size_t from,
size_t to)
const;
257#if qCacheTextMeasurementsForPM
258 nonvirtual DistanceType CalcSegmentSize_CACHING (
size_t from,
size_t to)
const;
262 nonvirtual
void CalcSegmentSize_FillIn (
size_t rowStart,
size_t rowEnd, DistanceType* distanceVector)
const;
265 virtual size_t ResetTabStops (
size_t from,
const Led_tChar* text,
size_t nTChars, DistanceType* charLocations,
size_t startSoFar)
const;
269 nonvirtual
void Invariant ()
const;
270#if qStroika_Foundation_Debug_AssertionsChecked
272 virtual void Invariant_ ()
const;
276#if qCacheTextMeasurementsForPM
282 class PartitioningTextImager::MeasureTextCache :
private Partition::PartitionWatcher,
public MarkerOwner {
284 using inherited =
void*;
287 MeasureTextCache (
const PartitionPtr& partition);
288 ~MeasureTextCache ();
291 virtual void AboutToSplit (PartitionMarker* pm,
size_t at,
void** infoRecord)
const noexcept override;
292 virtual void DidSplit (
void* infoRecord)
const noexcept override;
293 virtual void AboutToCoalece (PartitionMarker* pm,
void** infoRecord)
const noexcept override;
294 virtual void DidCoalece (
void* infoRecord)
const noexcept override;
297 virtual TextStore* PeekAtTextStore ()
const override;
300 virtual void EarlyDidUpdateText (
const UpdateInfo& updateInfo)
noexcept override;
303 struct CacheEltLRUCacheTraits;
306 struct COMPARE_ITEM {
307 COMPARE_ITEM (PartitionMarker* pm,
size_t startingRowAt)
309 , fRowStartingAt (startingRowAt)
312 PartitionMarker* fPM;
313 size_t fRowStartingAt;
318 CacheElt (
const COMPARE_ITEM& ci);
319 CacheElt (
const CacheElt&) =
default;
322 COMPARE_ITEM fValidFor;
325 Foundation::Memory::InlineBuffer<DistanceType> fMeasurementsCache;
328 friend struct CacheEltLRUCacheTraits;
329 friend class PartitioningTextImager::MeasureTextCache;
333 struct CacheElt_COMPARE_ITEM_KeyEqualsCompareFunctionType_ {
334 bool operator() (
const CacheElt::COMPARE_ITEM& lhs,
const CacheElt::COMPARE_ITEM& rhs)
const
336 return lhs.fPM == rhs.fPM and lhs.fRowStartingAt == rhs.fRowStartingAt;
339 mutable Foundation::Cache::LRUCache<CacheElt::COMPARE_ITEM, CacheElt, CacheElt_COMPARE_ITEM_KeyEqualsCompareFunctionType_> fCache;
342 nonvirtual
void ClearAll ();
345 nonvirtual CacheElt LookupValue (PartitionMarker* pm,
size_t rowStart,
const function<CacheElt (PartitionMarker*,
size_t)>& valueFetcher);
348 PartitionPtr fPartition;
360#include "PartitioningTextImager.inl"