|
1 /* |
|
2 * Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * The CTmTextLayout class: TAGMA's simplest text class. It holds the layout of rectangular piece of text. |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 #include "TmLayoutImp.h" |
|
21 #include "TmHighlightSource.h" |
|
22 #include "TMINTERP.H" |
|
23 #include "TmChunkInterp.h" |
|
24 #include <txtfrmat.h> |
|
25 #include "TmTextDrawExt.h" |
|
26 #include <frmtlay.h> |
|
27 #include "tmreformat.h" |
|
28 #include "frmUtils.h" |
|
29 |
|
30 #define UNUSED_VAR(a) a = a |
|
31 |
|
32 /** |
|
33 Construct a TTmFormatParamBase object. Set iWrapWidth, iMaxHeight and iMaxLines to 'infinity' (KMaxTInt), |
|
34 iFlags to 0 (wrapping off, no truncation with ellipsis, etc.), and iEllipsis to the ordinary ellipsis character, U+2026. |
|
35 */ |
|
36 EXPORT_C TTmFormatParamBase::TTmFormatParamBase(): |
|
37 iWrapWidth(KMaxTInt), |
|
38 iMaxHeight(KMaxTInt), |
|
39 iMaxLines(KMaxTInt), |
|
40 iFlags(0), |
|
41 iEllipsis(0x2026) |
|
42 { |
|
43 } |
|
44 |
|
45 /** |
|
46 Construct a TTmFormatParam object, setting iStartChar to 0, iEndChar to 'infinity' (KMaxTInt) and iLineInPar to 0. |
|
47 */ |
|
48 EXPORT_C TTmFormatParam::TTmFormatParam(): |
|
49 iStartChar(0), |
|
50 iEndChar(KMaxTInt), |
|
51 iLineInPar(0) |
|
52 { |
|
53 } |
|
54 |
|
55 /** |
|
56 Construct a TTmFormatParam object with its base class part (TTmFormatParamBase) set to aBase, and setting iStartChar to 0, |
|
57 iEndChar to 'infinity' (KMaxTInt) and iLineInPar to 0. |
|
58 */ |
|
59 EXPORT_C TTmFormatParam::TTmFormatParam(const TTmFormatParamBase& aBase): |
|
60 TTmFormatParamBase(aBase), |
|
61 iStartChar(0), |
|
62 iEndChar(KMaxTInt), |
|
63 iLineInPar(0) |
|
64 { |
|
65 } |
|
66 |
|
67 /** |
|
68 Construct a TTmReformatParam object, setting everything to 0 or FALSE apart from iMaxExtraLines, which is |
|
69 set to 'infinity' (KMaxTInt). |
|
70 */ |
|
71 EXPORT_C TTmReformatParam::TTmReformatParam(): |
|
72 iStartChar(0), |
|
73 iOldLength(0), |
|
74 iNewLength(0), |
|
75 iMaxExtraLines(KMaxTInt), |
|
76 iParFormatChanged(FALSE), |
|
77 iParInvalid(FALSE) |
|
78 { |
|
79 } |
|
80 |
|
81 /** |
|
82 Construct a TTmReformatResult object, setting iHeightChange to 0 and iUnchangedTop and iUnformattedStart to |
|
83 'infinity' (KMaxTInt). |
|
84 */ |
|
85 EXPORT_C TTmReformatResult::TTmReformatResult(): |
|
86 iHeightChange(0), |
|
87 iUnchangedTop(KMaxTInt), |
|
88 iUnformattedStart(KMaxTInt) |
|
89 { |
|
90 } |
|
91 |
|
92 /** |
|
93 Construct an empty object with no text and zero width and height. |
|
94 It is legal to call all CTmTextLayout functions on an empty object, |
|
95 with the exception of AddParL and FormatL, which panic with ENoSource. |
|
96 */ |
|
97 EXPORT_C CTmTextLayout::CTmTextLayout() : |
|
98 iCurrentContextChar(NULL) |
|
99 { |
|
100 // do nothing |
|
101 } |
|
102 |
|
103 /** |
|
104 The destructor. |
|
105 */ |
|
106 EXPORT_C CTmTextLayout::~CTmTextLayout() |
|
107 { |
|
108 delete iBdStateAtEnd; |
|
109 } |
|
110 |
|
111 /** |
|
112 Set the text, discarding any existing layout information. The text from aParam.iStartChar to aParam.iEndChar is |
|
113 extracted from aSource and formatted. |
|
114 */ |
|
115 EXPORT_C void CTmTextLayout::SetTextL(MTmSource& aSource,const TTmFormatParam& aParam) |
|
116 { |
|
117 if (aParam.iMaxHeight <= 0 || |
|
118 aParam.iStartChar < 0 || aParam.iEndChar < aParam.iStartChar || |
|
119 aParam.iLineInPar < 0) |
|
120 TmPanic(EBadArg); |
|
121 |
|
122 if (iBdStateAtEnd) |
|
123 { |
|
124 iBdStateAtEnd->Reset(); |
|
125 } |
|
126 else |
|
127 { |
|
128 iBdStateAtEnd = new(ELeave) TBidirectionalContext; |
|
129 } |
|
130 |
|
131 |
|
132 iSource = &aSource; |
|
133 iCode.Reset(); |
|
134 iStartChar = aParam.iStartChar; |
|
135 CTmFormatContext::TInfo info; |
|
136 if (aParam.iFlags & TTmFormatParamBase::EWrap |
|
137 && (aParam.iWrapWidth < 1 || aParam.iMaxHeight < 1)) |
|
138 { |
|
139 // Illegal parameters, so we should not waste time formatting. |
|
140 // We will assume that good parameters will be along later. |
|
141 iHeight = 0; |
|
142 iEndChar = iStartChar; |
|
143 iWidth = 0; |
|
144 } |
|
145 else |
|
146 { |
|
147 //Get line context character from previous line if there is |
|
148 TTmDocPosSpec startDocPos(aParam.iStartChar - 1, static_cast<TTmDocPosSpec::TType>(1)); |
|
149 TTmInterpreter interpreter(TTmInterpreterParam(*this)); |
|
150 TBool lineFound = interpreter.DocPosToLine(startDocPos); |
|
151 if (lineFound) |
|
152 info.iContextCharPerLine = interpreter.LineContextCharChar(); |
|
153 else |
|
154 info.iContextCharPerLine = NULL; |
|
155 |
|
156 CTmFormatContext::FormatL(aSource,aParam,iCode,info,this,NULL,iBdStateAtEnd, NULL); |
|
157 iHeight = info.iHeight; |
|
158 iEndChar = info.iEndChar; |
|
159 iWidth = 0; |
|
160 AdjustWidth(aParam,info.iWidth); |
|
161 } |
|
162 } |
|
163 |
|
164 /** |
|
165 Format part of the text that has changed and indicate whether further formatting needs to be done. |
|
166 |
|
167 The backing text must remain constant during background formatting. What this means is that |
|
168 if background formatting is enabled (TTmReformatParam::iMaxExtraLines is some small number, causing |
|
169 formatting to end mid-way with TTmReformatResult::iUnformattedStart less than KMaxTInt), so that text |
|
170 can be formatted bit by bit by a higher-level object, as is done by CTextView, the backing text must not |
|
171 change between the series of calls to this function that make up a single reformatting act. |
|
172 */ |
|
173 EXPORT_C void CTmTextLayout::FormatL(const TTmFormatParamBase& aParam,const TTmReformatParam& aReformatParam, |
|
174 TTmReformatResult& aResult) |
|
175 { |
|
176 if (!iSource) |
|
177 TmPanic(ENoSource); |
|
178 |
|
179 CTmReformat* reformat = CTmReformat::NewLC(*this, aParam, aReformatParam); |
|
180 reformat->ReformatL(); |
|
181 CTmCode* new_code = &(reformat->NewCode()); |
|
182 TTmByteCodeFinder::TInfo oldCodeInfo = reformat->ReformatRange(); |
|
183 CTmFormatContext::TInfo newCodeInfo = reformat->FormatInfo(); |
|
184 TBool bd_changed = reformat->BidirectionalStateChanged(); |
|
185 /* |
|
186 Find the lines that have changed and need to be redisplayed. |
|
187 If aParagraphFormatChanged is true at least one paragraph format has changed, |
|
188 so the redraw rectangle includes the whole of the paragraphs affected. |
|
189 |
|
190 Also redraw the whole paragraph if background formatting is needed, or if the bidirectional state has changed. |
|
191 */ |
|
192 if (aReformatParam.iParFormatChanged || aResult.iUnformattedStart < KMaxTInt || bd_changed) |
|
193 { |
|
194 aResult.iRedrawRect = oldCodeInfo.iBounds; |
|
195 aResult.iRedrawRect.iBr.iY = aResult.iRedrawRect.iTl.iY + newCodeInfo.iHeight; |
|
196 } |
|
197 else |
|
198 { |
|
199 TTmInterpreterParam p(*this); |
|
200 p.iCodeStart = oldCodeInfo.iStartCodePos; |
|
201 p.iCodeEnd = oldCodeInfo.iEndCodePos; |
|
202 p.iTextStart = oldCodeInfo.iStartInfo.iStart; |
|
203 TTmInterpreter old_code_interpreter(p); |
|
204 p.iByteCode = new_code; |
|
205 p.iCodeStart = 0; |
|
206 p.iCodeEnd = new_code->Size(); |
|
207 TTmInterpreter new_code_interpreter(p); |
|
208 old_code_interpreter.CalculateRedrawRect(new_code_interpreter,aReformatParam.iStartChar, |
|
209 aReformatParam.iOldLength,aReformatParam.iNewLength,aResult.iRedrawRect); |
|
210 aResult.iRedrawRect.Move(0,oldCodeInfo.iBounds.iTl.iY); |
|
211 } |
|
212 |
|
213 // Delete the old bytecode and insert the new. |
|
214 iCode.ChangeL(oldCodeInfo.iStartCodePos,oldCodeInfo.iEndCodePos,*new_code); |
|
215 |
|
216 // Adjust the band's bounds. |
|
217 iHeight += newCodeInfo.iHeight - oldCodeInfo.iBounds.Height(); |
|
218 |
|
219 //if the range we are replacing includes the end of the current formatted range, |
|
220 //then the end BD state pointer may be invalidated, so we need to update it |
|
221 if(oldCodeInfo.iEndInfo.iEnd == iEndChar) |
|
222 { |
|
223 *iBdStateAtEnd = reformat->BidirectionalStateAtEnd(); |
|
224 } |
|
225 // Adjust the band's width if necessary. |
|
226 AdjustWidth(aParam,newCodeInfo.iWidth); |
|
227 |
|
228 // Adjust the band's length. |
|
229 TInt lengthOfOldRange = oldCodeInfo.iEndInfo.iEnd - oldCodeInfo.iStartInfo.iStart; |
|
230 TInt lengthOfNewRange = newCodeInfo.iEndChar - oldCodeInfo.iStartInfo.iStart; |
|
231 iEndChar += lengthOfNewRange - lengthOfOldRange; |
|
232 // Determine the change in height of the reformatted text. |
|
233 aResult.iHeightChange = newCodeInfo.iHeight - oldCodeInfo.iBounds.Height(); |
|
234 |
|
235 /* |
|
236 Set the top of the unchanged text, and if not all text has been formatted |
|
237 remove the first unformatted line from the redraw rect. |
|
238 */ |
|
239 if (aResult.iUnformattedStart < KMaxTInt) |
|
240 { |
|
241 TTmLineInfo info; |
|
242 TTmDocPosSpec pos(aResult.iUnformattedStart,TTmDocPosSpec::ETrailing); |
|
243 DocPosToLine(pos,info); |
|
244 aResult.iRedrawRect.iBr.iY = info.iOuterRect.iTl.iY; |
|
245 ParNumberToLine(info.iParNumber,KMaxTInt,info); |
|
246 aResult.iUnchangedTop = info.iOuterRect.iBr.iY - aResult.iHeightChange; |
|
247 } |
|
248 else |
|
249 aResult.iUnchangedTop = aResult.iRedrawRect.iBr.iY - aResult.iHeightChange; |
|
250 |
|
251 CleanupStack::PopAndDestroy(reformat); |
|
252 |
|
253 Invariant(); |
|
254 } |
|
255 |
|
256 /** |
|
257 Format a new paragraph immediately before or after the band and add it to the formatted text. |
|
258 If the text starts or ends in the middle of the paragraph, complete the paragraph. |
|
259 Return TRUE if text was successfully added, or FALSE if there is no more text to add, or |
|
260 the new text would have exceeded the maximum height allowed. Place the height of the new text in aHeightIncrease. |
|
261 Place the increase in the number of complete paragraphs (0 or 1) in aParagraphsIncrease. |
|
262 |
|
263 Note that this function will not necessarily add a whole paragraph to the band: if the client has restricted |
|
264 the amount of formatting to add by setting the relevant values in aParam, then these restrictions will |
|
265 be respected with the result that less than a paragraph of formatting may be generated. |
|
266 |
|
267 This is the case, for example, when CTextLayout adds text below the band. |
|
268 */ |
|
269 EXPORT_C TBool CTmTextLayout::AddParL(const TTmFormatParamBase& aParam,TBool aAtStart,TInt& aHeightIncrease, |
|
270 TInt& aParagraphsIncrease) |
|
271 { |
|
272 if (!iSource) |
|
273 TmPanic(ENoSource); |
|
274 |
|
275 aHeightIncrease = 0; |
|
276 aParagraphsIncrease = 0; |
|
277 int start_char = 0; |
|
278 int end_char = 0; |
|
279 int deleted_height = 0; |
|
280 TTmFormatParam format_param(aParam); |
|
281 |
|
282 TBidirectionalContext* pStartBd = NULL; |
|
283 TBidirectionalContext* pEndBd = NULL; |
|
284 TBidirectionalEndOfLineContext* pEOLContext = NULL; |
|
285 |
|
286 if (aAtStart) |
|
287 { |
|
288 if (iStartChar == 0) |
|
289 return FALSE; |
|
290 start_char = iSource->ParagraphStart(iStartChar - 1); |
|
291 end_char = iSource->ParagraphEnd(iStartChar - 1); |
|
292 if (end_char > iStartChar) |
|
293 { |
|
294 if (end_char > iEndChar) |
|
295 end_char = iEndChar; |
|
296 DeletePar(aParam,TRUE,KMaxTInt,deleted_height); |
|
297 } |
|
298 else |
|
299 aParagraphsIncrease = 1; |
|
300 } |
|
301 else |
|
302 { |
|
303 if (iEndChar > iSource->DocumentLength()) |
|
304 return FALSE; |
|
305 start_char = iEndChar; |
|
306 end_char = iSource->ParagraphEnd(iEndChar); |
|
307 |
|
308 pStartBd = iBdStateAtEnd; |
|
309 pEndBd = iBdStateAtEnd; |
|
310 |
|
311 TInt lastLineNumber = Lines()-1; |
|
312 if(lastLineNumber >= 0) |
|
313 { |
|
314 TTmLineInfo lastLine; |
|
315 TBool found = LineNumberToLine(lastLineNumber, lastLine); |
|
316 ASSERT(found); |
|
317 if(!(lastLine.iFlags & TTmLineInfo::EParEnd)) |
|
318 { |
|
319 format_param.iLineInPar = lastLine.iLineInPar+1; |
|
320 } |
|
321 } |
|
322 |
|
323 aParagraphsIncrease = 1; |
|
324 } |
|
325 |
|
326 CTmCode* new_code = new(ELeave) CTmCode; |
|
327 CleanupStack::PushL(new_code); |
|
328 format_param.iStartChar = start_char; |
|
329 format_param.iEndChar = end_char; |
|
330 int code_pos = aAtStart ? 0 : iCode.Size(); |
|
331 CTmFormatContext::TInfo info; |
|
332 |
|
333 //Get line context character from previous line if there is |
|
334 TTmDocPosSpec startDocPos(format_param.iStartChar - 1, static_cast<TTmDocPosSpec::TType>(1)); |
|
335 TTmInterpreter interpreter(TTmInterpreterParam(*this)); |
|
336 TBool lineFound = interpreter.DocPosToLine(startDocPos); |
|
337 if (lineFound) |
|
338 info.iContextCharPerLine = interpreter.LineContextCharChar(); |
|
339 else |
|
340 info.iContextCharPerLine = NULL; |
|
341 |
|
342 CTmFormatContext::FormatL(*iSource,format_param,*new_code,info,this, |
|
343 pStartBd, pEndBd, pEOLContext); |
|
344 |
|
345 // Insert the new code if any. |
|
346 aHeightIncrease = info.iHeight; |
|
347 if (aHeightIncrease > 0) |
|
348 { |
|
349 iCode.ChangeL(code_pos,code_pos,*new_code); |
|
350 |
|
351 iHeight += aHeightIncrease; |
|
352 if (aAtStart) |
|
353 iStartChar = start_char; |
|
354 else |
|
355 iEndChar = info.iEndChar; |
|
356 |
|
357 // Adjust the band's width if necessary. |
|
358 AdjustWidth(aParam,info.iWidth); |
|
359 } |
|
360 //if we did actually format to the paragraph end, reset the bd state |
|
361 if(!aAtStart) |
|
362 { |
|
363 if(iEndChar == format_param.iEndChar) |
|
364 { |
|
365 iBdStateAtEnd->Reset(); |
|
366 } |
|
367 } |
|
368 CleanupStack::PopAndDestroy(); // new code |
|
369 aHeightIncrease -= deleted_height; |
|
370 |
|
371 Invariant(); |
|
372 |
|
373 return aHeightIncrease > 0; |
|
374 } |
|
375 |
|
376 TBool CTmTextLayout::LastLine(TTmLineInfo& aLine) |
|
377 { |
|
378 TInt lastLineNumber = Lines()-1; |
|
379 if(lastLineNumber >= 0) |
|
380 { |
|
381 TTmLineInfo lastLine; |
|
382 TBool found = LineNumberToLine(lastLineNumber, aLine); |
|
383 ASSERT(found); |
|
384 return ETrue; |
|
385 } |
|
386 return EFalse; |
|
387 } |
|
388 |
|
389 void CTmTextLayout::SetCurrentContextChar(TUint aContextChar) |
|
390 { |
|
391 iCurrentContextChar = aContextChar; |
|
392 } |
|
393 |
|
394 TUint CTmTextLayout::GetCurrentContextChar() const |
|
395 { |
|
396 return iCurrentContextChar; |
|
397 } |
|
398 /** |
|
399 Extend the formatted range downwards. That is, starting at the end of the current |
|
400 formatted range, generate some new formatting and append it to the end of the range. |
|
401 @param aParam |
|
402 This controls how much new formatting to generate. We will generate formatting up whichever comes first of: |
|
403 - the character position specified in TTmFormatParam::iEndChar |
|
404 - the height specified (in pixels) in TTmFormatParamBase::iMaxHeight |
|
405 - the number of lines specified in TTmFormatParamBase::iMaxLines |
|
406 We replace the values specified in TTmFormatParam::iStartChar and TmFormatParam::iLineInPar |
|
407 @pre The object must have been initialised with an MTmSource, or it will panic. |
|
408 */ |
|
409 EXPORT_C void CTmTextLayout::ExtendFormattingDownwardsL(TTmFormatParam& aParam) |
|
410 { |
|
411 if (!iSource) |
|
412 TmPanic(ENoSource); |
|
413 |
|
414 aParam.iStartChar = iEndChar; |
|
415 |
|
416 if (iEndChar > iSource->DocumentLength()) |
|
417 return; |
|
418 if (aParam.iStartChar > aParam.iEndChar) |
|
419 return; |
|
420 |
|
421 TBidirectionalContext* pStartBd = iBdStateAtEnd; |
|
422 TBidirectionalContext* pEndBd = iBdStateAtEnd; |
|
423 TBidirectionalEndOfLineContext* pEOLContext = NULL; |
|
424 |
|
425 //if there is a last line (i.e. if there is any formatting at all) |
|
426 //and the last line is not a paragraph boundary, |
|
427 //then initialise the line number |
|
428 TTmLineInfo lastLine; |
|
429 TBool found = LastLine(lastLine); |
|
430 if(found && !(lastLine.iFlags & TTmLineInfo::EParEnd)) |
|
431 { |
|
432 aParam.iLineInPar = lastLine.iLineInPar+1; |
|
433 } |
|
434 |
|
435 //Generate the additional formatting |
|
436 CTmCode* newCode = new(ELeave) CTmCode; |
|
437 CleanupStack::PushL(newCode); |
|
438 |
|
439 TInt newCodePos = iCode.Size(); |
|
440 CTmFormatContext::TInfo info; |
|
441 |
|
442 //Get line context character from previous line if there is |
|
443 TTmDocPosSpec startDocPos(aParam.iStartChar - 1, static_cast<TTmDocPosSpec::TType>(1)); |
|
444 TTmInterpreter interpreter(TTmInterpreterParam(*this)); |
|
445 TBool lineFound = interpreter.DocPosToLine(startDocPos); |
|
446 if (lineFound) |
|
447 info.iContextCharPerLine = interpreter.LineContextCharChar(); |
|
448 else |
|
449 info.iContextCharPerLine = NULL; |
|
450 |
|
451 CTmFormatContext::FormatL(*iSource,aParam,*newCode,info,this,pStartBd, pEndBd, pEOLContext); |
|
452 |
|
453 // Insert the new code if any. |
|
454 if (info.iHeight > 0) |
|
455 { |
|
456 iCode.ChangeL(newCodePos,newCodePos,*newCode); |
|
457 iHeight += info.iHeight; |
|
458 iEndChar = info.iEndChar; |
|
459 AdjustWidth(aParam,info.iWidth); |
|
460 } |
|
461 //if we did actually format to the paragraph end, reset the bd state |
|
462 found = LastLine(lastLine); |
|
463 if(found && (lastLine.iFlags & TTmLineInfo::EParEnd)) |
|
464 { |
|
465 iBdStateAtEnd->Reset(); |
|
466 } |
|
467 |
|
468 CleanupStack::PopAndDestroy(); // new code |
|
469 Invariant(); |
|
470 } |
|
471 |
|
472 /** |
|
473 Delete the format for the first or last paragraph if its height does not exceed aMaxDeletedHeight. |
|
474 Return TRUE if a paragraph was successfully deleted. Place the height of the deleted paragraph in aHeightDecrease. |
|
475 */ |
|
476 EXPORT_C TBool CTmTextLayout::DeletePar(const TTmFormatParamBase& aParam,TBool aAtStart,TInt aMaxDeletedHeight, |
|
477 TInt& aHeightDecrease) |
|
478 { |
|
479 aHeightDecrease = 0; |
|
480 if (!iSource || iStartChar >= iEndChar) |
|
481 return FALSE; |
|
482 |
|
483 int pos = aAtStart ? iStartChar : iEndChar - 1; |
|
484 TTmByteCodeFinder finder(TTmInterpreterParam(*this), pos, pos); |
|
485 TTmByteCodeFinder::TInfo info; |
|
486 if (!finder.FindByteCode(TRUE,TRUE,KMaxTInt,info)) |
|
487 TmPanic(EFormatNotFound); |
|
488 if (info.iBounds.Height() > aMaxDeletedHeight) |
|
489 return FALSE; |
|
490 |
|
491 iCode.Delete(info.iStartCodePos,info.iEndCodePos - info.iStartCodePos); |
|
492 if (aAtStart) |
|
493 iStartChar = info.iEndInfo.iEnd; |
|
494 else |
|
495 iEndChar = info.iStartInfo.iStart; |
|
496 aHeightDecrease = info.iBounds.Height(); |
|
497 iHeight -= aHeightDecrease; |
|
498 |
|
499 // Adjust the band's width if necessary. |
|
500 AdjustWidth(aParam,0); |
|
501 |
|
502 Invariant(); |
|
503 |
|
504 return TRUE; |
|
505 } |
|
506 |
|
507 /** |
|
508 Delete as many lines of formatting as possible from the end of the formatted range, up to |
|
509 the maximum height specified in aMaxDeletedHeight. The height decrease is placed in aHeightDecrease. |
|
510 */ |
|
511 EXPORT_C void CTmTextLayout::DeleteFormattingFromEndL(const TTmFormatParamBase& aParam, TInt aMaxDeletedHeight, TInt& aHeightDecrease) |
|
512 { |
|
513 aHeightDecrease = 0; |
|
514 if (!iSource || iStartChar >= iEndChar) |
|
515 return; |
|
516 TBidirectionalContext* bdStart = new(ELeave) TBidirectionalContext; |
|
517 CleanupStack::PushL(bdStart); |
|
518 TBidirectionalContext* bdEnd = new(ELeave) TBidirectionalContext; |
|
519 CleanupStack::PushL(bdEnd); |
|
520 TTmByteCodeFinder::TInfo info; |
|
521 TTmByteCodeFinder sectionFinder(TTmInterpreterParam(*this), iStartChar, iStartChar); |
|
522 TBool found = sectionFinder.FindByteCodeAtEnd(info, aMaxDeletedHeight, iHeight, bdStart, bdEnd); |
|
523 if (!found) |
|
524 { |
|
525 CleanupStack::PopAndDestroy(2); |
|
526 } |
|
527 else |
|
528 { |
|
529 //should use an assignment operator here instead |
|
530 delete iBdStateAtEnd; |
|
531 iBdStateAtEnd = bdStart; |
|
532 CleanupStack::PopAndDestroy(bdEnd); |
|
533 CleanupStack::Pop(bdStart); |
|
534 iCode.Delete(info.iStartCodePos, info.iEndCodePos - info.iStartCodePos); |
|
535 iEndChar = info.iStartInfo.iStart; |
|
536 aHeightDecrease = info.iBounds.Height(); |
|
537 iHeight -= aHeightDecrease; |
|
538 // Adjust the band's width if necessary. |
|
539 AdjustWidth(aParam,0); |
|
540 Invariant(); |
|
541 } |
|
542 } |
|
543 |
|
544 /** |
|
545 Reset the object to its empty state; no source or formatting, height and width of 0, start and end char both 0. |
|
546 */ |
|
547 EXPORT_C void CTmTextLayout::Clear() |
|
548 { |
|
549 if(iBdStateAtEnd) |
|
550 iBdStateAtEnd->Reset(); |
|
551 iSource = NULL; |
|
552 iCode.Reset(); |
|
553 iWidth = 0; |
|
554 iHeight = 0; |
|
555 iStartChar = 0; |
|
556 iEndChar = 0; |
|
557 |
|
558 Invariant(); |
|
559 } |
|
560 |
|
561 /** |
|
562 Draw the text. |
|
563 |
|
564 @param aGc |
|
565 Graphics context to draw to. |
|
566 @param aTopLeft |
|
567 The origin of the formatted text in the coordinates of aGc. |
|
568 @param aClipRect |
|
569 The clipping rectangle in the coordinates of aGc. Nowhere outside this |
|
570 rectangle will be drawn. |
|
571 @param aDocBackground |
|
572 The default document background colour, which is used for regions not drawn |
|
573 by any custom background drawing routine and not covered by any text. If |
|
574 null, no background is drawn in these places. |
|
575 @param aDrawParBackground |
|
576 If false no default background is drawn on those areas covered by text. |
|
577 Custom background drawers are invoked regardless of this argument. |
|
578 */ |
|
579 |
|
580 EXPORT_C void CTmTextLayout::DrawLayout(CGraphicsContext& aGc, |
|
581 const TPoint& aTopLeft,const TRect& aClipRect, |
|
582 const TLogicalRgb* aDocBackground,TBool aDrawParBackground) const |
|
583 { |
|
584 DrawLayout(aGc, aTopLeft, aClipRect, aDocBackground, aDrawParBackground, NULL, NULL); |
|
585 } |
|
586 |
|
587 /** |
|
588 Draw the text. |
|
589 |
|
590 @param aGc |
|
591 Graphics context to draw to. |
|
592 @param aTopLeft |
|
593 The origin of the formatted text in the coordinates of aGc. |
|
594 @param aClipRect |
|
595 The clipping rectangle in the coordinates of aGc. Nowhere outside this |
|
596 rectangle will be drawn. |
|
597 @param aDocBackground |
|
598 The default document background colour, which is used for regions not drawn |
|
599 by any custom background drawing routine and not covered by any text. If |
|
600 null, no background is drawn in these places. |
|
601 @param aDrawParBackground |
|
602 If false no default background is drawn on those areas covered by text. |
|
603 Custom background drawers are invoked regardless of this argument. |
|
604 @param aHighlight |
|
605 The current selection. If null, no selection is drawn. |
|
606 @param aHighlightExtensions |
|
607 If not null, the selection highlight has its edges moved by the specified |
|
608 number of pixels |
|
609 */ |
|
610 |
|
611 EXPORT_C void CTmTextLayout::DrawLayout(CGraphicsContext& aGc, |
|
612 const TPoint& aTopLeft,const TRect& aClipRect, |
|
613 const TLogicalRgb* aDocBackground,TBool aDrawParBackground, |
|
614 const TCursorSelection* aHighlight, |
|
615 const TTmHighlightExtensions* aHighlightExtensions) const |
|
616 { |
|
617 if (iSource) |
|
618 { |
|
619 RTmDrawingInterpreter interpreter(*iSource, aGc, |
|
620 TTmInterpreterParam(*this), aTopLeft, aClipRect, aDocBackground, |
|
621 aDrawParBackground ? RTmDrawingInterpreter::EDrawParBackground : 0, |
|
622 aHighlight, aHighlightExtensions); |
|
623 interpreter.Draw(); |
|
624 interpreter.Close(); |
|
625 } |
|
626 } |
|
627 |
|
628 /** |
|
629 Draw the background, using the custom background graphics implemented by overriding MTmSource::DrawBackground if any: |
|
630 aTopLeft is the top-left corner of the text, aRect is the portion of the background to be drawn, and aBackground is |
|
631 the default background colour. This function is used by higher-level classes for drawing backgrounds outside the ordinary |
|
632 text area consistently with the ordinary background. |
|
633 */ |
|
634 EXPORT_C void CTmTextLayout::DrawBackground(CGraphicsContext& aGc,const TPoint& aTopLeft,const TRect& aClipRect, |
|
635 const TLogicalRgb& aBackground) const |
|
636 { |
|
637 if (iSource) |
|
638 { |
|
639 RTmDrawingInterpreter interpreter(*iSource, aGc, TTmInterpreterParam(*this), |
|
640 aTopLeft, aClipRect, &aBackground, 0, NULL, NULL); |
|
641 interpreter.DrawBackground(aClipRect, aBackground); |
|
642 interpreter.Close(); |
|
643 } |
|
644 } |
|
645 |
|
646 EXPORT_C void CTmTextLayout::InvertLayout(CGraphicsContext& aGc, |
|
647 const TPoint& aTopLeft, TInt aStartDocPos,TInt aEndDocPos) const |
|
648 { |
|
649 TTmHighlightExtensions highlightProperties; |
|
650 highlightProperties.SetAll(0); |
|
651 InvertLayout(aGc,aTopLeft,aStartDocPos,aEndDocPos,highlightProperties,0,0); |
|
652 } |
|
653 |
|
654 /** |
|
655 Analogous to InvertLayout(CGraphicsContext, const TPoint&, TInt, TInt) but with |
|
656 highlight extensions applied. |
|
657 @see InvertLayout(CGraphicsContext, const TPoint&, TInt, TInt) |
|
658 @publishedPartner |
|
659 @released |
|
660 */ |
|
661 EXPORT_C void CTmTextLayout::InvertLayout(CGraphicsContext& aGc, |
|
662 const TPoint& aTopLeft, TInt aStartDocPos, TInt aEndDocPos, |
|
663 const TTmHighlightExtensions& aHighlightExtensions, |
|
664 TInt aHighlightStartDocPos, TInt aHighlightEndDocPos) const |
|
665 { |
|
666 // note: Assumes that RWindow::BeginRedraw() has been called by the caller. |
|
667 |
|
668 if (NULL == iSource) |
|
669 { |
|
670 return; |
|
671 } |
|
672 |
|
673 TRect clipRect; |
|
674 GetUpdateBoundingRect(aStartDocPos, aEndDocPos, aTopLeft, clipRect); |
|
675 |
|
676 if (aStartDocPos < aHighlightStartDocPos) |
|
677 { |
|
678 aHighlightStartDocPos = aStartDocPos; |
|
679 } |
|
680 |
|
681 if (aEndDocPos > aHighlightEndDocPos) |
|
682 { |
|
683 aHighlightEndDocPos = aEndDocPos; |
|
684 } |
|
685 |
|
686 TCursorSelection selection; |
|
687 selection.SetSelection(aHighlightStartDocPos, aHighlightEndDocPos); |
|
688 |
|
689 TRect boundingRect; |
|
690 GetUpdateBoundingRect(aStartDocPos, aEndDocPos, aTopLeft, boundingRect); |
|
691 aHighlightExtensions.AbsExtendRect(boundingRect); |
|
692 boundingRect.Intersection(clipRect); |
|
693 if (! boundingRect.IsEmpty()) |
|
694 { |
|
695 RTmDrawingInterpreter interpreter(*iSource, aGc, TTmInterpreterParam(*this), |
|
696 aTopLeft, boundingRect, NULL, ETrue, &selection, &aHighlightExtensions, ETrue); |
|
697 interpreter.Draw(); |
|
698 interpreter.Close(); |
|
699 } |
|
700 } |
|
701 |
|
702 /** |
|
703 Calculate the bounding rectangle of the region that must be redrawn to redraw the given document section. |
|
704 @param aStartDocPos |
|
705 The section starting position |
|
706 @param aEndDocPos |
|
707 The section ending position |
|
708 @param aTopLeft |
|
709 Textview position in graphics context coordinates. The resulting region can be used |
|
710 to clip the drawing in that graphics context. |
|
711 @param aBoundingRect |
|
712 The resulting bounding rectangle, that is the smallest rectangle that should be redrawn |
|
713 to redraw the specified document section. |
|
714 */ |
|
715 EXPORT_C void CTmTextLayout::GetUpdateBoundingRect(TInt aStartDocPos, TInt aEndDocPos, |
|
716 const TPoint& aTopLeft, TRect& aBoundingRect) const |
|
717 { |
|
718 aBoundingRect = TRect(TRect::EUninitialized); |
|
719 |
|
720 if (! iSource || aEndDocPos <= aStartDocPos) |
|
721 { |
|
722 return; |
|
723 } |
|
724 |
|
725 RTmBoundingRectInterpreter interpreter(*iSource, *this); |
|
726 TRect rect(TRect::EUninitialized); // set by call to RTmBoundingRectInterpreter::FirstRect |
|
727 TTmDocPos start(aStartDocPos, TRUE); |
|
728 TTmDocPos end(aEndDocPos,FALSE); |
|
729 TBool found = interpreter.FirstRect(start.iPos, end.iPos, rect); |
|
730 while (found) |
|
731 { |
|
732 if (! rect.IsEmpty()) |
|
733 { |
|
734 rect.Move(aTopLeft); |
|
735 if(aBoundingRect.IsEmpty()) |
|
736 { |
|
737 aBoundingRect = rect; |
|
738 } |
|
739 else |
|
740 { |
|
741 aBoundingRect.BoundingRect(rect); |
|
742 } |
|
743 } |
|
744 |
|
745 found = interpreter.NextRect(rect); |
|
746 } |
|
747 interpreter.Close(); |
|
748 } |
|
749 |
|
750 EXPORT_C void CTmTextLayout::HighlightSection(CGraphicsContext& aGc, |
|
751 const TPoint& aTopLeft, TInt aStartDocPos, TInt aEndDocPos, const TRect& aClipRect) const |
|
752 { |
|
753 TTmHighlightExtensions highlightProperties; |
|
754 highlightProperties.SetAll(0); |
|
755 HighlightSection(aGc,aTopLeft,aStartDocPos,aEndDocPos,aClipRect,highlightProperties,0,0); |
|
756 } |
|
757 |
|
758 /** |
|
759 Analogous to HighlightSection(CGraphicsContext&, const TPoint&, TInt, TInt, |
|
760 const TRect&) but with highlight extensions applied. |
|
761 @see HighlightSecion(CGraphicsContext&, const TPoint&, TInt, TInt, const |
|
762 TRect&) |
|
763 @publishedPartner |
|
764 @released |
|
765 */ |
|
766 EXPORT_C void CTmTextLayout::HighlightSection(CGraphicsContext& aGc, |
|
767 const TPoint& aTopLeft, TInt aStartDocPos, TInt aEndDocPos, |
|
768 const TRect& aClipRect, const TTmHighlightExtensions& aHighlightExtensions, |
|
769 TInt aHighlightStartDocPos, TInt aHighlightEndDocPos) const |
|
770 { |
|
771 if (0 == aHighlightStartDocPos && 0 == aHighlightEndDocPos) |
|
772 { |
|
773 aHighlightStartDocPos = aStartDocPos; |
|
774 aHighlightEndDocPos = aEndDocPos; |
|
775 } |
|
776 else |
|
777 { |
|
778 if (aStartDocPos < aHighlightStartDocPos) |
|
779 { |
|
780 aHighlightStartDocPos = aStartDocPos; |
|
781 } |
|
782 |
|
783 if (aEndDocPos > aHighlightEndDocPos) |
|
784 { |
|
785 aHighlightEndDocPos = aEndDocPos; |
|
786 } |
|
787 } |
|
788 |
|
789 DrawSection(aGc, aTopLeft, aStartDocPos, aEndDocPos, aClipRect, aHighlightExtensions, |
|
790 aHighlightStartDocPos, aHighlightEndDocPos); |
|
791 } |
|
792 |
|
793 |
|
794 EXPORT_C void CTmTextLayout::DrawSection(CGraphicsContext& aGc, |
|
795 const TPoint& aTopLeft, TInt aStartDocPos, TInt aEndDocPos, const TRect& aClipRect) const |
|
796 { |
|
797 TTmHighlightExtensions highlightProperties; |
|
798 highlightProperties.SetAll(0); |
|
799 DrawSection(aGc,aTopLeft,aStartDocPos,aEndDocPos,aClipRect,highlightProperties,0,0); |
|
800 } |
|
801 |
|
802 /** |
|
803 Analogous to DrawSection(CGraphicsContext&, const TPoint&, TInt, TInt, const |
|
804 TRect&) but with highlight extensions applied. |
|
805 @see DrawSection(CGraphicsContext&, const TPoint&, TInt, TInt, const TRect&) |
|
806 @publishedPartner |
|
807 @released |
|
808 */ |
|
809 EXPORT_C void CTmTextLayout::DrawSection(CGraphicsContext& aGc, |
|
810 const TPoint& aTopLeft, TInt aStartDocPos, TInt aEndDocPos, |
|
811 const TRect& aClipRect, const TTmHighlightExtensions& aHighlightExtensions, |
|
812 TInt aHighlightStartDocPos, TInt aHighlightEndDocPos) const |
|
813 { |
|
814 // note: Assumes that RWindow::BeginRedraw() has been called by the caller. |
|
815 |
|
816 TCursorSelection selection; |
|
817 selection.SetSelection(aHighlightStartDocPos, aHighlightEndDocPos); |
|
818 |
|
819 TRect boundingRect; |
|
820 GetUpdateBoundingRect(aStartDocPos, aEndDocPos, aTopLeft, boundingRect); |
|
821 if (! boundingRect.IsEmpty()) |
|
822 { |
|
823 aHighlightExtensions.AbsExtendRect(boundingRect); |
|
824 boundingRect.Intersection(aClipRect); |
|
825 if (! boundingRect.IsEmpty()) |
|
826 { |
|
827 DrawLayout(aGc, aTopLeft, boundingRect, NULL, ETrue, &selection, &aHighlightExtensions); |
|
828 } |
|
829 } |
|
830 } |
|
831 |
|
832 /** |
|
833 Finds a document position and returns information about it and the line it is |
|
834 in. |
|
835 @param aDocPos The position to find. |
|
836 @param aPosInfo Returns information on the found position. |
|
837 @param aLineInfo Returns information on the line containing the position found. |
|
838 @return |
|
839 True if the position was found within the formatted text. False if the |
|
840 position was not in the formatted text. |
|
841 */ |
|
842 EXPORT_C TBool CTmTextLayout::FindDocPos(const TTmDocPosSpec& aDocPos, |
|
843 TTmPosInfo2& aPosInfo, TTmLineInfo& aLineInfo) const |
|
844 { |
|
845 if (!iSource) |
|
846 return FALSE; |
|
847 RTmGeneralInterpreter interpreter(*iSource, TTmInterpreterParam(*this)); |
|
848 TBool found = interpreter.FindDocPos(aDocPos,aPosInfo); |
|
849 aLineInfo = interpreter.LineInfo(); |
|
850 interpreter.Close(); |
|
851 return found; |
|
852 } |
|
853 |
|
854 /** |
|
855 Find a document position and return information about it and the line it is in. Return FALSE if the document |
|
856 position is outside the formatted text. The document position to be found is passed in aDocPos and the information |
|
857 about the position found is returned in aPosInfo. The line information is returned in aLineInfo. |
|
858 @deprecated 7.0s |
|
859 */ |
|
860 EXPORT_C TBool CTmTextLayout::FindDocPos(const TTmDocPos& aDocPos,TTmPosInfo& aPosInfo,TTmLineInfo& aLineInfo) const |
|
861 { |
|
862 TTmDocPosSpec dp = aDocPos; |
|
863 TTmPosInfo2 pi; |
|
864 TBool r = FindDocPos(dp, pi, aLineInfo); |
|
865 aPosInfo = pi; |
|
866 return r; |
|
867 } |
|
868 |
|
869 /** |
|
870 Finds a document position and returns information about it and the line it is |
|
871 in. |
|
872 @param aDocPos The position to find. |
|
873 @param aPosInfo Returns information on the found position. |
|
874 @param aLineInfo Returns information on the line containing the position found. |
|
875 @param aSubscript Returns the subscript height value. |
|
876 @return |
|
877 True if the position was found within the formatted text. False if the |
|
878 position was not in the formatted text. |
|
879 */ |
|
880 EXPORT_C TBool CTmTextLayout::FindDocPos(const TTmDocPosSpec& aDocPos, |
|
881 TTmPosInfo2& aPosInfo, TTmLineInfo& aLineInfo, TInt& aSubscript) const |
|
882 { |
|
883 if (!iSource) |
|
884 return FALSE; |
|
885 RTmGeneralInterpreter interpreter(*iSource, TTmInterpreterParam(*this)); |
|
886 TBool found = interpreter.FindDocPos(aDocPos,aPosInfo); |
|
887 aLineInfo = interpreter.LineInfo(); |
|
888 aSubscript = interpreter.Subscript(); |
|
889 interpreter.Close(); |
|
890 return found; |
|
891 } |
|
892 |
|
893 /** |
|
894 Finds a document position (i.e. the edge between two adjacent characters) by |
|
895 x-y position relative to the top-left corner of the formatted text. |
|
896 @param aXyPos Position to find. |
|
897 @param aPosInfo Returns information on the position closest to aXyPos. |
|
898 @param aLineInfo Returns information on the line containing aXyPos. |
|
899 @return |
|
900 True if the Y-position is within the formatted text, or false otherwise. |
|
901 */ |
|
902 EXPORT_C TBool CTmTextLayout::FindXyPos(const TPoint& aXyPos, |
|
903 TTmPosInfo2& aPosInfo, TTmLineInfo& aLineInfo) const |
|
904 { |
|
905 if (!iSource) |
|
906 return FALSE; |
|
907 RTmGeneralInterpreter interpreter(*iSource, TTmInterpreterParam(*this)); |
|
908 TBool found = interpreter.FindXyPos(aXyPos,aPosInfo); |
|
909 aLineInfo = interpreter.LineInfo(); |
|
910 interpreter.Close(); |
|
911 return found; |
|
912 } |
|
913 |
|
914 /** |
|
915 Find an x-y position, relative to the top-left corner of the text, and return information about it and the line it is in. |
|
916 Return FALSE if the position is outside the formatted text. The document position to be found is passed in aDocPos and |
|
917 the information about the position found is returned in aPosInfo. The line information is returned in aLineInfo. |
|
918 @deprecated 7.0s |
|
919 */ |
|
920 EXPORT_C TBool CTmTextLayout::FindXyPos(const TPoint& aXyPos,TTmPosInfo& aPosInfo,TTmLineInfo& aLineInfo) const |
|
921 { |
|
922 TTmPosInfo2 pi; |
|
923 TBool r = FindXyPos(aXyPos, pi, aLineInfo); |
|
924 aPosInfo = pi; |
|
925 return r; |
|
926 } |
|
927 |
|
928 /** |
|
929 Return the number of formatted lines. |
|
930 */ |
|
931 EXPORT_C TInt CTmTextLayout::Lines() const |
|
932 { |
|
933 if (!iSource) |
|
934 return 0; |
|
935 TTmInterpreter interpreter(TTmInterpreterParam(*this)); |
|
936 return interpreter.Lines(); |
|
937 } |
|
938 |
|
939 /** |
|
940 Return the number of formatted paragraphs. |
|
941 */ |
|
942 EXPORT_C TInt CTmTextLayout::Paragraphs() const |
|
943 { |
|
944 if (!iSource) |
|
945 return 0; |
|
946 TTmInterpreter interpreter(TTmInterpreterParam(*this)); |
|
947 return interpreter.Paragraphs(); |
|
948 } |
|
949 |
|
950 /** |
|
951 Returns information (including line number and formatting information) of the |
|
952 line containing a given document position. |
|
953 @param aDocPos Position to find. |
|
954 @param aLineInfo |
|
955 Returns information about the line containing aDocPos if aDocPos is within |
|
956 the formatted text, or an undefined value if not. |
|
957 @return True if the aDocPos was within the formatted text. |
|
958 */ |
|
959 EXPORT_C TBool CTmTextLayout::DocPosToLine(const TTmDocPosSpec& aDocPos, |
|
960 TTmLineInfo& aLineInfo) const |
|
961 { |
|
962 if (!iSource) |
|
963 return FALSE; |
|
964 TTmInterpreter interpreter(TTmInterpreterParam(*this)); |
|
965 TBool found = interpreter.DocPosToLine(aDocPos); |
|
966 aLineInfo = interpreter.LineInfo(); |
|
967 return found; |
|
968 } |
|
969 |
|
970 /** |
|
971 Retrieve information about the line containing a certain document position. |
|
972 Put information about the line containing aDocPos in aLineInfo. Return FALSE if aDocPos is not in the formatted text. |
|
973 @deprecated 7.0s |
|
974 */ |
|
975 EXPORT_C TBool CTmTextLayout::DocPosToLine(const TTmDocPos& aDocPos,TTmLineInfo& aLineInfo) const |
|
976 { |
|
977 TTmDocPosSpec dp = aDocPos; |
|
978 return DocPosToLine(dp, aLineInfo); |
|
979 } |
|
980 |
|
981 /** |
|
982 Retrieve information about a line, referring to the line by its line number. |
|
983 |
|
984 Put information about the line numbered aLineNumber, counting the first formatted line as 0, in aLineInfo. |
|
985 Return FALSE if aLineNumber is not formatted. |
|
986 */ |
|
987 EXPORT_C TBool CTmTextLayout::LineNumberToLine(TInt aLineNumber,TTmLineInfo& aLineInfo) const |
|
988 { |
|
989 if (!iSource) |
|
990 return FALSE; |
|
991 TTmInterpreter interpreter(TTmInterpreterParam(*this)); |
|
992 TBool found = interpreter.LineNumberToLine(aLineNumber); |
|
993 aLineInfo = interpreter.LineInfo(); |
|
994 return found; |
|
995 } |
|
996 |
|
997 /** |
|
998 Retrieve information about a line, referring to the line by its paragraph number and line number within the paragraph. |
|
999 |
|
1000 Put information about line aLineNumber in paragraph aParNumber, counting the first formatted paragraph as 0, |
|
1001 in aLineInfo. Return FALSE if aParNumber is not formatted. If aLineInPar is greater than the number of lines in |
|
1002 the paragraph the last line in the paragraph is returned. |
|
1003 */ |
|
1004 EXPORT_C TBool CTmTextLayout::ParNumberToLine(TInt aParNumber,TInt aLineInPar,TTmLineInfo& aLineInfo) const |
|
1005 { |
|
1006 if (!iSource) |
|
1007 return FALSE; |
|
1008 TTmInterpreter interpreter(TTmInterpreterParam(*this)); |
|
1009 TBool found = interpreter.ParNumberToLine(aParNumber,aLineInPar); |
|
1010 aLineInfo = interpreter.LineInfo(); |
|
1011 return found; |
|
1012 } |
|
1013 |
|
1014 /** |
|
1015 Retrieve information about a line containing a certain y coordinate. |
|
1016 |
|
1017 Put information about the line containing the y coordinate aYPos, relative to 0 as the top of the formatted text, in |
|
1018 aLineInfo. Return FALSE if aYPos is outside all formatted lines. |
|
1019 */ |
|
1020 EXPORT_C TBool CTmTextLayout::YPosToLine(TInt aYPos,TTmLineInfo& aLineInfo) const |
|
1021 { |
|
1022 if (!iSource) |
|
1023 return FALSE; |
|
1024 TTmInterpreter interpreter(TTmInterpreterParam(*this)); |
|
1025 TBool found = interpreter.YPosToLine(aYPos); |
|
1026 aLineInfo = interpreter.LineInfo(); |
|
1027 return found; |
|
1028 } |
|
1029 |
|
1030 |
|
1031 /** |
|
1032 Retrieve the text as displayed on a particular line. |
|
1033 |
|
1034 The text will be returned in display order, after all transformations have been |
|
1035 applied to the backing text. These transformations include bidirectional |
|
1036 reordering (making Arabic and Hebrew go right to left, etc.), ligation |
|
1037 (combining adjacent characters into a single glyph), suppressing control |
|
1038 characters, and converting characters to visible forms like visible spaces if |
|
1039 necessary. |
|
1040 |
|
1041 Precondition: SetTextL must have been called on this object before |
|
1042 GetDisplayedText can be called. |
|
1043 |
|
1044 Please note that any text that has passed through a shaper (for example |
|
1045 Devanagari text) will be replaced in the returned text with the Unicode |
|
1046 Replacement Character 0xFFFD. This is because the shaper produces glyph codes, |
|
1047 not Unicode characters, and this is because Unicode does not contain all the |
|
1048 ligatures and glyph variants required to display such scripts correctly. |
|
1049 |
|
1050 @param aLineNumber The line to fetch the display text of. |
|
1051 @param aText A buffer into which the display text is placed. |
|
1052 @param aNeeded |
|
1053 Returns the number of characters in the displayed line. The text is |
|
1054 truncated if aText is not big enough, aNeeded returns how large the buffer |
|
1055 would need to be to return the whole line. |
|
1056 @return |
|
1057 EFalse if the operation is impossible, perhaps because aLineNumber |
|
1058 is too large to be within the text. |
|
1059 @since 7.0 |
|
1060 */ |
|
1061 EXPORT_C TBool CTmTextLayout::GetDisplayedTextL(TInt aLineNumber, TDes& aText, |
|
1062 TInt& aNeeded) const |
|
1063 { |
|
1064 __ASSERT_ALWAYS(iSource, TmPanic(ENoSource)); |
|
1065 RTmGeneralInterpreter interpreter(*iSource, TTmInterpreterParam(*this)); |
|
1066 CleanupClosePushL(interpreter); |
|
1067 TBool result = interpreter.GetDisplayedTextL(aLineNumber, aText,0, aNeeded); |
|
1068 CleanupStack::PopAndDestroy(); |
|
1069 return result; |
|
1070 } |
|
1071 |
|
1072 /** |
|
1073 Retrieve the text as displayed on a particular line. Return FALSE if the operation is impossible (e.g., because no |
|
1074 MTmSource has yet been assigned). The text is returned in aText. The number of characters needed, which may be greater |
|
1075 than the size of aText, is placed in aNeeded. |
|
1076 |
|
1077 The text will be returned in display order, after all transformations have been applied to the backing text. These |
|
1078 transformations include bidirectional reordering (making Arabic and Hebrew go right to left, etc.), ligation (combining |
|
1079 adjacent characters into a single glyph), suppressing control characters, and converting characters to visible forms like |
|
1080 visible spaces if necessary. |
|
1081 @deprecated 7.0 It can fail due to environmental conditions, and should therefore be leavable. Use GetDisplayedTextL instead. |
|
1082 */ |
|
1083 EXPORT_C TBool CTmTextLayout::GetDisplayedText(TInt aLineNumber,TDes& aText,TInt& aNeeded) const |
|
1084 { |
|
1085 if (!iSource) |
|
1086 return FALSE; |
|
1087 TBool result = EFalse; |
|
1088 TRAPD(err, result = GetDisplayedTextL(aLineNumber, aText, aNeeded)); |
|
1089 UNUSED_VAR(err); |
|
1090 return result; |
|
1091 } |
|
1092 |
|
1093 /** |
|
1094 Get the size of the minimal bounding box of the text when formatted to the specified wrap width. |
|
1095 The width may be greater than aWrapWidth. To find the minimum width for the text, |
|
1096 pass 0 for aWrapWidth. To find the minimum height, pass KMaxTInt for aWrapWidth. |
|
1097 */ |
|
1098 EXPORT_C void CTmTextLayout::GetMinimumLayoutSizeL(TInt aWrapWidth,TSize& aSize) const |
|
1099 { |
|
1100 GetMinimumLayoutSizeL(aWrapWidth,ETrue,aSize); |
|
1101 } |
|
1102 |
|
1103 /** |
|
1104 Get the size of the minimal bounding box of the text when formatted to the specified wrap width. |
|
1105 The width may be greater than aWrapWidth. To find the minimum width for the text, |
|
1106 pass 0 for aWrapWidth. To find the minimum height, pass KMaxTInt for aWrapWidth. |
|
1107 Use aAllowLegalLineBreaksOnly to set whether or not illegal line breaks should be considered |
|
1108 when determining aSize. |
|
1109 */ |
|
1110 EXPORT_C void CTmTextLayout::GetMinimumLayoutSizeL(TInt aWrapWidth,TBool aAllowLegalLineBreaksOnly,TSize& aSize) const |
|
1111 { |
|
1112 if (!iSource) |
|
1113 { |
|
1114 aSize.iWidth = aSize.iHeight = 0; |
|
1115 return; |
|
1116 } |
|
1117 TTmFormatParam param; |
|
1118 param.iWrapWidth = aWrapWidth; |
|
1119 param.iFlags = TTmFormatParam::EWrap; |
|
1120 if(aAllowLegalLineBreaksOnly) |
|
1121 param.iFlags |= TTmFormatParam::ELegalLineBreaksOnly; |
|
1122 param.iStartChar = iStartChar; |
|
1123 param.iEndChar = iEndChar; |
|
1124 CTmCode* code = new(ELeave) CTmCode; |
|
1125 CleanupStack::PushL(code); |
|
1126 CTmFormatContext::TInfo info; |
|
1127 |
|
1128 //Get line context character from previous line if there is |
|
1129 TTmDocPosSpec startDocPos(param.iStartChar - 1, static_cast<TTmDocPosSpec::TType>(1)); |
|
1130 TTmInterpreter interpreter(TTmInterpreterParam(*this)); |
|
1131 TBool lineFound = interpreter.DocPosToLine(startDocPos); |
|
1132 if (lineFound) |
|
1133 info.iContextCharPerLine = interpreter.LineContextCharChar(); |
|
1134 else |
|
1135 info.iContextCharPerLine = NULL; |
|
1136 |
|
1137 CTmFormatContext::FormatL(*iSource,param,*code,info,const_cast<CTmTextLayout*>(this)); |
|
1138 CleanupStack::PopAndDestroy(); // code |
|
1139 aSize.iWidth = info.iWidth; |
|
1140 aSize.iHeight = info.iHeight; |
|
1141 } |
|
1142 |
|
1143 /** |
|
1144 Find the width of the widest line in the specified vertical range. The width is the 'inner width'; that of the text |
|
1145 itself not including indents or margins. |
|
1146 */ |
|
1147 EXPORT_C TInt CTmTextLayout::WidthOfWidestLine(TInt aTop,TInt aBottom) const |
|
1148 { |
|
1149 if (!iSource) |
|
1150 return 0; |
|
1151 TTmInterpreter interpreter(TTmInterpreterParam(*this)); |
|
1152 return interpreter.WidthOfWidestLine(aTop, aBottom); |
|
1153 } |
|
1154 |
|
1155 EXPORT_C void CTmTextLayout::HorizontalExtremes( |
|
1156 TInt &aLeft, TInt &aRight, TInt aTopY, TInt aBottomY) const |
|
1157 { |
|
1158 if (!iSource) |
|
1159 { |
|
1160 aLeft = KMaxTInt; |
|
1161 aRight = KMinTInt; |
|
1162 return; |
|
1163 } |
|
1164 TTmInterpreter interpreter(TTmInterpreterParam(*this)); |
|
1165 interpreter.HorizontalExtremes(aLeft, aRight, aTopY, aBottomY); |
|
1166 } |
|
1167 |
|
1168 /** |
|
1169 Finds information about the visual position closest to the point specified. If |
|
1170 there are two positions at this place that represent the ends of blocks that |
|
1171 are not logically contiguous, different positions representing the ends of |
|
1172 these blocks are returned. there is an ambiguity at this position, the document |
|
1173 positions that represent the ends of the different blocks that meet here are |
|
1174 returned. |
|
1175 @param aXyPos |
|
1176 The position to find. |
|
1177 @param aPosLeft |
|
1178 The position returned. If this position is ambiguous, this is the position |
|
1179 attached to the block on the left. |
|
1180 @param aPosRight |
|
1181 The position returned. If this position is ambiguous, this is the position |
|
1182 attached to the block on the right. If it is not ambiguous, aPosLeft == |
|
1183 aPosRight. |
|
1184 @param aLineInfo |
|
1185 Information about the line containing aPosLeft and aPosRight. |
|
1186 @return |
|
1187 ETrue if the position was found. EFalse otherwise. If EFalse, aPosLeft, |
|
1188 aPosRight and aLineInfo are undefined. |
|
1189 */ |
|
1190 EXPORT_C TBool CTmTextLayout::FindXyPosWithDisambiguation( |
|
1191 const TPoint& aXyPos, |
|
1192 TTmPosInfo2& aPosLeft, TTmPosInfo2& aPosRight, |
|
1193 TTmLineInfo& aLineInfo) const |
|
1194 { |
|
1195 if (!iSource) |
|
1196 return EFalse; |
|
1197 |
|
1198 RTmGeneralInterpreter interpreter(*iSource, TTmInterpreterParam(*this)); |
|
1199 if (!interpreter.YPosToLine(aXyPos.iY)) |
|
1200 return EFalse; |
|
1201 aLineInfo = interpreter.LineInfo(); |
|
1202 |
|
1203 RTmGraphemeEdgeIterator edgeIterator; |
|
1204 edgeIterator.Begin(interpreter); |
|
1205 TTmVisualDocPos pos; |
|
1206 |
|
1207 edgeIterator.FindXPos(aXyPos.iX, pos); |
|
1208 aPosLeft = pos.LeftEdge(); |
|
1209 aPosRight = pos.RightEdge(); |
|
1210 |
|
1211 edgeIterator.Close(); |
|
1212 interpreter.Close(); |
|
1213 return pos.Ambiguity() != TTmVisualDocPos::ENotFound; |
|
1214 } |
|
1215 |
|
1216 /** |
|
1217 Finds the position after the horizontally spacing element after aStart. A |
|
1218 horizontally spacing element is a spacing glyph (such as a letter or number) |
|
1219 plus all its combining accent, or other spacing character such as a tab or |
|
1220 carriage return. This function will also skip any zero-width characters that |
|
1221 precede the next horizontally spacing element. |
|
1222 @param aStart |
|
1223 Starting position. The returned position will be greater than this. |
|
1224 @return |
|
1225 The position of the first trailing edge beyond aStart not visually |
|
1226 coincident with the leading edge of aStart, or KErrNotFound if there is |
|
1227 none, or it is not within formatted text. |
|
1228 */ |
|
1229 EXPORT_C TInt CTmTextLayout::FindNextPos(TInt aStart) const |
|
1230 { |
|
1231 if (!iSource) |
|
1232 return KErrNotFound; |
|
1233 |
|
1234 RTmGeneralInterpreter interpreter(*iSource, TTmInterpreterParam(*this)); |
|
1235 |
|
1236 if (!interpreter.DocPosToLine(TTmDocPos(aStart + 1, EFalse))) |
|
1237 return KErrNotFound; |
|
1238 |
|
1239 RTmGraphemeEdgeIterator edgeIterator; |
|
1240 edgeIterator.Begin(interpreter); |
|
1241 |
|
1242 TInt pos = edgeIterator.NextPosition(aStart); |
|
1243 |
|
1244 edgeIterator.Close(); |
|
1245 interpreter.Close(); |
|
1246 return pos; |
|
1247 } |
|
1248 |
|
1249 /** |
|
1250 Finds the position before the horizontally spacing element before aStart. |
|
1251 Zero-width characters immediately before aStart are also skipped. |
|
1252 @param aStart |
|
1253 Starting position. The returned position will be greater than this. |
|
1254 @return |
|
1255 The position of the first trailing edge beyond aStart not visually |
|
1256 coincident with the leading edge of aStart, or KErrNotFound if there is |
|
1257 none, or it is not within formatted text. |
|
1258 @see FindNextPos |
|
1259 */ |
|
1260 EXPORT_C TInt CTmTextLayout::FindPreviousPos(TInt aStart) const |
|
1261 { |
|
1262 if (!iSource) |
|
1263 return KErrNotFound; |
|
1264 |
|
1265 RTmGeneralInterpreter interpreter(*iSource, TTmInterpreterParam(*this)); |
|
1266 |
|
1267 if (!interpreter.DocPosToLine(TTmDocPos(aStart - 1, ETrue))) |
|
1268 return KErrNotFound; |
|
1269 |
|
1270 RTmGraphemeEdgeIterator edgeIterator; |
|
1271 edgeIterator.Begin(interpreter); |
|
1272 |
|
1273 TInt pos = edgeIterator.PreviousPosition(aStart); |
|
1274 |
|
1275 edgeIterator.Close(); |
|
1276 interpreter.Close(); |
|
1277 return pos; |
|
1278 } |
|
1279 |
|
1280 /** |
|
1281 Finds information about the position visually to the left of the position |
|
1282 specified, as long as it is on the same line. If there are two positions at |
|
1283 this place that represent the ends of blocks that are not logically contiguous, |
|
1284 different positions representing the ends of these blocks are returned. |
|
1285 @param aDocPos |
|
1286 The position to find. |
|
1287 @param aPosLeft |
|
1288 The position returned. If this position is ambiguous, this is the position |
|
1289 attached to the block on the left. |
|
1290 @param aPosRight |
|
1291 The position returned. If this position is ambiguous, this is the position |
|
1292 attached to the block on the right. If it is not ambiguous, aPosLeft == |
|
1293 aPosRight. |
|
1294 @return |
|
1295 ETrue if the position was found on the same line as aDocPos. EFalse |
|
1296 otherwise. If EFalse, aPosLeft and aPosRight are undefined. |
|
1297 */ |
|
1298 EXPORT_C TBool CTmTextLayout::GetNextPosLeftWithDisambiguation( |
|
1299 const TTmDocPosSpec& aDocPos, |
|
1300 TTmPosInfo2& aPosLeft, TTmPosInfo2& aPosRight) const |
|
1301 { |
|
1302 if (!iSource) |
|
1303 return EFalse; |
|
1304 |
|
1305 RTmGeneralInterpreter interpreter(*iSource, TTmInterpreterParam(*this)); |
|
1306 if (!interpreter.DocPosToLine(aDocPos)) |
|
1307 return EFalse; |
|
1308 |
|
1309 RTmGraphemeEdgeIterator edgeIterator; |
|
1310 edgeIterator.Begin(interpreter); |
|
1311 TTmPosInfo2 closest; |
|
1312 TTmVisualDocPos next; |
|
1313 |
|
1314 edgeIterator.FindEdgeLeftwards(aDocPos, closest, next); |
|
1315 aPosLeft = next.LeftEdge(); |
|
1316 aPosRight = next.RightEdge(); |
|
1317 |
|
1318 edgeIterator.Close(); |
|
1319 interpreter.Close(); |
|
1320 return next.Ambiguity() != TTmVisualDocPos::ENotFound; |
|
1321 } |
|
1322 |
|
1323 /** |
|
1324 Finds information about the position visually to the right of the position |
|
1325 specified, as long as it is on the same line. If there are two positions at |
|
1326 this place that represent the ends of blocks that are not logically contiguous, |
|
1327 different positions representing the ends of these blocks are returned. |
|
1328 @param aDocPos |
|
1329 The position to find. |
|
1330 @param aPosLeft |
|
1331 The position returned. If this position is ambiguous, this is the position |
|
1332 attached to the block on the left. |
|
1333 @param aPosRight |
|
1334 The position returned. If this position is ambiguous, this is the position |
|
1335 attached to the block on the right. If it is not ambiguous, aPosLeft == |
|
1336 aPosRight. |
|
1337 @return |
|
1338 ETrue if the position was found on the same line as aDocPos. EFalse |
|
1339 otherwise. If EFalse, aPosLeft and aPosRight are undefined. |
|
1340 */ |
|
1341 EXPORT_C TBool CTmTextLayout::GetNextPosRightWithDisambiguation( |
|
1342 const TTmDocPosSpec& aDocPos, |
|
1343 TTmPosInfo2& aPosLeft, TTmPosInfo2& aPosRight) const |
|
1344 { |
|
1345 if (!iSource) |
|
1346 return EFalse; |
|
1347 |
|
1348 RTmGeneralInterpreter interpreter(*iSource, TTmInterpreterParam(*this)); |
|
1349 if (!interpreter.DocPosToLine(aDocPos)) |
|
1350 return EFalse; |
|
1351 |
|
1352 RTmGraphemeEdgeIterator edgeIterator; |
|
1353 edgeIterator.Begin(interpreter); |
|
1354 TTmPosInfo2 closest; |
|
1355 TTmVisualDocPos next; |
|
1356 |
|
1357 edgeIterator.FindEdgeRightwards(aDocPos, closest, next); |
|
1358 aPosLeft = next.LeftEdge(); |
|
1359 aPosRight = next.RightEdge(); |
|
1360 |
|
1361 edgeIterator.Close(); |
|
1362 interpreter.Close(); |
|
1363 return next.Ambiguity() != TTmVisualDocPos::ENotFound; |
|
1364 } |
|
1365 |
|
1366 /** |
|
1367 Find the nearest document position to the current one in the visual direction |
|
1368 specified. This only works if the document position is within formatted text. |
|
1369 False is returned if this condition is not met. |
|
1370 @param aDocPos Start position. |
|
1371 @param aInfo |
|
1372 Returns the position found, or an undefined value if aDocPos is not in |
|
1373 formatted text or is already at the end of the line in the direction being |
|
1374 searched. |
|
1375 @param aToLeft True if the direction to search in is leftwards. |
|
1376 @return True if the next position was found (see the description of aInfo). |
|
1377 */ |
|
1378 EXPORT_C TBool CTmTextLayout::GetNextVisualCursorPos( |
|
1379 const TTmDocPosSpec& aDocPos, TTmPosInfo2& aInfo, TBool aToLeft) const |
|
1380 { |
|
1381 TTmPosInfo2 dummy; |
|
1382 return aToLeft? |
|
1383 GetNextPosLeftWithDisambiguation(aDocPos, dummy, aInfo) |
|
1384 : GetNextPosRightWithDisambiguation(aDocPos, aInfo, dummy); |
|
1385 } |
|
1386 |
|
1387 /** |
|
1388 Get the next cursor position in visual order. This function is useful for text that contains Arabic, Hebrew, or |
|
1389 other right-to-left languages because it allows the cursor to be moved right or left on the display whatever the |
|
1390 order of the backing text. |
|
1391 |
|
1392 The cursor position to the left or right of aDocPos is found, depending on the value of aToLeft. Information about |
|
1393 the resulting position is returned in aInfo. The function returns TRUE if successful, FALSE if not. A FALSE return value |
|
1394 means that there is no text, or aDocPos is outside the formatted text, or aDocPos cannot move in the required direction |
|
1395 because it is at the end of the line. |
|
1396 @deprecated 7.0s |
|
1397 */ |
|
1398 EXPORT_C TBool CTmTextLayout::GetNextVisualCursorPos(const TTmDocPos& aDocPos,TTmPosInfo& aInfo,TBool aToLeft) const |
|
1399 { |
|
1400 TTmDocPosSpec dp = aDocPos; |
|
1401 TTmPosInfo2 pi; |
|
1402 TBool r = GetNextVisualCursorPos(dp, pi, aToLeft); |
|
1403 aInfo = pi; |
|
1404 return r; |
|
1405 } |
|
1406 |
|
1407 /** |
|
1408 Returns the position at the left or right extreme of the line containing aPos. |
|
1409 @param aToRight EFalse for finding the left hand end, ETrue for the right. |
|
1410 @param aExtreme Returns the document position at the end requested. |
|
1411 @return |
|
1412 EFalse if the call failed either because the position was unformatted or |
|
1413 because the line contained no text. |
|
1414 */ |
|
1415 EXPORT_C TBool CTmTextLayout::LineExtreme(const TTmDocPosSpec& aPos, |
|
1416 TBool aToRight, TTmDocPos& aExtreme) const |
|
1417 { |
|
1418 TTmPosInfo2 posInfo; |
|
1419 TTmLineInfo lineInfo; |
|
1420 if (!FindDocPos(aPos, posInfo, lineInfo)) |
|
1421 return EFalse; |
|
1422 TPoint extreme( |
|
1423 aToRight? lineInfo.iInnerRect.iBr.iX : lineInfo.iInnerRect.iTl.iX, |
|
1424 lineInfo.iInnerRect.iTl.iY); |
|
1425 if (!FindXyPos(extreme, posInfo, lineInfo)) |
|
1426 return EFalse; |
|
1427 aExtreme = posInfo.iDocPos; |
|
1428 return ETrue; |
|
1429 } |
|
1430 |
|
1431 /** |
|
1432 Returns the chunks of text adjacent to aPos. |
|
1433 @param aLeft Returns a description of the chunk on the left of the cursor. |
|
1434 @param aRight Returns a description of the chunk on the right. |
|
1435 @return |
|
1436 EFalse if the call failed because the line is not formatted or contains |
|
1437 no text. |
|
1438 */ |
|
1439 EXPORT_C TBool CTmTextLayout::FindAdjacentChunks(const TTmDocPosSpec& aPos, |
|
1440 CTmTextLayout::TTmChunkDescription& aLeft, |
|
1441 CTmTextLayout::TTmChunkDescription& aRight) const |
|
1442 { |
|
1443 // Following block of code is used to check whether a doc position is shared by two text chunks. |
|
1444 TBool overlapped = EFalse; |
|
1445 TTmChunkInterpreter tempCi(*this); |
|
1446 if (!tempCi.ChunkSetToLeftOfLine(aPos)) |
|
1447 return EFalse; |
|
1448 TTmChunkInterpreter::TContainment contain1 = tempCi.ChunkContainsPos(aPos); |
|
1449 TTmChunkInterpreter::TContainment contain2; |
|
1450 while(tempCi.ChunkNext()) |
|
1451 { |
|
1452 contain2 = tempCi.ChunkContainsPos(aPos); |
|
1453 if ( (contain1 == TTmChunkInterpreter::EMiddleOfChunk && contain2 != TTmChunkInterpreter::ENotInChunk) |
|
1454 || (contain1 != TTmChunkInterpreter::ENotInChunk && contain2 == TTmChunkInterpreter::EMiddleOfChunk) ) |
|
1455 { |
|
1456 overlapped = ETrue; |
|
1457 break; |
|
1458 } |
|
1459 if ( contain1 != TTmChunkInterpreter::ENotInChunk ) |
|
1460 break; |
|
1461 contain1 = contain2; |
|
1462 } |
|
1463 // end of checking... |
|
1464 |
|
1465 TTmChunkInterpreter ci(*this); |
|
1466 if (!ci.ChunkSetToLeftOfLine(aPos)) |
|
1467 return EFalse; |
|
1468 aLeft.iStart = -1; |
|
1469 if (aPos.iPos == ci.LineInfo().iStart |
|
1470 && aPos.iType == TTmDocPosSpec::ETrailing |
|
1471 && !(ci.LineInfo().iFlags & TTmLineInfo::EParRightToLeft)) |
|
1472 { |
|
1473 aRight.iStart = ci.ChunkStart(); |
|
1474 aRight.iEnd = ci.ChunkEnd(); |
|
1475 aRight.iRightToLeft = ci.ChunkRightToLeft(); |
|
1476 return ETrue; |
|
1477 } |
|
1478 TTmChunkInterpreter::TContainment containment = ci.ChunkContainsPos(aPos); |
|
1479 // When a doc postion is overlapped, it would be in middle of one chunk and on edge of another |
|
1480 // chunk, so (MiddleOfChunk && overlapped) is also included. |
|
1481 while (containment == TTmChunkInterpreter::ENotInChunk |
|
1482 || containment == TTmChunkInterpreter::ERightEdgeOfChunk |
|
1483 ||(containment == TTmChunkInterpreter::EMiddleOfChunk && overlapped)) |
|
1484 { |
|
1485 aLeft.iStart = ci.ChunkStart(); |
|
1486 aLeft.iEnd = ci.ChunkEnd(); |
|
1487 aLeft.iRightToLeft = ci.ChunkRightToLeft(); |
|
1488 if (!ci.ChunkNext()) |
|
1489 { |
|
1490 aRight.iStart = -1; |
|
1491 return ETrue; |
|
1492 } |
|
1493 |
|
1494 if ( containment == TTmChunkInterpreter::ENotInChunk ) |
|
1495 { |
|
1496 containment = ci.ChunkContainsPos(aPos); |
|
1497 } |
|
1498 else if (containment == TTmChunkInterpreter::EMiddleOfChunk && overlapped) |
|
1499 { |
|
1500 containment = ci.ChunkContainsPos(aPos); |
|
1501 // just in case the doc position is in middle of both of the two overlapped chunks, |
|
1502 // however this should not happen. |
|
1503 if (containment == TTmChunkInterpreter::EMiddleOfChunk) |
|
1504 break; |
|
1505 } |
|
1506 else if (containment == TTmChunkInterpreter::ERightEdgeOfChunk) |
|
1507 { |
|
1508 containment = TTmChunkInterpreter::ELeftEdgeOfChunk; |
|
1509 } |
|
1510 } |
|
1511 if (containment == TTmChunkInterpreter::ELeftEdgeOfChunk) |
|
1512 { |
|
1513 aRight.iStart = ci.ChunkStart(); |
|
1514 aRight.iEnd = ci.ChunkEnd(); |
|
1515 aRight.iRightToLeft = ci.ChunkRightToLeft(); |
|
1516 return ETrue; |
|
1517 } |
|
1518 // position is in the middle of a chunk, so we will split it. |
|
1519 if (ci.ChunkRightToLeft()) |
|
1520 { |
|
1521 aLeft.iRightToLeft = ETrue; |
|
1522 aRight.iRightToLeft = ETrue; |
|
1523 aRight.iStart = ci.ChunkStart(); |
|
1524 aRight.iEnd = aPos.iPos; |
|
1525 aLeft.iStart = aPos.iPos; |
|
1526 aLeft.iEnd = ci.ChunkEnd(); |
|
1527 } |
|
1528 else |
|
1529 { |
|
1530 aLeft.iRightToLeft = EFalse; |
|
1531 aRight.iRightToLeft = EFalse; |
|
1532 aLeft.iStart = ci.ChunkStart(); |
|
1533 aLeft.iEnd = aPos.iPos; |
|
1534 aRight.iStart = aPos.iPos; |
|
1535 aRight.iEnd = ci.ChunkEnd(); |
|
1536 } |
|
1537 return ETrue; |
|
1538 } |
|
1539 |
|
1540 /** |
|
1541 Returns metrics for the cursor suitable for the document position and placement |
|
1542 specified, as well as information about the line containing the position |
|
1543 specified. |
|
1544 @param aDocPos The document position to return information about. |
|
1545 @param aPlacement The shape of the cursor. |
|
1546 @param aLineInfo |
|
1547 Returns information about the line containing aDocPos if this position is |
|
1548 within the formatted text, or an undefined value otherwise. |
|
1549 @param aOrigin |
|
1550 Returns a position to which aWidth, aAscent and aDescent is relative if the |
|
1551 position is within formatted text. Returns an undefined value otherwise. |
|
1552 This position will be on the baseline of the character found. |
|
1553 @param aWidth |
|
1554 When aPlacement is ECursorVertical aWidth represents which side of the |
|
1555 origin to paint the cursor, -1 paint left, +1 paint right. When aPlacement |
|
1556 is ECursorUnderlineXXXX aWidth represents the X offset from the origin X to |
|
1557 draw the cursor between, -ve for previous & +ve for next when text L2R |
|
1558 (e.g. Latin), +ve for previous & -ve for next when text is R2L (e.g. Arabic) |
|
1559 @param aAscent |
|
1560 Returns how far above aOrigin the cursor extends if aDocPos is within |
|
1561 formatted text, or an undefined value otherwise. |
|
1562 @param aDescent |
|
1563 Returns how far below aOrigin the cursor extends if aDocPos is within |
|
1564 formatted text, or an undefined value otherwise. |
|
1565 */ |
|
1566 EXPORT_C TBool CTmTextLayout::GetCursor(const TTmDocPosSpec& aDocPos,TTmCursorPlacement aPlacement, |
|
1567 TTmLineInfo& aLineInfo,TPoint& aOrigin,TInt& aWidth,TInt& aAscent,TInt& aDescent) const |
|
1568 { |
|
1569 aOrigin.SetXY(0,0); |
|
1570 aWidth = aAscent = aDescent = 0; |
|
1571 if (!iSource) |
|
1572 return EFalse; |
|
1573 |
|
1574 RTmGeneralInterpreter interpreter(*iSource, TTmInterpreterParam(*this)); |
|
1575 if (!interpreter.DocPosToLine(aDocPos)) |
|
1576 return EFalse; |
|
1577 RTmGraphemeEdgeIterator edgeIterator; |
|
1578 edgeIterator.Begin(interpreter); |
|
1579 |
|
1580 TTmPosInfo2 this_info; |
|
1581 TTmVisualDocPos next; |
|
1582 TBool go_left = (aPlacement == ECursorUnderlinePrev); |
|
1583 RTmGraphemeEdgeIterator::TEdgesFound found = go_left? |
|
1584 edgeIterator.FindEdgeLeftwards(aDocPos, this_info, next) |
|
1585 : edgeIterator.FindEdgeRightwards(aDocPos, this_info, next); |
|
1586 if (found == RTmGraphemeEdgeIterator::ENone) |
|
1587 { |
|
1588 edgeIterator.Close(); |
|
1589 interpreter.Close(); |
|
1590 return EFalse; |
|
1591 } |
|
1592 TPoint nextPoint = this_info.iEdge; |
|
1593 if (found == RTmGraphemeEdgeIterator::ENearestAndNext) |
|
1594 nextPoint = next.NearestToX(nextPoint.iX)->iEdge; |
|
1595 |
|
1596 aOrigin = go_left ? nextPoint : this_info.iEdge; |
|
1597 aLineInfo = interpreter.LineInfo(); |
|
1598 |
|
1599 int pos = this_info.iDocPos.iPos; |
|
1600 if (pos > interpreter.LineInfo().iStart || !interpreter.ParStart()) |
|
1601 pos--; |
|
1602 TPtrC text; |
|
1603 CTmTextFontCache* font = NULL; |
|
1604 interpreter.GetText(pos,KMaxTInt,text,NULL,&font); |
|
1605 |
|
1606 if (font) |
|
1607 { |
|
1608 if (aPlacement == ECursorVertical) |
|
1609 { |
|
1610 aAscent = font->Font().AscentInPixels(); |
|
1611 aDescent = font->Font().DescentInPixels(); |
|
1612 // In case the cursor is positioned on some super/sub or normal |
|
1613 // font we need to adjust the Y position of the cursor with the |
|
1614 // font's baseline offset so the cursor sits on the same horizon |
|
1615 // as the text. |
|
1616 aOrigin.iY += font->Font().BaselineOffsetInPixels(); |
|
1617 // -1 indicates that the cursor should hang to the left: this is |
|
1618 // for right-to-left paragraphs. |
|
1619 aWidth = aLineInfo.iFlags & TTmLineInfo::EParRightToLeft? -1 : 1; |
|
1620 } |
|
1621 else |
|
1622 { |
|
1623 aAscent = 0; |
|
1624 aDescent = 1; |
|
1625 aWidth = nextPoint.iX - this_info.iEdge.iX; |
|
1626 // The next if doesn't work to well with ECursorUnderlinePrev |
|
1627 // placement as it is an approximation. |
|
1628 if (aWidth == 0) // Triggered when at start or end of text line |
|
1629 aWidth = font->Font().HeightInPixels() / 2; |
|
1630 if (aWidth < 0) |
|
1631 aWidth = -aWidth; |
|
1632 } |
|
1633 font->Close(); |
|
1634 } |
|
1635 else |
|
1636 found = RTmGraphemeEdgeIterator::ENone; |
|
1637 edgeIterator.Close(); |
|
1638 interpreter.Close(); |
|
1639 return found != RTmGraphemeEdgeIterator::ENone; |
|
1640 } |
|
1641 |
|
1642 /** |
|
1643 Return cursor metrics suitable for the supplied document position and placement. |
|
1644 The cursor is defined like a character, with an origin, width, height and depth. |
|
1645 This allows the caller to preserve the origin while overriding the other metrics. |
|
1646 @deprecated 7.0s |
|
1647 */ |
|
1648 EXPORT_C TBool CTmTextLayout::GetCursor(const TTmDocPos& aDocPos,TTmCursorPlacement aPlacement, |
|
1649 TTmLineInfo& aLineInfo,TPoint& aOrigin,TInt& aWidth,TInt& aAscent,TInt& aDescent) const |
|
1650 { |
|
1651 TTmDocPosSpec dp = aDocPos; |
|
1652 return GetCursor(dp, aPlacement, aLineInfo, aOrigin, aWidth, aAscent, aDescent); |
|
1653 } |
|
1654 |
|
1655 /** |
|
1656 Return the amount of memory used by a CTmTextLayout object, |
|
1657 The amount returned is in bytes. |
|
1658 The amount returned does not include memory used by non-owned objects. |
|
1659 */ |
|
1660 EXPORT_C TInt CTmTextLayout::MemoryUsed() const |
|
1661 { |
|
1662 return sizeof(*this) + iCode.MemoryUsed() - sizeof(iCode); |
|
1663 } |
|
1664 |
|
1665 /** |
|
1666 Stops or allows text to be drawn. Included to allow users to control visibility |
|
1667 if text is part of an invisible control. |
|
1668 */ |
|
1669 EXPORT_C void CTmTextLayout::MakeVisible(TBool aVisible) |
|
1670 { |
|
1671 if(aVisible) |
|
1672 { |
|
1673 iDrawingInterpFlags &= ~RTmDrawingInterpreter::EInvisible; |
|
1674 } |
|
1675 else |
|
1676 { |
|
1677 iDrawingInterpFlags |= RTmDrawingInterpreter::EInvisible; |
|
1678 } |
|
1679 } |
|
1680 |
|
1681 TInt CTmTextLayout::GetDrawingInterpFlags() const |
|
1682 { |
|
1683 return iDrawingInterpFlags; |
|
1684 } |
|
1685 |
|
1686 #ifdef _DEBUG |
|
1687 void CTmTextLayout::Invariant() const |
|
1688 { |
|
1689 int lines = Lines(); |
|
1690 if (lines > 0) |
|
1691 { |
|
1692 TTmLineInfo info; |
|
1693 if (!LineNumberToLine(lines - 1,info)) |
|
1694 TmPanic(EInvariant); |
|
1695 int end = info.iEnd; |
|
1696 if (end != iEndChar) |
|
1697 TmPanic(EInvariant); |
|
1698 } |
|
1699 } |
|
1700 #endif |
|
1701 |
|
1702 /* |
|
1703 Adjust the width of the text, taking overwidth paragraphs like non-wrapped ones into account. |
|
1704 aParam is the formatting parameters. |
|
1705 aWidthOfNewText is the width of the widest line of any new text that has been inserted and has caused the adjustment. |
|
1706 */ |
|
1707 void CTmTextLayout::AdjustWidth(const TTmFormatParamBase& aParam,TInt aWidthOfNewText) |
|
1708 { |
|
1709 if (aParam.IsWrapping()) |
|
1710 { |
|
1711 int wrap_width = aParam.iWrapWidth; |
|
1712 int x_scale = 1000; |
|
1713 int y_scale = 1000; |
|
1714 CalculateScale(*iSource,x_scale,y_scale); |
|
1715 if (x_scale != 1000) |
|
1716 wrap_width = wrap_width * x_scale / 1000; |
|
1717 if (iWidth > wrap_width || aWidthOfNewText > wrap_width) |
|
1718 { |
|
1719 iWidth = WidthOfWidestLine(); |
|
1720 if (iWidth < wrap_width) |
|
1721 iWidth = wrap_width; |
|
1722 } |
|
1723 else |
|
1724 iWidth = wrap_width; |
|
1725 } |
|
1726 else |
|
1727 iWidth = WidthOfWidestLine(); |
|
1728 } |
|
1729 |
|
1730 /** |
|
1731 The equality operator. |
|
1732 @return True if both sides are identical. |
|
1733 */ |
|
1734 EXPORT_C TBool TTmDocPos::operator==(const TTmDocPos& aPos) const |
|
1735 { |
|
1736 return iPos == aPos.iPos && !iLeadingEdge == !aPos.iLeadingEdge; |
|
1737 } |
|
1738 |
|
1739 /** |
|
1740 Greater than operator. |
|
1741 @return |
|
1742 True if the left side of the operator is further on in the document than |
|
1743 the right hand side. |
|
1744 */ |
|
1745 EXPORT_C TBool TTmDocPos::operator>(const TTmDocPos& aPos) const |
|
1746 { |
|
1747 return iPos > aPos.iPos || (iPos == aPos.iPos && iLeadingEdge && !aPos.iLeadingEdge); |
|
1748 } |
|
1749 |
|
1750 /** |
|
1751 Greater than or equal to operator. |
|
1752 @return |
|
1753 True if the left side of the operator is further on in the document than |
|
1754 the right hand side or if both sides are identical. |
|
1755 */ |
|
1756 EXPORT_C TBool TTmDocPos::operator>=(const TTmDocPos& aPos) const |
|
1757 { |
|
1758 return iPos > aPos.iPos || (iPos == aPos.iPos && (iLeadingEdge || !aPos.iLeadingEdge)); |
|
1759 } |