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