Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / source / core / inc / scriptinfo.hxx
blob21c3c2240cc4436d00fdf35e8684bf8232512e73
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #ifndef INCLUDED_SW_SOURCE_CORE_INC_SCRIPTINFO_HXX
21 #define INCLUDED_SW_SOURCE_CORE_INC_SCRIPTINFO_HXX
23 #include <vector>
24 #include <deque>
25 #include <unordered_set>
26 #include <rtl/ustrbuf.hxx>
27 #include <o3tl/typed_flags_set.hxx>
28 #include <i18nlangtag/lang.h>
29 #include <tools/long.hxx>
30 #include "TextFrameIndex.hxx"
31 #include <doc.hxx>
33 class SwTextNode;
34 class SwTextFrame;
35 class Point;
36 class MultiSelection;
37 enum class SwFontScript;
38 namespace sw { struct MergedPara; }
39 namespace sw::mark { class IBookmark; }
41 #define SPACING_PRECISION_FACTOR 100
43 // encapsulates information about script changes
44 class SwScriptInfo
46 public:
47 enum CompType { KANA, SPECIAL_LEFT, SPECIAL_RIGHT, NONE, SPECIAL_MIDDLE};
48 enum class MarkKind { Start = (1<<0), End = (1<<1), Point = (1<<2) };
50 private:
51 //! Records a single change in script type.
52 struct ScriptChangeInfo
54 TextFrameIndex position; //!< Character position at which we change script
55 sal_uInt8 type; //!< Script type (Latin/Asian/Complex) that we change to.
56 ScriptChangeInfo(TextFrameIndex pos, sal_uInt8 typ) : position(pos), type(typ) {};
58 //TODO - This is sorted, so should probably be a std::set rather than vector.
59 // But we also use random access (probably unnecessarily).
60 std::vector<ScriptChangeInfo> m_ScriptChanges;
61 //! Records a single change in direction.
62 struct DirectionChangeInfo
64 TextFrameIndex position; //!< Character position at which we change direction.
65 sal_uInt8 type; //!< Direction that we change to.
66 DirectionChangeInfo(TextFrameIndex pos, sal_uInt8 typ) : position(pos), type(typ) {};
68 std::vector<DirectionChangeInfo> m_DirectionChanges;
69 std::deque<TextFrameIndex> m_Kashida;
70 /// indexes into m_Kashida
71 std::unordered_set<size_t> m_KashidaInvalid;
72 std::deque<TextFrameIndex> m_NoKashidaLine;
73 std::deque<TextFrameIndex> m_NoKashidaLineEnd;
74 std::vector<TextFrameIndex> m_HiddenChg;
75 std::vector<std::tuple<TextFrameIndex, MarkKind, Color, OUString>> m_Bookmarks;
76 //! Records a single change in compression.
77 struct CompressionChangeInfo
79 TextFrameIndex position; //!< Character position where the change occurs.
80 TextFrameIndex length; //!< Length of the segment.
81 CompType type; //!< Type of compression that we change to.
82 CompressionChangeInfo(TextFrameIndex pos, TextFrameIndex len, CompType typ) : position(pos), length(len), type(typ) {};
84 std::vector<CompressionChangeInfo> m_CompressionChanges;
85 #ifdef DBG_UTIL
86 CompType DbgCompType(const TextFrameIndex nPos) const;
87 #endif
89 TextFrameIndex m_nInvalidityPos;
90 sal_uInt8 m_nDefaultDir;
92 void UpdateBidiInfo( const OUString& rText );
93 bool IsKashidaValid(size_t nKashPos) const;
94 // returns true if nKashPos is newly marked invalid
95 bool MarkKashidaInvalid(size_t nKashPos);
96 void ClearKashidaInvalid(size_t nKashPos);
97 bool MarkOrClearKashidaInvalid(TextFrameIndex nStt, TextFrameIndex nLen,
98 bool bMark, sal_Int32 nMarkCount);
99 bool IsKashidaLine(TextFrameIndex nCharIdx) const;
100 // examines the range [ nStart, nStart + nEnd ] if there are kanas
101 // returns start index of kana entry in array, otherwise SAL_MAX_SIZE
102 size_t HasKana(TextFrameIndex nStart, TextFrameIndex nEnd) const;
104 public:
106 SwScriptInfo();
107 ~SwScriptInfo();
109 // determines script changes
110 void InitScriptInfo(const SwTextNode& rNode, sw::MergedPara const* pMerged, bool bRTL);
111 void InitScriptInfo(const SwTextNode& rNode, sw::MergedPara const* pMerged);
113 // set/get position from which data is invalid
114 void SetInvalidityA(const TextFrameIndex nPos)
116 if (nPos < m_nInvalidityPos)
117 m_nInvalidityPos = nPos;
119 TextFrameIndex GetInvalidityA() const
121 return m_nInvalidityPos;
124 // get default direction for paragraph
125 sal_uInt8 GetDefaultDir() const { return m_nDefaultDir; };
127 // array operations, nCnt refers to array position
128 size_t CountScriptChg() const { return m_ScriptChanges.size(); }
129 TextFrameIndex GetScriptChg(const size_t nCnt) const
131 assert(nCnt < m_ScriptChanges.size());
132 return m_ScriptChanges[nCnt].position;
134 sal_uInt8 GetScriptType( const size_t nCnt ) const
136 assert( nCnt < m_ScriptChanges.size());
137 return m_ScriptChanges[nCnt].type;
140 size_t CountDirChg() const { return m_DirectionChanges.size(); }
141 TextFrameIndex GetDirChg(const size_t nCnt) const
143 assert(nCnt < m_DirectionChanges.size());
144 return m_DirectionChanges[ nCnt ].position;
146 sal_uInt8 GetDirType( const size_t nCnt ) const
148 assert(nCnt < m_DirectionChanges.size());
149 return m_DirectionChanges[ nCnt ].type;
152 size_t CountKashida() const
154 return m_Kashida.size();
157 TextFrameIndex GetKashida(const size_t nCnt) const
159 assert(nCnt < m_Kashida.size());
160 return m_Kashida[nCnt];
163 size_t CountCompChg() const { return m_CompressionChanges.size(); };
164 TextFrameIndex GetCompStart(const size_t nCnt) const
166 assert(nCnt < m_CompressionChanges.size());
167 return m_CompressionChanges[ nCnt ].position;
169 TextFrameIndex GetCompLen(const size_t nCnt) const
171 assert(nCnt < m_CompressionChanges.size());
172 return m_CompressionChanges[ nCnt ].length;
174 CompType GetCompType( const size_t nCnt ) const
176 assert(nCnt < m_CompressionChanges.size());
177 return m_CompressionChanges[ nCnt ].type;
180 size_t CountHiddenChg() const { return m_HiddenChg.size(); };
181 TextFrameIndex GetHiddenChg(const size_t nCnt) const
183 assert(nCnt < m_HiddenChg.size());
184 return m_HiddenChg[ nCnt ];
186 TextFrameIndex NextHiddenChg(TextFrameIndex nPos) const;
187 TextFrameIndex NextBookmark(TextFrameIndex nPos) const;
188 std::vector<std::tuple<MarkKind, Color, OUString>>
189 GetBookmarks(TextFrameIndex const nPos);
190 static void CalcHiddenRanges(const SwTextNode& rNode,
191 MultiSelection& rHiddenMulti,
192 std::vector<std::pair<sw::mark::IBookmark const*, MarkKind>> * pBookmarks);
193 static void selectHiddenTextProperty(const SwTextNode& rNode,
194 MultiSelection &rHiddenMulti,
195 std::vector<std::pair<sw::mark::IBookmark const*, MarkKind>> * pBookmarks);
196 static void selectRedLineDeleted(const SwTextNode& rNode, MultiSelection &rHiddenMulti, bool bSelect=true);
198 // "high" level operations, nPos refers to string position
199 TextFrameIndex NextScriptChg(TextFrameIndex nPos) const;
200 sal_Int16 ScriptType(const TextFrameIndex nPos) const;
202 // Returns the position of the next direction level change.
203 // If bLevel is set, the position of the next level which is smaller
204 // than the level at position nPos is returned. This is required to
205 // obtain the end of a SwBidiPortion
206 TextFrameIndex NextDirChg(const TextFrameIndex nPos,
207 const sal_uInt8* pLevel = nullptr) const;
208 sal_uInt8 DirType(const TextFrameIndex nPos) const;
210 // HIDDEN TEXT STUFF START
212 /** Hidden text range information - static and non-version
214 @descr Determines if a given position is inside a hidden text range. The
215 static version tries to obtain a valid SwScriptInfo object
216 via the SwTextNode, otherwise it calculates the values from scratch.
217 The non-static version uses the internally cached information
218 for the calculation.
220 @param rNode
221 The text node.
222 @param nPos
223 The given position that should be checked.
224 @param rnStartPos
225 Return parameter for the start position of the hidden range.
226 COMPLETE_STRING if nPos is not inside a hidden range.
227 @param rnEndPos
228 Return parameter for the end position of the hidden range.
229 0 if nPos is not inside a hidden range.
230 @param rnEndPos
231 Return parameter that contains all the hidden text ranges. Optional.
232 @return
233 returns true if there are any hidden characters in this paragraph.
236 static bool GetBoundsOfHiddenRange( const SwTextNode& rNode, sal_Int32 nPos,
237 sal_Int32& rnStartPos, sal_Int32& rnEndPos,
238 std::vector<sal_Int32>* pList = nullptr );
239 bool GetBoundsOfHiddenRange(TextFrameIndex nPos, TextFrameIndex & rnStartPos,
240 TextFrameIndex & rnEndPos) const;
242 static bool IsInHiddenRange( const SwTextNode& rNode, sal_Int32 nPos );
244 /** Hidden text attribute handling
246 @descr Takes a string and either deletes the hidden ranges or sets
247 a given character in place of the hidden characters.
249 @param rNode
250 The text node.
251 @param rText
252 The string to modify.
253 @param cChar
254 The character that should replace the hidden characters.
255 @param bDel
256 If set, the hidden ranges will be deleted from the text node.
258 static sal_Int32 MaskHiddenRanges(
259 const SwTextNode& rNode, OUStringBuffer& rText,
260 const sal_Int32 nStt, const sal_Int32 nEnd,
261 const sal_Unicode cChar );
263 /** Hidden text attribute handling
265 @descr Takes a SwTextNode and deletes the hidden ranges from the node.
267 @param rNode
268 The text node.
270 static void DeleteHiddenRanges( SwTextNode& rNode );
272 // HIDDEN TEXT STUFF END
274 // modifies the kerning array according to a given compress value
275 tools::Long Compress( KernArray& rKernArray, TextFrameIndex nIdx, TextFrameIndex nLen,
276 const sal_uInt16 nCompress, const sal_uInt16 nFontHeight,
277 const bool bCentered,
278 Point* pPoint = nullptr ) const;
280 /** Performs a kashida justification on the kerning array
282 @descr Add some extra space for kashida justification to the
283 positions in the kerning array.
284 @param pKernArray
285 The printers kerning array. Optional.
286 @param nStt
287 Start referring to the paragraph.
288 @param nLen
289 The number of characters to be considered.
290 @param nSpaceAdd
291 The value which has to be added to a kashida opportunity.
292 @return The number of kashida opportunities in the given range
294 sal_Int32 KashidaJustify( KernArray* pKernArray, sal_Bool* pKashidaArray,
295 TextFrameIndex nStt, TextFrameIndex nLen, tools::Long nSpaceAdd = 0) const;
297 /** Clears array of kashidas marked as invalid
299 void ClearKashidaInvalid(TextFrameIndex const nStt, TextFrameIndex const nLen)
301 MarkOrClearKashidaInvalid(nStt, nLen, false, 0);
304 /** Marks nCnt kashida positions as invalid
305 pKashidaPositions: array of char indices relative to the paragraph
307 void MarkKashidasInvalid(sal_Int32 nCnt, const TextFrameIndex* pKashidaPositions);
309 /** Marks nCnt kashida positions as invalid
310 in the given text range
312 bool MarkKashidasInvalid(sal_Int32 const nCnt,
313 TextFrameIndex const nStt, TextFrameIndex const nLen)
315 return MarkOrClearKashidaInvalid(nStt, nLen, true, nCnt);
318 /** retrieves kashida opportunities for a given text range.
320 rKashidaPositions: buffer to receive the char indices of the
321 kashida opportunities relative to the paragraph
323 void GetKashidaPositions(TextFrameIndex nStt, TextFrameIndex nLen,
324 std::vector<TextFrameIndex>& rKashidaPosition);
326 /** Use regular blank justification instead of kashdida justification for the given line of text.
327 nStt Start char index of the line referring to the paragraph.
328 nLen Number of characters in the line
330 void SetNoKashidaLine(TextFrameIndex nStt, TextFrameIndex nLen);
332 /** Clear forced blank justification for a given line.
333 nStt Start char index of the line referring to the paragraph.
334 nLen Number of characters in the line
336 void ClearNoKashidaLine(TextFrameIndex nStt, TextFrameIndex nLen);
338 /** Checks if text is Arabic text.
340 @descr Checks if text is Arabic text.
341 @param rText
342 The text to check
343 @param nStt
344 Start index of the text
345 @return Returns if the language is an Arabic language
347 static bool IsArabicText(const OUString& rText, TextFrameIndex nStt, TextFrameIndex nLen);
349 /** Performs a thai justification on the kerning array
351 @descr Add some extra space for thai justification to the
352 positions in the kerning array.
353 @param aText
354 The String
355 @param pKernArray
356 The printers kerning array. Optional.
357 @param nIdx
358 Start referring to the paragraph.
359 @param nLen
360 The number of characters to be considered.
361 @param nSpaceAdd
362 The value which has to be added to the cells.
363 @return The number of extra spaces in the given range
365 static TextFrameIndex ThaiJustify( std::u16string_view aText, KernArray* pKernArray,
366 TextFrameIndex nIdx,
367 TextFrameIndex nLen,
368 TextFrameIndex nNumberOfBlanks = TextFrameIndex(0),
369 tools::Long nSpaceAdd = 0 );
371 static TextFrameIndex CountCJKCharacters(const OUString &rText,
372 TextFrameIndex nPos, TextFrameIndex nEnd, LanguageType aLang);
374 static void CJKJustify( const OUString& rText, KernArray& rKernArray,
375 TextFrameIndex nStt,
376 TextFrameIndex nLen, LanguageType aLang,
377 tools::Long nSpaceAdd, bool bIsSpaceStop );
379 /// return a frame for the node, ScriptInfo is its member...
380 /// (many clients need both frame and SI, and both have to match)
381 static SwScriptInfo* GetScriptInfo( const SwTextNode& rNode,
382 SwTextFrame const** o_pFrame = nullptr,
383 bool bAllowInvalid = false);
385 SwFontScript WhichFont(TextFrameIndex nIdx) const;
386 static SwFontScript WhichFont(sal_Int32 nIdx, OUString const & rText);
389 namespace o3tl
392 template<> struct typed_flags<SwScriptInfo::MarkKind> : is_typed_flags<SwScriptInfo::MarkKind, 0x07> {};
396 #endif
398 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */