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