nss: upgrade to release 3.73
[LibreOffice.git] / sw / source / core / inc / scriptinfo.hxx
blob7e660309aa54cb9a27f5b1f259f5e80fd9c44fe3
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"
32 class SwTextNode;
33 class SwTextFrame;
34 class Point;
35 class MultiSelection;
36 enum class SwFontScript;
37 namespace sw { struct MergedPara; }
38 namespace sw::mark { class IBookmark; }
40 #define SPACING_PRECISION_FACTOR 100
42 // encapsulates information about script changes
43 class SwScriptInfo
45 public:
46 enum CompType { KANA, SPECIAL_LEFT, SPECIAL_RIGHT, NONE, SPECIAL_MIDDLE};
47 enum class MarkKind { Start = (1<<0), End = (1<<1), Point = (1<<2) };
49 private:
50 //! Records a single change in script type.
51 struct ScriptChangeInfo
53 TextFrameIndex position; //!< Character position at which we change script
54 sal_uInt8 type; //!< Script type (Latin/Asian/Complex) that we change to.
55 ScriptChangeInfo(TextFrameIndex pos, sal_uInt8 typ) : position(pos), type(typ) {};
57 //TODO - This is sorted, so should probably be a std::set rather than vector.
58 // But we also use random access (probably unnecessarily).
59 std::vector<ScriptChangeInfo> m_ScriptChanges;
60 //! Records a single change in direction.
61 struct DirectionChangeInfo
63 TextFrameIndex position; //!< Character position at which we change direction.
64 sal_uInt8 type; //!< Direction that we change to.
65 DirectionChangeInfo(TextFrameIndex pos, sal_uInt8 typ) : position(pos), type(typ) {};
67 std::vector<DirectionChangeInfo> m_DirectionChanges;
68 std::deque<TextFrameIndex> m_Kashida;
69 /// indexes into m_Kashida
70 std::unordered_set<size_t> m_KashidaInvalid;
71 std::deque<TextFrameIndex> m_NoKashidaLine;
72 std::deque<TextFrameIndex> m_NoKashidaLineEnd;
73 std::vector<TextFrameIndex> m_HiddenChg;
74 std::vector<std::pair<TextFrameIndex, MarkKind>> m_Bookmarks;
75 //! Records a single change in compression.
76 struct CompressionChangeInfo
78 TextFrameIndex position; //!< Character position where the change occurs.
79 TextFrameIndex length; //!< Length of the segment.
80 CompType type; //!< Type of compression that we change to.
81 CompressionChangeInfo(TextFrameIndex pos, TextFrameIndex len, CompType typ) : position(pos), length(len), type(typ) {};
83 std::vector<CompressionChangeInfo> m_CompressionChanges;
84 #ifdef DBG_UTIL
85 CompType DbgCompType(const TextFrameIndex nPos) const;
86 #endif
88 TextFrameIndex m_nInvalidityPos;
89 sal_uInt8 m_nDefaultDir;
91 void UpdateBidiInfo( const OUString& rText );
92 bool IsKashidaValid(size_t nKashPos) const;
93 // returns true if nKashPos is newly marked invalid
94 bool MarkKashidaInvalid(size_t nKashPos);
95 void ClearKashidaInvalid(size_t nKashPos);
96 bool MarkOrClearKashidaInvalid(TextFrameIndex nStt, TextFrameIndex nLen,
97 bool bMark, sal_Int32 nMarkCount);
98 bool IsKashidaLine(TextFrameIndex nCharIdx) const;
99 // examines the range [ nStart, nStart + nEnd ] if there are kanas
100 // returns start index of kana entry in array, otherwise SAL_MAX_SIZE
101 size_t HasKana(TextFrameIndex nStart, TextFrameIndex nEnd) const;
103 public:
105 SwScriptInfo();
106 ~SwScriptInfo();
108 // determines script changes
109 void InitScriptInfo(const SwTextNode& rNode, sw::MergedPara const* pMerged, bool bRTL);
110 void InitScriptInfo(const SwTextNode& rNode, sw::MergedPara const* pMerged);
112 // set/get position from which data is invalid
113 void SetInvalidityA(const TextFrameIndex nPos)
115 if (nPos < m_nInvalidityPos)
116 m_nInvalidityPos = nPos;
118 TextFrameIndex GetInvalidityA() const
120 return m_nInvalidityPos;
123 // get default direction for paragraph
124 sal_uInt8 GetDefaultDir() const { return m_nDefaultDir; };
126 // array operations, nCnt refers to array position
127 size_t CountScriptChg() const { return m_ScriptChanges.size(); }
128 TextFrameIndex GetScriptChg(const size_t nCnt) const
130 assert(nCnt < m_ScriptChanges.size());
131 return m_ScriptChanges[nCnt].position;
133 sal_uInt8 GetScriptType( const size_t nCnt ) const
135 assert( nCnt < m_ScriptChanges.size());
136 return m_ScriptChanges[nCnt].type;
139 size_t CountDirChg() const { return m_DirectionChanges.size(); }
140 TextFrameIndex GetDirChg(const size_t nCnt) const
142 assert(nCnt < m_DirectionChanges.size());
143 return m_DirectionChanges[ nCnt ].position;
145 sal_uInt8 GetDirType( const size_t nCnt ) const
147 assert(nCnt < m_DirectionChanges.size());
148 return m_DirectionChanges[ nCnt ].type;
151 size_t CountKashida() const
153 return m_Kashida.size();
156 TextFrameIndex GetKashida(const size_t nCnt) const
158 assert(nCnt < m_Kashida.size());
159 return m_Kashida[nCnt];
162 size_t CountCompChg() const { return m_CompressionChanges.size(); };
163 TextFrameIndex GetCompStart(const size_t nCnt) const
165 assert(nCnt < m_CompressionChanges.size());
166 return m_CompressionChanges[ nCnt ].position;
168 TextFrameIndex GetCompLen(const size_t nCnt) const
170 assert(nCnt < m_CompressionChanges.size());
171 return m_CompressionChanges[ nCnt ].length;
173 CompType GetCompType( const size_t nCnt ) const
175 assert(nCnt < m_CompressionChanges.size());
176 return m_CompressionChanges[ nCnt ].type;
179 size_t CountHiddenChg() const { return m_HiddenChg.size(); };
180 TextFrameIndex GetHiddenChg(const size_t nCnt) const
182 assert(nCnt < m_HiddenChg.size());
183 return m_HiddenChg[ nCnt ];
185 TextFrameIndex NextHiddenChg(TextFrameIndex nPos) const;
186 TextFrameIndex NextBookmark(TextFrameIndex nPos) const;
187 MarkKind GetBookmark(TextFrameIndex nPos) const;
188 static void CalcHiddenRanges(const SwTextNode& rNode,
189 MultiSelection& rHiddenMulti,
190 std::vector<std::pair<sw::mark::IBookmark const*, MarkKind>> * pBookmarks);
191 static void selectHiddenTextProperty(const SwTextNode& rNode,
192 MultiSelection &rHiddenMulti,
193 std::vector<std::pair<sw::mark::IBookmark const*, MarkKind>> * pBookmarks);
194 static void selectRedLineDeleted(const SwTextNode& rNode, MultiSelection &rHiddenMulti, bool bSelect=true);
196 // "high" level operations, nPos refers to string position
197 TextFrameIndex NextScriptChg(TextFrameIndex nPos) const;
198 sal_Int16 ScriptType(const TextFrameIndex nPos) const;
200 // Returns the position of the next direction level change.
201 // If bLevel is set, the position of the next level which is smaller
202 // than the level at position nPos is returned. This is required to
203 // obtain the end of a SwBidiPortion
204 TextFrameIndex NextDirChg(const TextFrameIndex nPos,
205 const sal_uInt8* pLevel = nullptr) const;
206 sal_uInt8 DirType(const TextFrameIndex nPos) const;
208 // HIDDEN TEXT STUFF START
210 /** Hidden text range information - static and non-version
212 @descr Determines if a given position is inside a hidden text range. The
213 static version tries to obtain a valid SwScriptInfo object
214 via the SwTextNode, otherwise it calculates the values from scratch.
215 The non-static version uses the internally cached information
216 for the calculation.
218 @param rNode
219 The text node.
220 @param nPos
221 The given position that should be checked.
222 @param rnStartPos
223 Return parameter for the start position of the hidden range.
224 COMPLETE_STRING if nPos is not inside a hidden range.
225 @param rnEndPos
226 Return parameter for the end position of the hidden range.
227 0 if nPos is not inside a hidden range.
228 @param rnEndPos
229 Return parameter that contains all the hidden text ranges. Optional.
230 @return
231 returns true if there are any hidden characters in this paragraph.
234 static bool GetBoundsOfHiddenRange( const SwTextNode& rNode, sal_Int32 nPos,
235 sal_Int32& rnStartPos, sal_Int32& rnEndPos,
236 std::vector<sal_Int32>* pList = nullptr );
237 bool GetBoundsOfHiddenRange(TextFrameIndex nPos, TextFrameIndex & rnStartPos,
238 TextFrameIndex & rnEndPos) const;
240 static bool IsInHiddenRange( const SwTextNode& rNode, sal_Int32 nPos );
242 /** Hidden text attribute handling
244 @descr Takes a string and either deletes the hidden ranges or sets
245 a given character in place of the hidden characters.
247 @param rNode
248 The text node.
249 @param rText
250 The string to modify.
251 @param cChar
252 The character that should replace the hidden characters.
253 @param bDel
254 If set, the hidden ranges will be deleted from the text node.
256 static sal_Int32 MaskHiddenRanges(
257 const SwTextNode& rNode, OUStringBuffer& rText,
258 const sal_Int32 nStt, const sal_Int32 nEnd,
259 const sal_Unicode cChar );
261 /** Hidden text attribute handling
263 @descr Takes a SwTextNode and deletes the hidden ranges from the node.
265 @param rNode
266 The text node.
268 static void DeleteHiddenRanges( SwTextNode& rNode );
270 // HIDDEN TEXT STUFF END
272 // modifies the kerning array according to a given compress value
273 tools::Long Compress( tools::Long* pKernArray, TextFrameIndex nIdx, TextFrameIndex nLen,
274 const sal_uInt16 nCompress, const sal_uInt16 nFontHeight,
275 const bool bCentered,
276 Point* pPoint = nullptr ) const;
278 /** Performs a kashida justification on the kerning array
280 @descr Add some extra space for kashida justification to the
281 positions in the kerning array.
282 @param pKernArray
283 The printers kerning array. Optional.
284 @param pScrArray
285 The screen 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( tools::Long* pKernArray, tools::Long* pScrArray,
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 rText
354 The String
355 @param pKernArray
356 The printers kerning array. Optional.
357 @param pScrArray
358 The screen kerning array. Optional.
359 @param nIdx
360 Start referring to the paragraph.
361 @param nLen
362 The number of characters to be considered.
363 @param nSpaceAdd
364 The value which has to be added to the cells.
365 @return The number of extra spaces in the given range
367 static TextFrameIndex ThaiJustify( const OUString& rText, tools::Long* pKernArray,
368 tools::Long* pScrArray, TextFrameIndex nIdx,
369 TextFrameIndex nLen,
370 TextFrameIndex nNumberOfBlanks = TextFrameIndex(0),
371 tools::Long nSpaceAdd = 0 );
373 static TextFrameIndex CountCJKCharacters(const OUString &rText,
374 TextFrameIndex nPos, TextFrameIndex nEnd, LanguageType aLang);
376 static void CJKJustify( const OUString& rText, tools::Long* pKernArray,
377 tools::Long* pScrArray, TextFrameIndex nStt,
378 TextFrameIndex nLen, LanguageType aLang,
379 tools::Long nSpaceAdd, bool bIsSpaceStop );
381 /// return a frame for the node, ScriptInfo is its member...
382 /// (many clients need both frame and SI, and both have to match)
383 static SwScriptInfo* GetScriptInfo( const SwTextNode& rNode,
384 SwTextFrame const** o_pFrame = nullptr,
385 bool bAllowInvalid = false);
387 SwFontScript WhichFont(TextFrameIndex nIdx) const;
388 static SwFontScript WhichFont(sal_Int32 nIdx, OUString const & rText);
391 namespace o3tl
394 template<> struct typed_flags<SwScriptInfo::MarkKind> : is_typed_flags<SwScriptInfo::MarkKind, 0x07> {};
398 #endif
400 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */