Stroika Library 3.0d25
 
Loading...
Searching...
No Matches
BiDiLayoutEngine.h
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
4#ifndef _Stroika_Frameworks_Led_BiDiLayoutEngine_h_
5#define _Stroika_Frameworks_Led_BiDiLayoutEngine_h_ 1
6
7#include "Stroika/Frameworks/StroikaPreComp.h"
8
9#include <compare>
10#include <memory>
11
13
14/*
15@MODULE: BiDiLayout
16@DESCRIPTION: <p>Code to break up a string to be displayed - which might contain right-to-left text mixed
17 with left-to-right text into logical and display text runs according to the UNICODE Bidirectional
18 editing algorithm.
19 </p>
20 <p>NOTE: no layout engine is implemented - every paragraph comes out as ONE left-to-right run. The Uniscribe
21 and FriBidi code was removed in 3.0d25 (it had not compiled since 2012). If right-to-left text is ever needed,
22 see https://github.com/SophistSolutions/Stroika/issues/1182 for what to use.
23 </p>
24
25 */
26
27#include "Stroika/Frameworks/Led/GDI.h"
28#include "Stroika/Frameworks/Led/Support.h"
29
30namespace Stroika::Frameworks::Led {
31
32 /*
33 @CLASS: TextLayoutBlock
34 @DESCRIPTION: <p>xxx -- XPLAIN - Add ref to URL docs for this API. Note always pass in PARAGRAPH as unit for layout (cuz in spec)
35 </p>
36 */
37 class TextLayoutBlock {
38 protected:
39 TextLayoutBlock () = default;
40 virtual ~TextLayoutBlock () = default;
41
42 public:
43 nonvirtual const Led_tChar* PeekAtRealText () const;
44 nonvirtual const Led_tChar* PeekAtVirtualText () const;
45 nonvirtual size_t GetTextLength () const;
46
47 public:
48 virtual void PeekAtRealText_ (const Led_tChar** startText, const Led_tChar** endText) const = 0;
49 virtual void PeekAtVirtualText_ (const Led_tChar** startText, const Led_tChar** endText) const = 0;
50
51 public:
52 nonvirtual TextDirection GetCharacterDirection (size_t realCharOffset) const;
53
54 public:
55 nonvirtual size_t MapRealOffsetToVirtual (size_t i) const;
56 nonvirtual size_t MapVirtualOffsetToReal (size_t i) const;
57
58 public:
59 struct ScriptRunElt {
60 // NB: Since length of a run is always the same for virtual and real - we COULD make this struct smaller!
61 TextDirection fDirection;
62 size_t fRealStart;
63 size_t fRealEnd;
64 size_t fVirtualStart;
65 size_t fVirtualEnd;
66
67 nonvirtual bool operator== (const ScriptRunElt& rhs) const = default;
68 };
69 struct LessThanVirtualStart;
70
71 public:
72 virtual vector<ScriptRunElt> GetScriptRuns () const = 0;
73
74 public:
75 nonvirtual void CopyOutRealText (const ScriptRunElt& scriptRunElt, Led_tChar* buf) const;
76 nonvirtual void CopyOutVirtualText (const ScriptRunElt& scriptRunElt, Led_tChar* buf) const;
77
78 public:
79 nonvirtual void PeekAtRealText (const ScriptRunElt& scriptRunElt, const Led_tChar** startText, const Led_tChar** endText) const;
80 nonvirtual Led_tString GetRealText () const;
81 nonvirtual Led_tString GetRealText (const ScriptRunElt& scriptRunElt) const;
82 nonvirtual void PeekAtVirtualText (const ScriptRunElt& scriptRunElt, const Led_tChar** startText, const Led_tChar** endText) const;
83 nonvirtual Led_tString GetVirtualText () const;
84 nonvirtual Led_tString GetVirtualText (const ScriptRunElt& scriptRunElt) const;
85
86 public:
87 nonvirtual bool operator== (const TextLayoutBlock& rhs) const;
88
89 // Debug support
90 public:
91 nonvirtual void Invariant () const;
92#if qStroika_Foundation_Debug_AssertionsChecked
93 protected:
94 virtual void Invariant_ () const;
95#endif
96 };
97
98 /*
99 @CLASS: TextLayoutBlock::LessThanVirtualStart
100 @BASES:
101 @DESCRIPTION:
102 <p>Use this class when you have a vector of ScriptRunElt and want to sort it by virtual start.</p>
103 <p>As in:
104 </p>
105 <code><pre>
106 vector&lt;TextLayoutBlock::ScriptRunElt&gt; runs = get_em ();
107 sort (runs.begin (), runs.end (), TextLayoutBlock::LessThanVirtualStart ());
108 </pre></code>
109 */
110 struct TextLayoutBlock::LessThanVirtualStart {
111 bool operator() (const ScriptRunElt& lhs, const ScriptRunElt& rhs)
112 {
113 int diff = int (lhs.fVirtualStart) - int (rhs.fVirtualStart);
114 return (diff < 0);
115 }
116 };
117
118 /*
119 @CLASS: TextLayoutBlock_Basic
120 @DESCRIPTION: <p>NB: the CTOR copies the argument string by value, and doesn't retain the pointer itself.
121 </p>
122 */
123 class TextLayoutBlock_Basic : public TextLayoutBlock {
124 private:
125 using inherited = TextLayoutBlock;
126
127 public:
128 TextLayoutBlock_Basic (const Led_tChar* realText, const Led_tChar* realTextEnd);
129 TextLayoutBlock_Basic (const Led_tChar* realText, const Led_tChar* realTextEnd, TextDirection initialDirection);
130
131 private:
132 nonvirtual void Construct (const Led_tChar* realText, const Led_tChar* realTextEnd, const TextDirection* initialDirection);
133
134 private:
135 nonvirtual void Construct_Default ();
136
137 public:
138 virtual void PeekAtRealText_ (const Led_tChar** startText, const Led_tChar** endText) const override;
139 virtual void PeekAtVirtualText_ (const Led_tChar** startText, const Led_tChar** endText) const override;
140
141 public:
142 virtual vector<ScriptRunElt> GetScriptRuns () const override;
143
144 private:
145 size_t fTextLength;
146 Foundation::Memory::InlineBuffer<Led_tChar> fRealText;
147 Foundation::Memory::InlineBuffer<Led_tChar> fVirtualText;
148 vector<ScriptRunElt> fScriptRuns;
149 };
150
151 /*
152 @CLASS: TextLayoutBlock_Copy
153 @DESCRIPTION: <p>This class is designed to allow for very cheap and quick copying of TextLayoutBlocks. This class
154 and be stack/assign copied (not just by pointer). It is an indexpensive way to cache a TextLayoutBlock, or
155 to return one from a function.
156 </p>
157 */
158 class TextLayoutBlock_Copy : public TextLayoutBlock {
159 private:
160 using inherited = TextLayoutBlock;
161
162 public:
163 TextLayoutBlock_Copy (const TextLayoutBlock& from);
164 TextLayoutBlock_Copy (const TextLayoutBlock_Copy& from);
165
166 public:
167 virtual void PeekAtRealText_ (const Led_tChar** startText, const Led_tChar** endText) const override;
168 virtual void PeekAtVirtualText_ (const Led_tChar** startText, const Led_tChar** endText) const override;
169
170 public:
171 virtual vector<ScriptRunElt> GetScriptRuns () const override;
172
173 private:
174 struct BlockRep {
175 nonvirtual void operator delete (void* p);
176
177 size_t fTextLength{};
178 const Led_tChar* fRealText{};
179 const Led_tChar* fVirtualText{};
180 const ScriptRunElt* fScriptRuns{};
181 const ScriptRunElt* fScriptRunsEnd{};
182 // and we allocate extra space off the end of this object for the acutal data...
183 };
184 shared_ptr<BlockRep> fRep;
185 };
186
187 /*
188 @CLASS: TextLayoutBlock_VirtualSubset
189 @DESCRIPTION: <p>NB: Saves a reference to its CTOR argument- 'subsetOf' so this must be destroyed AFTER
190 the original.</p>
191 <p>It is not obvious if this code should may a COPY of the 'real text' or refer back to the same original text with its original
192 offsets. However - the problem with doing so is that since we've picked a contigous range of the virtual space, that does
193 not coorespond to a contiguous space in the real space necessarily - except for the entire original buffer. That wouldn't be
194 the same size - however - as the virtual buffer. Our API assumes these two spaces are the same size. So - the best compromise
195 appears to be to copy the source text into a new buffer with new offsets that range from 0 to max-length and have nothing todo with
196 the original buffer offsets.
197 </p>
198 */
199 class TextLayoutBlock_VirtualSubset : public TextLayoutBlock {
200 private:
201 using inherited = TextLayoutBlock;
202
203 public:
204 TextLayoutBlock_VirtualSubset (const TextLayoutBlock& subsetOf, size_t vStart, size_t vEnd);
205
206 public:
207 virtual void PeekAtRealText_ (const Led_tChar** startText, const Led_tChar** endText) const override;
208 virtual void PeekAtVirtualText_ (const Led_tChar** startText, const Led_tChar** endText) const override;
209
210 public:
211 virtual vector<ScriptRunElt> GetScriptRuns () const override;
212
213 private:
214 const TextLayoutBlock& fSubsetOf;
215 size_t fStart{};
216 size_t fEnd{};
217 vector<ScriptRunElt> fScriptRuns;
218 Foundation::Memory::InlineBuffer<Led_tChar> fRealText;
219 };
220
221}
222
223/*
224 ********************************************************************************
225 ***************************** Implementation Details ***************************
226 ********************************************************************************
227 */
228#include "BiDiLayoutEngine.inl"
229
230#endif /*_Stroika_Frameworks_Led_BiDiLayoutEngine_h_*/