fixed bug (TapGesture improvement)
[platform/framework/native/uifw.git] / src / graphics / text / FGrp_TextTextComposite.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0/
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an ”AS IS” BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /*
19  * @file        FGrp_TextTextComposite.cpp
20  * @brief       This is the implementation file for TextComposite class.
21  */
22
23 // Includes
24 #include <new>
25 #include <fribidi.h>
26 #include <FBaseSysLog.h>
27 #include <FApp_AppInfo.h>
28 #include "FGrp_TextCommon.h"
29 #include "FGrp_TextTextElement.h"
30 #include "FGrp_TextTextSimple.h"
31 #include "FGrp_TextTextImage.h"
32 #include "FGrp_TextTextCutLink.h"
33 #include "FGrp_TextTextLine.h"
34 #include "FGrp_TextTextColumn.h"
35 #include "FGrp_TextTextCutLinkListInfo.h"
36 #include "FGrp_TextTextComposite.h"
37 #include "FGrp_TextTextUtility.h"
38 #include "FGrp_CanvasImpl.h"
39 #include "FGrp_CoordinateSystemUtils.h"
40
41 using namespace Tizen::Base;
42 using namespace Tizen::Base::Utility;
43 using namespace Tizen::Base::Collection;
44
45 #define Release(x) \
46         if (x) \
47         { \
48                 delete x; \
49                 x = null; \
50         }
51
52 namespace // unnamed
53 {
54         const float LINE_FEED_WIDTH = 8.0f;
55 }
56
57 namespace Tizen { namespace Graphics
58 {
59
60 namespace _Text
61 {
62
63 struct NoneWrapComposeInfo
64 {
65         int prevTextOffset;
66         int prevTextLength;
67         float prevWidth;
68         float prevHeight;
69         int prevEndType;
70 };
71
72 TextComposite::TextComposite(TextElement* pTextElement)
73 {
74         __pTextElementList = new (std::nothrow) LinkedList;
75         SysTryReturn(NID_GRP, __pTextElementList, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
76
77         __wrap = TEXT_OBJECT_WRAP_TYPE_WORD;
78         __workStart = 0;
79         __workLength = 0;
80         __workWidth = 0;
81         __length = 0;
82         __displayBlock = false;
83         __defaultBlockColor = Color(183, 212, 247);
84         __cursorIndex = -1;
85
86         __ignoreRearBlank = true;
87         __ignoreFrontBlank = false;
88
89         __rearSpaceHideMode = TEXT_OBJECT_SPACE_HIDE_TYPE_ONE;
90         __frontSpaceHideMode = TEXT_OBJECT_SPACE_HIDE_TYPE_ONE;
91
92         __lineSpacing = 0;
93         __elementVertialAlignment = TEXT_OBJECT_ALIGNMENT_BOTTOM;
94         __pCurrentTextColumn = null;
95         __pCutLinkListInfo = new (std::nothrow)TextCutLinkListInfo;
96
97         {
98                 wchar_t abbrevText[2];
99                 abbrevText[0] = TEXT_ABBREV_CHARACTER;
100                 abbrevText[1] = 0;
101
102                 __pAbbrevTextElement = new (std::nothrow)TextSimple(abbrevText, 1, TEXT_ELEMENT_SOURCE_TYPE_INTERNAL, null,
103                                 Color::GetColor(COLOR_ID_BLACK), Color::GetColor(COLOR_ID_WHITE), Color::GetColor(COLOR_ID_WHITE));
104         }
105
106         if (pTextElement != null)
107         {
108                 AppendElement(*pTextElement);
109         }
110         __drawAbbrevText = false;
111         __drawTextEllipsis = false;
112         __TextObjectEllipsisType = TEXT_OBJECT_ELLIPSIS_TYPE_TAIL;
113
114         __partialComposingModeEnabled = false;
115         __lineIndexCompositeDone = 0;
116         __totalComposedHeight = 0;
117         __composePartialLimitHeight = 0;
118
119         __headEllipsisTextLength = 0;
120         __headEllipsisWidth = 0;
121         __middleEllipsisHeadWidth = 0;
122         __middleEllipsisTextLengthInHead = 0;
123         __middleEllipsisTextLengthInTail = 0;
124         __middleEllipsisWidth = 0;
125         __isChanged = false;
126
127         __pSweepInfo = null;
128 }
129
130 TextComposite::~TextComposite(void)
131 {
132         Release(__pCutLinkListInfo);
133         Release(__pAbbrevTextElement);
134
135         if (__pTextElementList)
136         {
137                 RemoveAllElements(true);
138                 delete __pTextElementList;
139                 __pTextElementList = null;
140         }
141 }
142
143 int
144 TextComposite::ForwardAnalyze(int startTextIndex, int textLength, int maxWidth, TextObjectWrapType wrap, int& actualLength,
145                                                            int& width, int& height)
146 {
147         float maxWidthF = _CoordinateSystemUtils::ConvertToFloat(maxWidth);
148         float widthF = _CoordinateSystemUtils::ConvertToFloat(width);
149         float heightF = _CoordinateSystemUtils::ConvertToFloat(height);
150
151         int r =  ForwardAnalyze(startTextIndex, textLength, maxWidthF, wrap, actualLength, widthF, heightF);
152
153         width = _CoordinateSystemUtils::ConvertToInteger(widthF);
154         height = _CoordinateSystemUtils::ConvertToInteger(heightF);
155
156         return r;
157 }
158
159 int
160 TextComposite::ForwardAnalyze(int startTextIndex, int textLength, float maxWidth, TextObjectWrapType wrap, int& actualLength,
161                                                            float& width, float& height)
162 {
163         SysTryReturn(NID_GRP, 0 <= startTextIndex && startTextIndex < __length, -1, E_INVALID_ARG
164                         , "[E_INVALID_ARG] The argument is invalid. startTextIndex(%d)", startTextIndex);
165         SysTryReturn(NID_GRP, textLength <= __length, -1, E_INVALID_ARG
166                         , "[E_INVALID_ARG] The argument is invalid. textLength(%d)", textLength);
167
168         result r = E_SUCCESS;
169         FloatDimension textSize;
170         int elementTextOffset = 0;
171         int elementIndex = 0;
172         int textIndexFromElementOffset = 0;
173         float remainingWidth = 0;
174         int remainingLength = 0;
175         int textCount = 0;
176         int currentLength = 0;
177         int ret = TEXT_RETBY_NORMAL;
178
179         IEnumerator* pEnum = null;
180         TextElement* pTextElement = null;
181
182         bool isFirstWord = true;
183         FloatDimension tempTextSize;
184         int tempTextCount = 0;
185         actualLength = 0;
186         width = 0;
187         height = 0;
188
189         pTextElement = GetElementAtTextIndex(startTextIndex, elementTextOffset, elementIndex, currentLength,textIndexFromElementOffset);
190         SysTryReturn(NID_GRP, pTextElement, -1, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
191
192         textCount = 0;
193         remainingWidth = maxWidth;
194         remainingLength = textLength;
195         currentLength = Math::Min(remainingLength, currentLength);
196
197         pEnum = __pTextElementList->GetEnumeratorN();
198         for (int i = 0; i <= elementIndex; i++)
199         {
200                 r = pEnum->MoveNext();
201                 SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Fail to move next element.", GetErrorMessage(r));
202         }
203
204         while ((remainingWidth != 0) && (remainingLength != 0))
205         {
206                 ret = pTextElement->ForwardAnalyze(textIndexFromElementOffset, currentLength, remainingWidth,
207                                                                                          wrap, textCount, textSize.width, textSize.height);
208
209                 if (textSize.width == 0 && textCount == 0)
210                 {
211                         break;
212                 }
213
214                 textSize.height += __lineSpacing;
215                 remainingWidth -= textSize.width;
216                 remainingLength -= textCount;
217                 currentLength -= textCount;
218
219                 actualLength += textCount;
220                 width += textSize.width;
221                 height = (textSize.height > height) ? textSize.height : height;
222
223                 if (__wrap == TEXT_OBJECT_WRAP_TYPE_WORD && ret != TEXT_RETBY_LIMITWIDTH)
224                 {
225                         tempTextCount = actualLength;
226                         tempTextSize.width = width;
227                         tempTextSize.height = height;
228                 }
229
230                 if (ret == TEXT_RETBY_OVERWIDTH || ret == TEXT_RETBY_LINEFEED)
231                 {
232                         break;
233                 }
234
235                 if (__wrap == TEXT_OBJECT_WRAP_TYPE_WORD)
236                 {
237                         if (ret == TEXT_RETBY_LIMITWIDTH)
238                         {
239                                 if (isFirstWord == false)
240                                 {
241                                         actualLength = tempTextCount;
242                                         width = tempTextSize.width;
243                                         height = tempTextSize.height;
244
245                                         ret = TEXT_RETBY_NORMAL;
246                                 }
247                                 break;
248                         }
249
250                         isFirstWord = false;
251
252                         if (0 < currentLength)
253                         {
254                                 textIndexFromElementOffset += textCount;
255                                 continue;
256                         }
257                 }
258                 else
259                 {
260                         if (ret == TEXT_RETBY_LIMITWIDTH)
261                         {
262                                 break;
263                         }
264                 }
265
266                 if (pEnum->MoveNext() != E_SUCCESS)
267                 {
268                         break;
269                 }
270
271                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
272                 if (pTextElement == null)
273                 {
274                         break;
275                 }
276
277                 isFirstWord = true;
278                 textIndexFromElementOffset = pTextElement->GetValue(SET_TEXT_OFFSET);
279                 currentLength = Math::Min(pTextElement->GetTextLength(), remainingLength);
280         }
281
282         if (ret == TEXT_RETBY_LIMITLENGTH)
283         {
284                 ret = TEXT_RETBY_NORMAL;
285         }
286
287         SetLastResult(E_SUCCESS);
288         Release(pEnum);
289         return ret;
290
291 CATCH:
292         Release(pEnum);
293         return -1;
294 }
295
296 int
297 TextComposite::ForwardAnalyzeWithBaseline(int startTextIndex, int textLength, int maxWidth, TextObjectWrapType wrap, int& actualLength,
298                                                            int& width, int& height, int& baseline)
299 {
300         float maxWidthF = _CoordinateSystemUtils::ConvertToFloat(maxWidth);
301         float widthF = _CoordinateSystemUtils::ConvertToFloat(width);
302         float heightF = _CoordinateSystemUtils::ConvertToFloat(height);
303         float baselineF = _CoordinateSystemUtils::ConvertToFloat(baseline);
304
305         int r = ForwardAnalyzeWithBaseline(startTextIndex, textLength, maxWidthF, wrap, actualLength, widthF, heightF, baselineF);
306
307         width = _CoordinateSystemUtils::ConvertToInteger(widthF);
308         height = _CoordinateSystemUtils::ConvertToInteger(heightF);
309         baseline = _CoordinateSystemUtils::ConvertToInteger(baselineF);
310
311         return r;
312 }
313
314 int
315 TextComposite::ForwardAnalyzeWithBaseline(int startTextIndex, int textLength, float maxWidth, TextObjectWrapType wrap, int& actualLength,
316                                                            float& width, float& height, float& baseline)
317 {
318         SysTryReturn(NID_GRP, 0 <= startTextIndex && startTextIndex < __length
319                         , -1, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid. startTextIndex(%d)", startTextIndex);
320
321         SysTryReturn(NID_GRP, startTextIndex +  textLength <= __length
322                         , -1, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid. textLength(%d)", textLength);
323
324         result r = E_SUCCESS;
325
326         FloatDimension textSize;
327         int elementTextOffset = 0;
328         int elementIndex = 0;
329         int textIndexFromElementOffset = 0;
330         float remainingWidth = 0;
331         int remainingLength = 0;
332         int textCount = 0;
333         int currentLength = 0;
334         int ret = TEXT_RETBY_NORMAL;
335         bool isMaxHeightImage = false;
336
337         IEnumerator* pEnum = null;
338         TextElement* pTextElement = null;
339
340         bool isFirstWord = true;
341         FloatDimension tempTextSize;
342         int tempTextCount = 0;
343         actualLength = 0;
344         width = 0;
345         height = 0;
346
347         pTextElement = GetElementAtTextIndex(startTextIndex, elementTextOffset, elementIndex, currentLength,
348                                                                                          textIndexFromElementOffset);
349         SysTryReturn(NID_GRP, pTextElement, -1, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
350
351         textCount = 0;
352         remainingWidth = maxWidth;
353         remainingLength = textLength;
354         currentLength = Math::Min(remainingLength, currentLength);
355         baseline = pTextElement->GetBaselineF();
356
357         pEnum = __pTextElementList->GetEnumeratorN();
358         for (int i = 0; i <= elementIndex; i++)
359         {
360                 r = pEnum->MoveNext();
361                 SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Fail to move next element.", GetErrorMessage(r));
362         }
363
364         while (remainingLength != 0)
365         {
366                 ret = pTextElement->ForwardAnalyze(textIndexFromElementOffset, currentLength, remainingWidth,
367                                                                                          wrap, textCount, textSize.width, textSize.height);
368
369                 textSize.height += __lineSpacing;
370                 remainingWidth -= textSize.width;
371                 remainingLength -= textCount;
372                 currentLength -= textCount;
373
374                 actualLength += textCount;
375                 width += textSize.width;
376                 baseline = (pTextElement->GetBaselineF() > baseline) ? pTextElement->GetBaselineF() : baseline;
377
378                 if (height < textSize.height)
379                 {
380                         height = textSize.height;
381
382                         (pTextElement->GetType() == TEXT_ELEMENT_TYPE_IMAGE) ? isMaxHeightImage = true : isMaxHeightImage = false;
383                 }
384
385                 if (__wrap == TEXT_OBJECT_WRAP_TYPE_WORD && ret != TEXT_RETBY_LIMITWIDTH)
386                 {
387                         tempTextCount = actualLength;
388                         tempTextSize.width = width;
389                         tempTextSize.height = height;
390                 }
391
392                 if (ret == TEXT_RETBY_OVERWIDTH || ret == TEXT_RETBY_LINEFEED)
393                 {
394                         break;
395                 }
396
397                 if (__wrap == TEXT_OBJECT_WRAP_TYPE_WORD)
398                 {
399                         if (ret == TEXT_RETBY_LIMITWIDTH)
400                         {
401                                 if (isFirstWord == false)
402                                 {
403                                         actualLength = tempTextCount;
404                                         width = tempTextSize.width;
405                                         height = tempTextSize.height;
406
407                                         ret = TEXT_RETBY_NORMAL;
408                                 }
409                                 break;
410                         }
411
412                         isFirstWord = false;
413
414                         if (0 < currentLength)
415                         {
416                                 textIndexFromElementOffset += textCount;
417                                 continue;
418                         }
419                 }
420                 else
421                 {
422                         if (ret == TEXT_RETBY_LIMITWIDTH)
423                         {
424                                 break;
425                         }
426                 }
427
428                 if (pEnum->MoveNext() != E_SUCCESS)
429                 {
430                         break;
431                 }
432
433                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
434                 if (pTextElement == null)
435                 {
436                         break;
437                 }
438
439                 isFirstWord = true;
440                 textIndexFromElementOffset = pTextElement->GetValue(SET_TEXT_OFFSET);
441                 currentLength = Math::Min(pTextElement->GetTextLength(), remainingLength);
442         }
443
444         if (ret == TEXT_RETBY_LIMITLENGTH)
445         {
446                 ret = TEXT_RETBY_NORMAL;
447         }
448
449         if (isMaxHeightImage)
450         {
451                 height += baseline;
452         }
453
454         SetLastResult(E_SUCCESS);
455         Release(pEnum);
456         return ret;
457
458 CATCH:
459         Release(pEnum);
460         return -1;
461 }
462
463 result
464 TextComposite::GetRegion(int textIndex, int textLength, float& width, float& height) const
465 {
466         if (textLength == 0)
467         {
468                 width = 0;
469                 height = 0;
470
471                 return E_SUCCESS;
472         }
473
474         SysTryReturn(NID_GRP, 0 <= textIndex && textIndex < __length, E_INVALID_ARG, E_INVALID_ARG
475                 , "[E_INVALID_ARG] The argument is invalid. textIndex(%d) __length(%d)", textIndex, __length);
476         SysTryReturn(NID_GRP, textLength <= __length, E_INVALID_ARG, E_INVALID_ARG
477                 , "[E_INVALID_ARG] The argument is invalid. textIndex(%d) __length(%d)", textIndex, __length);
478
479         result r = E_SUCCESS;
480         IEnumerator* pEnum = null;
481         TextElement* pTextElement = null;
482         FloatDimension textSize;
483         int currentLength = 0;
484         int elementTextOffset = 0;
485         int elementIndex = 0;
486         int textIndexFromElementOffset = 0;
487
488         width = 0;
489         height = 0;
490
491         pTextElement = GetElementAtTextIndex(textIndex, elementTextOffset, elementIndex, currentLength, textIndexFromElementOffset);
492         SysTryReturn(NID_GRP, pTextElement, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
493
494         pEnum = __pTextElementList->GetEnumeratorN();
495         for (int i = 0; i <= elementIndex; i++)
496         {
497                 r = pEnum->MoveNext();
498                 SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Fail to move next element.", GetErrorMessage(r));
499         }
500
501         currentLength = Math::Min(currentLength, textLength);
502
503         while (textLength != 0)
504         {
505                 pTextElement->GetRegion(textIndexFromElementOffset, currentLength, textSize.width, textSize.height);
506
507                 width += textSize.width;
508                 height = (height > textSize.height) ? height : textSize.height;
509                 textLength -= currentLength;
510
511                 if (pEnum->MoveNext() != E_SUCCESS)
512                 {
513                         break;
514                 }
515
516                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
517                 if (pTextElement == null)
518                 {
519                         break;
520                 }
521
522                 textIndexFromElementOffset = pTextElement->GetValue(SET_TEXT_OFFSET);
523                 currentLength = Math::Min(textLength, pTextElement->GetTextLength());
524         }
525
526         Release(pEnum);
527         return r;
528
529 CATCH:
530         width = 0;
531         height = 0;
532
533         Release(pEnum);
534         return r;
535 }
536
537 float
538 TextComposite::GetHeightF(int textIndex) const
539 {
540         if (__length == 0)
541         {
542                 return 0;
543         }
544
545         SysTryReturn(NID_GRP, 0 <= textIndex && textIndex < __length, -1, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
546
547         TextElement* pTextElement = null;
548         int currentLength = 0;
549         int elementTextOffset = 0;
550         int elementIndex = 0;
551         int textIndexFromElementOffset = 0;
552
553         pTextElement = GetElementAtTextIndex(textIndex, elementTextOffset, elementIndex, currentLength, textIndexFromElementOffset);
554         SysTryCatch(NID_GRP, pTextElement, , E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
555
556         return pTextElement->GetHeightF();
557
558 CATCH:
559         return -1;
560 }
561
562 result
563 TextComposite::Draw(_CanvasImpl& canvasImpl, FloatRectangle& displayRect, int startTextIndex, int textLength, const TextObjectAlignment alignment,
564                                          const TextObjectActionType action)
565 {
566         if (textLength == 0)
567         {
568                 return E_SUCCESS;
569         }
570
571         SysTryReturn(NID_GRP, 0 <= startTextIndex && startTextIndex < __length, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
572         SysTryReturn(NID_GRP, textLength <= __length, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
573
574         result r = E_SUCCESS;
575         IEnumerator* pEnum = null;
576         TextElement* pTextElement = null;
577         FloatDimension textSize;
578         FloatDimension spaceCharDim;
579         FloatDimension abbrevTextDim;
580         FloatRectangle adjustedRect = displayRect;
581         FloatRectangle blockRect;
582         int currentLength = 0;
583         int elementTextOffset = 0;
584         int elementIndex = 0;
585         int textIndexFromElementOffset = 0;
586         bool drawAbbrevText = false;
587
588         if (__ignoreRearBlank && __rearSpaceHideMode == TEXT_OBJECT_SPACE_HIDE_TYPE_ONE)
589         {
590                 pTextElement = GetElementAtTextIndex(startTextIndex + textLength - 1, elementTextOffset, elementIndex, currentLength, textIndexFromElementOffset);
591                 SysTryCatch(NID_GRP, pTextElement, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get element.");
592
593                 const TextSimple* pSimpleText = dynamic_cast <const TextSimple*>(pTextElement);
594                 if (pSimpleText != null)
595                 {
596                         int length = startTextIndex + textLength - elementTextOffset - 1;
597                         const wchar_t* pText = pSimpleText->GetText();
598                         SysTryReturn(NID_GRP, pText, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text.");
599
600                         SysTryReturn(NID_GRP, length >= 0 && length < pSimpleText->GetTextLength()
601                                 , E_OUT_OF_RANGE, E_OUT_OF_RANGE, "[E_OUT_OF_RANGE] text index(%d) must greater than 0 and must be less than total string length(%d)",length, pSimpleText->GetTextLength());
602
603                         if (pText[length] == (wchar_t)L' ')
604                         {
605                                 GetRegion(length + elementTextOffset, 1, spaceCharDim.width, spaceCharDim.height);
606                                 textLength--;
607                         }
608                 }
609         }
610
611         pTextElement = GetElementAtTextIndex(startTextIndex, elementTextOffset, elementIndex, currentLength, textIndexFromElementOffset);
612         SysTryCatch(NID_GRP, pTextElement, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get element.");
613
614         if (__ignoreFrontBlank && __frontSpaceHideMode == TEXT_OBJECT_SPACE_HIDE_TYPE_ONE && textLength > 0)
615         {
616                 const TextSimple* pSimpleText = dynamic_cast <const TextSimple*>(pTextElement);
617                 if (pSimpleText != null)
618                 {
619                         int index = startTextIndex - elementTextOffset;
620                         const wchar_t* pText = pSimpleText->GetText();
621                         SysTryReturn(NID_GRP, pText, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text.");
622
623                         SysTryReturn(NID_GRP, index >= 0 && index < pSimpleText->GetTextLength()
624                                 , E_OUT_OF_RANGE, E_OUT_OF_RANGE, "[E_OUT_OF_RANGE] text index(%d) must greater than 0 and must be less than total string length(%d)",index, pSimpleText->GetTextLength());
625
626                         if (pText[index] == (wchar_t)L' ')
627                         {
628                                 GetRegion(textIndexFromElementOffset, 1, spaceCharDim.width, spaceCharDim.height);
629                                 textLength--;
630                                 currentLength--;
631                                 startTextIndex++;
632                                 textIndexFromElementOffset++;
633                         }
634                 }
635         }
636
637         GetRegion(startTextIndex, textLength, textSize.width, textSize.height);
638         if (action == TEXT_OBJECT_ACTION_TYPE_ABBREV)
639         {
640                 TextElement* pLastTextElement = (textLength == 0) ? GetElementAtTextIndex(startTextIndex) : GetElementAtTextIndex(startTextIndex + textLength - 1);
641                 SysTryCatch(NID_GRP, pLastTextElement, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get element.");
642
643                 if (pLastTextElement->GetType() == TEXT_ELEMENT_TYPE_TEXT)
644                 {
645                         TextSimple* pSimpleText = dynamic_cast < TextSimple* >(pLastTextElement);
646                         SysTryCatch(NID_GRP, pSimpleText, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to cast text element.");
647
648                         SetAbbrevObjectFontInfo(pSimpleText);
649                         __pAbbrevTextElement->GetRegion(0, 1, abbrevTextDim.width, abbrevTextDim.height);
650                 }
651
652                 ForwardAnalyze(startTextIndex, __length - startTextIndex, adjustedRect.width - abbrevTextDim.width
653                         , TEXT_OBJECT_WRAP_TYPE_CHARACTER, textLength, textSize.width, textSize.height);
654
655                 textSize.width += abbrevTextDim.width;
656                 currentLength = Math::Min(currentLength, textLength);
657                 drawAbbrevText = true;
658         }
659
660         switch (alignment & TEXT_ALIGNMASK_HORIZ)
661         {
662         case TEXT_OBJECT_ALIGNMENT_CENTER:
663                 if (textSize.width < adjustedRect.width)
664                 {
665                         adjustedRect.x += (adjustedRect.width - textSize.width) / 2;
666                 }
667                 break;
668
669         case TEXT_OBJECT_ALIGNMENT_RIGHT:
670                 if (textSize.width < adjustedRect.width)
671                 {
672                         adjustedRect.x += adjustedRect.width - textSize.width;
673                 }
674                 break;
675
676         case TEXT_OBJECT_ALIGNMENT_LEFT:
677                 // fall through
678         default:
679                 break;
680         }
681
682         pEnum = __pTextElementList->GetEnumeratorN();
683         for (int i = 0; i <= elementIndex; i++)
684         {
685                 r = pEnum->MoveNext();
686                 SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Fail to move next element.", GetErrorMessage(r));
687         }
688
689         if (drawAbbrevText && IsRTL(startTextIndex, textLength))
690         {
691                 if (pTextElement->IsBackGroundDrawingModeEnable())
692                 {
693                         r = canvasImpl.FillRectangle(pTextElement->GetBackgroundColor(), FloatRectangle(adjustedRect.x, displayRect.y, abbrevTextDim.width, displayRect.height));
694                         SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
695                 }
696
697                 __pAbbrevTextElement->Draw(canvasImpl, adjustedRect, 0, 1, (TextObjectAlignment)(TEXT_OBJECT_ALIGNMENT_TOP | TEXT_OBJECT_ALIGNMENT_LEFT), action);
698
699                 adjustedRect.x += abbrevTextDim.width;
700                 adjustedRect.width -= abbrevTextDim.width;
701
702                 drawAbbrevText = false;
703         }
704
705         blockRect = FloatRectangle(adjustedRect.x, displayRect.y, adjustedRect.width, adjustedRect.height);
706         currentLength = Math::Min(textLength, currentLength);
707
708         while (textLength > 0)
709         {
710                 textLength -= currentLength;
711
712                 pTextElement->GetRegion(textIndexFromElementOffset, currentLength, textSize.width, textSize.height);
713
714                 switch (alignment & TEXT_ALIGNMASK_VERT)
715                 {
716                 case TEXT_OBJECT_ALIGNMENT_MIDDLE:
717                         adjustedRect.y = displayRect.y + (displayRect.height - textSize.height) / 2;
718                         break;
719
720                 case TEXT_OBJECT_ALIGNMENT_BOTTOM:
721                         adjustedRect.y = displayRect.y + (displayRect.height - textSize.height);
722                         break;
723
724                 case TEXT_OBJECT_ALIGNMENT_TOP:
725                         // fall through
726                 default:
727                         adjustedRect.y = displayRect.y;
728                         break;
729                 }
730
731                 if (pTextElement->IsBackGroundDrawingModeEnable())
732                 {
733                         DrawBackgroundBlock(canvasImpl, FloatRectangle(adjustedRect.x, displayRect.y, adjustedRect.width, adjustedRect.height), startTextIndex, currentLength, alignment, action);
734                 }
735
736                 bool isAlternateLookEnabled = (pTextElement->GetValue(SET_ALTERNATE_LOOK) > 0) ? true : false;
737                 if (__displayBlock && isAlternateLookEnabled == false)
738                 {
739                         DrawBlock(canvasImpl, blockRect, startTextIndex, currentLength, alignment, action);
740                 }
741
742                 pTextElement->Draw(canvasImpl, adjustedRect, textIndexFromElementOffset, currentLength, alignment, action);
743
744                 adjustedRect.x += textSize.width;
745                 adjustedRect.width -= textSize.width;
746
747                 if (!textLength || adjustedRect.width <= 0)
748                 {
749                         break;
750                 }
751
752                 startTextIndex += currentLength;
753
754                 if (pEnum->MoveNext() != E_SUCCESS)
755                 {
756                         break;
757                 }
758
759                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
760                 SysTryCatch(NID_GRP, pTextElement, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get element.");
761
762                 textIndexFromElementOffset = pTextElement->GetValue(SET_TEXT_OFFSET);
763                 currentLength = Math::Min(textLength, pTextElement->GetTextLength());
764
765                 if (currentLength == 0)
766                 {
767                         break;
768                 }
769         }
770
771         if (drawAbbrevText)
772         {
773                 if (pTextElement->IsBackGroundDrawingModeEnable())
774                 {
775                         r = canvasImpl.FillRectangle(pTextElement->GetBackgroundColor(), FloatRectangle(adjustedRect.x, displayRect.y, abbrevTextDim.width, displayRect.height));
776                         SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
777                 }
778
779                 __pAbbrevTextElement->Draw(canvasImpl, adjustedRect, 0, 1, (TextObjectAlignment)(TEXT_OBJECT_ALIGNMENT_TOP | TEXT_OBJECT_ALIGNMENT_LEFT), action);
780
781                 adjustedRect.x += abbrevTextDim.width;
782                 adjustedRect.width -= abbrevTextDim.width;
783         }
784
785         Release(pEnum);
786         return E_SUCCESS;
787
788 CATCH:
789         Release(pEnum);
790         return r;
791 }
792
793 result
794 TextComposite::DrawWithEliipsis(_CanvasImpl& canvasImpl, FloatRectangle& displayRect, int startTextIndex, int textLength, const TextObjectAlignment alignment,
795                                          const TextObjectActionType action)
796 {
797         if (textLength == 0)
798         {
799                 return E_SUCCESS;
800         }
801
802         SysTryReturn(NID_GRP, 0 <= startTextIndex && startTextIndex < __length, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
803         SysTryReturn(NID_GRP, textLength <= __length, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
804
805         result r = E_SUCCESS;
806         IEnumerator* pEnum = null;
807         TextElement* pTextElement = null;
808         TextElement* pLastDisplayTextElement = null;
809         FloatDimension textSize;
810         FloatDimension spaceCharDim;
811         FloatDimension abbrevTextDim;
812         FloatRectangle adjustedRect = displayRect;
813         FloatRectangle blockRect;
814         int currentLength = 0;
815         int elementTextOffset = 0;
816         int elementIndex = 0;
817         int textIndexFromElementOffset = 0;
818         int LTRTextLength = 0;
819         int RTLTextLength = 0;
820         bool drawAbbrevText = false;
821
822         if (__ignoreRearBlank && __rearSpaceHideMode == TEXT_OBJECT_SPACE_HIDE_TYPE_ONE)
823         {
824                 pTextElement = GetElementAtTextIndex(startTextIndex + textLength - 1, elementTextOffset, elementIndex, currentLength, textIndexFromElementOffset);
825                 SysTryCatch(NID_GRP, pTextElement, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get element.");
826
827                 const TextSimple* pSimpleText = dynamic_cast <const TextSimple*>(pTextElement);
828                 if (pSimpleText != null)
829                 {
830                         int length = startTextIndex + textLength - elementTextOffset - 1;
831                         const wchar_t* pText = pSimpleText->GetText();
832                         SysTryReturn(NID_GRP, pText, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text.");
833
834                         SysTryReturn(NID_GRP, length >= 0 && length < pSimpleText->GetTextLength()
835                                 , E_OUT_OF_RANGE, E_OUT_OF_RANGE, "[E_OUT_OF_RANGE] text index(%d) must greater than 0 and must be less than total string length(%d)",length, pSimpleText->GetTextLength());
836
837                         if (pText[length] == (wchar_t)L' ')
838                         {
839                                 GetRegion(length + elementTextOffset, 1, spaceCharDim.width, spaceCharDim.height);
840                                 textLength--;
841                         }
842                 }
843         }
844
845         pTextElement = GetElementAtTextIndex(startTextIndex, elementTextOffset, elementIndex, currentLength, textIndexFromElementOffset);
846         SysTryCatch(NID_GRP, pTextElement, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get element.");
847
848         if (__ignoreFrontBlank && __frontSpaceHideMode == TEXT_OBJECT_SPACE_HIDE_TYPE_ONE && textLength > 0)
849         {
850                 const TextSimple* pSimpleText = dynamic_cast <const TextSimple*>(pTextElement);
851                 if (pSimpleText != null)
852                 {
853                         int index = startTextIndex - elementTextOffset;
854                         const wchar_t* pText = pSimpleText->GetText();
855                         SysTryReturn(NID_GRP, pText, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text.");
856
857                         SysTryReturn(NID_GRP, index >= 0 && index < pSimpleText->GetTextLength()
858                                 , E_OUT_OF_RANGE, E_OUT_OF_RANGE, "[E_OUT_OF_RANGE] text index(%d) must greater than 0 and must be less than total string length(%d)",index, pSimpleText->GetTextLength());
859
860                         if (pText[index] == (wchar_t)L' ')
861                         {
862                                 GetRegion(textIndexFromElementOffset, 1, spaceCharDim.width, spaceCharDim.height);
863                                 textLength--;
864                                 currentLength--;
865                                 startTextIndex++;
866                                 textIndexFromElementOffset++;
867                         }
868                 }
869         }
870
871         GetRegion(startTextIndex, textLength, textSize.width, textSize.height);
872         if (action == TEXT_OBJECT_ACTION_TYPE_ABBREV)
873         {
874                 pLastDisplayTextElement = (textLength == 0) ? GetElementAtTextIndex(startTextIndex) : GetElementAtTextIndex(startTextIndex + textLength - 1);
875                 SysTryCatch(NID_GRP, pLastDisplayTextElement, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get element.");
876
877                 if (pLastDisplayTextElement->GetType() == TEXT_ELEMENT_TYPE_TEXT)
878                 {
879                         TextSimple* pSimpleText = dynamic_cast < TextSimple* >(pLastDisplayTextElement);
880                         SysTryCatch(NID_GRP, pSimpleText, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to cast text element.");
881
882                         SetAbbrevObjectFontInfo(pSimpleText);
883                         __pAbbrevTextElement->GetRegion(0, 1, abbrevTextDim.width, abbrevTextDim.height);
884                 }
885
886                 ForwardAnalyze(startTextIndex, __length - startTextIndex, adjustedRect.width - abbrevTextDim.width
887                         , TEXT_OBJECT_WRAP_TYPE_CHARACTER, textLength, textSize.width, textSize.height);
888
889                 textSize.width += abbrevTextDim.width;
890                 currentLength = Math::Min(currentLength, textLength);
891                 drawAbbrevText = true;
892         }
893
894         switch (alignment & TEXT_ALIGNMASK_HORIZ)
895         {
896         case TEXT_OBJECT_ALIGNMENT_CENTER:
897                 if (textSize.width < adjustedRect.width)
898                 {
899                         adjustedRect.x += (adjustedRect.width - textSize.width) / 2;
900                 }
901                 break;
902
903         case TEXT_OBJECT_ALIGNMENT_RIGHT:
904                 if (textSize.width < adjustedRect.width)
905                 {
906                         adjustedRect.x += adjustedRect.width - textSize.width;
907                 }
908                 break;
909
910         case TEXT_OBJECT_ALIGNMENT_LEFT:
911                 // fall through
912         default:
913                 break;
914         }
915
916         pEnum = __pTextElementList->GetEnumeratorN();
917         for (int i = 0; i <= elementIndex; i++)
918         {
919                 r = pEnum->MoveNext();
920                 SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Fail to move next element.", GetErrorMessage(r));
921         }
922
923         blockRect = FloatRectangle(adjustedRect.x, displayRect.y, adjustedRect.width, adjustedRect.height);
924         currentLength = Math::Min(textLength, currentLength);
925
926         if (drawAbbrevText)
927         {
928                 if (IsRTLCharacter(startTextIndex + currentLength))
929                 {
930                         LTRTextLength = SearchLTRTextIndex(startTextIndex, startTextIndex + currentLength) - startTextIndex;
931                         RTLTextLength = textLength - LTRTextLength;
932
933                         if (LTRTextLength <= 0)
934                         {
935                                 if (pLastDisplayTextElement->IsBackGroundDrawingModeEnable())
936                                 {
937                                         r = canvasImpl.FillRectangle(pLastDisplayTextElement->GetBackgroundColor(), FloatRectangle(adjustedRect.x, displayRect.y, abbrevTextDim.width, displayRect.height));
938                                         SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
939                                 }
940
941                                 __pAbbrevTextElement->Draw(canvasImpl, adjustedRect, 0, 1, (TextObjectAlignment)(TEXT_OBJECT_ALIGNMENT_TOP | TEXT_OBJECT_ALIGNMENT_LEFT), action);
942
943                                 adjustedRect.x += abbrevTextDim.width;
944                                 adjustedRect.width -= abbrevTextDim.width;
945
946                                 drawAbbrevText = false;
947                         }
948                 }
949                 else
950                 {
951                         LTRTextLength = textLength;
952                         RTLTextLength = 0;
953                 }
954         }
955
956         if (LTRTextLength > 0)
957         {
958                 currentLength = Math::Min(LTRTextLength, currentLength);
959
960                 while (LTRTextLength > 0)
961                 {
962                         LTRTextLength -= currentLength;
963
964                         pTextElement->GetRegion(textIndexFromElementOffset, currentLength, textSize.width, textSize.height);
965
966                         switch (alignment & TEXT_ALIGNMASK_VERT)
967                         {
968                         case TEXT_OBJECT_ALIGNMENT_MIDDLE:
969                                 adjustedRect.y = displayRect.y + (displayRect.height - textSize.height) / 2;
970                                 break;
971
972                         case TEXT_OBJECT_ALIGNMENT_BOTTOM:
973                                 adjustedRect.y = displayRect.y + (displayRect.height - textSize.height);
974                                 break;
975
976                         case TEXT_OBJECT_ALIGNMENT_TOP:
977                                 // fall through
978                         default:
979                                 adjustedRect.y = displayRect.y;
980                                 break;
981                         }
982
983                         if (pTextElement->IsBackGroundDrawingModeEnable())
984                         {
985                                 DrawBackgroundBlock(canvasImpl, FloatRectangle(adjustedRect.x, displayRect.y, adjustedRect.width, adjustedRect.height), startTextIndex, currentLength, alignment, action);
986                         }
987
988                         bool isAlternateLookEnabled = (pTextElement->GetValue(SET_ALTERNATE_LOOK) > 0) ? true : false;
989                         if (__displayBlock && isAlternateLookEnabled == false)
990                         {
991                                 DrawBlock(canvasImpl, blockRect, startTextIndex, currentLength, alignment, action);
992                         }
993
994                         pTextElement->Draw(canvasImpl, adjustedRect, textIndexFromElementOffset, currentLength, alignment, action);
995
996                         adjustedRect.x += textSize.width;
997                         adjustedRect.width -= textSize.width;
998
999                         if (!LTRTextLength || adjustedRect.width <= 0)
1000                         {
1001                                 break;
1002                         }
1003
1004                         startTextIndex += currentLength;
1005
1006                         if (pEnum->MoveNext() != E_SUCCESS)
1007                         {
1008                                 break;
1009                         }
1010
1011                         pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
1012                         SysTryCatch(NID_GRP, pTextElement, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get element.");
1013
1014                         textIndexFromElementOffset = pTextElement->GetValue(SET_TEXT_OFFSET);
1015                         currentLength = Math::Min(LTRTextLength, pTextElement->GetTextLength());
1016
1017                         if (currentLength == 0)
1018                         {
1019                                 break;
1020                         }
1021                 }
1022
1023                 textIndexFromElementOffset += LTRTextLength;
1024                 textLength -= LTRTextLength;
1025         }
1026
1027         if (drawAbbrevText && (RTLTextLength > 0))
1028         {
1029                 if (pTextElement->IsBackGroundDrawingModeEnable())
1030                 {
1031                         r = canvasImpl.FillRectangle(pTextElement->GetBackgroundColor(), FloatRectangle(adjustedRect.x, displayRect.y, abbrevTextDim.width, displayRect.height));
1032                         SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
1033                 }
1034
1035                 __pAbbrevTextElement->Draw(canvasImpl, adjustedRect, 0, 1, (TextObjectAlignment)(TEXT_OBJECT_ALIGNMENT_TOP | TEXT_OBJECT_ALIGNMENT_LEFT), action);
1036
1037                 adjustedRect.x += abbrevTextDim.width;
1038                 adjustedRect.width -= abbrevTextDim.width;
1039
1040                 drawAbbrevText = false;
1041         }
1042
1043         if (RTLTextLength > 0)
1044         {
1045                 currentLength = Math::Min(RTLTextLength, currentLength);
1046
1047                 while (RTLTextLength > 0)
1048                 {
1049                         RTLTextLength -= currentLength;
1050
1051                         pTextElement->GetRegion(textIndexFromElementOffset, currentLength, textSize.width, textSize.height);
1052
1053                         switch (alignment & TEXT_ALIGNMASK_VERT)
1054                         {
1055                         case TEXT_OBJECT_ALIGNMENT_MIDDLE:
1056                                 adjustedRect.y = displayRect.y + (displayRect.height - textSize.height) / 2;
1057                                 break;
1058
1059                         case TEXT_OBJECT_ALIGNMENT_BOTTOM:
1060                                 adjustedRect.y = displayRect.y + (displayRect.height - textSize.height);
1061                                 break;
1062
1063                         case TEXT_OBJECT_ALIGNMENT_TOP:
1064                                 // fall through
1065                         default:
1066                                 adjustedRect.y = displayRect.y;
1067                                 break;
1068                         }
1069
1070                         if (pTextElement->IsBackGroundDrawingModeEnable())
1071                         {
1072                                 DrawBackgroundBlock(canvasImpl, FloatRectangle(adjustedRect.x, displayRect.y, adjustedRect.width, adjustedRect.height), startTextIndex, currentLength, alignment, action);
1073                         }
1074
1075                         bool isAlternateLookEnabled = (pTextElement->GetValue(SET_ALTERNATE_LOOK) > 0) ? true : false;
1076                         if (__displayBlock && isAlternateLookEnabled == false)
1077                         {
1078                                 DrawBlock(canvasImpl, blockRect, startTextIndex, currentLength, alignment, action);
1079                         }
1080
1081                         pTextElement->Draw(canvasImpl, adjustedRect, textIndexFromElementOffset, currentLength, alignment, action);
1082
1083                         adjustedRect.x += textSize.width;
1084                         adjustedRect.width -= textSize.width;
1085
1086                         if (!RTLTextLength || adjustedRect.width <= 0)
1087                         {
1088                                 break;
1089                         }
1090
1091                         startTextIndex += currentLength;
1092
1093                         if (pEnum->MoveNext() != E_SUCCESS)
1094                         {
1095                                 break;
1096                         }
1097
1098                         pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
1099                         SysTryCatch(NID_GRP, pTextElement, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get element.");
1100
1101                         textIndexFromElementOffset = pTextElement->GetValue(SET_TEXT_OFFSET);
1102                         currentLength = Math::Min(RTLTextLength, pTextElement->GetTextLength());
1103
1104                         if (currentLength == 0)
1105                         {
1106                                 break;
1107                         }
1108                 }
1109
1110                 textLength -= RTLTextLength;
1111         }
1112
1113         if (drawAbbrevText)
1114         {
1115                 if (pTextElement->IsBackGroundDrawingModeEnable())
1116                 {
1117                         r = canvasImpl.FillRectangle(pTextElement->GetBackgroundColor(), FloatRectangle(adjustedRect.x, displayRect.y, abbrevTextDim.width, displayRect.height));
1118                         SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
1119                 }
1120
1121                 __pAbbrevTextElement->Draw(canvasImpl, adjustedRect, 0, 1, (TextObjectAlignment)(TEXT_OBJECT_ALIGNMENT_TOP | TEXT_OBJECT_ALIGNMENT_LEFT), action);
1122
1123                 adjustedRect.x += abbrevTextDim.width;
1124                 adjustedRect.width -= abbrevTextDim.width;
1125         }
1126
1127         Release(pEnum);
1128         return E_SUCCESS;
1129
1130 CATCH:
1131         Release(pEnum);
1132         return r;
1133 }
1134
1135 result
1136 TextComposite::DrawWithBaseline(_CanvasImpl& canvasImpl, FloatRectangle& displayRect, int startTextIndex, int textLength, const TextObjectAlignment alignment,
1137                                          const TextObjectActionType action, int baseline)
1138 {
1139         if (textLength == 0)
1140         {
1141                 return E_SUCCESS;
1142         }
1143
1144         SysTryReturn(NID_GRP, 0 <= startTextIndex && startTextIndex < __length, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
1145         SysTryReturn(NID_GRP, textLength <= __length, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
1146
1147         result r = E_SUCCESS;
1148         IEnumerator* pEnum = null;
1149         TextElement* pTextElement = null;
1150
1151         FloatDimension textSize;
1152         FloatDimension spaceCharDim;
1153         FloatDimension abbrevTextDim;
1154         FloatRectangle adjustedRect = displayRect;
1155         FloatRectangle blockRect;
1156         int currentLength = 0;
1157         int elementTextOffset = 0;
1158         int elementIndex = 0;
1159         int textIndexFromElementOffset = 0;
1160         bool drawAbbrevText = false;
1161
1162         if (__ignoreRearBlank && __rearSpaceHideMode == TEXT_OBJECT_SPACE_HIDE_TYPE_ONE)
1163         {
1164                 pTextElement = GetElementAtTextIndex(startTextIndex + textLength - 1, elementTextOffset, elementIndex, currentLength, textIndexFromElementOffset);
1165                 SysTryCatch(NID_GRP, pTextElement, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get element.");
1166                 const TextSimple* pSimpleText = dynamic_cast <const TextSimple*>(pTextElement);
1167                 if (pSimpleText != null)
1168                 {
1169                         int length = startTextIndex + textLength - elementTextOffset - 1;
1170                         const wchar_t* pText = pSimpleText->GetText();
1171                         SysTryReturn(NID_GRP, pText, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text.");
1172
1173                         SysTryReturn(NID_GRP, length >= 0 && length < pSimpleText->GetTextLength()
1174                                 , E_OUT_OF_RANGE, E_OUT_OF_RANGE, "[E_OUT_OF_RANGE] text index(%d) must greater than 0 and must be less than total string length(%d)",length, pSimpleText->GetTextLength());
1175
1176                         if (pText[length] == (wchar_t)L' ')
1177                         {
1178                                 GetRegion(length + elementTextOffset, 1, spaceCharDim.width, spaceCharDim.height);
1179                                 textLength--;
1180                         }
1181                 }
1182         }
1183
1184         pTextElement = GetElementAtTextIndex(startTextIndex, elementTextOffset, elementIndex, currentLength, textIndexFromElementOffset);
1185         SysTryCatch(NID_GRP, pTextElement, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get element.");
1186
1187         if (__ignoreFrontBlank && __frontSpaceHideMode == TEXT_OBJECT_SPACE_HIDE_TYPE_ONE && textLength > 0)
1188         {
1189                 const TextSimple* pSimpleText = dynamic_cast <const TextSimple*>(pTextElement);
1190                 if (pSimpleText != null)
1191                 {
1192                         int index = startTextIndex - elementTextOffset;
1193                         const wchar_t* pText = pSimpleText->GetText();
1194                         SysTryReturn(NID_GRP, pText, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text.");
1195
1196                         SysTryReturn(NID_GRP, index >= 0 && index < pSimpleText->GetTextLength()
1197                                 , E_OUT_OF_RANGE, E_OUT_OF_RANGE, "[E_OUT_OF_RANGE] text index(%d) must greater than 0 and must be less than total string length(%d)",index, pSimpleText->GetTextLength());
1198
1199                         if (pText[index] == (wchar_t)L' ')
1200                         {
1201                                 GetRegion(textIndexFromElementOffset, 1, spaceCharDim.width, spaceCharDim.height);
1202                                 textLength--;
1203                                 startTextIndex++;
1204                                 textIndexFromElementOffset++;
1205                         }
1206                 }
1207         }
1208
1209         GetRegion(startTextIndex, textLength, textSize.width, textSize.height);
1210         if (action == TEXT_OBJECT_ACTION_TYPE_ABBREV)
1211         {
1212                 TextElement* pLastTextElement = GetElementAtTextIndex(startTextIndex + textLength - 1);
1213                 SysTryCatch(NID_GRP, pLastTextElement, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get element.");
1214
1215                 if (pLastTextElement->GetType() == TEXT_ELEMENT_TYPE_TEXT)
1216                 {
1217                         TextSimple* pSimpleText = dynamic_cast < TextSimple* >(pLastTextElement);
1218                         SysTryCatch(NID_GRP, pSimpleText, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to cast text element.");
1219
1220                         SetAbbrevObjectFontInfo(pSimpleText);
1221                         __pAbbrevTextElement->GetRegion(0, 1, abbrevTextDim.width, abbrevTextDim.height);
1222                 }
1223
1224                 ForwardAnalyze(startTextIndex, __length - startTextIndex, adjustedRect.width - abbrevTextDim.width
1225                         , TEXT_OBJECT_WRAP_TYPE_CHARACTER, textLength, textSize.width, textSize.height);
1226
1227                 textSize.width += abbrevTextDim.width;
1228                 currentLength = textLength;
1229                 drawAbbrevText = true;
1230         }
1231
1232         switch (alignment & TEXT_ALIGNMASK_HORIZ)
1233         {
1234         case TEXT_OBJECT_ALIGNMENT_CENTER:
1235                 if (textSize.width < adjustedRect.width)
1236                 {
1237                         adjustedRect.x += (adjustedRect.width - textSize.width) / 2;
1238                 }
1239                 break;
1240
1241         case TEXT_OBJECT_ALIGNMENT_RIGHT:
1242                 if (textSize.width < adjustedRect.width)
1243                 {
1244                         adjustedRect.x += adjustedRect.width - textSize.width;
1245                 }
1246                 break;
1247
1248         case TEXT_OBJECT_ALIGNMENT_LEFT:
1249                 // fall through
1250         default:
1251                 break;
1252         }
1253
1254         pEnum = __pTextElementList->GetEnumeratorN();
1255         for (int i = 0; i <= elementIndex; i++)
1256         {
1257                 r = pEnum->MoveNext();
1258                 SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Fail to move next element.", GetErrorMessage(r));
1259         }
1260
1261         blockRect = FloatRectangle(adjustedRect.x, displayRect.y, adjustedRect.width, adjustedRect.height);
1262         adjustedRect.y = displayRect.y + displayRect.height - baseline;
1263         canvasImpl.SetTextOrigin(TEXT_ORIGIN_BASELINE);
1264
1265         currentLength = Math::Min(textLength, currentLength);
1266
1267         while (textLength > 0)
1268         {
1269                 textLength -= currentLength;
1270
1271                 pTextElement->GetRegion(textIndexFromElementOffset, currentLength, textSize.width, textSize.height);
1272
1273                 if (pTextElement->IsBackGroundDrawingModeEnable())
1274                 {
1275                         DrawBackgroundBlock(canvasImpl, FloatRectangle(adjustedRect.x, displayRect.y, adjustedRect.width, adjustedRect.height), startTextIndex, currentLength, alignment, action);
1276                 }
1277
1278                 bool isAlternateLookEnabled = (pTextElement->GetValue(SET_ALTERNATE_LOOK) > 0) ? true : false;
1279                 if (__displayBlock && isAlternateLookEnabled == false)
1280                 {
1281                         DrawBlock(canvasImpl, blockRect, startTextIndex, currentLength, alignment, action);
1282                 }
1283
1284                 FloatRectangle imageRect = adjustedRect;
1285                 imageRect.y -= textSize.height;
1286                 TextElementType objectType = pTextElement->GetType();
1287
1288                 if (objectType == TEXT_ELEMENT_TYPE_CUTLINK || objectType == TEXT_ELEMENT_TYPE_TEXT)
1289                 {
1290                         pTextElement->Draw(canvasImpl, adjustedRect, textIndexFromElementOffset, currentLength, alignment, action);
1291                 }
1292                 else
1293                 {
1294                         pTextElement->Draw(canvasImpl, imageRect, textIndexFromElementOffset, currentLength, alignment, action);
1295                 }
1296
1297                 adjustedRect.x += textSize.width;
1298                 adjustedRect.width -= textSize.width;
1299
1300                 if (!textLength || adjustedRect.width <= 0)
1301                 {
1302                         break;
1303                 }
1304
1305                 startTextIndex += currentLength;
1306
1307                 if (pEnum->MoveNext() != E_SUCCESS)
1308                 {
1309                         break;
1310                 }
1311
1312                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
1313                 SysTryCatch(NID_GRP, pTextElement, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get element.");
1314
1315                 textIndexFromElementOffset = pTextElement->GetValue(SET_TEXT_OFFSET);
1316                 currentLength = Math::Min(textLength, pTextElement->GetTextLength());
1317
1318                 if (currentLength == 0)
1319                 {
1320                         break;
1321                 }
1322         }
1323
1324         if (drawAbbrevText)
1325         {
1326                 if (pTextElement->IsBackGroundDrawingModeEnable())
1327                 {
1328                         r = canvasImpl.FillRectangle(pTextElement->GetBackgroundColor(), FloatRectangle(adjustedRect.x, displayRect.y, abbrevTextDim.width, displayRect.height));
1329                         SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
1330                 }
1331
1332                 __pAbbrevTextElement->Draw(canvasImpl, adjustedRect, 0, 1, (TextObjectAlignment)(TEXT_OBJECT_ALIGNMENT_TOP | TEXT_OBJECT_ALIGNMENT_LEFT), action);
1333
1334                 adjustedRect.x += abbrevTextDim.width;
1335                 adjustedRect.width -= abbrevTextDim.width;
1336         }
1337
1338         canvasImpl.SetTextOrigin(TEXT_ORIGIN_LEFT_TOP);
1339
1340         Release(pEnum);
1341         return E_SUCCESS;
1342
1343 CATCH:
1344         canvasImpl.SetTextOrigin(TEXT_ORIGIN_LEFT_TOP);
1345
1346         Release(pEnum);
1347         return r;
1348 }
1349
1350 result
1351 TextComposite::DrawWithBaselineWithEllipsis(_CanvasImpl& canvasImpl, FloatRectangle& displayRect, int startTextIndex, int textLength, const TextObjectAlignment alignment,
1352                                          const TextObjectActionType action, int baseline)
1353 {
1354         if (textLength == 0)
1355         {
1356                 return E_SUCCESS;
1357         }
1358
1359         SysTryReturn(NID_GRP, 0 <= startTextIndex && startTextIndex < __length, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
1360         SysTryReturn(NID_GRP, textLength <= __length, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
1361
1362         result r = E_SUCCESS;
1363         IEnumerator* pEnum = null;
1364         TextElement* pTextElement = null;
1365         TextElement* pLastDisplayTextElement = null;
1366         FloatDimension textSize;
1367         FloatDimension spaceCharDim;
1368         FloatDimension abbrevTextDim;
1369         FloatRectangle adjustedRect = displayRect;
1370         FloatRectangle blockRect;
1371         int currentLength = 0;
1372         int elementTextOffset = 0;
1373         int elementIndex = 0;
1374         int textIndexFromElementOffset = 0;
1375         int LTRTextLength = 0;
1376         int RTLTextLength = 0;
1377         bool drawAbbrevText = false;
1378
1379         if (__ignoreRearBlank && __rearSpaceHideMode == TEXT_OBJECT_SPACE_HIDE_TYPE_ONE)
1380         {
1381                 pLastDisplayTextElement = GetElementAtTextIndex(startTextIndex + textLength - 1, elementTextOffset, elementIndex, currentLength, textIndexFromElementOffset);
1382                 SysTryCatch(NID_GRP, pLastDisplayTextElement, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get element.");
1383                 const TextSimple* pSimpleText = dynamic_cast <const TextSimple*>(pLastDisplayTextElement);
1384                 if (pSimpleText != null)
1385                 {
1386                         int length = startTextIndex + textLength - elementTextOffset - 1;
1387                         const wchar_t* pText = pSimpleText->GetText();
1388                         SysTryReturn(NID_GRP, pText, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text.");
1389
1390                         SysTryReturn(NID_GRP, length >= 0 && length < pSimpleText->GetTextLength()
1391                                 , E_OUT_OF_RANGE, E_OUT_OF_RANGE, "[E_OUT_OF_RANGE] text index(%d) must greater than 0 and must be less than total string length(%d)",length, pSimpleText->GetTextLength());
1392
1393                         if (pText[length] == (wchar_t)L' ')
1394                         {
1395                                 GetRegion(length + elementTextOffset, 1, spaceCharDim.width, spaceCharDim.height);
1396                                 textLength--;
1397                         }
1398                 }
1399         }
1400
1401         pTextElement = GetElementAtTextIndex(startTextIndex, elementTextOffset, elementIndex, currentLength, textIndexFromElementOffset);
1402         SysTryCatch(NID_GRP, pTextElement, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get element.");
1403
1404         if (__ignoreFrontBlank && __frontSpaceHideMode == TEXT_OBJECT_SPACE_HIDE_TYPE_ONE && textLength > 0)
1405         {
1406                 const TextSimple* pSimpleText = dynamic_cast <const TextSimple*>(pTextElement);
1407                 if (pSimpleText != null)
1408                 {
1409                         int index = startTextIndex - elementTextOffset;
1410                         const wchar_t* pText = pSimpleText->GetText();
1411                         SysTryReturn(NID_GRP, pText, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text.");
1412
1413                         SysTryReturn(NID_GRP, index >= 0 && index < pSimpleText->GetTextLength()
1414                                 , E_OUT_OF_RANGE, E_OUT_OF_RANGE, "[E_OUT_OF_RANGE] text index(%d) must greater than 0 and must be less than total string length(%d)",index, pSimpleText->GetTextLength());
1415
1416                         if (pText[index] == (wchar_t)L' ')
1417                         {
1418                                 GetRegion(textIndexFromElementOffset, 1, spaceCharDim.width, spaceCharDim.height);
1419                                 textLength--;
1420                                 startTextIndex++;
1421                                 textIndexFromElementOffset++;
1422                         }
1423                 }
1424         }
1425
1426         GetRegion(startTextIndex, textLength, textSize.width, textSize.height);
1427         if (action == TEXT_OBJECT_ACTION_TYPE_ABBREV)
1428         {
1429                 TextElement* pLastTextElement = GetElementAtTextIndex(startTextIndex + textLength - 1);
1430                 SysTryCatch(NID_GRP, pLastTextElement, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get element.");
1431
1432                 if (pLastTextElement->GetType() == TEXT_ELEMENT_TYPE_TEXT)
1433                 {
1434                         TextSimple* pSimpleText = dynamic_cast < TextSimple* >(pLastTextElement);
1435                         SysTryCatch(NID_GRP, pSimpleText, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to cast text element.");
1436
1437                         SetAbbrevObjectFontInfo(pSimpleText);
1438                         __pAbbrevTextElement->GetRegion(0, 1, abbrevTextDim.width, abbrevTextDim.height);
1439                 }
1440
1441                 ForwardAnalyze(startTextIndex, __length - startTextIndex, adjustedRect.width - abbrevTextDim.width
1442                         , TEXT_OBJECT_WRAP_TYPE_CHARACTER, textLength, textSize.width, textSize.height);
1443
1444                 textSize.width += abbrevTextDim.width;
1445                 currentLength = textLength;
1446                 drawAbbrevText = true;
1447         }
1448
1449         switch (alignment & TEXT_ALIGNMASK_HORIZ)
1450         {
1451         case TEXT_OBJECT_ALIGNMENT_CENTER:
1452                 if (textSize.width < adjustedRect.width)
1453                 {
1454                         adjustedRect.x += (adjustedRect.width - textSize.width) / 2;
1455                 }
1456                 break;
1457
1458         case TEXT_OBJECT_ALIGNMENT_RIGHT:
1459                 if (textSize.width < adjustedRect.width)
1460                 {
1461                         adjustedRect.x += adjustedRect.width - textSize.width;
1462                 }
1463                 break;
1464
1465         case TEXT_OBJECT_ALIGNMENT_LEFT:
1466                 // fall through
1467         default:
1468                 break;
1469         }
1470
1471         pEnum = __pTextElementList->GetEnumeratorN();
1472         for (int i = 0; i <= elementIndex; i++)
1473         {
1474                 r = pEnum->MoveNext();
1475                 SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Fail to move next element.", GetErrorMessage(r));
1476         }
1477
1478         blockRect = FloatRectangle(adjustedRect.x, displayRect.y, adjustedRect.width, adjustedRect.height);
1479         adjustedRect.y = displayRect.y + displayRect.height - baseline;
1480         canvasImpl.SetTextOrigin(TEXT_ORIGIN_BASELINE);
1481
1482         if (drawAbbrevText)
1483         {
1484                 if (IsRTLCharacter(startTextIndex + currentLength))
1485                 {
1486                         LTRTextLength = SearchLTRTextIndex(startTextIndex, startTextIndex + currentLength) - startTextIndex;
1487                         RTLTextLength = textLength - LTRTextLength;
1488
1489                         if (LTRTextLength <= 0)
1490                         {
1491                                 if (pLastDisplayTextElement && pLastDisplayTextElement->IsBackGroundDrawingModeEnable())
1492                                 {
1493                                         r = canvasImpl.FillRectangle(pLastDisplayTextElement->GetBackgroundColor(), FloatRectangle(adjustedRect.x, displayRect.y, abbrevTextDim.width, displayRect.height));
1494                                         SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
1495                                 }
1496
1497                                 __pAbbrevTextElement->Draw(canvasImpl, adjustedRect, 0, 1, (TextObjectAlignment)(TEXT_OBJECT_ALIGNMENT_TOP | TEXT_OBJECT_ALIGNMENT_LEFT), action);
1498
1499                                 adjustedRect.x += abbrevTextDim.width;
1500                                 adjustedRect.width -= abbrevTextDim.width;
1501
1502                                 drawAbbrevText = false;
1503                         }
1504                 }
1505                 else
1506                 {
1507                         LTRTextLength = textLength;
1508                         RTLTextLength = 0;
1509                 }
1510         }
1511
1512         if (LTRTextLength > 0)
1513         {
1514                 currentLength = Math::Min(LTRTextLength, currentLength);
1515
1516                 while (LTRTextLength > 0)
1517                 {
1518                         LTRTextLength -= currentLength;
1519
1520                         pTextElement->GetRegion(textIndexFromElementOffset, currentLength, textSize.width, textSize.height);
1521
1522                         if (pTextElement->IsBackGroundDrawingModeEnable())
1523                         {
1524                                 DrawBackgroundBlock(canvasImpl, FloatRectangle(adjustedRect.x, displayRect.y, adjustedRect.width, adjustedRect.height), startTextIndex, currentLength, alignment, action);
1525                         }
1526
1527                         bool isAlternateLookEnabled = (pTextElement->GetValue(SET_ALTERNATE_LOOK) > 0) ? true : false;
1528                         if (__displayBlock && isAlternateLookEnabled == false)
1529                         {
1530                                 DrawBlock(canvasImpl, blockRect, startTextIndex, currentLength, alignment, action);
1531                         }
1532
1533                         FloatRectangle imageRect = adjustedRect;
1534                         imageRect.y -= textSize.height;
1535                         TextElementType objectType = pTextElement->GetType();
1536
1537                         if (objectType == TEXT_ELEMENT_TYPE_CUTLINK || objectType == TEXT_ELEMENT_TYPE_TEXT)
1538                         {
1539                                 pTextElement->Draw(canvasImpl, adjustedRect, textIndexFromElementOffset, currentLength, alignment, action);
1540                         }
1541                         else
1542                         {
1543                                 pTextElement->Draw(canvasImpl, imageRect, textIndexFromElementOffset, currentLength, alignment, action);
1544                         }
1545
1546                         adjustedRect.x += textSize.width;
1547                         adjustedRect.width -= textSize.width;
1548
1549                         if (!LTRTextLength || adjustedRect.width <= 0)
1550                         {
1551                                 break;
1552                         }
1553
1554                         startTextIndex += currentLength;
1555
1556                         if (pEnum->MoveNext() != E_SUCCESS)
1557                         {
1558                                 break;
1559                         }
1560
1561                         pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
1562                         SysTryCatch(NID_GRP, pTextElement, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get element.");
1563
1564                         textIndexFromElementOffset = pTextElement->GetValue(SET_TEXT_OFFSET);
1565                         currentLength = Math::Min(LTRTextLength, pTextElement->GetTextLength());
1566
1567                         if (currentLength == 0)
1568                         {
1569                                 break;
1570                         }
1571                 }
1572
1573                 textIndexFromElementOffset += LTRTextLength;
1574                 textLength -= LTRTextLength;
1575         }
1576
1577         if (drawAbbrevText && (RTLTextLength > 0))
1578         {
1579                 if (pTextElement->IsBackGroundDrawingModeEnable())
1580                 {
1581                         r = canvasImpl.FillRectangle(pTextElement->GetBackgroundColor(), FloatRectangle(adjustedRect.x, displayRect.y, abbrevTextDim.width, displayRect.height));
1582                         SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
1583                 }
1584
1585                 __pAbbrevTextElement->Draw(canvasImpl, adjustedRect, 0, 1, (TextObjectAlignment)(TEXT_OBJECT_ALIGNMENT_TOP | TEXT_OBJECT_ALIGNMENT_LEFT), action);
1586
1587                 adjustedRect.x += abbrevTextDim.width;
1588                 adjustedRect.width -= abbrevTextDim.width;
1589
1590                 drawAbbrevText = false;
1591         }
1592
1593         if (RTLTextLength > 0)
1594         {
1595                 currentLength = Math::Min(RTLTextLength, currentLength);
1596
1597                 while (RTLTextLength > 0)
1598                 {
1599                         RTLTextLength -= currentLength;
1600
1601                         pTextElement->GetRegion(textIndexFromElementOffset, currentLength, textSize.width, textSize.height);
1602
1603                         if (pTextElement->IsBackGroundDrawingModeEnable())
1604                         {
1605                                 DrawBackgroundBlock(canvasImpl, FloatRectangle(adjustedRect.x, displayRect.y, adjustedRect.width, adjustedRect.height), startTextIndex, currentLength, alignment, action);
1606                         }
1607
1608                         bool isAlternateLookEnabled = (pTextElement->GetValue(SET_ALTERNATE_LOOK) > 0) ? true : false;
1609                         if (__displayBlock && isAlternateLookEnabled == false)
1610                         {
1611                                 DrawBlock(canvasImpl, blockRect, startTextIndex, currentLength, alignment, action);
1612                         }
1613
1614                         FloatRectangle imageRect = adjustedRect;
1615                         imageRect.y -= textSize.height;
1616                         TextElementType objectType = pTextElement->GetType();
1617
1618                         if (objectType == TEXT_ELEMENT_TYPE_CUTLINK || objectType == TEXT_ELEMENT_TYPE_TEXT)
1619                         {
1620                                 pTextElement->Draw(canvasImpl, adjustedRect, textIndexFromElementOffset, currentLength, alignment, action);
1621                         }
1622                         else
1623                         {
1624                                 pTextElement->Draw(canvasImpl, imageRect, textIndexFromElementOffset, currentLength, alignment, action);
1625                         }
1626
1627                         adjustedRect.x += textSize.width;
1628                         adjustedRect.width -= textSize.width;
1629
1630                         if (!RTLTextLength || adjustedRect.width <= 0)
1631                         {
1632                                 break;
1633                         }
1634
1635                         startTextIndex += currentLength;
1636
1637                         if (pEnum->MoveNext() != E_SUCCESS)
1638                         {
1639                                 break;
1640                         }
1641
1642                         pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
1643                         SysTryCatch(NID_GRP, pTextElement, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get element.");
1644
1645                         textIndexFromElementOffset = pTextElement->GetValue(SET_TEXT_OFFSET);
1646                         currentLength = Math::Min(RTLTextLength, pTextElement->GetTextLength());
1647
1648                         if (currentLength == 0)
1649                         {
1650                                 break;
1651                         }
1652                 }
1653
1654                 textLength -= RTLTextLength;
1655         }
1656
1657         if (drawAbbrevText)
1658         {
1659                 if (pTextElement->IsBackGroundDrawingModeEnable())
1660                 {
1661                         r = canvasImpl.FillRectangle(pTextElement->GetBackgroundColor(), FloatRectangle(adjustedRect.x, displayRect.y, abbrevTextDim.width, displayRect.height));
1662                         SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
1663                 }
1664
1665                 __pAbbrevTextElement->Draw(canvasImpl, adjustedRect, 0, 1, (TextObjectAlignment)(TEXT_OBJECT_ALIGNMENT_TOP | TEXT_OBJECT_ALIGNMENT_LEFT), action);
1666
1667                 adjustedRect.x += abbrevTextDim.width;
1668                 adjustedRect.width -= abbrevTextDim.width;
1669         }
1670
1671         canvasImpl.SetTextOrigin(TEXT_ORIGIN_LEFT_TOP);
1672
1673         Release(pEnum);
1674         return E_SUCCESS;
1675
1676 CATCH:
1677         canvasImpl.SetTextOrigin(TEXT_ORIGIN_LEFT_TOP);
1678
1679         Release(pEnum);
1680         return r;
1681 }
1682
1683 result
1684 TextComposite::DrawBlock(_CanvasImpl& canvasImpl, const FloatRectangle& displayRect, int startTextIndex, int textLength,
1685                 const TextObjectAlignment align, const TextObjectActionType action)
1686 {
1687         int lineIndex = __pCurrentTextColumn->GetLineIndexAtTextIndex(startTextIndex);
1688         TextLine* pTextLine = __pCurrentTextColumn->GetTextLine(lineIndex);
1689         SysTryReturn(NID_GRP, pTextLine, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
1690
1691         int lineOffset = pTextLine->GetTextOffset();
1692         int blockStartTextIndex = Math::Max(__workStart, startTextIndex);
1693         int blockEndTextIndex = Math::Min(__workStart + __workLength, startTextIndex + textLength);
1694         int blockTextLength = blockEndTextIndex - blockStartTextIndex;
1695
1696         if (blockStartTextIndex >= blockEndTextIndex)
1697         {
1698                 return E_SUCCESS;
1699         }
1700
1701         FloatRectangle lineBounds = pTextLine->GetBoundsF();
1702         blockStartTextIndex -= lineOffset;
1703         blockEndTextIndex -= lineOffset;
1704
1705         FloatRectangle blockRect = displayRect;
1706         blockRect.y = lineBounds.y;
1707
1708         Collection::ArrayListT<_FloatPair>* pGapList = pTextLine->GetTextExtentList();
1709
1710         float left = 0;
1711         float right = 0;
1712         float blockStart = 0;
1713         float blockEnd = 0;
1714
1715         _FloatPair currentGap;
1716         IEnumeratorT<_FloatPair >* pGapEnum = pGapList->GetEnumeratorN();
1717
1718         for (int i = 0; i <= blockStartTextIndex; i++)
1719         {
1720                 pGapEnum->MoveNext();
1721         }
1722
1723         for (int count = 0; count < blockTextLength; count++)
1724         {
1725                 pGapEnum->GetCurrent(currentGap);
1726
1727                 if (right == currentGap.first || left == currentGap.second)
1728                 {
1729                         blockStart = (currentGap.first < blockStart) ? currentGap.first : blockStart;
1730                         blockEnd = (currentGap.second > blockEnd) ? currentGap.second : blockEnd;
1731                 }
1732                 else
1733                 {
1734                         if (blockStart != blockEnd)
1735                         {
1736                                 canvasImpl.FillRectangle(__defaultBlockColor, FloatRectangle(blockRect.x + blockStart, displayRect.y, blockEnd - blockStart, displayRect.height));
1737                         }
1738
1739                         blockStart = currentGap.first;
1740                         blockEnd = currentGap.second;
1741                 }
1742
1743                 left = currentGap.first;
1744                 right = currentGap.second;
1745
1746                 pGapEnum->MoveNext();
1747         }
1748
1749         if (blockStart != blockEnd)
1750         {
1751                 canvasImpl.FillRectangle(__defaultBlockColor, FloatRectangle(blockRect.x + blockStart, displayRect.y, blockEnd - blockStart, displayRect.height));
1752         }
1753
1754         if ((pTextLine->GetEndType() == TEXT_RETBY_LINEFEED) && (pTextLine->GetTextLength() == blockEndTextIndex))
1755         {
1756                 canvasImpl.FillRectangle(__defaultBlockColor, FloatRectangle(blockRect.x + blockEnd, displayRect.y, LINE_FEED_WIDTH, displayRect.height));
1757         }
1758
1759         Release(pGapEnum);
1760
1761         return E_SUCCESS;
1762 }
1763
1764 result
1765 TextComposite::DrawBackgroundBlock(_CanvasImpl& canvasImpl, const FloatRectangle& displayRect, int startTextIndex, int textLength,
1766                 const TextObjectAlignment align, const TextObjectActionType action)
1767 {
1768         if (textLength == 0)
1769         {
1770                 return E_SUCCESS;
1771         }
1772
1773         TextLine* pTextLine = __pCurrentTextColumn->GetTextLine(__pCurrentTextColumn->GetLineIndexAtTextIndex(startTextIndex));
1774         SysTryReturn(NID_GRP, pTextLine, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
1775
1776         int blockEndTextIndex = startTextIndex + textLength;
1777         float prevLeft = 0;
1778         float prevRight = 0;
1779         float blockStart = 0;
1780         float blockEnd = 0;
1781         int currentLength = 0;
1782         int elementTextOffset = 0;
1783         int elementIndex = 0;
1784         int textIndexFromElementOffset = 0;
1785
1786         FloatRectangle lineBounds = pTextLine->GetBoundsF();
1787         blockEndTextIndex -= pTextLine->GetTextOffset();
1788         FloatRectangle blockRect = displayRect;
1789         blockRect.y = lineBounds.y;
1790
1791         TextElement* pTextElement = GetElementAtTextIndex(startTextIndex, elementTextOffset, elementIndex, currentLength, textIndexFromElementOffset);
1792         SysTryReturn(NID_GRP, pTextElement, -1, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
1793
1794         TextElementType objectType = pTextElement->GetType();
1795         if (objectType == TEXT_ELEMENT_TYPE_CUTLINK || objectType == TEXT_ELEMENT_TYPE_TEXT)
1796         {
1797                 TextSimple* pSimpleText = dynamic_cast < TextSimple* >(pTextElement);
1798                 if (pSimpleText != null)
1799                 {
1800                         Color backgroundColor = pSimpleText->GetBackgroundColor();
1801                         const wchar_t* pText = pSimpleText->GetTextSource();
1802
1803                         _FontImpl* pFontImpl = (_FontImpl::GetInstance(*const_cast < Font* >(pSimpleText->GetFont())));
1804                         SysTryReturn(NID_GRP, pFontImpl, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get native font instance.");
1805
1806                         Collection::ArrayListT<_FloatPair> elemenGapListF;
1807                         pFontImpl->GetTextExtentList(pText, textIndexFromElementOffset, textLength, elemenGapListF);
1808
1809                         _FloatPair currentGap;
1810                         IEnumeratorT<_FloatPair >* pEnum = elemenGapListF.GetEnumeratorN();
1811
1812                         while (pEnum->MoveNext() == E_SUCCESS)
1813                         {
1814                                 pEnum->GetCurrent(currentGap);
1815
1816                                 if (prevRight == currentGap.first || prevLeft == currentGap.second)
1817                                 {
1818                                         blockStart = (currentGap.first < blockStart) ? currentGap.first : blockStart;
1819                                         blockEnd = (currentGap.second > blockEnd) ? currentGap.second : blockEnd;
1820                                 }
1821                                 else
1822                                 {
1823                                         if (blockStart != blockEnd)
1824                                         {
1825                                                 canvasImpl.FillRectangle(backgroundColor, FloatRectangle(blockRect.x + blockStart, displayRect.y, blockEnd - blockStart, displayRect.height));
1826                                         }
1827
1828                                         blockStart = currentGap.first;
1829                                         blockEnd = currentGap.second;
1830                                 }
1831
1832                                 prevLeft = currentGap.first;
1833                                 prevRight = currentGap.second;
1834                         }
1835
1836                         if (blockStart != blockEnd)
1837                         {
1838                                 canvasImpl.FillRectangle(backgroundColor, FloatRectangle(blockRect.x + blockStart, displayRect.y, blockEnd - blockStart, displayRect.height));
1839                         }
1840
1841                         if ((pTextLine->GetEndType() == TEXT_RETBY_LINEFEED) && (pTextLine->GetTextLength() == blockEndTextIndex))
1842                         {
1843                                 canvasImpl.FillRectangle(backgroundColor, FloatRectangle(blockRect.x + blockEnd, displayRect.y, LINE_FEED_WIDTH, displayRect.height));
1844                         }
1845
1846                         Release(pEnum);
1847                 }
1848         }
1849
1850         return E_SUCCESS;
1851 }
1852
1853 result
1854 TextComposite::DrawLine(_CanvasImpl& canvasImpl, TextLine* pTextLine, const FloatRectangle& displayRect,
1855                 const TextObjectAlignment align, const TextObjectActionType action)
1856 {
1857         SysTryReturn(NID_GRP, pTextLine, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
1858
1859         int lineOffset = 0;
1860         int lineLength = 0;
1861
1862         FloatRectangle adjustedRect;
1863         FloatRectangle lineBounds;
1864         FloatDimension lineTextSize;
1865
1866         lineLength = pTextLine->GetTextLength();
1867         lineOffset = pTextLine->GetTextOffset();
1868
1869         lineBounds = pTextLine->GetBoundsF();
1870         pTextLine->GetRegion(0, lineLength, lineTextSize.width, lineTextSize.height);
1871
1872         adjustedRect = displayRect;
1873         adjustedRect.width = lineBounds.width;
1874         adjustedRect.height = lineBounds.height;
1875
1876         if (action == TEXT_OBJECT_ACTION_TYPE_ABBREV)
1877         {
1878                 if (__elementVertialAlignment & TEXT_OBJECT_ALIGNMENT_BASELINE)
1879                 {
1880                         return DrawWithBaselineWithEllipsis(canvasImpl, adjustedRect, lineOffset, lineLength,
1881                                         (TextObjectAlignment)((TEXT_ALIGNMASK_HORIZ & align) | TEXT_OBJECT_ALIGNMENT_BASELINE), action, pTextLine->GetBaseline());
1882                 }
1883                 else
1884                 {
1885                         return DrawWithEliipsis(canvasImpl, adjustedRect, lineOffset, lineLength,
1886                                         (TextObjectAlignment)((TEXT_ALIGNMASK_HORIZ & align) | __elementVertialAlignment), action);
1887                 }
1888         }
1889         else
1890         {
1891                 if (__elementVertialAlignment & TEXT_OBJECT_ALIGNMENT_BASELINE)
1892                 {
1893                         return DrawWithBaseline(canvasImpl, adjustedRect, lineOffset, lineLength,
1894                                         (TextObjectAlignment)((TEXT_ALIGNMASK_HORIZ & align) | TEXT_OBJECT_ALIGNMENT_BASELINE), action, pTextLine->GetBaseline());
1895                 }
1896                 else
1897                 {
1898                         return Draw(canvasImpl, adjustedRect, lineOffset, lineLength,
1899                                         (TextObjectAlignment)((TEXT_ALIGNMASK_HORIZ & align) | __elementVertialAlignment), action);
1900                 }
1901         }
1902 }
1903
1904 result
1905 TextComposite::GetValue(TextElement* pTextElement, TextComponentInfoValueType type, unsigned int* value) const
1906 {
1907         SysTryReturn(NID_GRP, pTextElement, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
1908
1909         TextElementType objectType = TextUtility::GetObjectTypeFromValueType(type);
1910
1911         SysTryReturn(NID_GRP, pTextElement->GetType() == objectType, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get type.");
1912
1913         *value = pTextElement->GetValue(type);
1914
1915         return E_SUCCESS;
1916 }
1917
1918 result
1919 TextComposite::InsertElementAt(TextElement& textElement, int textIndex)
1920 {
1921         SysTryReturn(NID_GRP, 0 <= textIndex && textIndex <= __length, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
1922
1923         result r = E_SUCCESS;
1924
1925         TextElement* pCurrentTextElement = null;
1926         TextElement* pNewTextElement = null;
1927
1928         int currentLength = 0;
1929         int elementTextOffset = 0;
1930         int elementIndex = 0;
1931         int textIndexFromElementOffset = 0;
1932
1933         pCurrentTextElement = GetElementAtTextIndex(textIndex, elementTextOffset, elementIndex,
1934                         currentLength, textIndexFromElementOffset);
1935
1936         if (pCurrentTextElement != null)
1937         {
1938                 if (textIndex == elementTextOffset)
1939                 {
1940                         r = __pTextElementList->InsertAt(textElement, elementIndex);
1941                         SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Fail to insert element.", GetErrorMessage(r));
1942                 }
1943                 else
1944                 {
1945                         pCurrentTextElement->SetTextLength(pCurrentTextElement->GetTextLength() - currentLength);
1946
1947                         r = __pTextElementList->InsertAt(textElement, ++elementIndex);
1948                         SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Fail to insert element.", GetErrorMessage(r));
1949
1950                         pNewTextElement = pCurrentTextElement->CloneN(SET_ALLVALUE_CLONE, 0);
1951                         SysTryReturn(NID_GRP, pNewTextElement, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to clone text element.");
1952
1953                         pNewTextElement->SetTextLength(currentLength);
1954
1955                         if (textIndexFromElementOffset != 0)
1956                         {
1957                                 pNewTextElement->SetValue(SET_TEXT_OFFSET, textIndexFromElementOffset);
1958                         }
1959
1960                         r = __pTextElementList->InsertAt(*pNewTextElement, ++elementIndex);
1961                         SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Fail to insert element.", GetErrorMessage(r));
1962                 }
1963         }
1964         else
1965         {
1966                 if (textIndex == __length)
1967                 {
1968                         r = __pTextElementList->Add(textElement);
1969                         SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Fail to add element.", GetErrorMessage(r));
1970                 }
1971                 else
1972                 {
1973                         return E_SYSTEM;
1974                 }
1975         }
1976
1977         int elementTextLength = textElement.GetTextLength();
1978
1979         __workStart = textIndex;
1980         __workLength = elementTextLength;
1981         __length += elementTextLength;
1982         __isChanged = true;
1983
1984         TextElementType objectType = textElement.GetType();
1985         if (objectType == TEXT_ELEMENT_TYPE_CUTLINK)
1986         {
1987                 TextCutLink* pLinkElement = dynamic_cast < TextCutLink* >(&textElement);
1988                 __pCutLinkListInfo->InsertCutLinkElementInfo(textIndex, *pLinkElement, elementTextLength);
1989         }
1990         else
1991         {
1992                 __pCutLinkListInfo->InsertText(textIndex, elementTextLength);
1993         }
1994
1995         if (objectType == TEXT_ELEMENT_TYPE_CUTLINK || objectType == TEXT_ELEMENT_TYPE_TEXT)
1996         {
1997                 TextSimple* pSimpleText = dynamic_cast < TextSimple* >(&textElement);
1998                 if (pSimpleText != null)
1999                 {
2000                         pSimpleText->SetUserWrap(__wrap);
2001                 }
2002         }
2003
2004         return r;
2005 }
2006
2007 result
2008 TextComposite::AppendElement(TextElement& textElement)
2009 {
2010         result r = E_SUCCESS;
2011         int elementTextLength = textElement.GetTextLength();
2012
2013         r = __pTextElementList->Add(textElement);
2014         SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Fail to add element.", GetErrorMessage(r));
2015
2016         __workStart = __length;
2017         __workLength = elementTextLength;
2018         __length += elementTextLength;
2019         __isChanged = true;
2020
2021         TextElementType objectType = textElement.GetType();
2022         if (objectType == TEXT_ELEMENT_TYPE_CUTLINK)
2023         {
2024                 TextCutLink* pLinkElement = dynamic_cast < TextCutLink* >(&textElement);
2025                 __pCutLinkListInfo->InsertCutLinkElementInfo(__workStart, *pLinkElement, elementTextLength);
2026         }
2027         else
2028         {
2029                 __pCutLinkListInfo->InsertText(__workStart, elementTextLength);
2030         }
2031
2032         if (objectType == TEXT_ELEMENT_TYPE_CUTLINK || objectType == TEXT_ELEMENT_TYPE_TEXT)
2033         {
2034                 TextSimple* pSimpleText = dynamic_cast < TextSimple* >(&textElement);
2035                 if (pSimpleText != null)
2036                 {
2037                         pSimpleText->SetUserWrap(__wrap);
2038                 }
2039         }
2040
2041         return r;
2042 }
2043
2044 result
2045 TextComposite::Remove(int startTextIndex, int textLength)
2046 {
2047         if (textLength == 0)
2048         {
2049                 return E_SUCCESS;
2050         }
2051
2052         result r = E_SUCCESS;
2053         TextElement* pNewTextElement = null;
2054         int startElementIndex = -1;
2055         int endElementIndex = -1;
2056         int elementTextOffset = 0;
2057         int elementIndex = 0;
2058         int currentLength = 0;
2059         int textIndexFromElementOffset = 0;
2060         int textIndex = startTextIndex;
2061         int remainingLength = textLength;
2062
2063         TextElement* pTextElement = GetElementAtTextIndex(textIndex, elementTextOffset, elementIndex, currentLength, textIndexFromElementOffset);
2064         SysTryReturn(NID_GRP, pTextElement, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
2065         SysTryReturn(NID_GRP, currentLength > 0, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] _Text::TextElement is invalid.");
2066
2067         startElementIndex = elementIndex;
2068
2069         if (elementTextOffset == textIndex && remainingLength == currentLength)
2070         {
2071                 __pTextElementList->RemoveAt(elementIndex, true);
2072
2073                 goto TRUE_CATCH;
2074         }
2075         else if (elementTextOffset < textIndex && remainingLength < currentLength)
2076         {
2077                 pTextElement->SetTextLength(pTextElement->GetTextLength() - currentLength);
2078
2079                 pNewTextElement = pTextElement->CloneN(SET_ALLVALUE_CLONE, 0);
2080                 SysTryReturn(NID_GRP, pNewTextElement, r, r, "[E_SYSTEM] Fail to clone text element.");
2081
2082                 pNewTextElement->SetTextLength(currentLength - remainingLength);
2083                 pNewTextElement->SetValue(SET_TEXT_OFFSET, textIndexFromElementOffset + remainingLength);
2084
2085                 r = __pTextElementList->InsertAt(*pNewTextElement, ++elementIndex);
2086                 SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Fail to insert element.", GetErrorMessage(r));
2087
2088                 endElementIndex = elementIndex;
2089
2090                 goto TRUE_CATCH;
2091         }
2092         else if (elementTextOffset < textIndex)
2093         {
2094                 pTextElement->SetTextLength(pTextElement->GetTextLength() - currentLength);
2095
2096                 textIndex += currentLength;
2097                 remainingLength -= currentLength;
2098                 elementIndex++;
2099         }
2100
2101         while (remainingLength > 0)
2102         {
2103                 pTextElement = static_cast < TextElement* >(__pTextElementList->GetAt(elementIndex));
2104                 if (!pTextElement)
2105                 {
2106                         endElementIndex = elementIndex;
2107                         break;
2108                 }
2109
2110                 textIndexFromElementOffset = pTextElement->GetValue(SET_TEXT_OFFSET);
2111                 currentLength = pTextElement->GetTextLength();
2112
2113                 if (remainingLength < currentLength)
2114                 {
2115                         pTextElement->SetTextLength(currentLength - remainingLength);
2116                         pTextElement->SetValue(SET_TEXT_OFFSET, textIndexFromElementOffset + remainingLength);
2117
2118                         endElementIndex = elementIndex;
2119                         break;
2120                 }
2121                 else
2122                 {
2123                         __pTextElementList->RemoveAt(elementIndex, true);
2124                 }
2125
2126                 endElementIndex = elementIndex;
2127                 remainingLength -= currentLength;
2128         }
2129
2130 TRUE_CATCH:
2131         __length -= textLength;
2132         Optimize(startElementIndex, endElementIndex);
2133         return E_SUCCESS;
2134
2135 CATCH:
2136         Release(pNewTextElement);
2137         return r;
2138 }
2139
2140 result
2141 TextComposite::RemoveElementAt(int elementIndex, bool deallocate)
2142 {
2143         SysTryReturn(NID_GRP, elementIndex >= 0 && elementIndex < __pTextElementList->GetCount()
2144                         , E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
2145
2146         result r = E_SUCCESS;
2147         TextElement* pTextElement = null;
2148
2149         pTextElement = static_cast < TextElement* >(__pTextElementList->GetAt(elementIndex));
2150         if (pTextElement != null)
2151         {
2152                 int elementTextLength = pTextElement->GetTextLength();
2153                 int elementTextOffset = GetFirstTextIndexAt(elementIndex);
2154
2155                 r = __pTextElementList->RemoveAt(elementIndex);
2156                 SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Fail to remove element.", GetErrorMessage(r));
2157
2158                 if (pTextElement->GetType() == TEXT_ELEMENT_TYPE_CUTLINK)
2159                 {
2160                         __pCutLinkListInfo->RemoveCutLinkElementInfo(dynamic_cast < TextCutLink* >(pTextElement));
2161                 }
2162                 else
2163                 {
2164                         __pCutLinkListInfo->RemoveText(elementTextOffset, elementTextLength);
2165                 }
2166
2167                 __length -= elementTextLength;
2168
2169                 if (deallocate)
2170                 {
2171                         Release(pTextElement);
2172                 }
2173         }
2174
2175         return r;
2176 }
2177
2178 result
2179 TextComposite::RemoveAllElements(bool deallocate)
2180 {
2181         result r = E_SUCCESS;
2182
2183         if (__pCutLinkListInfo)
2184         {
2185                 __pCutLinkListInfo->RemoveAllCutLinkElementInfos();
2186         }
2187
2188         __pTextElementList->RemoveAll(deallocate);
2189
2190         SysTryCatch(NID_GRP, __pTextElementList->GetCount() == 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to remove all elements.");
2191
2192         __workStart = 0;
2193         __workLength = 0;
2194         __length = 0;
2195         __displayBlock = false;
2196         __cursorIndex = -1;
2197
2198         return E_SUCCESS;
2199
2200 CATCH:
2201         __workStart = 0;
2202         __workLength = 0;
2203         __length = 0;
2204         __cursorIndex = -1;
2205
2206         return r;
2207 }
2208
2209 TextElement*
2210 TextComposite::SearchTextElement(TextElementType type, int textIndex, int& elementTextOffset) const
2211 {
2212         SysTryReturn(NID_GRP, 0 <= textIndex && textIndex < __length, null, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
2213
2214         result r = E_SUCCESS;
2215         IEnumerator* pEnum = null;
2216         TextElement* pTextElement = null;
2217
2218         int elementIndex = 0;
2219         int currentLength = 0;
2220         int textIndexFromElementOffset = 0;
2221
2222         pTextElement = GetElementAtTextIndex(textIndex, elementTextOffset, elementIndex, currentLength, textIndexFromElementOffset);
2223         SysTryReturn(NID_GRP, pTextElement, null, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
2224
2225         if (pTextElement->GetType() == type)
2226         {
2227                 return pTextElement;
2228         }
2229
2230         elementTextOffset += pTextElement->GetTextLength();
2231
2232         pEnum = __pTextElementList->GetEnumeratorN();
2233         for (int i = 0; i < elementIndex; i++)
2234         {
2235                 r = pEnum->MoveNext();
2236                 SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Fail to move next element.", GetErrorMessage(r));
2237         }
2238
2239         while (pEnum->MoveNext() == E_SUCCESS)
2240         {
2241                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
2242                 if (pTextElement == null)
2243                 {
2244                         continue;
2245                 }
2246
2247                 if (pTextElement->GetType() == type)
2248                 {
2249                         Release(pEnum);
2250                         SetLastResult(E_SUCCESS);
2251                         return pTextElement;
2252                 }
2253
2254                 elementTextOffset += pTextElement->GetTextLength();
2255         }
2256
2257         Release(pEnum);
2258         SetLastResult(E_SUCCESS);
2259         return null;
2260
2261 CATCH:
2262         Release(pEnum);
2263         return null;
2264 }
2265
2266 wchar_t*
2267 TextComposite::GetTextN(int startTextIndex, int textLength) const
2268 {
2269         SysTryReturn(NID_GRP, 0 <= startTextIndex && textLength <= __length, null, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
2270
2271         result r = E_SUCCESS;
2272         IEnumerator* pEnum = null;
2273
2274         int currentLength = 0;
2275         int elementTextOffset = 0;
2276         int elementIndex = 0;
2277         int textIndexFromElementOffset = 0;
2278
2279         wchar_t* pText = new (std::nothrow) wchar_t[textLength+1];
2280         SysTryReturn(NID_GRP, pText, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
2281
2282         wchar_t* pTextPointer = pText;
2283
2284         TextElement* pTextElement = GetElementAtTextIndex(startTextIndex, elementTextOffset, elementIndex, currentLength, textIndexFromElementOffset);
2285         SysTryCatch(NID_GRP, pTextElement, , E_SYSTEM, "[E_SYSTEM] Fail to get element.");
2286
2287         textIndexFromElementOffset = startTextIndex - elementTextOffset;
2288
2289         pEnum = __pTextElementList->GetEnumeratorN();
2290         for (int i = 0; i < elementIndex; i++)
2291         {
2292                 r = pEnum->MoveNext();
2293         }
2294
2295         while (pEnum->MoveNext() == E_SUCCESS)
2296         {
2297                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
2298                 if (pTextElement)
2299                 {
2300                         currentLength = Math::Min(pTextElement->GetTextLength() - textIndexFromElementOffset, textLength);
2301
2302                         TextElementType objectType = pTextElement->GetType();
2303
2304                         if (objectType == TEXT_ELEMENT_TYPE_TEXT || objectType == TEXT_ELEMENT_TYPE_CUTLINK)
2305                         {
2306                                 TextSimple* pSimpleText = dynamic_cast < TextSimple* >(pTextElement);
2307                                 if (pSimpleText)
2308                                 {
2309                                         const wchar_t* pSrcText = pSimpleText->GetText();
2310                                         TextUtility::CopyText(pTextPointer, &pSrcText[textIndexFromElementOffset], currentLength);
2311                                 }
2312
2313                                 textLength -= currentLength;
2314                                 pTextPointer += currentLength;
2315                         }
2316                 }
2317
2318                 if (textLength <= 0)
2319                 {
2320                         break;
2321                 }
2322
2323                 textIndexFromElementOffset = 0;
2324         }
2325
2326         Release(pEnum);
2327         return pText;
2328
2329 CATCH:
2330         if (pText)
2331         {
2332                 delete[] pText;
2333                 pText = null;
2334         }
2335
2336         Release(pEnum);
2337         return null;
2338 }
2339
2340 wchar_t
2341 TextComposite::GetCharacter(int textIndex) const
2342 {
2343         wchar_t ch = { 0 };
2344
2345         SysTryReturn(NID_GRP, 0 <= textIndex && textIndex <= __length, ch, E_INVALID_ARG
2346                         , "[E_INVALID_ARG] The argument is invalid. textIndex(%d), __length(%d)", textIndex, __length);
2347
2348         result r = E_SUCCESS;
2349         IEnumerator* pEnum = null;
2350         int currentLength = 0;
2351         int elementTextOffset = 0;
2352         int elementIndex = 0;
2353         int textIndexFromElementOffset = 0;
2354
2355         TextElement* pTextElement = GetElementAtTextIndex(textIndex, elementTextOffset, elementIndex, currentLength, textIndexFromElementOffset);
2356         SysTryReturn(NID_GRP, pTextElement, ch, E_SYSTEM, "[E_SYSTEM] Fail to get element.");
2357
2358         textIndexFromElementOffset = textIndex - elementTextOffset;
2359
2360         pEnum = __pTextElementList->GetEnumeratorN();
2361         for (int i = 0; i < elementIndex + 1; i++)
2362         {
2363                 r = pEnum->MoveNext();
2364         }
2365
2366         pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
2367
2368         if (pTextElement)
2369         {
2370                 TextElementType objectType = pTextElement->GetType();
2371
2372                 if (objectType == TEXT_ELEMENT_TYPE_TEXT || objectType == TEXT_ELEMENT_TYPE_CUTLINK)
2373                 {
2374                         TextSimple* pSimpleText = dynamic_cast < TextSimple* >(pTextElement);
2375                         if (pSimpleText)
2376                         {
2377                                 const wchar_t* pText = pSimpleText->GetText();
2378                                 ch = pText[textIndexFromElementOffset];
2379                         }
2380                 }
2381         }
2382
2383         Release(pEnum);
2384         return ch;
2385 }
2386
2387 result
2388 TextComposite::GetText(TextComposite* pTargetCompsiteText, int textIndex, int textLength)
2389 {
2390         SysTryReturn(NID_GRP, pTargetCompsiteText, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
2391         SysTryReturn(NID_GRP, 0 < textLength, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
2392
2393         result r = E_SUCCESS;
2394         IEnumerator* pEnum = null;
2395         TextElement* pTextElement = null;
2396         TextElement* pNewTextElement = null;
2397
2398         int currentLength = 0;
2399         int elementTextOffset = 0;
2400         int elementIndex = 0;
2401         int textIndexFromElementOffset = 0;
2402
2403         if (textIndex == -1 || textIndex < 0)
2404         {
2405                 textIndex = 0;
2406         }
2407
2408         pTextElement = GetElementAtTextIndex(textIndex, elementTextOffset, elementIndex, currentLength, textIndexFromElementOffset);
2409         SysTryReturn(NID_GRP, pTextElement, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get element.");
2410
2411         textIndexFromElementOffset = textIndex - elementTextOffset;
2412
2413         pEnum = __pTextElementList->GetEnumeratorN();
2414         for (int i = 0; i < elementIndex; i++)
2415         {
2416                 r = pEnum->MoveNext();
2417                 SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Fail to move next element.", GetErrorMessage(r));
2418         }
2419
2420         while (pEnum->MoveNext() == E_SUCCESS)
2421         {
2422                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
2423                 if (pTextElement == null)
2424                 {
2425                         continue;
2426                 }
2427
2428                 textIndexFromElementOffset = 0;
2429                 currentLength = Math::Min(pTextElement->GetTextLength(), textLength);
2430
2431                 pNewTextElement = pTextElement->CopyN(textIndexFromElementOffset, currentLength);
2432                 if (pNewTextElement != null)
2433                 {
2434                         pTargetCompsiteText->AppendElement(*pNewTextElement);
2435                 }
2436
2437                 textLength -= currentLength;
2438         }
2439
2440         Release(pEnum);
2441         return E_SUCCESS;
2442
2443 CATCH :
2444         Release(pEnum);
2445         return r;
2446 }
2447
2448 int
2449 TextComposite::Compose(FloatRectangle& rect, TextColumn* pTextColumn)
2450 {
2451         SysTryReturn(NID_GRP, pTextColumn, -1, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
2452
2453         __pCurrentTextColumn = pTextColumn;
2454
2455         int lineCount = 0;
2456
2457         if (__pTextElementList->GetCount() == 0 || __length == 0)
2458         {
2459                 pTextColumn->RemoveAllLines();
2460
2461                 return -1;
2462         }
2463
2464         switch (__wrap)
2465         {
2466         case TEXT_OBJECT_WRAP_TYPE_NONE:
2467         {
2468                 if (__drawAbbrevText)
2469                 {
2470                         __pCurrentTextColumn->PrepareCompose();
2471                         __drawTextEllipsis = false;
2472
2473                         if (__TextObjectEllipsisType == TEXT_OBJECT_ELLIPSIS_TYPE_TAIL)
2474                         {
2475                                 lineCount = ComposeInNoneWrap(rect);
2476                         }
2477                         else if (__TextObjectEllipsisType == TEXT_OBJECT_ELLIPSIS_TYPE_MIDDLE)
2478                         {
2479                                 lineCount = ComposeInNoneWrapMiddleEllipsis(rect);
2480                         }
2481                         else
2482                         {
2483                                 lineCount = ComposeInNoneWrapHeadEllipsis(rect);
2484                         }
2485                 }
2486                 else
2487                 {
2488                         bool setNoneWrapComposeInfo = false;
2489                         NoneWrapComposeInfo noneWrapComposeInfo;
2490
2491                         TextLine* pTextLine = __pCurrentTextColumn->GetTextLine(0);
2492                         if (pTextLine != null)
2493                         {
2494
2495                                 noneWrapComposeInfo.prevTextOffset = pTextLine->GetTextOffset();
2496                                 noneWrapComposeInfo.prevTextLength = pTextLine->GetTextLength();
2497                                 pTextLine->GetRegion(0, noneWrapComposeInfo.prevTextLength, noneWrapComposeInfo.prevWidth, noneWrapComposeInfo.prevHeight);
2498                                 noneWrapComposeInfo.prevEndType = pTextLine->GetEndType();
2499                                 setNoneWrapComposeInfo = true;
2500                         }
2501
2502                         __pCurrentTextColumn->PrepareCompose();
2503                         __drawTextEllipsis = false;
2504                         if (setNoneWrapComposeInfo)
2505                         {
2506                                 lineCount = ComposeInNoneWrap(rect, &noneWrapComposeInfo);
2507                         }
2508                         else
2509                         {
2510                                 lineCount = ComposeInNoneWrap(rect);
2511                         }
2512                 }
2513
2514                 __pCurrentTextColumn->FinishCompose();
2515                 break;
2516         }
2517
2518         case TEXT_OBJECT_WRAP_TYPE_CHARACTER:
2519         {
2520                 __pCurrentTextColumn->PrepareCompose();
2521                 lineCount = ComposeInWrap(rect);
2522                 __pCurrentTextColumn->FinishCompose();
2523                 break;
2524         }
2525
2526         case TEXT_OBJECT_WRAP_TYPE_WORD:
2527         {
2528                 if (IsPartialComposingModeEnabled())
2529                 {
2530                         if (__pCurrentTextColumn->GetTotalLineCount() == 0)
2531                         {
2532                                 __pCurrentTextColumn->PrepareCompose();
2533                         }
2534                         lineCount = ComposeInPartialMode(rect);
2535                 }
2536                 else
2537                 {
2538                         __pCurrentTextColumn->PrepareCompose();
2539                         lineCount = ComposeInWrap(rect);
2540                         __pCurrentTextColumn->CompareDeletedLine();
2541                         __pCurrentTextColumn->FinishCompose();
2542                 }
2543
2544                 break;
2545         }
2546         }
2547
2548         return lineCount;
2549 }
2550
2551 result
2552 TextComposite::SetRange(int textStartIndex, int textLength)
2553 {
2554         SysTryReturn(NID_GRP, 0 <= textStartIndex && textStartIndex <= __length, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
2555
2556         __workStart = textStartIndex;
2557         __workLength = textLength;
2558
2559         return E_SUCCESS;
2560 }
2561
2562 void
2563 TextComposite::GetRange(int& startTextIndex, int& textLength) const
2564 {
2565         startTextIndex = __workStart;
2566         textLength = __workLength;
2567 }
2568
2569 result
2570 TextComposite::SetDisplayBitmap(const Bitmap* pBitmap)
2571 {
2572         if (__workLength == 0)
2573         {
2574                 return E_SUCCESS;
2575         }
2576
2577         result r = E_SUCCESS;
2578         IEnumerator* pEnum = null;
2579         TextElement* pTextElement = null;
2580         TextElement* pNewTextElement = null;
2581         int startElementIndex = -1;
2582         int endElementIndex = -1;
2583         int textIndex = __workStart;
2584         int textLength = __workLength;
2585         int elementTextOffset = 0;
2586         int elementIndex = 0;
2587         int currentLength = 0;
2588         int textIndexFromElementOffset = 0;
2589         int found = false;
2590         TextComponentInfoValueType type = SET_ALTERNATE_DISPLAY_BITMAP;
2591
2592         BitmapDisplayProperty displayProperty;
2593         displayProperty.displayEnable = true;
2594         displayProperty.pBitmap = pBitmap;
2595
2596         while (textLength > 0)
2597         {
2598                 pTextElement = GetElementAtTextIndex(textIndex, elementTextOffset, elementIndex, currentLength, textIndexFromElementOffset);
2599                 SysTryReturn(NID_GRP, pTextElement, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
2600                 SysTryReturn(NID_GRP, 0 < currentLength, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] _Text::TextElement is invalid.");
2601
2602                 if (pTextElement->GetType() == TEXT_ELEMENT_TYPE_TEXT)
2603                 {
2604                         found = true;
2605                         startElementIndex = elementIndex;
2606                         break;
2607                 }
2608
2609                 textIndex += currentLength;
2610                 textLength -= currentLength;
2611         }
2612
2613         if (!found)
2614         {
2615                 return E_SUCCESS;
2616         }
2617
2618         if (elementTextOffset == textIndex && textLength == currentLength)
2619         {
2620                 pTextElement->SetValue(SET_ALTERNATE_DISPLAY_BITMAP,  (unsigned int)&displayProperty);
2621                 displayProperty.displayEnable = false;
2622                 goto TRUE_CATCH;
2623         }
2624         else if (elementTextOffset < textIndex && textLength < currentLength)
2625         {
2626                 pTextElement->SetTextLength(pTextElement->GetTextLength() - currentLength);
2627
2628                 pNewTextElement = pTextElement->CloneN(SET_ALTERNATE_DISPLAY_BITMAP,  (unsigned int)&displayProperty);
2629                 SysTryReturn(NID_GRP, pNewTextElement, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to clone text element.");
2630
2631                 pNewTextElement->SetTextLength(textLength);
2632                 pNewTextElement->SetValue(SET_TEXT_OFFSET, textIndexFromElementOffset);
2633                 displayProperty.displayEnable = false;
2634
2635                 r = __pTextElementList->InsertAt(*pNewTextElement, ++elementIndex);
2636                 SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Fail to insert element.", GetErrorMessage(r));
2637
2638                 pNewTextElement = pTextElement->CloneN(SET_ALLVALUE_CLONE, 0);
2639                 SysTryReturn(NID_GRP, pNewTextElement, r, r, "[E_SYSTEM] Fail to clone text element.");
2640
2641                 pNewTextElement->SetTextLength(currentLength - textLength);
2642                 pNewTextElement->SetValue(SET_TEXT_OFFSET, textIndexFromElementOffset + textLength);
2643
2644                 r = __pTextElementList->InsertAt(*pNewTextElement, ++elementIndex);
2645                 SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Fail to insert element.", GetErrorMessage(r));
2646
2647                 endElementIndex = elementIndex;
2648                 goto TRUE_CATCH;
2649         }
2650         else if (elementTextOffset < textIndex)
2651         {
2652                 pTextElement->SetTextLength(pTextElement->GetTextLength() - currentLength);
2653
2654                 pNewTextElement = pTextElement->CloneN(SET_ALTERNATE_DISPLAY_BITMAP,  (unsigned int)&displayProperty);
2655                 SysTryReturn(NID_GRP, pNewTextElement, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to clone text element.");
2656
2657                 pNewTextElement->SetValue(SET_TEXT_OFFSET, textIndexFromElementOffset);
2658                 pNewTextElement->SetTextLength(currentLength);
2659                 displayProperty.displayEnable = false;
2660
2661                 r = __pTextElementList->InsertAt(*pNewTextElement, ++elementIndex);
2662                 SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Fail to insert element.", GetErrorMessage(r));
2663
2664                 textIndex += currentLength;
2665                 textLength -= currentLength;
2666
2667                 if (textLength > 0)
2668                 {
2669                         pTextElement = GetElementAtTextIndex(textIndex, elementTextOffset, elementIndex, currentLength, textIndexFromElementOffset);
2670                         if (pTextElement == null)
2671                         {
2672                                 goto TRUE_CATCH;
2673                         }
2674                 }
2675                 else
2676                 {
2677                         endElementIndex = elementIndex;
2678                         goto TRUE_CATCH;
2679                 }
2680         }
2681
2682         pEnum = __pTextElementList->GetEnumeratorN();
2683         for (int i = 0; i <= elementIndex; i++)
2684         {
2685                 r = pEnum->MoveNext();
2686                 SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Fail to move next element.", GetErrorMessage(r));
2687         }
2688
2689         while (textLength > 0)
2690         {
2691                 TextElementType objectType = pTextElement->GetType();
2692                 TextElementType objectTypeFromValueType = TextUtility::GetObjectTypeFromValueType(type);
2693                 unsigned int elementValue = pTextElement->GetValue(SET_ALTERNATE_DISPLAY_BITMAP);
2694
2695                 if (objectType == objectTypeFromValueType &&  (unsigned int)&displayProperty != elementValue)
2696                 {
2697                         if (textLength < currentLength)
2698                         {
2699                                 pNewTextElement = pTextElement->CloneN(SET_ALLVALUE_CLONE, 0);
2700                                 SysTryReturn(NID_GRP, pNewTextElement, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to clone text element.");
2701
2702                                 pNewTextElement->SetTextLength(currentLength - textLength);
2703                                 pNewTextElement->SetValue(SET_TEXT_OFFSET, textIndexFromElementOffset + textLength);
2704
2705                                 pTextElement->SetValue(SET_ALTERNATE_DISPLAY_BITMAP,  (unsigned int)&displayProperty);
2706                                 pTextElement->SetTextLength(textLength);
2707
2708                                 r = __pTextElementList->InsertAt(*pNewTextElement, ++elementIndex);
2709                                 SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Fail to insert element.", GetErrorMessage(r));
2710
2711                                 break;
2712                         }
2713                         else
2714                         {
2715                                 pTextElement->SetValue(SET_ALTERNATE_DISPLAY_BITMAP,  (unsigned int)&displayProperty);
2716                         }
2717
2718                         displayProperty.displayEnable = false;
2719                         endElementIndex = elementIndex;
2720                 }
2721
2722                 elementTextOffset += currentLength;
2723                 textLength -= currentLength;
2724                 elementIndex++;
2725
2726                 if (pEnum->MoveNext() != E_SUCCESS)
2727                 {
2728                         break;
2729                 }
2730
2731                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
2732                 if (pTextElement == null)
2733                 {
2734                         break;
2735                 }
2736
2737                 currentLength = pTextElement->GetTextLength();
2738                 textIndexFromElementOffset = pTextElement->GetValue(SET_TEXT_OFFSET);
2739         }
2740
2741 TRUE_CATCH:
2742         Optimize(startElementIndex, endElementIndex);
2743         Release(pEnum);
2744         return E_SUCCESS;
2745
2746 CATCH:
2747         Release(pNewTextElement);
2748         Release(pEnum);
2749         return r;
2750 }
2751
2752 const Bitmap*
2753 TextComposite::GetDisplayBitmap(int textIndex) const
2754 {
2755         result r = E_SUCCESS;
2756         unsigned int value = 0;
2757
2758         r = GetValue(textIndex, SET_ALTERNATE_DISPLAY_BITMAP, &value);
2759         SysTryReturn(NID_GRP, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
2760
2761         return (Bitmap*)value;
2762 }
2763
2764 result
2765 TextComposite::SetFont(Font* pFont)
2766 {
2767         return SetValueToAllTextElements(SET_FONT, (unsigned int)pFont);
2768 }
2769
2770 Font*
2771 TextComposite::GetFont(int textIndex) const
2772 {
2773         unsigned int value = 0;
2774
2775         GetValue(textIndex, SET_FONT, &value);
2776         Font* pFont = static_cast < Font* >((void*)value);
2777
2778         SetLastResult(E_SUCCESS);
2779
2780         return pFont;
2781 }
2782
2783 result
2784 TextComposite::SetFontSize(int size)
2785 {
2786         return SetValueToAllTextElements(SET_FONT_SIZE, (unsigned int)size);
2787 }
2788
2789 result
2790 TextComposite::SetFontSize(float size)
2791 {
2792         return SetFontSize(_CoordinateSystemUtils::ConvertToInteger(size));
2793 }
2794
2795 int
2796 TextComposite::GetFontSize(int textIndex) const
2797 {
2798         return _CoordinateSystemUtils::ConvertToInteger(GetFontSizeF(textIndex));
2799 }
2800
2801 float
2802 TextComposite::GetFontSizeF(int textIndex) const
2803 {
2804         unsigned int value = 0;
2805
2806         result r = GetValue(textIndex, SET_FONT_SIZE, &value);
2807         SysTryReturn(NID_GRP, r == E_SUCCESS, -1, r, "[%s] Propagating.", GetErrorMessage(r));
2808
2809         return (float)value;
2810 }
2811
2812 result
2813 TextComposite::SetFontStyle(int style)
2814 {
2815         return SetValueToAllTextElements(SET_FONT_STYLE, (unsigned int)style);
2816 }
2817
2818 int
2819 TextComposite::GetFontStyle(int textIndex) const
2820 {
2821         unsigned int value = 0;
2822
2823         result r = GetValue(textIndex, SET_FONT_STYLE, &value);
2824         SysTryReturn(NID_GRP
2825                 , r == E_SUCCESS
2826                 , -1, r, "[%s] Propagating.", GetErrorMessage(r));
2827
2828         return (int)value;
2829 }
2830
2831 result
2832 TextComposite::SetForegroundColor(const Color& color)
2833 {
2834         return SetValueToAllTextElements(SET_FONT_FGCOLOR, (unsigned int)color.GetRGB32());
2835 }
2836
2837 Color
2838 TextComposite::GetForegroundColor(int textIndex) const
2839 {
2840         result r = E_SUCCESS;
2841         unsigned int value = 0;
2842
2843         r = GetValue(textIndex, SET_FONT_FGCOLOR, &value);
2844         SysTryReturn(NID_GRP, r == E_SUCCESS, Color::GetColor(COLOR_ID_BLACK), r, "[%s] Propagating.", GetErrorMessage(r));
2845
2846         return Color(value);
2847 }
2848
2849 result
2850 TextComposite::SetBackgroundColor(const Color& color)
2851 {
2852         return SetValueToAllTextElements(SET_FONT_BGCOLOR, (unsigned int)color.GetRGB32());
2853 }
2854
2855 Color
2856 TextComposite::GetBackgroundColor(int textIndex) const
2857 {
2858         result r = E_SUCCESS;
2859         unsigned int value = 0;
2860
2861         r = GetValue(textIndex, SET_FONT_BGCOLOR, &value);
2862         SysTryReturn(NID_GRP, r == E_SUCCESS, Color::GetColor(COLOR_ID_BLACK), r, "[%s] Propagating.", GetErrorMessage(r));
2863
2864         return Color(value);
2865 }
2866
2867 result
2868 TextComposite::SetOutlineColor(const Color& color)
2869 {
2870         return SetValueToAllTextElements(SET_FONT_OUTLINECOLOR, (unsigned int)color.GetRGB32());
2871 }
2872
2873 Color
2874 TextComposite::GetOutlineColor(int textIndex) const
2875 {
2876         result r = E_SUCCESS;
2877         unsigned int value = 0;
2878
2879         r = GetValue(textIndex, SET_FONT_OUTLINECOLOR, &value);
2880         SysTryReturn(NID_GRP, r == E_SUCCESS, Color::GetColor(COLOR_ID_BLACK), r, "[%s] Propagating.", GetErrorMessage(r));
2881
2882         return Color(value);
2883 }
2884
2885 Color
2886 TextComposite::GetAlternativeForegroundColor(int textIndex) const
2887 {
2888         SysTryReturn(NID_GRP, 0 <= textIndex && textIndex < __length
2889                         , Color::GetColor(COLOR_ID_BLACK), E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
2890
2891         result r = E_SUCCESS;
2892         unsigned int value = 0;
2893
2894         r = GetValue(textIndex, SET_ALTERNATIVE_FGCOLOR, &value);
2895         SysTryReturn(NID_GRP, r == E_SUCCESS, Color::GetColor(COLOR_ID_BLACK), r, "[%s] Propagating.", GetErrorMessage(r));
2896
2897         return Color(value);
2898 }
2899
2900 result
2901 TextComposite::SetAlternateLookEnabled(bool enable)
2902 {
2903         return SetValueToAllTextElements(SET_ALTERNATE_LOOK, (unsigned int)enable);
2904 }
2905
2906 int
2907 TextComposite::GetMaxLineHeight(void) const
2908 {
2909         IEnumerator* pEnum = null;
2910         TextElement* pTextElement = null;
2911         int height = 0;
2912         int maxHeight = 0;
2913
2914         pEnum = __pTextElementList->GetEnumeratorN();
2915         while (pEnum->MoveNext() == E_SUCCESS)
2916         {
2917                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
2918                 if (pTextElement == null)
2919                 {
2920                         continue;
2921                 }
2922
2923                 height = pTextElement->GetHeight();
2924                 maxHeight = Math::Max(maxHeight, height);
2925         }
2926
2927         Release(pEnum);
2928         return maxHeight;
2929 }
2930
2931 float
2932 TextComposite::GetMaxLineHeightF(void) const
2933 {
2934         return _CoordinateSystemUtils::ConvertToFloat(GetMaxLineHeight());
2935 }
2936
2937 TextElement*
2938 TextComposite::GetElementAtTextIndex(int textIndex, int& elementTextOffset, int& elementIndex, int& elementTextLength,
2939                                                                    int& textIndexFromElementOffset) const
2940 {
2941         result r = E_SUCCESS;
2942         IEnumerator* pEnum = null;
2943         TextElement* pTextElement = null;
2944         int offset = 0;
2945         int currentElementLength = 0;
2946
2947         elementTextOffset = 0;
2948         elementIndex = 0;
2949         elementTextLength = 0;
2950         textIndexFromElementOffset = 0;
2951
2952         if (__pTextElementList->GetCount() == 0)
2953         {
2954                 return null;
2955         }
2956
2957         pEnum = __pTextElementList->GetEnumeratorN();
2958         r = pEnum->MoveNext();
2959         SysTryReturn(NID_GRP, r == E_SUCCESS, null, r
2960                         , "[%s] Fail to move next element. Now Elements count is (%d)", GetErrorMessage(r), __pTextElementList->GetCount());
2961
2962         pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
2963         SysTryReturn(NID_GRP, pTextElement, null, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
2964
2965         while (1)
2966         {
2967                 currentElementLength = pTextElement->GetTextLength();
2968                 if (textIndex < elementTextOffset + currentElementLength)
2969                 {
2970                         offset = pTextElement->GetValue(SET_TEXT_OFFSET);
2971                         textIndexFromElementOffset = offset + (textIndex - elementTextOffset);
2972                         break;
2973                 }
2974                 else
2975                 {
2976                         if (currentElementLength == 0 && textIndex == elementTextOffset)
2977                         {
2978                                 offset = pTextElement->GetValue(SET_TEXT_OFFSET);
2979                                 textIndexFromElementOffset = offset + (textIndex - elementTextOffset);
2980                                 break;
2981                         }
2982                 }
2983
2984                 pTextElement = null;
2985                 if (pEnum->MoveNext() != E_SUCCESS)
2986                 {
2987                         break;
2988                 }
2989
2990                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
2991                 if (pTextElement == null)
2992                 {
2993                         break;
2994                 }
2995
2996                 elementTextOffset += currentElementLength;
2997                 elementIndex++;
2998         }
2999
3000         if (pTextElement != null)
3001         {
3002                 elementTextLength = elementTextOffset + currentElementLength - textIndex;
3003         }
3004
3005         Release(pEnum);
3006         return pTextElement;
3007 }
3008
3009 TextElement*
3010 TextComposite::GetElementAtTextIndex(int textIndex) const
3011 {
3012         result r = E_SUCCESS;
3013         IEnumerator* pEnum = null;
3014         TextElement* pTextElement = null;
3015         int currentElementLength = 0;
3016         int elementTextOffset = 0;
3017
3018         if (__pTextElementList->GetCount() == 0 || textIndex < 0)
3019         {
3020                 return null;
3021         }
3022
3023         pEnum = __pTextElementList->GetEnumeratorN();
3024         r = pEnum->MoveNext();
3025         SysTryReturn(NID_GRP, r == E_SUCCESS, null, r, "[%s] Fail to move next element. Now Elements count is (%d)"
3026                         , GetErrorMessage(r), __pTextElementList->GetCount());
3027
3028         pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
3029         SysTryReturn(NID_GRP, pTextElement, null, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
3030
3031         while (1)
3032         {
3033                 currentElementLength = pTextElement->GetTextLength();
3034                 if (textIndex < elementTextOffset + currentElementLength)
3035                 {
3036                         break;
3037                 }
3038                 else
3039                 {
3040                         if (currentElementLength == 0 && textIndex == elementTextOffset)
3041                         {
3042                                 break;
3043                         }
3044                 }
3045
3046                 pTextElement = null;
3047                 if (pEnum->MoveNext() != E_SUCCESS)
3048                 {
3049                         break;
3050                 }
3051
3052                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
3053                 if (pTextElement == null)
3054                 {
3055                         break;
3056                 }
3057
3058                 elementTextOffset += currentElementLength;
3059         }
3060
3061         Release(pEnum);
3062         return pTextElement;
3063 }
3064
3065 result
3066 TextComposite::SetWrap(TextObjectWrapType wrap)
3067 {
3068         if (__wrap == wrap)
3069         {
3070                 return E_SUCCESS;
3071         }
3072
3073         __wrap = wrap;
3074
3075         IEnumerator* pEnum = null;
3076         TextElement* pTextElement = null;
3077
3078         pEnum = __pTextElementList->GetEnumeratorN();
3079         while (pEnum->MoveNext() == E_SUCCESS)
3080         {
3081                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
3082                 if (pTextElement == null)
3083                 {
3084                         continue;
3085                 }
3086
3087                 TextElementType objectType = pTextElement->GetType();
3088                 if (objectType == TEXT_ELEMENT_TYPE_TEXT || objectType == TEXT_ELEMENT_TYPE_CUTLINK)
3089                 {
3090                         TextSimple* pSimpleText = dynamic_cast < TextSimple* >(pTextElement);
3091                         if (pSimpleText != null)
3092                         {
3093                                 pSimpleText->SetUserWrap(__wrap);
3094                         }
3095                 }
3096         }
3097
3098         Release(pEnum);
3099         return E_SUCCESS;
3100 }
3101
3102 result
3103 TextComposite::Optimize(int startElementIndex, int endElementIndex)
3104 {
3105         TextElement* pStartTextElement = null;
3106         TextElement* pEndTextElement = null;
3107         TextElement* pCurrentTextElement = null;
3108         TextElement* pNextTextElement = null;
3109         int elementIndex = 0;
3110         int elementCount = __pTextElementList->GetCount();
3111
3112         if (elementCount == 0)
3113         {
3114                 return E_SUCCESS;
3115         }
3116
3117         startElementIndex = (startElementIndex == -1 || startElementIndex < 0) ? 0 : startElementIndex;
3118         endElementIndex = (endElementIndex == -1 || endElementIndex < 0 || endElementIndex > elementCount - 1) ? elementCount - 1 : endElementIndex;
3119         startElementIndex = (0 < startElementIndex) ? startElementIndex - 1 : startElementIndex;
3120         endElementIndex = (endElementIndex < elementCount - 1) ? endElementIndex + 1 : endElementIndex;
3121
3122         if (endElementIndex - startElementIndex < 1)
3123         {
3124                 return E_SUCCESS;
3125         }
3126
3127         pStartTextElement = static_cast < TextElement* >(__pTextElementList->GetAt(startElementIndex));
3128         SysTryReturn(NID_GRP, pStartTextElement, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
3129
3130         pEndTextElement = static_cast < TextElement* >(__pTextElementList->GetAt(endElementIndex));
3131         SysTryReturn(NID_GRP, pEndTextElement, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
3132
3133         do
3134         {
3135                 pCurrentTextElement = pStartTextElement;
3136
3137                 elementIndex = startElementIndex + 1;
3138                 pNextTextElement = static_cast < TextElement* >(__pTextElementList->GetAt(elementIndex));
3139                 if (pNextTextElement == null)
3140                 {
3141                         break;
3142                 }
3143
3144                 if (TextUtility::CanMerge(pCurrentTextElement, pNextTextElement))
3145                 {
3146                         pCurrentTextElement->SetTextLength(pCurrentTextElement->GetTextLength() + pNextTextElement->GetTextLength());
3147                         __pTextElementList->RemoveAt(elementIndex, true);
3148                 }
3149                 else
3150                 {
3151                         pStartTextElement = pNextTextElement;
3152                         startElementIndex++;
3153                 }
3154
3155                 pStartTextElement = static_cast < TextElement* >(__pTextElementList->GetAt(startElementIndex));
3156                 if (pStartTextElement == null)
3157                 {
3158                         break;
3159                 }
3160         }
3161         while (startElementIndex != endElementIndex);
3162
3163         return E_SUCCESS;
3164 }
3165
3166 result
3167 TextComposite::ChangeTextOffset(wchar_t* pText, int elementIndex, int gap)
3168 {
3169         SysTryReturn(NID_GRP, 0 <= elementIndex, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
3170         SysTryReturn(NID_GRP, gap != 0, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
3171
3172         result r = E_SUCCESS;
3173         IEnumerator* pEnum = null;
3174         TextElement* pTextElement = null;
3175
3176         pEnum = __pTextElementList->GetEnumeratorN();
3177         for (int i = 0; i < elementIndex; i++)
3178         {
3179                 r = pEnum->MoveNext();
3180                 SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Fail to move next element.", GetErrorMessage(r));
3181         }
3182
3183         while (pEnum->MoveNext() == E_SUCCESS)
3184         {
3185                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
3186                 if (pTextElement == null)
3187                 {
3188                         continue;
3189                 }
3190
3191                 TextElementType objectType = pTextElement->GetType();
3192                 if (objectType == TEXT_ELEMENT_TYPE_TEXT || objectType == TEXT_ELEMENT_TYPE_CUTLINK)
3193                 {
3194                         TextSimple* pSimpleText = dynamic_cast < TextSimple* >(pTextElement);
3195                         if (pSimpleText != null)
3196                         {
3197                                 pSimpleText->ChangeTextOffset(pText, gap);
3198                         }
3199                 }
3200         }
3201
3202         Release(pEnum);
3203         return E_SUCCESS;
3204
3205 CATCH:
3206         Release(pEnum);
3207         return r;
3208 }
3209
3210 result
3211 TextComposite::NotifyTextChanged(wchar_t* pText, int startTextIndex, int textLength, int gap, Font* pFont,
3212                                                   const Color& fgColor, const Color& bgColor, const Color& outlineColor)
3213 {
3214         if (gap == 0)
3215         {
3216                 return E_SUCCESS;
3217         }
3218
3219         result r = E_SUCCESS;
3220         TextElement* pTextElement = null;
3221         TextElement* pNextTextElement = null;
3222
3223         int currentLength = 0;
3224         int elementTextOffset = 0;
3225         int elementIndex = 0;
3226         int textIndexFromElementOffset = 0;
3227         bool isOptimized = false;
3228
3229         SetWorkWidth(pFont, pText, __workStart, gap);
3230
3231         if (gap > 0)
3232         {
3233                 bool checkNextElement = false;
3234
3235                 if (__workStart == startTextIndex)
3236                 {
3237                         pTextElement = GetElementAtTextIndex(__workStart, elementTextOffset, elementIndex, currentLength,
3238                                                                                                          textIndexFromElementOffset);
3239                 }
3240                 else
3241                 {
3242                         pTextElement = GetElementAtTextIndex(__workStart - 1, elementTextOffset, elementIndex, currentLength,
3243                                                                                                          textIndexFromElementOffset);
3244                         checkNextElement = true;
3245                 }
3246
3247                 if (pTextElement == null)
3248                 {
3249                         TextSimple* pSimpleText = null;
3250                         pSimpleText = new (std::nothrow)TextSimple(pText, gap, TEXT_ELEMENT_SOURCE_TYPE_EXTERNAL, pFont, fgColor, bgColor, outlineColor);
3251                         SysTryReturn(NID_GRP, pSimpleText, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
3252
3253                         pSimpleText->SetTextOffset(__workStart - startTextIndex);
3254                         InsertElementAt(*pSimpleText, __workStart);
3255
3256                         return E_SUCCESS;
3257                 }
3258                 else
3259                 {
3260                         TextSimple* pSimpleText = null;
3261                         bool canMerge = false;
3262
3263                         TextElementType objectType = pTextElement->GetType();
3264                         if (objectType == TEXT_ELEMENT_TYPE_TEXT || objectType == TEXT_ELEMENT_TYPE_CUTLINK)
3265                         {
3266                                 pSimpleText = dynamic_cast < TextSimple* >(pTextElement);
3267                                 if (pSimpleText != null)
3268                                 {
3269                                         if (pSimpleText->IsSame(pText, pFont, fgColor, bgColor, outlineColor, false))
3270                                         {
3271                                                 canMerge = true;
3272                                         }
3273                                         else
3274                                         {
3275                                                 pTextElement = null;
3276                                         }
3277                                 }
3278                         }
3279                         else
3280                         {
3281                                 pTextElement = null;
3282                         }
3283
3284                         if (!canMerge && checkNextElement)
3285                         {
3286                                 pTextElement = null;
3287
3288                                 if (currentLength == 1)
3289                                 {
3290                                         pNextTextElement = static_cast < TextElement* >(__pTextElementList->GetAt(elementIndex+1));
3291                                         if (pNextTextElement != null)
3292                                         {
3293                                                 objectType = pNextTextElement->GetType();
3294                                                 if (objectType == TEXT_ELEMENT_TYPE_TEXT || objectType == TEXT_ELEMENT_TYPE_CUTLINK)
3295                                                 {
3296                                                         pSimpleText = dynamic_cast < TextSimple* >(pNextTextElement);
3297                                                         if (pSimpleText != null)
3298                                                         {
3299                                                                 if (pSimpleText->IsSame(pText, pFont, fgColor, bgColor, outlineColor, false))
3300                                                                 {
3301                                                                         elementIndex++;
3302                                                                         pTextElement = pNextTextElement;
3303                                                                 }
3304                                                                 else
3305                                                                 {
3306                                                                         pTextElement = null;
3307                                                                 }
3308                                                         }
3309                                                 }
3310                                                 else
3311                                                 {
3312                                                         pTextElement = null;
3313                                                 }
3314                                         }
3315                                         else
3316                                         {
3317                                                 pTextElement = null;
3318                                         }
3319                                 }
3320                         }
3321
3322                         if (pTextElement == null)
3323                         {
3324                                 TextSimple* pSimpleText = null;
3325                                 pSimpleText = new (std::nothrow)TextSimple(pText, gap, TEXT_ELEMENT_SOURCE_TYPE_EXTERNAL, pFont, fgColor, bgColor,
3326                                                                                                   outlineColor);
3327                                 SysTryReturn(NID_GRP, pSimpleText, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
3328
3329                                 pSimpleText->SetTextOffset(__workStart - startTextIndex);
3330                                 InsertElementAt(*pSimpleText, __workStart);
3331
3332                                 isOptimized = true;
3333                                 r = __pTextElementList->IndexOf(*pSimpleText, elementIndex);
3334                                 SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Fail to get element index.", GetErrorMessage(r));
3335                         }
3336                         else
3337                         {
3338                                 __pCutLinkListInfo->InsertText(startTextIndex, gap);
3339                                 __length += gap;
3340                                 pTextElement->SetTextLength(pTextElement->GetTextLength() + gap);
3341                         }
3342                 }
3343         }
3344         else if (gap < 0)
3345         {
3346                 int remainingGap = -gap;
3347                 int currentGap = 0;
3348                 int textIndex = 0;
3349                 int currentelementIndex = 0;
3350
3351                 textIndex = __workStart + remainingGap;
3352                 pTextElement = GetElementAtTextIndex(textIndex, elementTextOffset, elementIndex, currentLength,textIndexFromElementOffset);
3353                 if (pTextElement == null || elementTextOffset == textIndex)
3354                 {
3355                         pTextElement = GetElementAtTextIndex(textIndex - 1, elementTextOffset, elementIndex, currentLength,textIndexFromElementOffset);
3356                 }
3357
3358                 SysTryReturn(NID_GRP, pTextElement, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
3359
3360                 currentelementIndex = elementIndex;
3361                 currentGap = Math::Min(remainingGap, textIndex - elementTextOffset);
3362                 if (currentGap == pTextElement->GetTextLength())
3363                 {
3364                         RemoveElementAt(currentelementIndex);
3365                         elementIndex--;
3366                         isOptimized = true;
3367                 }
3368                 else
3369                 {
3370                         pTextElement->SetTextLength(pTextElement->GetTextLength() - currentGap);
3371                         __length -= currentGap;
3372                         if (currentGap < remainingGap)
3373                         {
3374                                 TextSimple* pSimpleText = dynamic_cast < TextSimple* >(pTextElement);
3375                                 if (pSimpleText != null)
3376                                 {
3377                                         int offset = pSimpleText->GetTextOffset();
3378                                         offset -= (remainingGap - currentGap);
3379                                         pSimpleText->SetTextOffset(offset);
3380                                 }
3381                         }
3382                 }
3383
3384                 remainingGap -= currentGap;
3385                 while (remainingGap > 0)
3386                 {
3387                         pTextElement = static_cast < TextElement* >(__pTextElementList->GetAt(--currentelementIndex));
3388                         SysTryReturn(NID_GRP, pTextElement, r, r, "[%s] Fail to get element.", GetErrorMessage(r));
3389
3390                         int elementTextLength = pTextElement->GetTextLength();
3391                         currentGap = Math::Min(elementTextLength, remainingGap);
3392
3393                         if (currentGap == elementTextLength)
3394                         {
3395                                 RemoveElementAt(currentelementIndex);
3396                                 elementIndex--;
3397                                 isOptimized = true;
3398                         }
3399                         else
3400                         {
3401                                 __pCutLinkListInfo->RemoveText(__workStart, currentGap);
3402                                 pTextElement->SetTextLength(elementTextLength - currentGap);
3403                                 __length -= currentGap;
3404                         }
3405
3406                         remainingGap -= currentGap;
3407                 }
3408         }
3409
3410         ChangeTextOffset(pText, elementIndex + 1, gap);
3411
3412         if (isOptimized)
3413         {
3414                 Optimize(elementIndex, elementIndex);
3415         }
3416
3417         return E_SUCCESS;
3418 }
3419
3420 int
3421 TextComposite::ForwardAnalyzeWithFocusedObjectType(int textIndex, int textLength, int maxWidth,
3422                                                                                                         int& cursorIndex, TextElementType& type)
3423 {
3424         return ForwardAnalyzeWithFocusedObjectType(textIndex, textLength
3425                                                 , _CoordinateSystemUtils::ConvertToFloat(maxWidth), cursorIndex, type);
3426 }
3427
3428 int
3429 TextComposite::ForwardAnalyzeWithFocusedObjectType(int textIndex, int textLength, float maxWidth,
3430                                                                                                         int& cursorIndex, TextElementType& type)
3431 {
3432         result r = E_SUCCESS;
3433         FloatDimension textSize;
3434         int currentLength = 0;
3435         int elementTextOffset = 0;
3436         int elementIndex = 0;
3437         int textIndexFromElementOffset = 0;
3438         int textCount = 0;
3439         float remainingWidth = 0;
3440         int remainingLength = 0;
3441         int ret = TEXT_RETBY_NORMAL;
3442         bool isFirstWord = true;
3443         int index = 0;
3444
3445         IEnumerator* pEnum = null;
3446         TextElement* pTextElement = null;
3447
3448         cursorIndex = 0;
3449         type = TEXT_ELEMENT_TYPE_MAX;
3450
3451         pTextElement = GetElementAtTextIndex(textIndex, elementTextOffset, elementIndex, currentLength, textIndexFromElementOffset);
3452         SysTryReturn(NID_GRP, pTextElement, -1, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
3453
3454         remainingWidth = maxWidth;
3455         remainingLength = textLength;
3456
3457         pEnum = __pTextElementList->GetEnumeratorN();
3458         for (int i = 0; i <= elementIndex; i++)
3459         {
3460                 r = pEnum->MoveNext();
3461                 SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Fail to move next element.", GetErrorMessage(r));
3462         }
3463
3464         currentLength = Math::Min(remainingLength, currentLength);
3465
3466         while (remainingWidth > 0 || remainingLength > 0)
3467         {
3468                 ret = pTextElement->ForwardAnalyze(textIndexFromElementOffset, currentLength, remainingWidth, __wrap, textCount , textSize.width, textSize.height);
3469                 TextElementType objectType = pTextElement->GetType();
3470
3471                 if ((objectType == TEXT_ELEMENT_TYPE_TEXT || objectType == TEXT_ELEMENT_TYPE_CUTLINK) && (ret == TEXT_RETBY_LIMITWIDTH))
3472                 {
3473                         FloatDimension tempTextSize;
3474                         r = pTextElement->GetRegion(textIndexFromElementOffset, textCount  + 1, tempTextSize.width, tempTextSize.height);
3475                         SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
3476
3477                         if ((remainingWidth - textSize.width) > (tempTextSize.width - remainingWidth))
3478                         {
3479                                 textSize.width = tempTextSize.width;
3480                                 textCount++;
3481                         }
3482                 }
3483
3484                 remainingWidth -= textSize.width;
3485                 remainingWidth = (remainingWidth < 0) ? 0 : remainingWidth;
3486
3487                 remainingLength -= textCount;
3488                 currentLength -= textCount ;
3489                 cursorIndex += textCount ;
3490
3491                 if (__wrap == TEXT_OBJECT_WRAP_TYPE_WORD && ret != TEXT_RETBY_LIMITWIDTH)
3492                 {
3493                         index = cursorIndex;
3494                 }
3495
3496                 if (remainingLength <= currentLength)
3497                 {
3498                         break;
3499                 }
3500
3501                 if (ret == TEXT_RETBY_OVERWIDTH || ret == TEXT_RETBY_LINEFEED)
3502                 {
3503                         break;
3504                 }
3505
3506                 if (__wrap == TEXT_OBJECT_WRAP_TYPE_WORD)
3507                 {
3508                         if (ret == TEXT_RETBY_LIMITWIDTH)
3509                         {
3510                                 if (isFirstWord == false)
3511                                 {
3512                                         cursorIndex = index;
3513                                         ret = TEXT_RETBY_NORMAL;
3514                                 }
3515                                 break;
3516                         }
3517
3518                         isFirstWord = false;
3519
3520                         if (currentLength > 0)
3521                         {
3522                                 textIndexFromElementOffset += textCount ;
3523                                 continue;
3524                         }
3525                 }
3526                 else
3527                 {
3528                         if (ret == TEXT_RETBY_LIMITWIDTH)
3529                         {
3530                                 break;
3531                         }
3532                 }
3533
3534                 if (pEnum->MoveNext() != E_SUCCESS)
3535                 {
3536                         break;
3537                 }
3538
3539                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
3540                 if (pTextElement == null)
3541                 {
3542                         break;
3543                 }
3544
3545                 textIndexFromElementOffset = pTextElement->GetValue(SET_TEXT_OFFSET);
3546                 currentLength = Math::Min(pTextElement->GetTextLength(), remainingLength);
3547         }
3548
3549         if (ret == TEXT_RETBY_LIMITLENGTH)
3550         {
3551                 ret = TEXT_RETBY_NORMAL;
3552         }
3553
3554         SetLastResult(E_SUCCESS);
3555         Release(pEnum);
3556         return ret;
3557
3558 CATCH:
3559         Release(pEnum);
3560         return -1;
3561 }
3562
3563 void
3564 TextComposite::HideFrontSpace(TextObjectSpaceHideType mode)
3565 {
3566         __ignoreFrontBlank = true;
3567         __frontSpaceHideMode = mode;
3568 }
3569
3570 void
3571 TextComposite::HideRearSpace(TextObjectSpaceHideType mode)
3572 {
3573         __ignoreRearBlank = true;
3574         __rearSpaceHideMode = mode;
3575 }
3576
3577 int
3578 TextComposite::ForwardAnalyzeInNoneCursorMode(int startTextIndex, int textLength, int maxWidth, int& textIndex)
3579 {
3580         return ForwardAnalyzeInNoneCursorMode(startTextIndex, textLength
3581                                                                                 , _CoordinateSystemUtils::ConvertToFloat(maxWidth), textIndex);
3582 }
3583
3584 int
3585 TextComposite::ForwardAnalyzeInNoneCursorMode(int startTextIndex, int textLength, float maxWidth, int& textIndex)
3586 {
3587         result r = E_SUCCESS;
3588         FloatDimension textSize;
3589         int currentLength = 0;
3590         int elementTextOffset = 0;
3591         int elementIndex = 0;
3592         int textIndexFromElementOffset = 0;
3593         int textCount = 0;
3594         float remainingWidth = 0;
3595         int remainingLength = 0;
3596         int ret = TEXT_RETBY_NORMAL;
3597         bool isFirstWord = true;
3598         int index = 0;
3599         textIndex = 0;
3600
3601         IEnumerator* pEnum = null;
3602         TextElement* pTextElement = null;
3603
3604         pTextElement = GetElementAtTextIndex(startTextIndex, elementTextOffset, elementIndex, currentLength, textIndexFromElementOffset);
3605         SysTryReturn(NID_GRP, pTextElement, -1, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
3606
3607         textCount = 0;
3608         remainingWidth = maxWidth;
3609         remainingLength = textLength;
3610
3611         pEnum = __pTextElementList->GetEnumeratorN();
3612         for (int i = 0; i <= elementIndex; i++)
3613         {
3614                 r = pEnum->MoveNext();
3615                 SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Fail to move next element.", GetErrorMessage(r));
3616         }
3617
3618         currentLength = Math::Min(remainingLength, currentLength);
3619
3620         while (remainingWidth > 0 || remainingLength > 0)
3621         {
3622                 ret = pTextElement->ForwardAnalyze(textIndexFromElementOffset, currentLength, remainingWidth,
3623                                                                                                                                                 __wrap, textCount, textSize.width, textSize.width);
3624
3625                 TextElementType objectType = pTextElement->GetType();
3626
3627                 if ((objectType == TEXT_ELEMENT_TYPE_TEXT || objectType == TEXT_ELEMENT_TYPE_CUTLINK) && (ret == TEXT_RETBY_LIMITWIDTH))
3628                 {
3629                         FloatDimension tempTextSize;
3630                         r = pTextElement->GetRegion(textIndexFromElementOffset, textCount + 1, tempTextSize.width, tempTextSize.height);
3631                         SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
3632
3633                         textSize.width = tempTextSize.width;
3634                         textCount++;
3635                 }
3636
3637                 remainingWidth -= textSize.width;
3638                 remainingWidth = (remainingWidth < 0) ? 0 : remainingWidth;
3639
3640                 remainingLength -= textCount;
3641                 currentLength -= textCount;
3642                 textIndex += textCount;
3643
3644                 if (__wrap == TEXT_OBJECT_WRAP_TYPE_WORD && ret != TEXT_RETBY_LIMITWIDTH)
3645                 {
3646                         index = textIndex;
3647                 }
3648
3649                 if (remainingLength <= currentLength)
3650                 {
3651                         break;
3652                 }
3653
3654                 if (ret == TEXT_RETBY_OVERWIDTH || ret == TEXT_RETBY_LINEFEED)
3655                 {
3656                         break;
3657                 }
3658
3659                 if (__wrap == TEXT_OBJECT_WRAP_TYPE_WORD)
3660                 {
3661                         if (ret == TEXT_RETBY_LIMITWIDTH)
3662                         {
3663                                 if (isFirstWord == false)
3664                                 {
3665                                         textIndex = index;
3666                                         ret = TEXT_RETBY_NORMAL;
3667                                 }
3668                                 break;
3669                         }
3670
3671                         isFirstWord = false;
3672
3673                         if (currentLength > 0)
3674                         {
3675                                 textIndexFromElementOffset += textCount;
3676                                 continue;
3677                         }
3678                 }
3679                 else
3680                 {
3681                         if (ret == TEXT_RETBY_LIMITWIDTH)
3682                         {
3683                                 break;
3684                         }
3685                 }
3686
3687                 if (pEnum->MoveNext() != E_SUCCESS)
3688                 {
3689                         break;
3690                 }
3691
3692                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
3693                 if (pTextElement == null)
3694                 {
3695                         break;
3696                 }
3697
3698                 textIndexFromElementOffset = pTextElement->GetValue(SET_TEXT_OFFSET);
3699                 currentLength = Math::Min(pTextElement->GetTextLength(), remainingLength);
3700         }
3701
3702         if (ret == TEXT_RETBY_LIMITLENGTH)
3703         {
3704                 ret = TEXT_RETBY_NORMAL;
3705         }
3706
3707         SetLastResult(E_SUCCESS);
3708         Release(pEnum);
3709         return ret;
3710
3711 CATCH:
3712         Release(pEnum);
3713         return ret;
3714 }
3715
3716 int
3717 TextComposite::GetCutLinkElementCount(void) const
3718 {
3719         return __pCutLinkListInfo->GetCutLinkElementCount();
3720 }
3721
3722 int
3723 TextComposite::GetCutLinkElementIndexAt(int textIndex) const
3724 {
3725         return __pCutLinkListInfo->GetCutLinkElementIndexAt(textIndex);
3726 }
3727
3728 TextCutLink*
3729 TextComposite::GetCutLinkElementAtCutLinkElementIndex(int index) const
3730 {
3731         return __pCutLinkListInfo->GetCutLinkElementAtCutLinkElementIndex(index);
3732 }
3733
3734 result
3735 TextComposite::ResetAllCutLinkElementsState(void)
3736 {
3737         return __pCutLinkListInfo->ResetAllCutLinkElementsState();
3738 }
3739
3740 result
3741 TextComposite::ChangeCutLinkState(int linkIndex, bool select)
3742 {
3743         return __pCutLinkListInfo->ChangeCutLinkState(linkIndex, select);
3744 }
3745
3746 result
3747 TextComposite::SetValueToAllTextElements(TextComponentInfoValueType type, unsigned int value)
3748 {
3749         if (__workLength == 0)
3750         {
3751                 return E_SUCCESS;
3752         }
3753
3754         result r = E_SUCCESS;
3755         IEnumerator* pEnum = null;
3756         TextElement* pTextElement = null;
3757         TextElement* pNewTextElement = null;
3758         int startElementIndex = -1;
3759         int endElementIndex = -1;
3760         int textIndex = 0;
3761         int textLength = 0;
3762         int elementTextOffset = 0;
3763         int elementIndex = 0;
3764         int currentLength = 0;
3765         int textIndexFromElementOffset = 0;
3766         int found = false;
3767
3768         textIndex = __workStart;
3769         textLength = __workLength;
3770
3771         while (textLength > 0)
3772         {
3773                 pTextElement = GetElementAtTextIndex(textIndex, elementTextOffset, elementIndex, currentLength, textIndexFromElementOffset);
3774                 SysTryReturn(NID_GRP, pTextElement, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text element. textIndex(%d)", textIndex);
3775                 SysTryReturn(NID_GRP, 0 < currentLength, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] _Text::TextElement is invalid.");
3776
3777                 TextElementType objectType = pTextElement->GetType();
3778                 unsigned int elementValue = pTextElement->GetValue(type);
3779                 TextElementType objectTypeFromValueType = TextUtility::GetObjectTypeFromValueType(type);
3780
3781                 if (objectType == objectTypeFromValueType && value != elementValue)
3782                 {
3783                         found = true;
3784                         startElementIndex = elementIndex;
3785                         break;
3786                 }
3787                 else if ((COMMONOBJECT_VALUE_START <= type && type < MAX_COMMONOBJECT_VALUE) && (value != elementValue))
3788                 {
3789                         found = true;
3790                         startElementIndex = elementIndex;
3791                         break;
3792                 }
3793
3794                 textIndex += currentLength;
3795                 textLength -= currentLength;
3796         }
3797
3798         if (!found)
3799         {
3800                 return E_SUCCESS;
3801         }
3802
3803         if (elementTextOffset == textIndex && textLength == currentLength)
3804         {
3805                 pTextElement->SetValue(type, value);
3806                 goto TRUE_CATCH;
3807         }
3808         else if (elementTextOffset < textIndex && textLength < currentLength)
3809         {
3810                 pTextElement->SetTextLength(pTextElement->GetTextLength() - currentLength);
3811
3812                 pNewTextElement = pTextElement->CloneN(type, value);
3813                 SysTryReturn(NID_GRP, pNewTextElement, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to clone text element.");
3814
3815                 pNewTextElement->SetTextLength(textLength);
3816                 pNewTextElement->SetValue(SET_TEXT_OFFSET, textIndexFromElementOffset);
3817
3818                 r = __pTextElementList->InsertAt(*pNewTextElement, ++elementIndex);
3819                 SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Fail to insert element.", GetErrorMessage(r));
3820
3821                 pNewTextElement = pTextElement->CloneN(SET_ALLVALUE_CLONE, 0);
3822                 SysTryReturn(NID_GRP, pNewTextElement, r, r, "[E_SYSTEM] Fail to clone text element.");
3823
3824                 pNewTextElement->SetTextLength(currentLength - textLength);
3825                 pNewTextElement->SetValue(SET_TEXT_OFFSET, textIndexFromElementOffset + textLength);
3826
3827                 r = __pTextElementList->InsertAt(*pNewTextElement, ++elementIndex);
3828                 SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Fail to insert element.", GetErrorMessage(r));
3829
3830                 endElementIndex = elementIndex;
3831                 goto TRUE_CATCH;
3832         }
3833         else if (elementTextOffset < textIndex)
3834         {
3835                 pTextElement->SetTextLength(pTextElement->GetTextLength() - currentLength);
3836
3837                 pNewTextElement = pTextElement->CloneN(type, value);
3838                 SysTryReturn(NID_GRP, pNewTextElement, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to clone text element.");
3839
3840                 pNewTextElement->SetValue(SET_TEXT_OFFSET, textIndexFromElementOffset);
3841                 pNewTextElement->SetTextLength(currentLength);
3842
3843                 r = __pTextElementList->InsertAt(*pNewTextElement, ++elementIndex);
3844                 SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Fail to insert element.", GetErrorMessage(r));
3845
3846                 textIndex += currentLength;
3847                 textLength -= currentLength;
3848
3849                 if (textLength > 0)
3850                 {
3851                         pTextElement = GetElementAtTextIndex(textIndex, elementTextOffset, elementIndex, currentLength, textIndexFromElementOffset);
3852                         if (pTextElement == null)
3853                         {
3854                                 goto TRUE_CATCH;
3855                         }
3856                 }
3857                 else
3858                 {
3859                         endElementIndex = elementIndex;
3860                         goto TRUE_CATCH;
3861                 }
3862         }
3863
3864         pEnum = __pTextElementList->GetEnumeratorN();
3865         for (int i = 0; i <= elementIndex; i++)
3866         {
3867                 r = pEnum->MoveNext();
3868                 SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Fail to move next element.", GetErrorMessage(r));
3869         }
3870
3871         while (textLength > 0)
3872         {
3873                 TextElementType objectType = pTextElement->GetType();
3874                 TextElementType objectTypeFromValueType = TextUtility::GetObjectTypeFromValueType(type);
3875                 unsigned int elementValue = pTextElement->GetValue(type);
3876
3877                 if (objectType == objectTypeFromValueType && value != elementValue)
3878                 {
3879                         if (textLength < currentLength)
3880                         {
3881                                 pNewTextElement = pTextElement->CloneN(SET_ALLVALUE_CLONE, 0);
3882                                 SysTryReturn(NID_GRP, pNewTextElement, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to clone text element.");
3883
3884                                 pNewTextElement->SetTextLength(currentLength - textLength);
3885                                 pNewTextElement->SetValue(SET_TEXT_OFFSET, textIndexFromElementOffset + textLength);
3886
3887                                 pTextElement->SetValue(type, value);
3888                                 pTextElement->SetTextLength(textLength);
3889
3890                                 r = __pTextElementList->InsertAt(*pNewTextElement, ++elementIndex);
3891                                 SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Fail to insert element.", GetErrorMessage(r));
3892
3893                                 break;
3894                         }
3895                         else
3896                         {
3897                                 pTextElement->SetValue(type, value);
3898                         }
3899
3900                         endElementIndex = elementIndex;
3901                 }
3902
3903                 elementTextOffset += currentLength;
3904                 textLength -= currentLength;
3905                 elementIndex++;
3906
3907                 if (pEnum->MoveNext() != E_SUCCESS)
3908                 {
3909                         break;
3910                 }
3911
3912                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
3913                 if (pTextElement == null)
3914                 {
3915                         break;
3916                 }
3917
3918                 currentLength = pTextElement->GetTextLength();
3919                 textIndexFromElementOffset = pTextElement->GetValue(SET_TEXT_OFFSET);
3920         }
3921
3922 TRUE_CATCH:
3923         Optimize(startElementIndex, endElementIndex);
3924         Release(pEnum);
3925         return E_SUCCESS;
3926
3927 CATCH:
3928         Release(pNewTextElement);
3929         Release(pEnum);
3930         return r;
3931 }
3932
3933 bool
3934 TextComposite::SetAbbrevObjectFontInfo(TextSimple* pSimpleText)
3935 {
3936         SysTryReturn(NID_GRP, __pAbbrevTextElement, false, E_INVALID_STATE, "[E_INVALID_STATE] This instance is not constructed yet.");
3937
3938         __pAbbrevTextElement->SetFont(pSimpleText->GetFont());
3939         __pAbbrevTextElement->SetForegroundColor(pSimpleText->GetForegroundColor());
3940         __pAbbrevTextElement->SetBackgroundColor(pSimpleText->GetBackgroundColor());
3941         __pAbbrevTextElement->SetOutlineColor(pSimpleText->GetOutlineColor());
3942         __pAbbrevTextElement->SetAlternativeForegroundColor(pSimpleText->GetAlternativeForegroundColor());
3943         __pAbbrevTextElement->SetAlternateLookEnabled(pSimpleText->IsAlternateLookEnabled());
3944
3945         return true;
3946 }
3947
3948 int
3949 TextComposite::ComposeInNoneWrap(FloatRectangle& rect, NoneWrapComposeInfo* pNoneWrapComposeInfo)
3950 {
3951         SysTryReturn(NID_GRP, __pCurrentTextColumn, -1, E_INVALID_STATE, "[E_INVALID_STATE] This instance is not constructed yet.");
3952
3953         TextLine* pTextLine = null;
3954         FloatRectangle lineBounds;
3955         FloatDimension textSize;
3956         int lineOffset = 0;
3957         int lineLength = 0;
3958         int endType = TEXT_RETBY_NORMAL;
3959         bool isChanged = false;
3960         float baseline = 0;
3961         int textIndex = 0;
3962
3963         textIndex = (__workStart < 0) ? 0 : __workStart;
3964         textIndex = (textIndex > __length) ? __length : textIndex;
3965         bool forwardSearch = (textIndex == __length) ? false : true;
3966
3967         if (__pCurrentTextColumn->GetTotalLineCount() > 0)
3968         {
3969                 pTextLine = __pCurrentTextColumn->GetTextLine(0);
3970                 SysTryReturn(NID_GRP, pTextLine, -1, E_SYSTEM, "[E_SYSTEM] Fail to get text line.");
3971
3972                 lineBounds = pTextLine->GetBoundsF();
3973                 endType = pTextLine->GetEndType();
3974
3975                 if (lineBounds.width != rect.width)
3976                 {
3977                         isChanged = true;
3978                 }
3979
3980                 lineOffset = pTextLine->GetTextOffset();
3981                 lineLength = pTextLine->GetTextLength();
3982
3983                 if (lineOffset <= textIndex && textIndex < lineOffset + lineLength)
3984                 {
3985                         isChanged = true;
3986                 }
3987         }
3988         else
3989         {
3990                 pTextLine = new (std::nothrow)TextLine(this);
3991                 SysTryReturn(NID_GRP, pTextLine, -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
3992
3993                 if (forwardSearch)
3994                 {
3995                         if (pNoneWrapComposeInfo != null)
3996                         {
3997                                 lineOffset = pNoneWrapComposeInfo->prevTextOffset;
3998                         }
3999                         else
4000                         {
4001                                 lineOffset = 0;
4002                         }
4003                 }
4004                 else
4005                 {
4006                         lineOffset = __length - 1;
4007                 }
4008
4009                 lineLength = 0;
4010                 lineBounds.width = rect.width;
4011                 lineBounds.x = 0;
4012                 lineBounds.y = 0;
4013                 lineBounds.height = 0;
4014
4015                 __pCurrentTextColumn->AddLineDuringCompose(pTextLine);
4016
4017                 isChanged = true;
4018         }
4019
4020         if (isChanged)
4021         {
4022                 lineBounds.width = rect.width;
4023                 lineBounds.x = 0;
4024                 lineBounds.y = 0;
4025
4026                 if (forwardSearch)
4027                 {
4028                         endType = ForwardAnalyzeWithBaseline(lineOffset, __length - lineOffset, lineBounds.width, __wrap,
4029                                                                           lineLength, textSize.width, textSize.height, baseline);
4030
4031                         lineBounds.height = textSize.height;
4032                         pTextLine->SetBounds(lineBounds);
4033                         pTextLine->SetTextOffset(lineOffset);
4034                         pTextLine->SetTextLength(lineLength);
4035                         pTextLine->SetRegion(textSize.width, textSize.height);
4036                         pTextLine->SetEndType(endType);
4037                         pTextLine->SetBaseline(baseline);
4038                         GetTextExtentList(pTextLine);
4039                 }
4040                 else
4041                 {
4042                         int textCount = 0;
4043
4044                         BackwardAnalyze(lineOffset, lineBounds.width, &textCount, &textSize.width, &textSize.height);
4045
4046                         lineBounds.height = textSize.height;
4047                         lineOffset -= (textCount - 1);
4048                         lineLength = textCount;
4049                         endType = (lineOffset == 0) ? TEXT_RETBY_NORMAL : TEXT_RETBY_LIMITWIDTH;
4050
4051                         pTextLine->SetBounds(lineBounds);
4052                         pTextLine->SetTextOffset(lineOffset);
4053                         pTextLine->SetTextLength(lineLength);
4054                         pTextLine->SetRegion(textSize.width, textSize.height);
4055                         pTextLine->SetEndType(endType);
4056                         pTextLine->SetBaseline(baseline);
4057                         GetTextExtentList(pTextLine);
4058                 }
4059         }
4060
4061         if (__length == 0)
4062         {
4063                 pTextLine->SetEndType(TEXT_RETBY_NORMAL);
4064                 return 1;
4065         }
4066
4067         rect.height = lineBounds.height;
4068
4069         if (textIndex < lineOffset)
4070         {
4071                 lineOffset = textIndex;
4072                 endType = ForwardAnalyze(lineOffset, __length - lineOffset, lineBounds.width, __wrap,
4073                                                                   lineLength, textSize.width, textSize.height);
4074
4075                 lineBounds.height = textSize.height;
4076         }
4077         else if (forwardSearch && textIndex >= lineOffset + lineLength)
4078         {
4079                 FloatDimension needDim;
4080                 GetRegion(lineOffset + lineLength, textIndex - (lineOffset + lineLength) + 1, needDim.width, needDim.height);
4081
4082                 int index = 0;
4083                 float remainingWidth = needDim.width - (lineBounds.width - textSize.width);
4084
4085                 FloatDimension charDim;
4086                 textSize.width += needDim.width;
4087                 lineLength += textIndex - (lineOffset + lineLength) + 1;
4088
4089                 while (1)
4090                 {
4091                         GetRegion(lineOffset, 1, charDim.width, charDim.height);
4092                         lineOffset++;
4093                         index++;
4094                         remainingWidth -= charDim.width;
4095                         textSize.width -= charDim.width;
4096
4097                         if (remainingWidth <= 0)
4098                         {
4099                                 break;
4100                         }
4101                 }
4102
4103                 lineLength -= index;
4104         }
4105         else if (endType != TEXT_RETBY_LIMITWIDTH && lineLength != __length)
4106         {
4107                 if (lineOffset > 0)
4108                 {
4109                         FloatDimension lineTextSize;
4110                         int textCount = 0;
4111                         float remainingWidth = 0;
4112
4113                         pTextLine->GetRegion(0, lineLength, lineTextSize.width, lineTextSize.height);
4114                         remainingWidth = lineBounds.width - lineTextSize.width;
4115                         BackwardAnalyze(lineOffset - 1, remainingWidth, &textCount, &textSize.width, &textSize.height);
4116
4117                         if (textSize.width > 0)
4118                         {
4119                                 lineOffset -= textCount;
4120                                 lineLength += textCount;
4121                                 textSize.width += lineTextSize.width;
4122                                 lineBounds.height = textSize.height;
4123                                 endType = TEXT_RETBY_LIMITLENGTH;
4124                         }
4125                         else
4126                         {
4127                                 return 1;
4128                         }
4129                 }
4130                 else
4131                 {
4132                         return 1;
4133                 }
4134         }
4135         else
4136         {
4137                 return 1;
4138         }
4139
4140         pTextLine->SetBounds(lineBounds);
4141         pTextLine->SetRegion(textSize.width, textSize.height);
4142         pTextLine->SetTextLength(lineLength);
4143         pTextLine->SetTextOffset(lineOffset);
4144         pTextLine->SetEndType(endType);
4145         pTextLine->SetBaseline(baseline);
4146         GetTextExtentList(pTextLine);
4147
4148         return 1;
4149 }
4150
4151 result
4152 TextComposite::GetTextExtentList(TextLine* pTextLine) const
4153 {
4154         result r = E_SUCCESS;
4155         int lineOffset = pTextLine->GetTextOffset();
4156         int lineLength = pTextLine->GetTextLength();
4157         int elementTextOffset = 0;
4158         int elementIndex = 0;
4159         int currentLength = 0;
4160         int textIndexFromElementOffset = 0;
4161         int remainingLength = 0;
4162         float right = 0;
4163         float maxWidth = 0;
4164
4165         TextElement* pTextElement = GetElementAtTextIndex(lineOffset, elementTextOffset, elementIndex, currentLength, textIndexFromElementOffset);
4166         SysTryReturn(NID_GRP, pTextElement, -1, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
4167
4168         remainingLength = lineLength;
4169         currentLength = Math::Min(remainingLength, currentLength);
4170
4171         IEnumerator* pEnum = __pTextElementList->GetEnumeratorN();
4172         for (int i = 0; i <= elementIndex; i++)
4173         {
4174                 r = pEnum->MoveNext();
4175         }
4176
4177         Collection::ArrayListT<_FloatPair>* pGapListF = new (std::nothrow) Collection::ArrayListT<_FloatPair>;
4178         _FloatPair currentGap;
4179
4180         while (remainingLength != 0)
4181         {
4182                 TextElementType objectType = pTextElement->GetType();
4183                 if (objectType == TEXT_ELEMENT_TYPE_CUTLINK || objectType == TEXT_ELEMENT_TYPE_TEXT)
4184                 {
4185                         TextSimple* pSimpleText = dynamic_cast < TextSimple* >(pTextElement);
4186                         if (pSimpleText != null)
4187                         {
4188                                 const Bitmap* pBitmap = pSimpleText->GetBitmap();
4189                                 if (pBitmap)
4190                                 {
4191                                         currentGap.first = maxWidth;
4192                                         currentGap.second = currentGap.first + pBitmap->GetWidth();
4193
4194                                         pGapListF->Add(currentGap);
4195                                         right = (right < currentGap.second) ? currentGap.second : right;
4196                                 }
4197                                 else
4198                                 {
4199                                         _FontImpl* pFontImpl = _FontImpl::GetInstance(*const_cast < Font* >(pSimpleText->GetFont()));
4200                                         SysTryCatch(NID_GRP, pFontImpl, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get native font instance.");
4201
4202                                         Collection::ArrayListT<_FloatPair> pCurrentElementGapListF;
4203
4204                                         const wchar_t* pText = pSimpleText->GetTextSource();
4205                                         pFontImpl->GetTextExtentList(pText, textIndexFromElementOffset, currentLength, pCurrentElementGapListF);
4206
4207                                         IEnumeratorT<_FloatPair >* pCurrentElementGapEnum = pCurrentElementGapListF.GetEnumeratorN();
4208                                         while (pCurrentElementGapEnum->MoveNext() == E_SUCCESS)
4209                                         {
4210                                                 pCurrentElementGapEnum->GetCurrent(currentGap);
4211
4212                                                 currentGap.first = maxWidth + currentGap.first;
4213                                                 currentGap.second = maxWidth + currentGap.second;
4214
4215                                                 pGapListF->Add(currentGap);
4216                                                 right = (right < currentGap.second) ? currentGap.second : right;
4217                                         }
4218
4219                                         Release(pCurrentElementGapEnum);
4220                                 }
4221                         }
4222                 }
4223                 else if (objectType == TEXT_ELEMENT_TYPE_IMAGE)
4224                 {
4225                         TextImage* pImageText = dynamic_cast < TextImage* >(pTextElement);
4226                         if (pImageText != null)
4227                         {
4228                                 FloatRectangle rect = pImageText->GetBoundsF();
4229
4230                                 currentGap.first = maxWidth;
4231                                 currentGap.second = currentGap.first + rect.width;
4232
4233                                 pGapListF->Add(currentGap);
4234                                 right = (right < currentGap.second) ? currentGap.second : right;
4235                         }
4236                 }
4237
4238                 remainingLength -= currentLength;
4239
4240                 if (pEnum->MoveNext() != E_SUCCESS)
4241                 {
4242                         break;
4243                 }
4244
4245                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
4246                 if (pTextElement == null)
4247                 {
4248                         break;
4249                 }
4250
4251                 textIndexFromElementOffset = pTextElement->GetValue(SET_TEXT_OFFSET);
4252                 currentLength = Math::Min(pTextElement->GetTextLength(), remainingLength);
4253                 maxWidth = right;
4254                 right = 0;
4255         }
4256
4257         pTextLine->SetTextExtentList(pGapListF);
4258
4259         Release(pEnum);
4260
4261         return E_SUCCESS;
4262
4263 CATCH:
4264         Release(pEnum);
4265
4266         Release(pGapListF);
4267
4268         return r;
4269 }
4270
4271 int
4272 TextComposite::ComposeInWrap(FloatRectangle& rect)
4273 {
4274         SysTryReturn(NID_GRP, __pCurrentTextColumn, -1, E_INVALID_STATE, "[E_INVALID_STATE] This instance is not constructed yet.");
4275
4276         int textCount = 0;
4277         int lineCount = 0;
4278         int textIndex = 0;
4279         int remainingLength = 0;
4280         float remainingWidth = 0;
4281         float remainingHeight = 0;
4282         float offsetY = 0;
4283         bool hasPrevLine = false;
4284         FloatDimension textSize;
4285         TextLine* pTextLine = null;
4286         int ret = 0;
4287         int endType = TEXT_RETBY_NORMAL;
4288         FloatRectangle lineBounds;
4289         FloatDimension lineTextSize;
4290         int lineOffset = 0;
4291         int lineLength = 0;
4292         int displayLineCount = 0;
4293         float displayHeight = 0;
4294         float baseline = 0;
4295         float lineBaseline = 0;
4296
4297         pTextLine = __pCurrentTextColumn->GetPrevLineChangedStartLine();
4298         if (pTextLine != null)
4299         {
4300                 endType = pTextLine->GetEndType();
4301                 lineOffset = pTextLine->GetTextOffset();
4302                 lineLength = pTextLine->GetTextLength();
4303                 lineBounds = pTextLine->GetBoundsF();
4304                 lineBaseline = pTextLine->GetBaselineF();
4305                 pTextLine->GetRegion(0, pTextLine->GetTextLength(), lineTextSize.width, lineTextSize.height);
4306
4307                 if (endType != TEXT_RETBY_LINEFEED)
4308                 {
4309                         textIndex = lineOffset + lineLength;
4310                         remainingLength = __length - textIndex;
4311                         remainingWidth = lineBounds.width - lineTextSize.width;
4312                         hasPrevLine = true;
4313
4314                         if (remainingLength == 0)
4315                         {
4316                                 return -1;
4317                         }
4318                 }
4319                 else
4320                 {
4321                         textIndex = lineOffset + lineLength;
4322                         remainingLength = __length - textIndex;
4323                         remainingWidth = rect.width;
4324                         offsetY = lineBounds.y + lineBounds.height;
4325
4326                         if (remainingLength == 0)
4327                         {
4328                                 float nextY = offsetY;
4329                                 lineTextSize.height = lineBounds.height;
4330
4331                                 pTextLine = new (std::nothrow)TextLine(this);
4332                                 SysTryReturn(NID_GRP, pTextLine, -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
4333
4334                                 lineBounds.y = nextY;
4335
4336                                 pTextLine->SetBounds(lineBounds);
4337                                 pTextLine->SetRegion(0.0f, lineTextSize.height);
4338                                 pTextLine->SetTextLength(0);
4339                                 pTextLine->SetTextOffset(textIndex);
4340                                 pTextLine->SetEndType(TEXT_RETBY_LINEFEED);
4341                                 pTextLine->SetBaseline(0);
4342                                 GetTextExtentList(pTextLine);
4343
4344                                 __pCurrentTextColumn->AddLineDuringCompose(pTextLine);
4345
4346                                 if (lineBounds.y + lineBounds.height <= rect.height)
4347                                 {
4348                                         __pCurrentTextColumn->SetDisplayLineCount(++displayLineCount);
4349                                         displayHeight += lineBounds.height;
4350                                         __pCurrentTextColumn->SetDisplayHeight(displayHeight);
4351                                 }
4352
4353                                 return 1;
4354                         }
4355                 }
4356         }
4357         else
4358         {
4359                 textIndex = 0;
4360                 remainingLength = __length;
4361                 remainingWidth = rect.width;
4362
4363                 __pCurrentTextColumn->SetChangedStartLineIndex(0);
4364         }
4365
4366         if (!hasPrevLine)
4367         {
4368                 pTextLine = new (std::nothrow)TextLine(this);
4369                 SysTryReturn(NID_GRP, pTextLine, -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
4370
4371                 lineBounds.x = rect.x;
4372                 lineBounds.width = rect.width;
4373                 lineBounds.y = offsetY;
4374                 lineTextSize.height = 0;
4375
4376                 if (remainingLength == 0)
4377                 {
4378                         lineTextSize.height = GetHeightF(0);
4379                         lineBounds.height = lineTextSize.height;
4380
4381                         pTextLine->SetBounds(lineBounds);
4382                         pTextLine->SetRegion(0.0f, lineTextSize.height);
4383                         pTextLine->SetTextLength(0);
4384                         pTextLine->SetTextOffset(textIndex);
4385                         pTextLine->SetEndType(TEXT_RETBY_NORMAL);
4386                         pTextLine->SetBaseline(0);
4387                         GetTextExtentList(pTextLine);
4388
4389                         __pCurrentTextColumn->AddLineDuringCompose(pTextLine);
4390
4391                         if (lineBounds.y + lineBounds.height <= rect.height)
4392                         {
4393                                 __pCurrentTextColumn->SetDisplayLineCount(++displayLineCount);
4394                                 displayHeight += lineBounds.height;
4395                                 __pCurrentTextColumn->SetDisplayHeight(displayHeight);
4396                         }
4397
4398                         return 1;
4399                 }
4400         }
4401
4402         remainingHeight = rect.height;
4403
4404         while (remainingLength != 0)
4405         {
4406                 ret = ForwardAnalyzeWithBaseline(textIndex, remainingLength, remainingWidth, __wrap, textCount, textSize.width, textSize.height, baseline);
4407
4408                 if (ret == -1)
4409                 {
4410                         Release(pTextLine);
4411                         break;
4412                 }
4413
4414                 if (!hasPrevLine)
4415                 {
4416                         if (textCount == 0)
4417                         {
4418                                 textCount = 1;
4419                         }
4420
4421                         lineOffset = textIndex;
4422                         lineLength = textCount;
4423                         lineTextSize.width = textSize.width;
4424                         lineTextSize.height = textSize.height;
4425                         lineBounds.height = textSize.height;
4426                         endType = ret;
4427
4428                         pTextLine->SetBounds(lineBounds);
4429                         pTextLine->SetRegion(lineTextSize.width, lineTextSize.height);
4430                         pTextLine->SetTextLength(lineLength);
4431                         pTextLine->SetTextOffset(lineOffset);
4432                         pTextLine->SetEndType(ret);
4433                         pTextLine->SetBaseline(baseline);
4434                         GetTextExtentList(pTextLine);
4435
4436                         __pCurrentTextColumn->AddLineDuringCompose(pTextLine);
4437                         lineCount++;
4438
4439                         if (lineBounds.y + lineBounds.height <= rect.height)
4440                         {
4441                                 __pCurrentTextColumn->SetDisplayLineCount(++displayLineCount);
4442                                 displayHeight += lineBounds.height;
4443                                 __pCurrentTextColumn->SetDisplayHeight(displayHeight);
4444                         }
4445                 }
4446                 else
4447                 {
4448                         if (__wrap == TEXT_OBJECT_WRAP_TYPE_WORD)
4449                         {
4450                                 if (ret != TEXT_RETBY_LIMITWIDTH)
4451                                 {
4452                                         lineLength += textCount;
4453                                         lineTextSize.width += textSize.width;
4454                                         lineBounds.height = (lineBounds.height > textSize.height) ? lineBounds.height: textSize.height;
4455                                         lineTextSize.height = lineBounds.height;
4456                                         endType = ret;
4457                                         baseline = (lineBaseline > baseline) ? baseline : lineBaseline;
4458
4459                                         pTextLine->SetBounds(lineBounds);
4460                                         pTextLine->SetRegion(lineTextSize.width, lineTextSize.height);
4461                                         pTextLine->SetTextLength(lineLength);
4462                                         pTextLine->SetEndType(endType);
4463                                         pTextLine->SetBaseline(baseline);
4464                                         GetTextExtentList(pTextLine);
4465
4466                                         __pCurrentTextColumn->CheckComposeDone(pTextLine);
4467                                 }
4468                                 else
4469                                 {
4470                                         textCount = 0;
4471                                 }
4472                         }
4473                         else
4474                         {
4475                                 lineLength += textCount;
4476                                 lineTextSize.width += textSize.width;
4477                                 lineBounds.height = (lineBounds.height > textSize.height) ? lineBounds.height : textSize.height;
4478                                 lineTextSize.height = lineBounds.height;
4479                                 endType = ret;
4480                                 baseline = (lineBaseline > baseline) ? baseline : lineBaseline;
4481
4482                                 pTextLine->SetBounds(lineBounds);
4483                                 pTextLine->SetRegion(lineTextSize.width, lineTextSize.height);
4484                                 pTextLine->SetTextLength(lineLength);
4485                                 pTextLine->SetEndType(endType);
4486                                 pTextLine->SetBaseline(baseline);
4487                                 GetTextExtentList(pTextLine);
4488
4489                                 __pCurrentTextColumn->CheckComposeDone(pTextLine);
4490                         }
4491
4492                         if (textCount > 0)
4493                         {
4494                                 __pCurrentTextColumn->SetChangedStartLineIndex(pTextLine->GetIndex());
4495                         }
4496
4497                         hasPrevLine = false;
4498                 }
4499
4500                 if (__pCurrentTextColumn->IsComposeDone())
4501                 {
4502                         break;
4503                 }
4504
4505                 textIndex += textCount;
4506                 remainingLength -= textCount;
4507
4508                 remainingHeight -= lineTextSize.height;
4509
4510                 if (remainingLength > 0)
4511                 {
4512                         float nextY = lineBounds.y + lineBounds.height;
4513
4514                         pTextLine = new (std::nothrow)TextLine(this);
4515                         SysTryReturn(NID_GRP, pTextLine, -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
4516
4517                         lineBounds.x = rect.x;
4518                         lineBounds.y = nextY;
4519                         lineBounds.width = rect.width;
4520                         lineTextSize.height = 0;
4521
4522                         remainingWidth = rect.width;
4523                 }
4524                 else
4525                 {
4526                         if (endType == TEXT_RETBY_LINEFEED)
4527                         {
4528                                 float nextY = lineBounds.y + lineBounds.height;
4529                                 lineTextSize.height = lineBounds.height;
4530
4531                                 pTextLine = new (std::nothrow)TextLine(this);
4532                                 SysTryReturn(NID_GRP, pTextLine, -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
4533
4534                                 lineBounds.x = rect.x;
4535                                 lineBounds.y = nextY;
4536                                 lineBounds.width = rect.width;
4537                                 lineBounds.height = lineTextSize.height;
4538
4539                                 pTextLine->SetBounds(lineBounds);
4540                                 pTextLine->SetRegion(0.0f, lineTextSize.height);
4541                                 pTextLine->SetTextLength(0);
4542                                 pTextLine->SetTextOffset(textIndex);
4543                                 pTextLine->SetEndType(TEXT_RETBY_LINEFEED);
4544                                 pTextLine->SetBaseline(0);
4545                                 GetTextExtentList(pTextLine);
4546
4547                                 __pCurrentTextColumn->AddLineDuringCompose(pTextLine);
4548                                 lineCount++;
4549
4550                                 if (lineBounds.y + lineBounds.height <= rect.height)
4551                                 {
4552                                         __pCurrentTextColumn->SetDisplayLineCount(++displayLineCount);
4553                                         displayHeight += lineBounds.height;
4554                                         __pCurrentTextColumn->SetDisplayHeight(displayHeight);
4555                                 }
4556
4557                                 pTextLine = null;
4558                                 break;
4559                         }
4560                 }
4561         }
4562
4563         FloatDimension columnTextSize;
4564         __pCurrentTextColumn->GetRegion(0, __length, columnTextSize.width, columnTextSize.height);
4565         rect.height = columnTextSize.height;
4566
4567         if (pTextLine)
4568         {
4569                 __pCurrentTextColumn->SetChangedLastLineIndex(pTextLine->GetIndex());
4570         }
4571
4572         if (Tizen::App::_AppInfo::IsOspCompat())
4573         {
4574                 __pCurrentTextColumn->SetDisplayLineCount(0);
4575                 __pCurrentTextColumn->SetDisplayHeight(0);
4576         }
4577
4578         return lineCount;
4579 }
4580
4581 int
4582 TextComposite::ComposeInPartialMode(FloatRectangle& rect)
4583 {
4584         SysTryReturn(NID_GRP, __pCurrentTextColumn, -1, E_INVALID_STATE
4585                 , "[E_INVALID_STATE] This instance is not constructed yet.");
4586
4587         int textCount = 0;
4588         int lineCount = 0;
4589         int textIndex = 0;
4590         int remainingLength = 0;
4591         float remainingWidth = 0;
4592         float remainingHeight = 0;
4593         int lineOffset = 0;
4594         int lineLength = 0;
4595         float offsetY = 0;
4596         int ret = 0;
4597         FloatDimension textSize;
4598         FloatDimension lineTextSize;
4599         FloatRectangle lineBounds;
4600         bool hasPrevLine = false;
4601         int displayLineCount = 0;
4602         float displayHeight = 0;
4603         float baseline = 0;
4604         float lineBaseline = 0;
4605         TextLine* pTextLine = null;
4606         int endType = TEXT_RETBY_NORMAL;
4607
4608         if (__lineIndexCompositeDone != 0)
4609         {
4610                 pTextLine = __pCurrentTextColumn->GetTextLine(__lineIndexCompositeDone - 1);
4611                 lineCount = __lineIndexCompositeDone;
4612         }
4613
4614         if (pTextLine != null)
4615         {
4616                 endType = pTextLine->GetEndType();
4617                 lineOffset = pTextLine->GetTextOffset();
4618                 lineLength = pTextLine->GetTextLength();
4619                 lineBounds = pTextLine->GetBoundsF();
4620                 lineBaseline = pTextLine->GetBaselineF();
4621                 pTextLine->GetRegion(0, pTextLine->GetTextLength(), lineTextSize.width, lineTextSize.height);
4622
4623                 if (endType != TEXT_RETBY_LINEFEED)
4624                 {
4625                         textIndex = lineOffset + lineLength;
4626                         remainingLength = __length - textIndex;
4627                         remainingWidth = lineBounds.width - lineTextSize.width;
4628                         hasPrevLine = true;
4629
4630                         if (remainingLength == 0)
4631                         {
4632                                 return -1;
4633                         }
4634                 }
4635                 else
4636                 {
4637                         textIndex = lineOffset + lineLength;
4638                         remainingLength = __length - textIndex;
4639                         remainingWidth = rect.width;
4640                         offsetY = lineBounds.y + lineBounds.height;
4641
4642                         if (remainingLength == 0)
4643                         {
4644                                 float nextY = offsetY;
4645                                 lineTextSize.height = lineBounds.height;
4646
4647                                 pTextLine = new (std::nothrow)TextLine(this);
4648                                 SysTryReturn(NID_GRP, pTextLine, -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
4649
4650                                 lineBounds.y = nextY;
4651
4652                                 pTextLine->SetBounds(lineBounds);
4653                                 pTextLine->SetRegion(0.0f, lineTextSize.height);
4654                                 pTextLine->SetTextLength(0);
4655                                 pTextLine->SetTextOffset(textIndex);
4656                                 pTextLine->SetEndType(TEXT_RETBY_LINEFEED);
4657                                 pTextLine->SetBaseline(0);
4658                                 GetTextExtentList(pTextLine);
4659
4660                                 __pCurrentTextColumn->AddLineDuringCompose(pTextLine);
4661
4662                                 if (lineBounds.y + lineBounds.height <= rect.height)
4663                                 {
4664                                         __pCurrentTextColumn->SetDisplayLineCount(++displayLineCount);
4665                                         displayHeight += lineBounds.height;
4666                                         __pCurrentTextColumn->SetDisplayHeight(displayHeight);
4667                                 }
4668
4669                                 return 1;
4670                         }
4671                 }
4672         }
4673         else
4674         {
4675                 textIndex = 0;
4676                 remainingLength = __length;
4677                 remainingWidth = rect.width;
4678
4679                 __pCurrentTextColumn->SetChangedStartLineIndex(0);
4680         }
4681
4682         if (!hasPrevLine)
4683         {
4684                 pTextLine = new (std::nothrow)TextLine(this);
4685                 SysTryReturn(NID_GRP, pTextLine, -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
4686
4687                 lineBounds.x = rect.x;
4688                 lineBounds.width = rect.width;
4689                 lineBounds.y = offsetY;
4690                 lineTextSize.height = 0;
4691
4692                 if (remainingLength == 0)
4693                 {
4694                         lineTextSize.height = GetHeightF(0);
4695                         lineBounds.height = lineTextSize.height;
4696
4697                         pTextLine->SetBounds(lineBounds);
4698                         pTextLine->SetRegion(0.0f, lineTextSize.height);
4699                         pTextLine->SetTextLength(0);
4700                         pTextLine->SetTextOffset(textIndex);
4701                         pTextLine->SetEndType(TEXT_RETBY_NORMAL);
4702                         pTextLine->SetBaseline(0);
4703                         GetTextExtentList(pTextLine);
4704
4705                         __pCurrentTextColumn->AddLineDuringCompose(pTextLine);
4706
4707                         if (lineBounds.y + lineBounds.height <= rect.height)
4708                         {
4709                                 __pCurrentTextColumn->SetDisplayLineCount(++displayLineCount);
4710                                 displayHeight += lineBounds.height;
4711                                 __pCurrentTextColumn->SetDisplayHeight(displayHeight);
4712                         }
4713
4714                         return 1;
4715                 }
4716         }
4717
4718         remainingHeight = GetComposePartialLimitHeightF();
4719         if (remainingHeight == 0)
4720         {
4721                 remainingHeight = rect.height;
4722         }
4723         if (remainingHeight < lineBounds.height && remainingLength > 0)
4724         {
4725                 remainingHeight = lineBounds.height;
4726         }
4727
4728         while (remainingLength != 0)
4729         {
4730                 ret = ForwardAnalyzeWithBaseline(textIndex, remainingLength, remainingWidth, __wrap, textCount, textSize.width, textSize.height, baseline);
4731
4732                 if (ret == -1)
4733                 {
4734                         Release(pTextLine);
4735                         break;
4736                 }
4737
4738                 if (!hasPrevLine)
4739                 {
4740                         if (textCount == 0)
4741                         {
4742                                 textCount = 1;
4743                         }
4744
4745                         lineOffset = textIndex;
4746                         lineLength = textCount;
4747                         lineTextSize.width = textSize.width;
4748                         lineTextSize.height = textSize.height;
4749                         lineBounds.height = textSize.height;
4750                         endType = ret;
4751
4752                         pTextLine->SetBounds(lineBounds);
4753                         pTextLine->SetRegion(lineTextSize.width, lineTextSize.height);
4754                         pTextLine->SetTextLength(lineLength);
4755                         pTextLine->SetTextOffset(lineOffset);
4756                         pTextLine->SetEndType(endType);
4757                         pTextLine->SetBaseline(baseline);
4758                         GetTextExtentList(pTextLine);
4759
4760                         __pCurrentTextColumn->AddLineDuringCompose(pTextLine);
4761
4762                         if (lineBounds.y + lineBounds.height <= rect.height)
4763                         {
4764                                 __pCurrentTextColumn->SetDisplayLineCount(++displayLineCount);
4765                                 displayHeight += lineBounds.height;
4766                                 __pCurrentTextColumn->SetDisplayHeight(displayHeight);
4767                         }
4768
4769                         lineCount++;
4770                         __lineIndexCompositeDone++;
4771                         __totalComposedHeight += lineTextSize.height;
4772                 }
4773                 else
4774                 {
4775                         if (__wrap == TEXT_OBJECT_WRAP_TYPE_WORD)
4776                         {
4777                                 if (ret != TEXT_RETBY_LIMITWIDTH)
4778                                 {
4779                                         lineLength += textCount;
4780                                         lineTextSize.width += textSize.width;
4781                                         lineBounds.height = (lineBounds.height > textSize.height) ? lineBounds.height: textSize.height;
4782                                         lineTextSize.height = lineBounds.height;
4783                                         endType = ret;
4784                                         baseline = (lineBaseline > baseline) ? baseline : lineBaseline;
4785
4786                                         pTextLine->SetBounds(lineBounds);
4787                                         pTextLine->SetRegion(lineTextSize.width, lineTextSize.height);
4788                                         pTextLine->SetTextLength(lineLength);
4789                                         pTextLine->SetEndType(endType);
4790                                         pTextLine->SetBaseline(baseline);
4791                                         GetTextExtentList(pTextLine);
4792                                 }
4793                                 else
4794                                 {
4795                                         textCount = 0;
4796                                 }
4797                         }
4798                         else
4799                         {
4800                                 lineLength += textCount;
4801                                 lineTextSize.width += textSize.width;
4802                                 lineBounds.height = (lineBounds.height > textSize.height) ? lineBounds.height  : textSize.height;
4803                                 lineTextSize.height = lineBounds.height;
4804                                 endType = ret;
4805                                 baseline = (lineBaseline > baseline) ? baseline : lineBaseline;
4806
4807                                 pTextLine->SetBounds(lineBounds);
4808                                 pTextLine->SetRegion(lineTextSize.width, lineTextSize.height);
4809                                 pTextLine->SetTextLength(lineLength);
4810                                 pTextLine->SetEndType(endType);
4811                                 pTextLine->SetBaseline(baseline);
4812                                 GetTextExtentList(pTextLine);
4813                         }
4814
4815                         if (textCount > 0)
4816                         {
4817                                 __pCurrentTextColumn->SetChangedStartLineIndex(pTextLine->GetIndex());
4818                         }
4819
4820                         hasPrevLine = false;
4821                 }
4822
4823                 if (__pCurrentTextColumn->IsComposeDone())
4824                 {
4825                         break;
4826                 }
4827
4828                 textIndex += textCount;
4829                 remainingLength -= textCount;
4830                 remainingHeight -= lineTextSize.height;
4831
4832                 if (remainingHeight < 0)
4833                 {
4834                         return lineCount;
4835                 }
4836
4837                 if (remainingLength > 0)
4838                 {
4839                         float nextY = lineBounds.y + lineBounds.height;
4840
4841                         pTextLine = new (std::nothrow)TextLine(this);
4842                         SysTryReturn(NID_GRP, pTextLine, -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
4843
4844                         lineBounds.x = rect.x;
4845                         lineBounds.y = nextY;
4846                         lineBounds.width = rect.width;
4847                         lineTextSize.height = 0;
4848
4849                         remainingWidth = rect.width;
4850                 }
4851                 else
4852                 {
4853                         if (endType == TEXT_RETBY_LINEFEED)
4854                         {
4855                                 float nextY = lineBounds.y + lineBounds.height;
4856                                 lineTextSize.height = lineBounds.height;
4857
4858                                 pTextLine = new (std::nothrow)TextLine(this);
4859                                 SysTryReturn(NID_GRP, pTextLine, -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
4860
4861                                 lineBounds.x = rect.x;
4862                                 lineBounds.y = nextY;
4863                                 lineBounds.width = rect.width;
4864                                 lineBounds.height = lineTextSize.height;
4865
4866                                 pTextLine->SetBounds(lineBounds);
4867                                 pTextLine->SetRegion(0.0f, lineTextSize.height);
4868                                 pTextLine->SetTextLength(0);
4869                                 pTextLine->SetTextOffset(textIndex);
4870                                 pTextLine->SetEndType(TEXT_RETBY_LINEFEED);
4871                                 pTextLine->SetBaseline(0);
4872                                 GetTextExtentList(pTextLine);
4873
4874                                 __pCurrentTextColumn->AddLineDuringCompose(pTextLine);
4875
4876                                 lineCount++;
4877
4878                                 if (lineBounds.y + lineBounds.height <= rect.height)
4879                                 {
4880                                         __pCurrentTextColumn->SetDisplayLineCount(++displayLineCount);
4881                                         displayHeight += lineBounds.height;
4882                                         __pCurrentTextColumn->SetDisplayHeight(displayHeight);
4883                                 }
4884
4885                                 __lineIndexCompositeDone++;
4886                                 __totalComposedHeight += lineTextSize.height;
4887                                 __pCurrentTextColumn->FinishCompose();
4888
4889                                 pTextLine = null;
4890                                 break;
4891                         }
4892                         else
4893                         {
4894                                 __pCurrentTextColumn->FinishCompose();
4895                         }
4896                 }
4897         }
4898
4899         rect.height = __totalComposedHeight;
4900
4901         if (pTextLine)
4902         {
4903                 __pCurrentTextColumn->SetChangedLastLineIndex(pTextLine->GetIndex());
4904         }
4905
4906         if (Tizen::App::_AppInfo::IsOspCompat())
4907         {
4908                 __pCurrentTextColumn->SetDisplayLineCount(0);
4909                 __pCurrentTextColumn->SetDisplayHeight(0);
4910         }
4911
4912         return lineCount;
4913 }
4914
4915 int
4916 TextComposite::ComposeInNoneWrapMiddleEllipsis(FloatRectangle& rect)
4917 {
4918         int endType = TEXT_RETBY_NORMAL;
4919         FloatRectangle lineBounds;
4920         FloatDimension abbrevTextDim;
4921         FloatDimension textSize;
4922         int length = 0;
4923         float maxHeight = 0;
4924         float baseline = 0;
4925
4926         lineBounds.width = rect.width;
4927         lineBounds.x = 0;
4928         lineBounds.y = 0;
4929         lineBounds.height = rect.height;
4930         endType = ForwardAnalyzeWithBaseline(0, __length, lineBounds.width, __wrap, length, textSize.width, textSize.height, baseline);
4931
4932         if (endType != TEXT_RETBY_LIMITWIDTH)
4933         {
4934                 __drawTextEllipsis = false;
4935                 return ComposeInNoneWrap(rect);
4936         }
4937
4938         __drawTextEllipsis = true;
4939
4940         TextElement* pTextElement = null;
4941         TextSimple* pSimpleText = null;
4942
4943         pTextElement = static_cast < TextElement* >(__pTextElementList->GetAt(0));
4944         SysTryReturn(NID_GRP, pTextElement, -1, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
4945
4946         TextElementType objectType = pTextElement->GetType();
4947         SysTryReturn(NID_GRP, objectType == TEXT_ELEMENT_TYPE_CUTLINK || objectType == TEXT_ELEMENT_TYPE_TEXT, -1, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
4948
4949         pSimpleText = dynamic_cast < TextSimple* >(pTextElement);
4950         if (pSimpleText != null)
4951         {
4952                 SetAbbrevObjectFontInfo(pSimpleText);
4953         }
4954
4955         __pAbbrevTextElement->GetRegion(0, 1, abbrevTextDim.width, abbrevTextDim.height);
4956         __middleEllipsisWidth = abbrevTextDim.width;
4957
4958         ForwardAnalyze(0, __length, ((lineBounds.width - __middleEllipsisWidth + 10.0f) / 2.0f), __wrap, length, textSize.width, textSize.height);
4959         __middleEllipsisTextLengthInHead = length;
4960         __middleEllipsisHeadWidth = textSize.width;
4961
4962         maxHeight = textSize.height;
4963
4964         ForwardAnalyze(__middleEllipsisTextLengthInHead, __length - __middleEllipsisTextLengthInHead, lineBounds.width - __middleEllipsisWidth -
4965                                    __middleEllipsisHeadWidth, __wrap, length, textSize.width, textSize.height);
4966
4967         __middleEllipsisTextLengthInTail = length;
4968         maxHeight = (maxHeight < textSize.height) ? textSize.height : maxHeight;
4969
4970         TextLine* pTextLine = new (std::nothrow)TextLine(this);
4971         SysTryReturn(NID_GRP, pTextLine, -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
4972
4973         pTextLine->SetBounds(lineBounds);
4974         pTextLine->SetRegion(lineBounds.width, maxHeight);
4975         pTextLine->SetTextLength(__length);
4976         pTextLine->SetTextOffset(0);
4977         pTextLine->SetEndType(TEXT_RETBY_NORMAL);
4978         pTextLine->SetBaseline(baseline);
4979         GetTextExtentList(pTextLine);
4980
4981         __pCurrentTextColumn->AddLineDuringCompose(pTextLine);
4982
4983         lineBounds.height = maxHeight;
4984
4985         return 1;
4986 }
4987
4988 int
4989 TextComposite::ComposeInNoneWrapHeadEllipsis(FloatRectangle& rect)
4990 {
4991         SysTryReturn(NID_GRP, __pCurrentTextColumn, -1, E_INVALID_STATE, "[E_INVALID_STATE] This instance is not constructed yet.");
4992
4993         int endType = TEXT_RETBY_NORMAL;
4994         FloatRectangle lineBounds;
4995         FloatDimension abbrevTextDim;
4996         FloatDimension textSize;
4997         int length = 0;
4998         float maxHeight = 0;
4999         float baseline = 0;
5000
5001         lineBounds.width = rect.width;
5002         lineBounds.x = 0;
5003         lineBounds.y = 0;
5004         lineBounds.height = rect.height;
5005         endType = ForwardAnalyzeWithBaseline(0, __length, lineBounds.width, __wrap, length, textSize.width, textSize.height, baseline);
5006
5007         if (endType != TEXT_RETBY_LIMITWIDTH)
5008         {
5009                 __drawTextEllipsis = false;
5010                 return ComposeInNoneWrap(rect);
5011         }
5012
5013         __drawTextEllipsis = true;
5014         TextElement* pTextElement = null;
5015         TextSimple* pSimpleText = null;
5016
5017         pTextElement = static_cast < TextElement* >(__pTextElementList->GetAt(0));
5018         SysTryReturn(NID_GRP, pTextElement, -1, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
5019
5020         TextElementType objectType = pTextElement->GetType();
5021         SysTryReturn(NID_GRP, objectType == TEXT_ELEMENT_TYPE_CUTLINK || objectType == TEXT_ELEMENT_TYPE_TEXT
5022                 , -1, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
5023
5024         pSimpleText = dynamic_cast < TextSimple* >(pTextElement);
5025         if (pSimpleText != null)
5026         {
5027                 SetAbbrevObjectFontInfo(pSimpleText);
5028         }
5029
5030         __pAbbrevTextElement->GetRegion(0, 1, abbrevTextDim.width, abbrevTextDim.height);
5031         __headEllipsisWidth = abbrevTextDim.width;
5032
5033         BackwardAnalyze(__length - 1, lineBounds.width - abbrevTextDim.width, &__headEllipsisTextLength, &textSize.width, &textSize.height);
5034         maxHeight = textSize.height;
5035
5036         TextLine* pTextLine = new (std::nothrow)TextLine(this);
5037         SysTryReturn(NID_GRP, pTextLine, -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
5038
5039         pTextLine->SetBounds(lineBounds);
5040         pTextLine->SetRegion(lineBounds.width, maxHeight);
5041         pTextLine->SetTextLength(__length);
5042         pTextLine->SetTextOffset(0);
5043         pTextLine->SetEndType(TEXT_RETBY_NORMAL);
5044         pTextLine->SetBaseline(baseline);
5045         GetTextExtentList(pTextLine);
5046
5047         __pCurrentTextColumn->AddLineDuringCompose(pTextLine);
5048
5049         lineBounds.height = maxHeight;
5050
5051         return 1;
5052 }
5053
5054 result
5055 TextComposite::DrawAbbrev(_CanvasImpl& canvasImpl, const FloatRectangle& displayRect, const TextObjectAlignment align)
5056 {
5057         if (__TextObjectEllipsisType == TEXT_OBJECT_ELLIPSIS_TYPE_MIDDLE)
5058         {
5059                 return DrawAbbrevInMiddleEllipsis(canvasImpl, displayRect, align);
5060         }
5061         else if (__TextObjectEllipsisType == TEXT_OBJECT_ELLIPSIS_TYPE_HEAD)
5062         {
5063                 return DrawAbbrevInHeadEllipsis(canvasImpl, displayRect, align);
5064         }
5065
5066         return E_SYSTEM;
5067 }
5068
5069 result
5070 TextComposite::GetValue(int textIndex, TextComponentInfoValueType type, unsigned int* value) const
5071 {
5072         IEnumerator* pEnum = null;
5073         TextElement* pTextElement = null;
5074         int offset = 0;
5075         int elementTextLength = 0;
5076
5077         pEnum = __pTextElementList->GetEnumeratorN();
5078         while (pEnum->MoveNext() == E_SUCCESS)
5079         {
5080                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
5081                 if (pTextElement == null)
5082                 {
5083                         continue;
5084                 }
5085
5086                 elementTextLength = pTextElement->GetTextLength();
5087
5088                 if (textIndex < offset + elementTextLength)
5089                 {
5090                         TextElementType objectType = pTextElement->GetType();
5091
5092                         if (objectType != TextUtility::GetObjectTypeFromValueType(type) && objectType != TEXT_ELEMENT_TYPE_CUTLINK)
5093                         {
5094                                 Release(pEnum);
5095                                 return E_INVALID_ARG;
5096                         }
5097
5098                         *value = pTextElement->GetValue(type);
5099                         Release(pEnum);
5100                         return E_SUCCESS;
5101                 }
5102
5103                 offset += elementTextLength;
5104         }
5105
5106         Release(pEnum);
5107         return E_INVALID_ARG;
5108 }
5109
5110 bool
5111 TextComposite::BackwardAnalyze(int startTextIndex, float maxWidth, int* actualLength, float* width, float* height)
5112 {
5113         float remainingWidth = 0;
5114         int length = 0;
5115         FloatDimension textSize;
5116
5117         *actualLength = 0;
5118         *width = 0;
5119         *height = 0;
5120
5121         remainingWidth = maxWidth;
5122         length = 1;
5123
5124         while (startTextIndex >= 0 && textSize.width < remainingWidth)
5125         {
5126                 GetRegion(startTextIndex, length, textSize.width, textSize.height);
5127
5128                 if (textSize.width <= remainingWidth)
5129                 {
5130                         *actualLength = length;
5131                         *width = textSize.width;
5132                         *height = textSize.height;
5133                 }
5134
5135                 startTextIndex--;
5136                 length++;
5137         }
5138
5139         return true;
5140 }
5141
5142 int
5143 TextComposite::GetFirstTextIndexAt(int elementIndex) const
5144 {
5145         SysTryReturn(NID_GRP, elementIndex >= 0 && elementIndex < __pTextElementList->GetCount(), -1, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
5146
5147         IEnumerator* pEnum = null;
5148         TextElement* pTextElement = null;
5149
5150         int index = 0;
5151         int elementTextOffset = 0;
5152
5153         if (elementIndex == 0)
5154         {
5155                 return 0;
5156         }
5157
5158         pEnum = __pTextElementList->GetEnumeratorN();
5159         while (pEnum->MoveNext() == E_SUCCESS)
5160         {
5161                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
5162                 if (pTextElement == null)
5163                 {
5164                         continue;
5165                 }
5166
5167                 if (index == elementIndex)
5168                 {
5169                         break;
5170                 }
5171
5172                 elementTextOffset += pTextElement->GetTextLength();
5173
5174                 pTextElement = null;
5175                 index++;
5176         }
5177
5178         Release(pEnum);
5179
5180         if (pTextElement != null)
5181         {
5182                 return elementTextOffset;
5183         }
5184
5185         return -1;
5186 }
5187
5188 result
5189 TextComposite::DrawAbbrevInMiddleEllipsis(_CanvasImpl& canvasImpl, const FloatRectangle& displayRect, const TextObjectAlignment alignment)
5190 {
5191         TextLine* pTextLine = __pCurrentTextColumn->GetTextLine(0);
5192         SysTryReturn(NID_GRP, pTextLine, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text line.");
5193
5194         FloatDimension textSize;
5195         FloatRectangle adjustedRect;
5196
5197         pTextLine->GetRegion(0, __length, textSize.width, textSize.height);
5198         adjustedRect.x = displayRect.x;
5199         adjustedRect.width = displayRect.width;
5200
5201         switch (alignment & TEXT_ALIGNMASK_VERT)
5202         {
5203         case TEXT_OBJECT_ALIGNMENT_MIDDLE:
5204                 adjustedRect.y = displayRect.y + (displayRect.height - textSize.height) / 2;
5205                 break;
5206
5207         case TEXT_OBJECT_ALIGNMENT_BOTTOM:
5208                 adjustedRect.y = displayRect.y + (displayRect.height - textSize.height);
5209                 break;
5210
5211         case TEXT_OBJECT_ALIGNMENT_TOP:
5212                 // fall through
5213         default:
5214                 adjustedRect.y = displayRect.y;
5215                 break;
5216         }
5217         adjustedRect.height = displayRect.height - (displayRect.y - adjustedRect.y);
5218
5219         TextElement* pTextElement = null;
5220         TextSimple* pSimpleText = null;
5221
5222         pTextElement = static_cast < TextElement* >(__pTextElementList->GetAt(0));
5223         SysTryReturn(NID_GRP, pTextElement, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
5224
5225         TextElementType objectType = pTextElement->GetType();
5226         SysTryReturn(NID_GRP, objectType == TEXT_ELEMENT_TYPE_CUTLINK || objectType == TEXT_ELEMENT_TYPE_TEXT
5227                 , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to draw to symbol object.");
5228
5229         pSimpleText = dynamic_cast < TextSimple* >(pTextElement);
5230         if (pSimpleText != null)
5231         {
5232                 SetAbbrevObjectFontInfo(pSimpleText);
5233         }
5234
5235         DrawPartial(canvasImpl, adjustedRect, 0, __middleEllipsisTextLengthInHead);
5236
5237         adjustedRect.x += __middleEllipsisHeadWidth;
5238         __pAbbrevTextElement->Draw(canvasImpl, adjustedRect, 0, 1, (TextObjectAlignment)(TEXT_OBJECT_ALIGNMENT_TOP | TEXT_OBJECT_ALIGNMENT_LEFT), TEXT_OBJECT_ACTION_TYPE_NONE);
5239
5240         adjustedRect.x += __middleEllipsisWidth;
5241         DrawPartial(canvasImpl, adjustedRect, __length - __middleEllipsisTextLengthInTail, __middleEllipsisTextLengthInTail);
5242
5243         return E_SUCCESS;
5244 }
5245
5246 result
5247 TextComposite::DrawAbbrevInHeadEllipsis(_CanvasImpl& canvasImpl, const FloatRectangle& displayRect, const TextObjectAlignment alignment)
5248 {
5249         TextLine* pTextLine = __pCurrentTextColumn->GetTextLine(0);
5250         SysTryReturn(NID_GRP, pTextLine, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text line.");
5251
5252         result r = E_SUCCESS;
5253         FloatDimension textSize;
5254         FloatRectangle adjustedRect;
5255
5256         pTextLine->GetRegion(0, __length, textSize.width, textSize.height);
5257         adjustedRect.x = displayRect.x;
5258         adjustedRect.width = displayRect.width;
5259
5260         switch (alignment & TEXT_ALIGNMASK_VERT)
5261         {
5262         case TEXT_OBJECT_ALIGNMENT_MIDDLE:
5263                 adjustedRect.y = displayRect.y + (displayRect.height - textSize.height) / 2;
5264                 break;
5265
5266         case TEXT_OBJECT_ALIGNMENT_BOTTOM:
5267                 adjustedRect.y = displayRect.y + (displayRect.height - textSize.height);
5268                 break;
5269
5270         case TEXT_OBJECT_ALIGNMENT_TOP:
5271                 // fall through
5272         default:
5273                 adjustedRect.y = displayRect.y;
5274                 break;
5275         }
5276         adjustedRect.height = displayRect.height - (displayRect.y - adjustedRect.y);
5277
5278         TextElement* pTextElement = null;
5279         TextSimple* pSimpleText = null;
5280
5281         pTextElement = static_cast < TextElement* >(__pTextElementList->GetAt(0));
5282         r = GetLastResult();
5283         SysTryReturn(NID_GRP, pTextElement, r, r, "[%s] Fail to get element.", GetErrorMessage(r));
5284
5285         TextElementType objectType = pTextElement->GetType();
5286         SysTryReturn(NID_GRP, objectType == TEXT_ELEMENT_TYPE_CUTLINK || objectType == TEXT_ELEMENT_TYPE_TEXT
5287                 , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to draw to symbol object.");
5288
5289         pSimpleText = dynamic_cast < TextSimple* >(pTextElement);
5290         if (pSimpleText != null)
5291         {
5292                 SetAbbrevObjectFontInfo(pSimpleText);
5293         }
5294
5295         __pAbbrevTextElement->Draw(canvasImpl, adjustedRect, 0, 1, (TextObjectAlignment)(TEXT_OBJECT_ALIGNMENT_TOP | TEXT_OBJECT_ALIGNMENT_LEFT), TEXT_OBJECT_ACTION_TYPE_NONE);
5296
5297         adjustedRect.x += __headEllipsisWidth;
5298         DrawPartial(canvasImpl, adjustedRect, __length - __headEllipsisTextLength, __headEllipsisTextLength);
5299
5300         return E_SUCCESS;
5301 }
5302
5303 result
5304 TextComposite::DrawPartial(_CanvasImpl& canvasImpl, FloatRectangle& displayRect, int startTextIndex, int textLength)
5305 {
5306         SysTryReturn(NID_GRP, 0 <= startTextIndex && startTextIndex < __length, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
5307         SysTryReturn(NID_GRP, textLength <= __length, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
5308
5309         result r = E_SUCCESS;
5310         IEnumerator* pEnum = null;
5311         TextElement* pTextElement = null;
5312
5313         FloatDimension textSize;
5314         int currentLength = 0;
5315         int textIndexFromElementOffset = 0;
5316         int nodeIndex = 0;
5317         int elementTextOffset = 0;
5318         FloatRectangle adjustedRect = displayRect;
5319         int blockStartTextIndex = 0;
5320         int blockEndTextIndex = 0;
5321         bool isAlternateLookEnabled = false;
5322         int textIndex = startTextIndex;
5323
5324         pTextElement = GetElementAtTextIndex(textIndex, elementTextOffset, nodeIndex, currentLength,
5325                                                                                          textIndexFromElementOffset);
5326         SysTryReturn(NID_GRP, pTextElement, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
5327
5328         currentLength = Math::Min(textLength, currentLength);
5329
5330         pEnum = __pTextElementList->GetEnumeratorN();
5331         while (textLength > 0)
5332         {
5333                 textLength -= currentLength;
5334
5335                 pTextElement->GetRegion(textIndexFromElementOffset, currentLength, textSize.width, textSize.height);
5336
5337                 if (pTextElement->IsBackGroundDrawingModeEnable())
5338                 {
5339                         r = canvasImpl.FillRectangle(pTextElement->GetBackgroundColor(), FloatRectangle(adjustedRect.x, displayRect.y, textSize.width, displayRect.height));
5340                         SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
5341                 }
5342
5343                 isAlternateLookEnabled = (pTextElement->GetValue(SET_ALTERNATE_LOOK) > 0) ? true : false;
5344                 if ((__displayBlock) && (isAlternateLookEnabled == false))
5345                 {
5346                         FloatDimension tempTextSize;
5347                         float adjustedX = 0;
5348
5349                         blockStartTextIndex = Math::Max(__workStart, textIndex);
5350                         blockEndTextIndex = Math::Min(__workStart + __workLength, textIndex + currentLength);
5351                         if (blockStartTextIndex < blockEndTextIndex)
5352                         {
5353                                 blockStartTextIndex = textIndexFromElementOffset + (blockStartTextIndex - textIndex);
5354                                 blockEndTextIndex = textIndexFromElementOffset + (blockEndTextIndex - textIndex);
5355                                 adjustedX = adjustedRect.x;
5356
5357                                 if (textIndexFromElementOffset < blockStartTextIndex)
5358                                 {
5359                                         pTextElement->GetRegion(textIndexFromElementOffset, blockStartTextIndex - textIndexFromElementOffset,
5360                                                                                                         tempTextSize.width, tempTextSize.height);
5361                                         adjustedX += tempTextSize.width;
5362                                 }
5363
5364                                 FloatRectangle blockRect = adjustedRect;
5365                                 blockRect.x = adjustedX;
5366                         }
5367                 }
5368
5369                 pTextElement->Draw(canvasImpl, adjustedRect, textIndexFromElementOffset, currentLength, (TextObjectAlignment)(TEXT_OBJECT_ALIGNMENT_TOP | TEXT_OBJECT_ALIGNMENT_LEFT),
5370                                                          TEXT_OBJECT_ACTION_TYPE_NONE);
5371
5372                 adjustedRect.x += textSize.width;
5373                 adjustedRect.width -= textSize.width;
5374
5375                 if (!textLength || adjustedRect.width <= 0)
5376                 {
5377                         break;
5378                 }
5379
5380                 textIndex += currentLength;
5381
5382                 if (pEnum->MoveNext() != E_SUCCESS)
5383                 {
5384                         break;
5385                 }
5386
5387                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
5388
5389                 textIndexFromElementOffset = pTextElement->GetValue(SET_TEXT_OFFSET);
5390                 currentLength = Math::Min(textLength, pTextElement->GetTextLength());
5391
5392                 if (currentLength == 0)
5393                 {
5394                         break;
5395                 }
5396         }
5397
5398         Release(pEnum);
5399         return E_SUCCESS;
5400 }
5401
5402 void
5403 TextComposite::SetPartialComposingModeEnabled(bool enable)
5404 {
5405         __partialComposingModeEnabled = enable;
5406 }
5407
5408 bool
5409 TextComposite::IsPartialComposingModeEnabled(void) const
5410 {
5411         return __partialComposingModeEnabled;
5412 }
5413
5414 bool
5415 TextComposite::InitPartialComposeMode(void)
5416 {
5417         __lineIndexCompositeDone = 0;
5418         __totalComposedHeight = 0;
5419         __composePartialLimitHeight = 0;
5420
5421         SysTryReturn(NID_GRP, __pCurrentTextColumn, false, E_INVALID_STATE, "[E_INVALID_STATE] This instance is not constructed yet.");
5422
5423         __pCurrentTextColumn->SetFirstDisplayLineIndex(0);
5424         __pCurrentTextColumn->SetFirstDisplayPositionY(0);
5425         __pCurrentTextColumn->PrepareCompose();
5426
5427         return true;
5428 }
5429
5430 bool
5431 TextComposite::IsComposeDone() const
5432 {
5433         SysTryReturn(NID_GRP, __pCurrentTextColumn, false, E_INVALID_STATE, "[E_INVALID_STATE] This instance is not constructed yet.");
5434
5435         return __pCurrentTextColumn->IsComposeDone();
5436 }
5437
5438 result
5439 TextComposite::GetCutLinkObjectInfo(int cutLinkIndex, int& textStartIndex, int& textLength) const
5440 {
5441         return __pCutLinkListInfo->GetCutLinkObjectInfo(cutLinkIndex, textStartIndex, textLength);
5442 }
5443
5444 int
5445 TextComposite::GetTotalComposedHeight(void) const
5446 {
5447         return _CoordinateSystemUtils::ConvertToInteger(__totalComposedHeight);
5448 }
5449
5450 float
5451 TextComposite::GetTotalComposedHeightF(void) const
5452 {
5453         return __totalComposedHeight;
5454 }
5455
5456 int
5457 TextComposite::GetAnalysedTotalHeight(void) const
5458 {
5459         return _CoordinateSystemUtils::ConvertToInteger(GetAnalysedTotalHeightF());
5460 }
5461
5462 float
5463 TextComposite::GetAnalysedTotalHeightF(void) const
5464 {
5465         TextLine* pTextLine = null;
5466         pTextLine = __pCurrentTextColumn->GetTextLine(__lineIndexCompositeDone - 1);
5467
5468         if (!pTextLine)
5469         {
5470                 return 0;
5471         }
5472
5473         int lineOffset = pTextLine->GetTextOffset();
5474         int lineLength = pTextLine->GetTextLength();
5475
5476         int composedLength = lineOffset + lineLength;
5477         if (composedLength == 0)
5478         {
5479                 return 0;
5480         }
5481
5482         return (float)(GetTotalComposedHeightF() * __length / composedLength);
5483 }
5484
5485 void
5486 TextComposite::SetComposePartialLimitHeight(int limitHeight)
5487 {
5488         __composePartialLimitHeight = _CoordinateSystemUtils::ConvertToFloat(limitHeight);
5489 }
5490
5491 void
5492 TextComposite::SetComposePartialLimitHeight(float limitHeight)
5493 {
5494         __composePartialLimitHeight = limitHeight;
5495 }
5496
5497 int
5498 TextComposite::GetComposePartialLimitHeight(void) const
5499 {
5500         return _CoordinateSystemUtils::ConvertToInteger(__composePartialLimitHeight);
5501 }
5502
5503 float
5504 TextComposite::GetComposePartialLimitHeightF(void) const
5505 {
5506         return __composePartialLimitHeight;
5507 }
5508
5509 TextElementType
5510 TextComposite::GetObjectType(int textIndex) const
5511 {
5512         TextElement* pTextElement = null;
5513
5514         int currentLength = 0;
5515         int elementIndex = 0;
5516         int textIndexFromElementOffset = 0;
5517         int elementTextOffset = 0;
5518
5519         pTextElement = GetElementAtTextIndex(textIndex, elementTextOffset, elementIndex, currentLength, textIndexFromElementOffset);
5520         if (pTextElement == null)
5521         {
5522                 return TEXT_ELEMENT_TYPE_NONE;
5523         }
5524         else
5525         {
5526                 return pTextElement->GetType();
5527         }
5528 }
5529
5530 int
5531 TextComposite::GetElementIndexOf(TextElement& textElement) const
5532 {
5533         int index = 0;
5534
5535         result r = E_SUCCESS;
5536
5537         r = __pTextElementList->IndexOf(textElement, index);
5538         SysTryReturn(NID_GRP, r == E_SUCCESS, false, r, "[%s] Fail to add element.", GetErrorMessage(r));
5539
5540         return index;
5541 }
5542
5543 TextElement*
5544 TextComposite::GetElementAtElementIndex(int nodeIndex) const
5545 {
5546         result r = E_SUCCESS;
5547
5548         TextElement* pTextElement = null;
5549         pTextElement = static_cast < TextElement* >(__pTextElementList->GetAt(nodeIndex));
5550         SysTryReturn(NID_GRP, r == E_SUCCESS, null, r, "[%s] Fail to add element.", GetErrorMessage(r));
5551
5552         return pTextElement;
5553 }
5554
5555 int
5556 TextComposite::GetTextLength(void) const
5557 {
5558         return __length;
5559 }
5560
5561 int
5562 TextComposite::GetElementCount(void) const
5563 {
5564         return __pTextElementList->GetCount();
5565 }
5566
5567 void
5568 TextComposite::SetBlock(bool enable)
5569 {
5570         __displayBlock = enable;
5571 }
5572
5573 result
5574 TextComposite::SetImageAlign(TextObjectAlignment align)
5575 {
5576         return SetValueToAllTextElements(SET_IMAGE_ALIGN, (unsigned int)align);
5577 }
5578
5579 TextObjectWrapType
5580 TextComposite::GetWrap(void) const
5581 {
5582         return __wrap;
5583 }
5584
5585 void
5586 TextComposite::SetLineSpace(int gap)
5587 {
5588         SetLineSpace(_CoordinateSystemUtils::ConvertToFloat(gap));
5589 }
5590
5591 void
5592 TextComposite::SetLineSpace(float gap)
5593 {
5594         __lineSpacing = gap;
5595 }
5596
5597 int
5598 TextComposite::GetLineSpace(void) const
5599 {
5600         return _CoordinateSystemUtils::ConvertToInteger(__lineSpacing);
5601 }
5602
5603 float
5604 TextComposite::GetLineSpaceF(void) const
5605 {
5606         return __lineSpacing;
5607 }
5608
5609 void
5610 TextComposite::SetElementVerticalAlignment(TextObjectAlignment alignment)
5611 {
5612         __elementVertialAlignment = alignment;
5613 }
5614
5615 TextObjectAlignment
5616 TextComposite::GetElementVerticalAlignment(void) const
5617 {
5618         return __elementVertialAlignment;
5619 }
5620
5621 void
5622 TextComposite::SetCursorIndex(int cursorIndex)
5623 {
5624         __cursorIndex = cursorIndex;
5625 }
5626
5627 int
5628 TextComposite::GetCursorIndex(void) const
5629 {
5630         return __cursorIndex;
5631 }
5632
5633 void
5634 TextComposite::SetTextObjectEllipsisType(TextObjectEllipsisType type)
5635 {
5636         __TextObjectEllipsisType = type;
5637 }
5638
5639 TextObjectEllipsisType
5640 TextComposite::GetTextObjectEllipsisType(void) const
5641 {
5642         return __TextObjectEllipsisType;
5643 }
5644
5645 void
5646 TextComposite::SetTextAbbreviationEnabled(bool enable)
5647 {
5648         __drawAbbrevText = enable;
5649 }
5650
5651 bool
5652 TextComposite::IsTextAbbreviationEnabled(void) const
5653 {
5654         if (__drawAbbrevText && __drawTextEllipsis)
5655         {
5656                 return true;
5657         }
5658
5659         return false;
5660 }
5661
5662 bool
5663 TextComposite::GetBlock(void) const
5664 {
5665         return __displayBlock;
5666 }
5667
5668 int
5669 TextComposite::GetWorkStart(void) const
5670 {
5671         return __workStart;
5672 }
5673
5674 int
5675 TextComposite::GetWorkLength(void) const
5676 {
5677         return __workLength;
5678 }
5679
5680 TextObjectAlignment
5681 TextComposite::GetImageAlign(int textIndex) const
5682 {
5683         result r = E_SUCCESS;
5684         unsigned int value = 0;
5685
5686         r = GetValue(textIndex, SET_IMAGE_ALIGN, &value);
5687         SysTryReturn(NID_GRP, r == E_SUCCESS, TEXT_OBJECT_ALIGNMENT_INVALID, r, "[%s] Propagating.", GetErrorMessage(r));
5688
5689         return (TextObjectAlignment)value;
5690 }
5691
5692 bool
5693 TextComposite::IsChanged(void) const
5694 {
5695         return __isChanged;
5696 }
5697
5698 void
5699 TextComposite::SetBlockColor(const Color& color)
5700 {
5701         __defaultBlockColor = color;
5702 }
5703
5704 Color
5705 TextComposite::GetBlockColor(void) const
5706 {
5707         return __defaultBlockColor;
5708 }
5709
5710 Tizen::Base::String
5711 TextComposite::GetDisplayableText(FloatRectangle displayRect, TextObjectActionType action)
5712 {
5713         int firstDisplayLineIndex = __pCurrentTextColumn->GetFirstDisplayLineIndex();
5714         TextLine* pTextLine = __pCurrentTextColumn->GetTextLine(firstDisplayLineIndex);
5715         SysTryReturn(NID_GRP, pTextLine, L"", E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid. (firstDisplayLineIndex = %d)", firstDisplayLineIndex);
5716
5717         int firstDisplayTextIndex = pTextLine->GetTextOffset();
5718         int displayableTextLength = 0;
5719         int displayableLineCount = __pCurrentTextColumn->CalculateDisplayableLineCount(displayRect, action);
5720         int lastDisplayLineIndex = firstDisplayLineIndex + displayableLineCount - 1;
5721
5722         for (int i = firstDisplayLineIndex; i < lastDisplayLineIndex; i++)
5723         {
5724                 pTextLine = __pCurrentTextColumn->GetTextLine(i);
5725                 SysTryReturn(NID_GRP, pTextLine, L"", E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid. (line index = %d)", i);
5726
5727                 displayableTextLength += pTextLine->GetTextLength();
5728         }
5729
5730         pTextLine = __pCurrentTextColumn->GetTextLine(lastDisplayLineIndex);
5731         SysTryReturn(NID_GRP, pTextLine, L"", E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid. (lastDisplayLineIndex = %d)", lastDisplayLineIndex);
5732
5733         int lineOffset = pTextLine->GetTextOffset();
5734         int lineLength = pTextLine->GetTextLength();
5735         int elementTextOffset = 0;
5736         int elementIndex = 0;
5737         int currentLength = 0;
5738         int textIndexFromElementOffset = 0;
5739         int remainingLength = lineLength;
5740
5741         if (lineOffset + remainingLength < __length) // abbreviation mode
5742         {
5743                 TextElement* pTextElement = GetElementAtTextIndex(lineOffset, elementTextOffset, elementIndex, currentLength, textIndexFromElementOffset);
5744                 SysTryReturn(NID_GRP, pTextElement, String(L""), E_SYSTEM, "[E_SYSTEM] Fail to get element.");
5745
5746                 if (__ignoreFrontBlank && __frontSpaceHideMode == TEXT_OBJECT_SPACE_HIDE_TYPE_ONE)
5747                 {
5748                         const TextSimple* pSimpleText = dynamic_cast <const TextSimple*>(pTextElement);
5749                         if (pSimpleText != null)
5750                         {
5751                                 int index = lineOffset - elementTextOffset;
5752                                 const wchar_t* pText = pSimpleText->GetText();
5753                                 SysTryReturn(NID_GRP, pText, String(L""), E_SYSTEM, "[E_SYSTEM] Fail to get text.");
5754
5755                                 SysTryReturn(NID_GRP, index >= 0 && index < pSimpleText->GetTextLength()
5756                                         , String(L""), E_OUT_OF_RANGE, "[E_OUT_OF_RANGE] text index(%d) must greater than 0 and must be less than total string length(%d)"
5757                                         ,index, pSimpleText->GetTextLength());
5758
5759                                 if (pText[index] == (wchar_t)L' ')
5760                                 {
5761                                         remainingLength--;
5762                                         lineOffset++;
5763                                 }
5764                         }
5765                 }
5766
5767                 if (action == TEXT_OBJECT_ACTION_TYPE_ABBREV)
5768                 {
5769                         FloatDimension textSize;
5770                         FloatDimension abbrevTextSize;
5771                         FloatRectangle lineBounds = pTextLine->GetBoundsF();
5772
5773                         GetRegion(lineOffset, remainingLength, textSize.width, textSize.height);
5774
5775                         TextElement* pLastTextElement = GetElementAtTextIndex(lineOffset + lineLength - 1);
5776                         SysTryReturn(NID_GRP, pLastTextElement, -1, E_SYSTEM, "[E_SYSTEM] Fail to get element.");
5777
5778                         if (pLastTextElement->GetType() == TEXT_ELEMENT_TYPE_TEXT)
5779                         {
5780                                 TextSimple* pSimpleText = dynamic_cast < TextSimple* >(pLastTextElement);
5781                                 SysTryReturn(NID_GRP, pSimpleText, String(L""), E_SYSTEM, "[E_SYSTEM] Fail to cast text element.");
5782
5783                                 SetAbbrevObjectFontInfo(pSimpleText);
5784                                 __pAbbrevTextElement->GetRegion(0, 1, abbrevTextSize.width, abbrevTextSize.height);
5785                         }
5786
5787                         ForwardAnalyze(lineOffset, __length - lineOffset, lineBounds.width - abbrevTextSize.width
5788                                 , TEXT_OBJECT_WRAP_TYPE_CHARACTER, lineLength, textSize.width, textSize.height);
5789                 }
5790         }
5791
5792         displayableTextLength += lineLength;
5793
5794         wchar_t* pText = GetTextN(firstDisplayTextIndex, displayableTextLength);
5795         SysTryReturn(NID_GRP, pText, String(L""), E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
5796
5797         String text(pText);
5798         delete[] pText;
5799
5800         return text;
5801 }
5802
5803 result
5804 TextComposite::SetWorkWidth(Font* pFont, wchar_t* pText, int workStart, int textLength)
5805 {
5806         result r = E_SUCCESS;
5807         float width = 0;
5808         float height = 0;
5809         int workLength = 0;
5810         const wchar_t* pSrc = &pText[workStart];
5811
5812         workLength = Math::Abs(textLength);
5813
5814         r = TextUtility::GetTextExtent(pFont, pSrc, workLength, false, width, height);
5815         SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
5816
5817         if (textLength < 0)
5818         {
5819                 __workWidth = -width;
5820         }
5821         else
5822         {
5823                 __workWidth = width;
5824         }
5825
5826         return E_SUCCESS;
5827 }
5828
5829 float
5830 TextComposite::GetWorkWidth(void)
5831 {
5832    return __workWidth;
5833 }
5834
5835 void
5836 TextComposite::SetTextSweepInfo(TextObjectSweepInfo* pTextSweepInfo)
5837 {
5838         __pSweepInfo = pTextSweepInfo;
5839 }
5840
5841 void
5842 TextComposite::GetTextSweepInfo(TextObjectSweepInfo& textSweepInfo)
5843 {
5844         textSweepInfo.isValid = __pSweepInfo->isValid;
5845         textSweepInfo.sweepType = __pSweepInfo->sweepType;
5846         textSweepInfo.sweepEventType = __pSweepInfo->sweepEventType;
5847         textSweepInfo.anchorTextIndex = __pSweepInfo->anchorTextIndex;
5848         textSweepInfo.anchorLineIndex = __pSweepInfo->anchorLineIndex;
5849         textSweepInfo.sweepRegionStartLineIndex = __pSweepInfo->sweepRegionStartLineIndex;
5850         textSweepInfo.sweepRegionLineCount = __pSweepInfo->sweepRegionLineCount;
5851         textSweepInfo.insertedLineCount = __pSweepInfo->insertedLineCount;
5852         textSweepInfo.deletedLineCount = __pSweepInfo->deletedLineCount;
5853         textSweepInfo.widthChanged = __pSweepInfo->widthChanged;
5854 }
5855
5856 void
5857 TextComposite::UpdateTextSweepInfo(TextObjectSweepInfo* pTextSweepInfo)
5858 {
5859         __pSweepInfo->isValid = pTextSweepInfo->isValid;
5860         __pSweepInfo->sweepType = pTextSweepInfo->sweepType;
5861         __pSweepInfo->sweepEventType = pTextSweepInfo->sweepEventType;
5862         __pSweepInfo->anchorTextIndex = pTextSweepInfo->anchorTextIndex;
5863         __pSweepInfo->anchorLineIndex = pTextSweepInfo->anchorLineIndex;
5864         __pSweepInfo->sweepRegionStartLineIndex = pTextSweepInfo->sweepRegionStartLineIndex;
5865         __pSweepInfo->sweepRegionLineCount = pTextSweepInfo->sweepRegionLineCount;
5866         __pSweepInfo->insertedLineCount = pTextSweepInfo->insertedLineCount;
5867         __pSweepInfo->deletedLineCount = pTextSweepInfo->deletedLineCount;
5868         __pSweepInfo->widthChanged = pTextSweepInfo->widthChanged;
5869 }
5870
5871 bool
5872 TextComposite::IsRTL(int startTextIndex, int textLength) const
5873 {
5874         SysTryReturn(NID_GRP, 0 <= startTextIndex && textLength <= __length, false, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
5875
5876         result r = E_SUCCESS;
5877         IEnumerator* pEnum = null;
5878
5879         int currentLength = 0;
5880         int elementTextOffset = 0;
5881         int elementIndex = 0;
5882         int textIndexFromElementOffset = 0;
5883
5884         if(textLength == 0)
5885         {
5886                 return false;
5887         }
5888
5889         TextElement* pTextElement = GetElementAtTextIndex(startTextIndex, elementTextOffset, elementIndex, currentLength, textIndexFromElementOffset);
5890         SysTryCatch(NID_GRP, pTextElement, , E_SYSTEM, "[E_SYSTEM] Fail to get element.");
5891
5892         textIndexFromElementOffset = startTextIndex - elementTextOffset;
5893
5894         pEnum = __pTextElementList->GetEnumeratorN();
5895         for (int i = 0; i < elementIndex; i++)
5896         {
5897                 r = pEnum->MoveNext();
5898         }
5899
5900         while (pEnum->MoveNext() == E_SUCCESS)
5901         {
5902                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
5903                 if (pTextElement)
5904                 {
5905                         currentLength = Math::Min(pTextElement->GetTextLength() - textIndexFromElementOffset, textLength);
5906
5907                         TextElementType objectType = pTextElement->GetType();
5908
5909                         if (objectType == TEXT_ELEMENT_TYPE_TEXT || objectType == TEXT_ELEMENT_TYPE_CUTLINK)
5910                         {
5911                                 TextSimple* pSimpleText = dynamic_cast < TextSimple* >(pTextElement);
5912                                 if (pSimpleText)
5913                                 {
5914                                         const wchar_t* pSrcText = pSimpleText->GetText();
5915                                         SysTryCatch(NID_GRP, pSrcText, , E_SYSTEM, "[E_SYSTEM] Fail to get text.");
5916
5917                                         const wchar_t* pPointer = &pSrcText[textIndexFromElementOffset];
5918                                         SysTryCatch(NID_GRP, pPointer, , E_SYSTEM, "[E_SYSTEM] Fail to get text.");
5919
5920                                         for (int i = 0; i< currentLength; i++)
5921                                         {
5922                                                 if(*pPointer == null)
5923                                                 {
5924                                                         break;
5925                                                 }
5926                                                 FriBidiChar bidiText[1] = { *pPointer };
5927                                                 FriBidiCharType type[1] = { 0 };
5928                                                 fribidi_get_bidi_types(bidiText, 1, type);
5929
5930                                                 if ((type[0] & FRIBIDI_MASK_RTL) != 0)
5931                                                 {
5932                                                         Release(pEnum);
5933                                                         return true;
5934                                                 }
5935                                                 else if (((type[0] & FRIBIDI_MASK_STRONG) != 0) && ((type[0] & FRIBIDI_MASK_LETTER) != 0))
5936                                                 {
5937                                                         Release(pEnum);
5938                                                         return false;
5939                                                 }
5940
5941                                                 pPointer++;
5942                                         }
5943
5944                                 }
5945
5946                                 textLength -= currentLength;
5947                         }
5948                 }
5949
5950                 if (textLength <= 0)
5951                 {
5952                         break;
5953                 }
5954
5955                 textIndexFromElementOffset = 0;
5956         }
5957
5958         Release(pEnum);
5959         return false;
5960
5961 CATCH:
5962         Release(pEnum);
5963
5964         return false;
5965 }
5966
5967 bool
5968 TextComposite::IsRTLCharacter(int textIndex) const
5969 {
5970         SysTryReturn(NID_GRP, 0 <= textIndex, false, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
5971         bool isRTL = false;
5972
5973         for (int i = textIndex; i >= 0; i--)
5974         {
5975                 wchar_t ch = GetCharacter(i);
5976                 if (TextUtility::IsStrongCharacter(ch))
5977                 {
5978                         if (TextUtility::IsRTLCharacter(GetCharacter(i)))
5979                         {
5980                                 isRTL = true;
5981                         }
5982                         else
5983                         {
5984                                 isRTL = false;
5985                         }
5986                         break;
5987                 }
5988         }
5989
5990         return isRTL;
5991 }
5992
5993 int
5994 TextComposite::SearchLTRTextIndex(int startTextIndex,int fromTextIndex) const
5995 {
5996         SysTryReturn(NID_GRP, 0 <= fromTextIndex, -1, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
5997
5998         bool isLTR = false;
5999         int LTRTextIndex = -1;
6000         wchar_t ch = 0;
6001
6002         for (int i = fromTextIndex; i >= startTextIndex; i--)
6003         {
6004                 ch = GetCharacter(i);
6005
6006                 if (TextUtility::IsLTRCharacter(ch))
6007                 {
6008                         isLTR = true;
6009                 }
6010
6011                 if (isLTR == true)
6012                 {
6013                         LTRTextIndex = i + 1;
6014
6015                         while(1)
6016                         {
6017                                 ch = GetCharacter(LTRTextIndex);
6018                                 if (TextUtility::IsStrongCharacter(ch))
6019                                 {
6020                                         break;
6021                                 }
6022
6023                                 LTRTextIndex++;
6024                         }
6025
6026                         break;
6027                 }
6028         }
6029
6030         LTRTextIndex = (startTextIndex <= LTRTextIndex && LTRTextIndex <= fromTextIndex) ? LTRTextIndex : startTextIndex;
6031
6032         return LTRTextIndex;
6033 }
6034
6035 }}} // Tizen::Graphics::_Text