Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #ifndef INCLUDED_SW_SOURCE_CORE_INC_SCRIPTINFO_HXX
21 : #define INCLUDED_SW_SOURCE_CORE_INC_SCRIPTINFO_HXX
22 :
23 : #include <list>
24 : #include <deque>
25 : #include "swscanner.hxx"
26 : #include <rtl/ustrbuf.hxx>
27 : #include <osl/diagnose.h>
28 :
29 : class SwTextNode;
30 : class Point;
31 : class MultiSelection;
32 : typedef std::list< sal_Int32 > PositionList;
33 :
34 : #define SPACING_PRECISION_FACTOR 100
35 :
36 : // encapsultes information about script changes
37 : class SwScriptInfo
38 : {
39 : public:
40 : enum CompType { KANA, SPECIAL_LEFT, SPECIAL_RIGHT, NONE };
41 :
42 : private:
43 : //! Records a single change in script type.
44 : struct ScriptChangeInfo
45 : {
46 : sal_Int32 position; //!< Character position at which we change script
47 : sal_uInt8 type; //!< Script type (Latin/Asian/Complex) that we change to.
48 47640 : inline ScriptChangeInfo(sal_Int32 pos, sal_uInt8 typ) : position(pos), type(typ) {};
49 : };
50 : //TODO - This is sorted, so should probably be a std::set rather than vector.
51 : // But we also use random access (probably unnecessarily).
52 : std::vector<ScriptChangeInfo> aScriptChanges;
53 : //! Records a single change in direction.
54 : struct DirectionChangeInfo
55 : {
56 : sal_Int32 position; //!< Character position at which we change direction.
57 : sal_uInt8 type; //!< Direction that we change to.
58 64 : inline DirectionChangeInfo(sal_Int32 pos, sal_uInt8 typ) : position(pos), type(typ) {};
59 : };
60 : std::vector<DirectionChangeInfo> aDirectionChanges;
61 : std::deque< sal_Int32 > aKashida;
62 : std::deque< sal_Int32 > aKashidaInvalid;
63 : std::deque< sal_Int32 > aNoKashidaLine;
64 : std::deque< sal_Int32 > aNoKashidaLineEnd;
65 : std::deque< sal_Int32 > aHiddenChg;
66 : //! Records a single change in compression.
67 : struct CompressionChangeInfo
68 : {
69 : sal_Int32 position; //!< Character position where the change occurs.
70 : sal_Int32 length; //!< Length of the segment.
71 : CompType type; //!< Type of compression that we change to.
72 0 : inline CompressionChangeInfo(sal_Int32 pos, sal_Int32 len, CompType typ) : position(pos), length(len), type(typ) {};
73 : };
74 : std::vector<CompressionChangeInfo> aCompressionChanges;
75 : #ifdef DBG_UTIL
76 : CompType DbgCompType( const sal_Int32 nPos ) const;
77 : #endif
78 :
79 : sal_Int32 nInvalidityPos;
80 : sal_uInt8 nDefaultDir;
81 :
82 : void UpdateBidiInfo( const OUString& rText );
83 :
84 : bool IsKashidaValid(sal_Int32 nKashPos) const;
85 : void MarkKashidaInvalid(sal_Int32 nKashPos);
86 : void ClearKashidaInvalid(sal_Int32 nKashPos);
87 : bool MarkOrClearKashidaInvalid(sal_Int32 nStt, sal_Int32 nLen, bool bMark, sal_Int32 nMarkCount);
88 : bool IsKashidaLine(sal_Int32 nCharIdx) const;
89 : // examines the range [ nStart, nStart + nEnd ] if there are kanas
90 : // returns start index of kana entry in array, otherwise SAL_MAX_SIZE
91 : size_t HasKana( sal_Int32 nStart, const sal_Int32 nEnd ) const;
92 :
93 : public:
94 :
95 : SwScriptInfo();
96 : ~SwScriptInfo();
97 :
98 : // determines script changes
99 : void InitScriptInfo( const SwTextNode& rNode, bool bRTL );
100 : void InitScriptInfo( const SwTextNode& rNode );
101 :
102 : // set/get position from which data is invalid
103 5419 : void SetInvalidityA(const sal_Int32 nPos)
104 : {
105 5419 : if (nPos < nInvalidityPos)
106 4515 : nInvalidityPos = nPos;
107 5419 : }
108 192283 : sal_Int32 GetInvalidityA() const
109 : {
110 192283 : return nInvalidityPos;
111 : }
112 :
113 : // get default direction for paragraph
114 6869 : inline sal_uInt8 GetDefaultDir() const { return nDefaultDir; };
115 :
116 : // array operations, nCnt refers to array position
117 916364 : size_t CountScriptChg() const { return aScriptChanges.size(); }
118 973847 : sal_Int32 GetScriptChg( const size_t nCnt ) const
119 : {
120 : OSL_ENSURE( nCnt < aScriptChanges.size(),"No ScriptChange today!");
121 973847 : return aScriptChanges[nCnt].position;
122 : }
123 688819 : sal_uInt8 GetScriptType( const size_t nCnt ) const
124 : {
125 : OSL_ENSURE( nCnt < aScriptChanges.size(),"No ScriptType today!");
126 688819 : return aScriptChanges[nCnt].type;
127 : }
128 :
129 286960 : size_t CountDirChg() const { return aDirectionChanges.size(); }
130 1697 : sal_Int32 GetDirChg( const size_t nCnt ) const
131 : {
132 : OSL_ENSURE( nCnt < aDirectionChanges.size(),"No DirChange today!");
133 1697 : return aDirectionChanges[ nCnt ].position;
134 : }
135 495 : sal_uInt8 GetDirType( const size_t nCnt ) const
136 : {
137 : OSL_ENSURE( nCnt < aDirectionChanges.size(),"No DirType today!");
138 495 : return aDirectionChanges[ nCnt ].type;
139 : }
140 :
141 864 : size_t CountKashida() const
142 : {
143 864 : return aKashida.size();
144 : }
145 :
146 0 : sal_Int32 GetKashida(const size_t nCnt) const
147 : {
148 : OSL_ENSURE( nCnt < aKashida.size(),"No Kashidas today!");
149 0 : return aKashida[nCnt];
150 : }
151 :
152 2279 : size_t CountCompChg() const { return aCompressionChanges.size(); };
153 0 : sal_Int32 GetCompStart( const size_t nCnt ) const
154 : {
155 : OSL_ENSURE( nCnt < aCompressionChanges.size(),"No CompressionStart today!");
156 0 : return aCompressionChanges[ nCnt ].position;
157 : }
158 0 : sal_Int32 GetCompLen( const size_t nCnt ) const
159 : {
160 : OSL_ENSURE( nCnt < aCompressionChanges.size(),"No CompressionLen today!");
161 0 : return aCompressionChanges[ nCnt ].length;
162 : }
163 0 : CompType GetCompType( const size_t nCnt ) const
164 : {
165 : OSL_ENSURE( nCnt < aCompressionChanges.size(),"No CompressionType today!");
166 0 : return aCompressionChanges[ nCnt ].type;
167 : }
168 :
169 325078 : size_t CountHiddenChg() const { return aHiddenChg.size(); };
170 32 : sal_Int32 GetHiddenChg( const size_t nCnt ) const
171 : {
172 : OSL_ENSURE( nCnt < aHiddenChg.size(),"No HiddenChg today!");
173 32 : return aHiddenChg[ nCnt ];
174 : }
175 : static void CalcHiddenRanges(const SwTextNode& rNode, MultiSelection& rHiddenMulti);
176 : static void selectHiddenTextProperty(const SwTextNode& rNode, MultiSelection &rHiddenMulti);
177 : static void selectRedLineDeleted(const SwTextNode& rNode, MultiSelection &rHiddenMulti, bool bSelect=true);
178 :
179 : // "high" level operations, nPos refers to string position
180 : sal_Int32 NextScriptChg( const sal_Int32 nPos ) const;
181 : sal_Int16 ScriptType( const sal_Int32 nPos ) const;
182 :
183 : // Returns the position of the next direction level change.
184 : // If bLevel is set, the position of the next level which is smaller
185 : // than the level at position nPos is returned. This is required to
186 : // obtain the end of a SwBidiPortion
187 : sal_Int32 NextDirChg( const sal_Int32 nPos,
188 : const sal_uInt8* pLevel = 0 ) const;
189 : sal_uInt8 DirType( const sal_Int32 nPos ) const;
190 :
191 : // HIDDEN TEXT STUFF START
192 :
193 : /** Hidden text range information - static and non-version
194 :
195 : @descr Determines if a given position is inside a hidden text range. The
196 : static version tries to obtain a valid SwScriptInfo object
197 : via the SwTextNode, otherwise it calculates the values from scratch.
198 : The non-static version uses the internally cached informatio
199 : for the calculation.
200 :
201 : @param rNode
202 : The text node.
203 : @param nPos
204 : The given position that should be checked.
205 : @param rnStartPos
206 : Return parameter for the start position of the hidden range.
207 : COMPLETE_STRING if nPos is not inside a hidden range.
208 : @param rnEndPos
209 : Return parameter for the end position of the hidden range.
210 : 0 if nPos is not inside a hidden range.
211 : @param rnEndPos
212 : Return parameter that contains all the hidden text ranges. Optional.
213 : @return
214 : returns true if there are any hidden characters in this paragraph.
215 :
216 : */
217 : static bool GetBoundsOfHiddenRange( const SwTextNode& rNode, sal_Int32 nPos,
218 : sal_Int32& rnStartPos, sal_Int32& rnEndPos,
219 : PositionList* pList = 0 );
220 : bool GetBoundsOfHiddenRange( sal_Int32 nPos, sal_Int32& rnStartPos,
221 : sal_Int32& rnEndPos, PositionList* pList = 0 ) const;
222 :
223 : static bool IsInHiddenRange( const SwTextNode& rNode, sal_Int32 nPos );
224 :
225 : /** Hidden text attribute handling
226 :
227 : @descr Takes a string and either deletes the hidden ranges or sets
228 : a given character in place of the hidden characters.
229 :
230 : @param rNode
231 : The text node.
232 : @param rText
233 : The string to modify.
234 : @param cChar
235 : The character that should replace the hidden characters.
236 : @param bDel
237 : If set, the hidden ranges will be deleted from the text node.
238 : */
239 : static sal_Int32 MaskHiddenRanges(
240 : const SwTextNode& rNode, OUStringBuffer& rText,
241 : const sal_Int32 nStt, const sal_Int32 nEnd,
242 : const sal_Unicode cChar );
243 :
244 : /** Hidden text attribute handling
245 :
246 : @descr Takes a SwTextNode and deletes the hidden ranges from the node.
247 :
248 : @param rNode
249 : The text node.
250 : */
251 : static void DeleteHiddenRanges( SwTextNode& rNode );
252 :
253 : // HIDDEN TEXT STUFF END
254 :
255 : // modifies the kerning array according to a given compress value
256 : long Compress( long* pKernArray, sal_Int32 nIdx, sal_Int32 nLen,
257 : const sal_uInt16 nCompress, const sal_uInt16 nFontHeight,
258 : Point* pPoint = NULL ) const;
259 :
260 : /** Performs a kashida justification on the kerning array
261 :
262 : @descr Add some extra space for kashida justification to the
263 : positions in the kerning array.
264 : @param pKernArray
265 : The printers kerning array. Optional.
266 : @param pScrArray
267 : The screen kerning array. Optional.
268 : @param nStt
269 : Start referring to the paragraph.
270 : @param nLen
271 : The number of characters to be considered.
272 : @param nSpaceAdd
273 : The value which has to be added to a kashida opportunity.
274 : @return The number of kashida opportunities in the given range
275 : */
276 : sal_Int32 KashidaJustify( long* pKernArray, long* pScrArray,
277 : sal_Int32 nStt, sal_Int32 nLen, long nSpaceAdd = 0) const;
278 :
279 : /** Clears array of kashidas marked as invalid
280 : */
281 0 : void ClearKashidaInvalid(sal_Int32 nStt, sal_Int32 nLen)
282 : {
283 0 : MarkOrClearKashidaInvalid(nStt, nLen, false, 0);
284 0 : }
285 :
286 : /** Marks nCnt kashida positions as invalid
287 : pKashidaPositions: array of char indices relative to the paragraph
288 : */
289 : bool MarkKashidasInvalid(sal_Int32 nCnt, sal_Int32* pKashidaPositions);
290 :
291 : /** Marks nCnt kashida positions as invalid
292 : in the given text range
293 : */
294 0 : bool MarkKashidasInvalid(sal_Int32 nCnt, sal_Int32 nStt, sal_Int32 nLen)
295 : {
296 0 : return MarkOrClearKashidaInvalid(nStt, nLen, true, nCnt);
297 : }
298 :
299 : /** retrieves kashida opportunities for a given text range.
300 : returns the number of kashida positions in the given text range
301 :
302 : pKashidaPositions: buffer to reveive the char indices of the
303 : kashida opportunties relative to the paragraph
304 : */
305 : sal_Int32 GetKashidaPositions(sal_Int32 nStt, sal_Int32 nLen,
306 : sal_Int32* pKashidaPosition);
307 :
308 : /** Use regular blank justification instead of kashdida justification for the given line of text.
309 : nStt Start char index of the line referring to the paragraph.
310 : nLen Number of characters in the line
311 : */
312 : void SetNoKashidaLine(sal_Int32 nStt, sal_Int32 nLen);
313 :
314 : /** Clear forced blank justification for a given line.
315 : nStt Start char index of the line referring to the paragraph.
316 : nLen Number of characters in the line
317 : */
318 : void ClearNoKashidaLine(sal_Int32 nStt, sal_Int32 nLen);
319 :
320 : /** Checks if text is Arabic text.
321 :
322 : @descr Checks if text is Arabic text.
323 : @param rText
324 : The text to check
325 : @param nStt
326 : Start index of the text
327 : @return Returns if the language is an Arabic language
328 : */
329 : static bool IsArabicText( const OUString& rText, sal_Int32 nStt, sal_Int32 nLen );
330 :
331 : /** Performs a thai justification on the kerning array
332 :
333 : @descr Add some extra space for thai justification to the
334 : positions in the kerning array.
335 : @param rText
336 : The String
337 : @param pKernArray
338 : The printers kerning array. Optional.
339 : @param pScrArray
340 : The screen kerning array. Optional.
341 : @param nIdx
342 : Start referring to the paragraph.
343 : @param nLen
344 : The number of characters to be considered.
345 : @param nSpaceAdd
346 : The value which has to be added to the cells.
347 : @return The number of extra spaces in the given range
348 : */
349 : static sal_Int32 ThaiJustify( const OUString& rText, long* pKernArray,
350 : long* pScrArray, sal_Int32 nIdx,
351 : sal_Int32 nLen, sal_Int32 nNumberOfBlanks = 0,
352 : long nSpaceAdd = 0 );
353 :
354 : static SwScriptInfo* GetScriptInfo( const SwTextNode& rNode,
355 : bool bAllowInvalid = false );
356 :
357 : static sal_uInt8 WhichFont(sal_Int32 nIdx, const OUString* pText, const SwScriptInfo* pSI);
358 : };
359 :
360 : #endif
361 :
362 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|