Tizen 2.1 base
[framework/osp/uifw.git] / src / graphics / text / FGrp_TextTextWidthManager.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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_TextTextWidthManager.cpp
20  * @brief       This is the implementation file for TextWidthManager class.
21  */
22
23 #include <FBaseSysLog.h>
24 #include "FGrp_TextCommon.h"
25 #include "FGrp_TextTextElement.h"
26 #include "FGrp_TextTextSimple.h"
27 #include "FGrp_TextTextCutLink.h"
28 #include "FGrp_TextTextComposite.h"
29 #include "FGrp_TextTextSimpleList.h"
30 #include "FGrp_TextTextWidthManager.h"
31
32 using namespace Tizen::Base::Utility;
33
34 namespace
35 {
36         const int MAX_TEXT_WIDTH_INFO_MERGE_LENGTH = 10;
37 }
38
39 namespace Tizen { namespace Graphics
40 {
41
42 namespace _Text
43 {
44
45 enum TextWidthInfoType
46 {
47         TEXT_WIDTH_INFO_UNKNOWN = 0,
48         TEXT_WIDTH_INFO_WORD,
49         TEXT_WIDTH_INFO_SPACE,
50         TEXT_WIDTH_INFO_ENTER,
51         TEXT_WIDTH_INFO_SYMBOL
52 };
53
54 struct TextWidthCommonInfo
55 {
56         TextWidthInfoType type;
57 };
58
59 struct UnknownTextWidthInfo : public TextWidthCommonInfo
60 {
61         int length;
62 };
63
64 struct WordTextWidthInfo : public TextWidthCommonInfo
65 {
66         int length;
67         int width;
68         int maxHeight;
69 };
70
71 struct SpaceTextWidthInfo : public TextWidthCommonInfo
72 {
73         int width;
74         int maxHeight;
75 };
76
77 struct EnterTextWidthInfo : public TextWidthCommonInfo
78 {
79         int length;
80         int maxHeight;
81 };
82
83 struct SymbolTextWidthInfo : public TextWidthCommonInfo
84 {
85         int width;
86         int maxHeight;
87 };
88
89 TextWidthManager::TextWidthManager(TextComposite* pCompositeText)
90 {
91         __isComposing = false;
92         __isInitialized = false;
93         __pCompositeText = pCompositeText;
94         __pTextWidthInfoList = null;
95         __pCurrentComposeTextElement = null;
96         __pCurrentWordWidthInfoNode = null;
97         __pCachedWordWidthInfoNode = null;
98         __currentTextElementLength = 0;
99         __currentTextElementType = TEXT_ELEMENT_TYPE_NONE;
100         __textOffsetOfCachedWidthInfo = 0;
101         __currentTextIndex = 0;
102         __strCurrentRelIndex = 0;
103         __textOffsetOfCurrentWidthInfo = 0;
104         __length = 0;
105         __currentComposeTextElementIndex = 0;
106 }
107
108 TextWidthManager::~TextWidthManager(void)
109 {
110         if (__isInitialized)
111         {
112                 Finalize();
113         }
114 }
115
116 bool
117 TextWidthManager::Initialize(int textLength)
118 {
119         if (__isInitialized)
120         {
121                 Finalize();
122         }
123
124         __pTextWidthInfoList = TextSimpleList::Create();
125         SysTryReturn(NID_GRP
126                                 , __pTextWidthInfoList
127                                 , false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
128
129         TextSimpleList::Init(__pTextWidthInfoList);
130
131         __length = 0;
132         __isComposing = false;
133         __isInitialized = true;
134         __pCurrentComposeTextElement = null;
135         __pCachedWordWidthInfoNode = null;
136         __currentComposeTextElementIndex = 0;
137
138         if (textLength > 0)
139         {
140                 InformTextInsert(0, textLength);
141         }
142
143         return true;
144 }
145
146 bool
147 TextWidthManager::Finalize(void)
148 {
149         if (!__isInitialized)
150         {
151                 return false;
152         }
153
154         if (__pTextWidthInfoList)
155         {
156                 TextWidthCommonInfo* pTextWidthCommonInfo = null;
157
158                 pTextWidthCommonInfo = static_cast < TextWidthCommonInfo* >(TextSimpleList::DeleteNthObject(__pTextWidthInfoList, 0));
159                 while (pTextWidthCommonInfo)
160                 {
161                         delete pTextWidthCommonInfo;
162                         pTextWidthCommonInfo = static_cast < TextWidthCommonInfo* >(TextSimpleList::DeleteNthObject(__pTextWidthInfoList, 0));
163                 }
164
165                 if (__pTextWidthInfoList->nodeCount != 0)
166                 {
167                         TextSimpleList::Init(__pTextWidthInfoList);
168                 }
169
170                 TextSimpleList::Destory(__pTextWidthInfoList);
171                 __pTextWidthInfoList = null;
172         }
173
174         __isInitialized = false;
175         __isComposing = false;
176         __length = 0;
177         __pCurrentComposeTextElement = null;
178         __pCachedWordWidthInfoNode = null;
179
180         return true;
181 }
182
183 bool
184 TextWidthManager::StartCompose(int textIndex)
185 {
186         if (!__isInitialized)
187         {
188                 return false;
189         }
190
191         if (__length <= textIndex)
192         {
193                 return false;
194         }
195
196         SimpleNode* pCurrentTextWidthInfoNode = null;
197         int currentWidthInfoTextOffset = 0;
198         TextWidthCommonInfo* pCurrentTextWidthInfo = null;
199
200         pCurrentTextWidthInfoNode = SearchTextWidthInfo(textIndex, currentWidthInfoTextOffset);
201         SysTryReturn(NID_GRP
202                         , pCurrentTextWidthInfoNode
203                         , false, E_SYSTEM, "[E_SYSTEM] Fail to get text width node.");
204
205         pCurrentTextWidthInfo = static_cast < TextWidthCommonInfo* >(pCurrentTextWidthInfoNode->pObject);
206         SysTryReturn(NID_GRP
207                         , pCurrentTextWidthInfo
208                         , false, E_SYSTEM, "[E_SYSTEM] Fail to get text width information.");
209
210         __pCurrentWordWidthInfoNode = pCurrentTextWidthInfoNode;
211         __textOffsetOfCurrentWidthInfo = textIndex - currentWidthInfoTextOffset;
212
213         int elementIndex = 0;
214         int elementTextOffset = 0;
215         __currentTextIndex = textIndex;
216         __pCurrentComposeTextElement = __pCompositeText->GetElementAtTextIndex(textIndex, elementTextOffset,
217                                                                                                                                                                         elementIndex, __currentTextElementLength, __strCurrentRelIndex);
218         SysTryReturn(NID_GRP
219                         , __pCurrentComposeTextElement
220                         , false, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
221
222         __currentComposeTextElementIndex = elementIndex;
223         __currentTextElementType = __pCurrentComposeTextElement->GetType();
224         __isComposing = true;
225
226         return true;
227 }
228
229 bool
230 TextWidthManager::GetCurrentLineInfo(int lineWidth, TextLineComposeInfo& textLineComposeInfo)
231 {
232         if (!__isComposing)
233         {
234                 return false;
235         }
236
237         if (__length <= __currentTextIndex)
238         {
239                 return false;
240         }
241
242         TextWidthCommonInfo* pCurrentTextWidthInfo = static_cast < TextWidthCommonInfo* >(__pCurrentWordWidthInfoNode->pObject);
243         SysTryReturn(NID_GRP
244                                 , pCurrentTextWidthInfo
245                                 , null, E_SYSTEM, "[E_SYSTEM] Fail to get text width information.");
246
247         if (__textOffsetOfCurrentWidthInfo != 0)
248         {
249                 UnknownTextWidthInfo* pUnknownTextWidthInfo = new (std::nothrow) UnknownTextWidthInfo;
250                 SysTryReturn(NID_GRP
251                                         , pUnknownTextWidthInfo
252                                         , false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
253
254                 pUnknownTextWidthInfo->type = TEXT_WIDTH_INFO_UNKNOWN;
255                 pUnknownTextWidthInfo->length = GetTextWidthInfoLength(pCurrentTextWidthInfo) - __textOffsetOfCurrentWidthInfo;
256
257                 __pCurrentWordWidthInfoNode = SplitWidthInfo(__pCurrentWordWidthInfoNode, __textOffsetOfCurrentWidthInfo,
258                                                                                                                                                                                                 pUnknownTextWidthInfo);
259
260                 SysTryReturn(NID_GRP
261                                         , __pCurrentWordWidthInfoNode
262                                         , null, E_SYSTEM, "[E_SYSTEM] Fail to get text width node.");
263
264                 __textOffsetOfCurrentWidthInfo = 0;
265
266                 pCurrentTextWidthInfo = static_cast < TextWidthCommonInfo* >(__pCurrentWordWidthInfoNode->pObject);
267                 SysTryReturn(NID_GRP
268                                         , pCurrentTextWidthInfo
269                                         , null, E_SYSTEM, "[E_SYSTEM] Fail to get text width information.");
270         }
271
272         int maxHeight = 0;
273         int remainingWidth = lineWidth;
274         int type = 0;
275         int textCount = 0;
276         int endType = TEXT_RETBY_NORMAL;
277         bool composeDone = false;
278         bool wordMeet = false;
279         bool enterMeet = false;
280         bool spaceMeetAfterWord = false;
281         bool cutLinkMeetAfterWord = false;
282
283         while (!composeDone)
284         {
285                 type = pCurrentTextWidthInfo->type;
286
287                 switch (type)
288                 {
289                 case TEXT_WIDTH_INFO_UNKNOWN:
290                 {
291                         AnalyzeCurrentUnKnownTextWidthInfo(remainingWidth);
292                 }
293                 break;
294
295                 case TEXT_WIDTH_INFO_WORD:
296                 {
297                         if (remainingWidth <= 0)
298                         {
299                                 break;
300                         }
301
302                         WordTextWidthInfo* pWordTtextWidthInfo = static_cast < WordTextWidthInfo* >(pCurrentTextWidthInfo);
303                         SysTryReturn(NID_GRP
304                                                 , pWordTtextWidthInfo
305                                                 , false, E_SYSTEM, "[E_SYSTEM] Fail to cast text width information.");
306
307                         if (pWordTtextWidthInfo->width <= remainingWidth)
308                         {
309                                 bool iswordoverWidth = false;
310                                 int widthAnalyzed = 0;
311                                 int strLengthAnalyzed = 0;
312                                 int heightAnalzyed = 0;
313                                 bool nextKorean = false;
314                                 bool includeCutLink = false;
315
316                                 AnalyzeNextTextWidthInfo(remainingWidth - pWordTtextWidthInfo->width, iswordoverWidth,
317                                                                                            widthAnalyzed, strLengthAnalyzed, heightAnalzyed, nextKorean, includeCutLink);
318
319                                 if (iswordoverWidth)
320                                 {
321                                         if ((nextKorean || !spaceMeetAfterWord) && !cutLinkMeetAfterWord)
322                                         {
323                                                 remainingWidth -= (widthAnalyzed + pWordTtextWidthInfo->width);
324                                                 if (maxHeight < pWordTtextWidthInfo->maxHeight)
325                                                 {
326                                                         maxHeight = pWordTtextWidthInfo->maxHeight;
327                                                 }
328
329                                                 if (maxHeight < heightAnalzyed)
330                                                 {
331                                                         maxHeight = heightAnalzyed;
332                                                 }
333
334                                                 textCount += (pWordTtextWidthInfo->length + strLengthAnalyzed);
335                                                 Seek(pWordTtextWidthInfo->length + strLengthAnalyzed);
336
337                                         }
338                                         endType = TEXT_RETBY_LIMITWIDTH;
339                                         composeDone = true;
340                                 }
341                                 else
342                                 {
343                                         remainingWidth -= (pWordTtextWidthInfo->width + widthAnalyzed);
344                                         if (maxHeight < pWordTtextWidthInfo->maxHeight)
345                                         {
346                                                 maxHeight = pWordTtextWidthInfo->maxHeight;
347                                         }
348                                         if (maxHeight < heightAnalzyed)
349                                         {
350                                                 maxHeight = heightAnalzyed;
351                                         }
352
353                                         textCount += (pWordTtextWidthInfo->length + strLengthAnalyzed);
354                                         Seek(pWordTtextWidthInfo->length + strLengthAnalyzed);
355
356                                         wordMeet = true;
357                                         cutLinkMeetAfterWord = includeCutLink;
358                                 }
359                         }
360                         else
361                         {
362                                 SysTryReturn(NID_GRP
363                                                         , __pCurrentWordWidthInfoNode
364                                                         , null, E_SYSTEM, "[E_SYSTEM] Fail to get text width node.");
365
366                                 bool nextKorean = false;
367                                 int textLengthBeforeSplit = GetTextWidthInfoLength(static_cast < TextWidthCommonInfo* >(__pCurrentWordWidthInfoNode->pObject));
368                                 pWordTtextWidthInfo = SplitCurrentWordWidthInfo(remainingWidth, nextKorean);
369                                 SysTryReturn(NID_GRP
370                                                         , pWordTtextWidthInfo
371                                                         , false, E_SYSTEM, "[E_SYSTEM] Fail to get text width information.");
372
373                                 if (textLengthBeforeSplit != pWordTtextWidthInfo->length)
374                                 {
375                                         if ((nextKorean || !spaceMeetAfterWord) && !cutLinkMeetAfterWord)
376                                         {
377                                                 remainingWidth -= pWordTtextWidthInfo->width;
378                                                 if (pWordTtextWidthInfo->maxHeight > maxHeight)
379                                                 {
380                                                         maxHeight = pWordTtextWidthInfo->maxHeight;
381                                                 }
382                                                 textCount += pWordTtextWidthInfo->length;
383                                                 Seek(pWordTtextWidthInfo->length);
384                                         }
385                                 }
386
387                                 endType = TEXT_RETBY_LIMITWIDTH;
388                                 composeDone = true;
389                         }
390                 }
391                 break;
392
393                 case TEXT_WIDTH_INFO_SPACE:
394                 {
395                         SpaceTextWidthInfo* pSpaceTextWidthInfo = static_cast < SpaceTextWidthInfo* >(pCurrentTextWidthInfo);
396                         SysTryReturn(NID_GRP
397                                                 , pSpaceTextWidthInfo
398                                                 , false, E_SYSTEM, "[E_SYSTEM] Fail to cast text width information.");
399
400                         if (remainingWidth >= pSpaceTextWidthInfo->width)
401                         {
402                                 remainingWidth -= pSpaceTextWidthInfo->width;
403                                 if (maxHeight < pSpaceTextWidthInfo->maxHeight)
404                                 {
405                                         maxHeight = pSpaceTextWidthInfo->maxHeight;
406                                 }
407
408                                 textCount++;
409
410                                 Seek(1);
411
412                                 if (wordMeet)
413                                 {
414                                         spaceMeetAfterWord = true;
415                                 }
416
417                                 cutLinkMeetAfterWord = false;
418                         }
419                         else
420                         {
421                                 endType = TEXT_RETBY_LIMITWIDTH;
422                                 composeDone = true;
423                         }
424                 }
425                 break;
426
427                 case TEXT_WIDTH_INFO_ENTER:
428                 {
429                         endType = TEXT_RETBY_LINEFEED;
430                         composeDone = true;
431                         EnterTextWidthInfo* pEnterTextWidthInfo = static_cast < EnterTextWidthInfo* >(pCurrentTextWidthInfo);
432                         SysTryReturn(NID_GRP
433                                                 , pEnterTextWidthInfo
434                                                 , false, E_SYSTEM, "[E_SYSTEM] Fail to cast text width information.");
435
436                         maxHeight = pEnterTextWidthInfo->maxHeight;
437                         textCount += pEnterTextWidthInfo->length;
438                         Seek(pEnterTextWidthInfo->length);
439
440                         enterMeet = true;
441                 }
442                 break;
443
444                 case TEXT_WIDTH_INFO_SYMBOL:
445                 {
446                         if (textCount == 0)
447                         {
448                                 SymbolTextWidthInfo* pSymbolTextWidthInfo = static_cast < SymbolTextWidthInfo* >(pCurrentTextWidthInfo);
449                                 SysTryReturn(NID_GRP
450                                                         , pSymbolTextWidthInfo
451                                                         , false, E_SYSTEM, "[E_SYSTEM] Fail to cast text width information.");
452
453                                 remainingWidth -= pSymbolTextWidthInfo->width;
454                                 maxHeight = pSymbolTextWidthInfo->maxHeight;
455                                 textCount++;
456                                 Seek(1);
457                         }
458                         else
459                         {
460                                 endType = TEXT_RETBY_NORMAL;
461                                 composeDone = true;
462                         }
463                 }
464                 break;
465                 }
466
467                 if (remainingWidth <= 0)
468                 {
469                         break;
470                 }
471
472                 if (!enterMeet && (__length <= __currentTextIndex))
473                 {
474                         endType = TEXT_RETBY_NORMAL;
475                         composeDone = true;
476                 }
477
478                 if (!composeDone)
479                 {
480                         SysTryReturn(NID_GRP
481                                                 , __pCurrentWordWidthInfoNode
482                                                 , null, E_SYSTEM, "[E_SYSTEM] Fail to get text width node.");
483
484                         pCurrentTextWidthInfo = static_cast < TextWidthCommonInfo* >(__pCurrentWordWidthInfoNode->pObject);
485                         SysTryReturn(NID_GRP
486                                                 , pCurrentTextWidthInfo
487                                                 , null, E_SYSTEM, "[E_SYSTEM] Fail to get text width information.");
488                 }
489         }
490
491         textLineComposeInfo.length = textCount;
492         textLineComposeInfo.width = lineWidth - remainingWidth;
493         textLineComposeInfo.height = maxHeight;
494         textLineComposeInfo.endType = endType;
495
496         return true;
497 }
498
499 bool
500 TextWidthManager::EndCompose(void)
501 {
502         __isComposing = false;
503         __pCurrentComposeTextElement = null;
504         __pCurrentWordWidthInfoNode = null;
505
506         return true;
507 }
508
509 bool
510 TextWidthManager::InformTextInsert(int textIndex, int textLength)
511 {
512         SimpleNode* pCurrentTextWidthInfoNode = null;
513         if (!__isInitialized)
514         {
515                 return false;
516         }
517
518         if (__isComposing)
519         {
520                 return false;
521         }
522
523         if (__length < textIndex)
524         {
525                 return false;
526         }
527
528         if (textIndex == __length)
529         {
530                 SimpleNode* pLastNode = TextSimpleList::GetLastNode(__pTextWidthInfoList);
531                 int strLastTextWidthInfo = 0;
532                 TextWidthCommonInfo* pLastTextWidthInfo = null;
533
534                 if (pLastNode != null)
535                 {
536                         pLastTextWidthInfo = static_cast < TextWidthCommonInfo* >(pLastNode->pObject);
537                         strLastTextWidthInfo = GetTextWidthInfoLength(pLastTextWidthInfo);
538                         SysTryReturn(NID_GRP
539                                                 , strLastTextWidthInfo
540                                                 , false, E_SYSTEM, "[E_SYSTEM] Fail to get text element node.");
541                 }
542
543                 if ((pLastNode == null) || (strLastTextWidthInfo + textLength > MAX_TEXT_WIDTH_INFO_MERGE_LENGTH))
544                 {
545                         UnknownTextWidthInfo* pUnknownTextWidthInfo = new (std::nothrow) UnknownTextWidthInfo;
546                         SysTryReturn(NID_GRP
547                                                 , pUnknownTextWidthInfo
548                                                 , false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
549
550                         pUnknownTextWidthInfo->type = TEXT_WIDTH_INFO_UNKNOWN;
551                         pUnknownTextWidthInfo->length = 0;
552
553                         pCurrentTextWidthInfoNode = TextSimpleList::AppendObject(__pTextWidthInfoList, pUnknownTextWidthInfo);
554                         SysTryReturn(NID_GRP
555                                                 , pCurrentTextWidthInfoNode
556                                                 , false, E_SYSTEM, "[E_SYSTEM] Fail to get text element node.");
557
558                         UpdateCachedTextWidhtInfo(__length, pCurrentTextWidthInfoNode);
559                         pUnknownTextWidthInfo->length = textLength;
560                 }
561                 else
562                 {
563                         UnknownTextWidthInfo* pUnknownTextWidthInfo = new (std::nothrow) UnknownTextWidthInfo;
564                         SysTryReturn(NID_GRP
565                                                 , pUnknownTextWidthInfo
566                                                 , false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
567
568                         pUnknownTextWidthInfo->type = TEXT_WIDTH_INFO_UNKNOWN;
569                         pUnknownTextWidthInfo->length = strLastTextWidthInfo;
570
571                         delete static_cast < TextWidthCommonInfo* >(pLastNode->pObject);
572                         pLastNode->pObject = pUnknownTextWidthInfo;
573
574                         UpdateCachedTextWidhtInfo(__length - strLastTextWidthInfo, pLastNode);
575                         pUnknownTextWidthInfo->length += textLength;
576                 }
577
578                 __length += textLength;
579
580                 return true;
581         }
582
583         int currentWidthInfoTextOffset = 0;
584         TextWidthCommonInfo* pCurrentTextWidthInfo = null;
585
586         pCurrentTextWidthInfoNode = SearchTextWidthInfo(textIndex, currentWidthInfoTextOffset);
587         if (pCurrentTextWidthInfoNode == null)
588         {
589                 return false;
590         }
591         pCurrentTextWidthInfo = static_cast < TextWidthCommonInfo* >(pCurrentTextWidthInfoNode->pObject);
592         SysTryReturn(NID_GRP
593                                 , pCurrentTextWidthInfo
594                                 , false, E_SYSTEM, "[E_SYSTEM] Fail to get text width information.");
595
596         int textIndexFromCurrentWidthInfoTextOffset = textIndex - currentWidthInfoTextOffset;
597         int widthinfoType = pCurrentTextWidthInfo->type;
598
599         switch (widthinfoType)
600         {
601         case TEXT_WIDTH_INFO_UNKNOWN:
602         {
603                 UpdateCachedTextWidhtInfo(currentWidthInfoTextOffset, pCurrentTextWidthInfoNode);
604
605                 UnknownTextWidthInfo* pUnknownTextWidthInfo = static_cast < UnknownTextWidthInfo* >(pCurrentTextWidthInfo);
606                 SysTryReturn(NID_GRP
607                                         , pUnknownTextWidthInfo
608                                         , false, E_SYSTEM, "[E_SYSTEM] Fail to get text width information.");
609                 pUnknownTextWidthInfo->length += textLength;
610                 __length += textLength;
611         }
612         break;
613
614         case TEXT_WIDTH_INFO_WORD:
615         {
616                 WordTextWidthInfo* pCurrentWordTextWidthInfo = static_cast < WordTextWidthInfo* >(pCurrentTextWidthInfo);
617                 SysTryReturn(NID_GRP
618                                         , pCurrentWordTextWidthInfo
619                                         , false, E_SYSTEM, "[E_SYSTEM] Fail to cast text width information.");
620
621                 if ((textIndexFromCurrentWidthInfoTextOffset == 0) &&
622                         (pCurrentWordTextWidthInfo->length + textLength > MAX_TEXT_WIDTH_INFO_MERGE_LENGTH))
623                 {
624                         UnknownTextWidthInfo* pUnknownTextWidthInfo = new (std::nothrow) UnknownTextWidthInfo;
625                         SysTryReturn(NID_GRP
626                                                 , pUnknownTextWidthInfo
627                                                 , false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
628
629                         pUnknownTextWidthInfo->type = TEXT_WIDTH_INFO_UNKNOWN;
630                         pUnknownTextWidthInfo->length = 0;
631
632                         pCurrentTextWidthInfoNode = TextSimpleList::InsertObjectBeforeNode(__pTextWidthInfoList, pCurrentTextWidthInfoNode,
633                                                                                                                                                                 pUnknownTextWidthInfo);
634                         UpdateCachedTextWidhtInfo(textIndex, pCurrentTextWidthInfoNode);
635                         pUnknownTextWidthInfo->length = textLength;
636                 }
637                 else
638                 {
639                         UnknownTextWidthInfo* pUnknownTextWidthInfo = new (std::nothrow) UnknownTextWidthInfo;
640                         SysTryReturn(NID_GRP
641                                                 , pUnknownTextWidthInfo
642                                                 , false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
643
644                         pUnknownTextWidthInfo->type = TEXT_WIDTH_INFO_UNKNOWN;
645                         pUnknownTextWidthInfo->length = pCurrentWordTextWidthInfo->length;
646                         delete static_cast < TextWidthCommonInfo* >(pCurrentTextWidthInfoNode->pObject);
647                         pCurrentTextWidthInfoNode->pObject = pUnknownTextWidthInfo;
648
649                         UpdateCachedTextWidhtInfo(currentWidthInfoTextOffset, pCurrentTextWidthInfoNode);
650                         pUnknownTextWidthInfo->length += textLength;
651                 }
652
653                 __length += textLength;
654         }
655         break;
656
657         case TEXT_WIDTH_INFO_SPACE:
658                 // fall through
659         case TEXT_WIDTH_INFO_ENTER:
660                 // fall through
661         case TEXT_WIDTH_INFO_SYMBOL:
662         {
663                 UnknownTextWidthInfo* pUnknownTextWidthInfo = new (std::nothrow) UnknownTextWidthInfo;
664                 SysTryReturn(NID_GRP
665                                         , pUnknownTextWidthInfo
666                                         , false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
667
668                 pUnknownTextWidthInfo->type = TEXT_WIDTH_INFO_UNKNOWN;
669                 pUnknownTextWidthInfo->length = GetTextWidthInfoLength(pCurrentTextWidthInfo);
670                 delete static_cast < TextWidthCommonInfo* >(pCurrentTextWidthInfoNode->pObject);
671                 pCurrentTextWidthInfoNode->pObject = pUnknownTextWidthInfo;
672
673                 UpdateCachedTextWidhtInfo(currentWidthInfoTextOffset, pCurrentTextWidthInfoNode);
674                 pUnknownTextWidthInfo->length += textLength;
675                 __length += textLength;
676         }
677         break;
678         }
679
680         return true;
681 }
682
683 bool
684 TextWidthManager::InformTextRemove(int textIndex, int textLength)
685 {
686         if (!__isInitialized)
687         {
688                 return false;
689         }
690
691         if (__isComposing)
692         {
693                 return false;
694         }
695
696         if (__length <= textIndex)
697         {
698                 return false;
699         }
700
701         if (__length < textIndex + textLength)
702         {
703                 textLength = __length - textIndex;
704         }
705
706         int strLengthRemove = textLength;
707         SimpleNode* pCurrentTextWidthInfoNode = null;
708         int currentWidthInfoTextOffset = 0;
709         TextWidthCommonInfo* pCurrentTextWidthInfo = null;
710
711         pCurrentTextWidthInfoNode = SearchTextWidthInfo(textIndex, currentWidthInfoTextOffset);
712         SysTryReturn(NID_GRP
713                                 , pCurrentTextWidthInfoNode
714                                 , false, E_SYSTEM, "[E_SYSTEM] Fail to get text text width node.");
715
716         pCurrentTextWidthInfo = static_cast < TextWidthCommonInfo* >(pCurrentTextWidthInfoNode->pObject);
717         SysTryReturn(NID_GRP
718                                 , pCurrentTextWidthInfo
719                                 , false, E_SYSTEM, "[E_SYSTEM] Fail to get text width information.");
720
721         int textIndexFromCurrentWidthInfoTextOffset = textIndex - currentWidthInfoTextOffset;
722         int currentWidthInfoTextLength = GetTextWidthInfoLength(pCurrentTextWidthInfo);
723         bool cachedUpdated = false;
724
725         if ((textIndexFromCurrentWidthInfoTextOffset != 0) || (currentWidthInfoTextLength > textLength))
726         {
727                 int strCurrrentRemoveLength = 0;
728                 if (textIndexFromCurrentWidthInfoTextOffset == 0)
729                 {
730                         strCurrrentRemoveLength = textLength;
731                 }
732                 else
733                 {
734                         if (textLength + textIndexFromCurrentWidthInfoTextOffset >= currentWidthInfoTextLength)
735                         {
736                                 strCurrrentRemoveLength = currentWidthInfoTextLength - textIndexFromCurrentWidthInfoTextOffset;
737                         }
738                         else
739                         {
740                                 strCurrrentRemoveLength = textLength;
741                         }
742                 }
743
744                 UpdateCachedTextWidhtInfo(currentWidthInfoTextOffset, pCurrentTextWidthInfoNode);
745                 cachedUpdated = true;
746
747                 UnknownTextWidthInfo* pUnknownTextWidthInfo = new (std::nothrow) UnknownTextWidthInfo;
748                 SysTryReturn(NID_GRP
749                                         , pUnknownTextWidthInfo
750                                         , false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
751
752                 pUnknownTextWidthInfo->type = TEXT_WIDTH_INFO_UNKNOWN;
753                 pUnknownTextWidthInfo->length = currentWidthInfoTextLength - strCurrrentRemoveLength;
754                 delete static_cast < TextWidthCommonInfo* >(pCurrentTextWidthInfoNode->pObject);
755                 pCurrentTextWidthInfoNode->pObject = pUnknownTextWidthInfo;
756
757                 pCurrentTextWidthInfoNode = pCurrentTextWidthInfoNode->pNext;
758
759                 textLength -= strCurrrentRemoveLength;
760         }
761
762         while (textLength)
763         {
764                 SimpleNode* pNextTextWidthInfoNode = null;
765
766                 SysTryReturn(NID_GRP
767                                         , pCurrentTextWidthInfoNode
768                                         , null, E_SYSTEM, "[E_SYSTEM] Fail to get text element node.");
769
770                 pCurrentTextWidthInfo = static_cast < TextWidthCommonInfo* >(pCurrentTextWidthInfoNode->pObject);
771                 SysTryReturn(NID_GRP
772                                         , pCurrentTextWidthInfo
773                                         , null, E_SYSTEM, "[E_SYSTEM] Fail to get text width information.");
774
775                 currentWidthInfoTextLength = GetTextWidthInfoLength(pCurrentTextWidthInfo);
776
777                 if (textLength < currentWidthInfoTextLength)
778                 {
779                         break;
780                 }
781
782                 pNextTextWidthInfoNode = pCurrentTextWidthInfoNode->pNext;
783
784                 TextSimpleList::DeleteNode(__pTextWidthInfoList, pCurrentTextWidthInfoNode);
785
786                 pCurrentTextWidthInfoNode = pNextTextWidthInfoNode;
787
788                 textLength -= currentWidthInfoTextLength;
789         }
790
791         if (textLength > 0)
792         {
793                 UnknownTextWidthInfo* pUnknownTextWidthInfo = new (std::nothrow) UnknownTextWidthInfo;
794                 SysTryReturn(NID_GRP
795                                         , pUnknownTextWidthInfo
796                                         , false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
797
798                 pUnknownTextWidthInfo->type = TEXT_WIDTH_INFO_UNKNOWN;
799                 pUnknownTextWidthInfo->length = currentWidthInfoTextLength - textLength;
800                 delete static_cast < TextWidthCommonInfo* >(pCurrentTextWidthInfoNode->pObject);
801                 pCurrentTextWidthInfoNode->pObject = pUnknownTextWidthInfo;
802         }
803
804         if (!cachedUpdated)
805         {
806                 UpdateCachedTextWidhtInfo(textIndex, pCurrentTextWidthInfoNode);
807         }
808
809         __length -= strLengthRemove;
810
811         return true;
812 }
813
814 int
815 TextWidthManager::GetTextWidthInfoLength(TextWidthCommonInfo* pTextWidthCommonInfo)
816 {
817         int type = pTextWidthCommonInfo->type;
818
819         switch (type)
820         {
821         case TEXT_WIDTH_INFO_UNKNOWN:
822         {
823                 UnknownTextWidthInfo* pUnknownTextWidthInfo = static_cast < UnknownTextWidthInfo* >(pTextWidthCommonInfo);
824                 SysTryReturn(NID_GRP
825                                         , pUnknownTextWidthInfo
826                                         , -1, E_SYSTEM, "[E_SYSTEM] Fail to cast text width information.");
827
828                 return pUnknownTextWidthInfo->length;
829         }
830
831         case TEXT_WIDTH_INFO_WORD:
832         {
833                 WordTextWidthInfo* pWordWidthInfo = static_cast < WordTextWidthInfo* >(pTextWidthCommonInfo);
834                 SysTryReturn(NID_GRP
835                                         , pWordWidthInfo
836                                         , -1, E_SYSTEM, "[E_SYSTEM] Fail to get text width information.");
837
838                 return pWordWidthInfo->length;
839         }
840
841         case TEXT_WIDTH_INFO_SPACE:
842                 return 1;
843
844         case TEXT_WIDTH_INFO_ENTER:
845         {
846                 EnterTextWidthInfo* pEnterWidthInfo = static_cast < EnterTextWidthInfo* >(pTextWidthCommonInfo);
847                 SysTryReturn(NID_GRP
848                                         , pEnterWidthInfo
849                                         , -1, E_SYSTEM, "[E_SYSTEM] Fail to cast text width information.");
850
851                 return pEnterWidthInfo->length;
852         }
853
854         case TEXT_WIDTH_INFO_SYMBOL:
855                 return 1;
856         }
857
858         return -1;
859 }
860
861 SimpleNode*
862 TextWidthManager::SplitWidthInfo(SimpleNode* pOrginalTextWidthInfoNode, int splitStartIndex,
863                                                                                 TextWidthCommonInfo* pTextWidthInfo)
864 {
865         TextWidthCommonInfo* pCurrentTextWidthInfo = static_cast < TextWidthCommonInfo* >(pOrginalTextWidthInfoNode->pObject);
866         SysTryReturn(NID_GRP
867                         , pCurrentTextWidthInfo
868                         , null, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
869
870         int type = pCurrentTextWidthInfo->type;
871
872         if (type == TEXT_WIDTH_INFO_UNKNOWN)
873         {
874                 UnknownTextWidthInfo* pUnknownTextWidthInfo = static_cast < UnknownTextWidthInfo* >(pCurrentTextWidthInfo);
875                 SysTryReturn(NID_GRP
876                                         , pUnknownTextWidthInfo
877                                         , null, E_SYSTEM, "[E_SYSTEM] Fail to cast text width information.");
878
879                 pUnknownTextWidthInfo->length = splitStartIndex;
880         }
881         else if (type == TEXT_WIDTH_INFO_WORD)
882         {
883                 UnknownTextWidthInfo* pUnknownTextWidthInfo = new (std::nothrow) UnknownTextWidthInfo;
884                 SysTryReturn(NID_GRP
885                                         , pUnknownTextWidthInfo
886                                         , null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
887
888                 pUnknownTextWidthInfo->type = TEXT_WIDTH_INFO_UNKNOWN;
889                 pUnknownTextWidthInfo->length = splitStartIndex;
890                 delete static_cast < TextWidthCommonInfo* >(pOrginalTextWidthInfoNode->pObject);
891                 pOrginalTextWidthInfoNode->pObject = pUnknownTextWidthInfo;
892         }
893
894         SimpleNode* pNode = TextSimpleList::InsertObjectAfterNode(__pTextWidthInfoList, pOrginalTextWidthInfoNode, pTextWidthInfo);
895         return pNode;
896 }
897
898 WordTextWidthInfo*
899 TextWidthManager::SplitCurrentWordWidthInfo(int limitWidth, bool& isNextKoreanStart)
900 {
901         TextWidthCommonInfo* pCurrentTextWidthInfo = static_cast < TextWidthCommonInfo* >(__pCurrentWordWidthInfoNode->pObject);
902         SysTryReturn(NID_GRP
903                         , pCurrentTextWidthInfo
904                         , null, E_SYSTEM, "[E_SYSTEM] Fail to get text width information.");
905
906         WordTextWidthInfo* pWordWidthInfo = static_cast < WordTextWidthInfo* >(pCurrentTextWidthInfo);
907         SysTryReturn(NID_GRP
908                         , pWordWidthInfo
909                         , null, E_SYSTEM, "[E_SYSTEM] Fail to get text width information.");
910
911         int currentWordWidth = pWordWidthInfo->width;
912         int currentWordLength = pWordWidthInfo->length;
913
914         if ((currentWordWidth - limitWidth) >= (currentWordWidth >> 2))
915         {
916                 TextElement* pTextElement = __pCurrentComposeTextElement;
917                 int textElementIndex = __currentComposeTextElementIndex;
918                 int strSrcRelIndex = __strCurrentRelIndex;
919                 int currentLength = Math::Min(__currentTextElementLength, currentWordLength);
920                 int stringLength = currentWordLength;
921                 int endType = TEXT_RETBY_NORMAL;
922                 int remainWidth = limitWidth;
923                 int charCount = 0;
924                 int width = 0;
925                 int height = 0;
926                 int maxHeight = 0;
927                 int textIndex = 0;
928
929                 while (stringLength != 0)
930                 {
931                         endType = pTextElement->ForwardAnalyze(strSrcRelIndex, currentLength, remainWidth,
932                                                                                                  TEXT_OBJECT_WRAP_TYPE_NONE, charCount, width, height);
933
934                         if (endType == TEXT_RETBY_LIMITWIDTH)
935                         {
936                                 textIndex += charCount;
937                                 strSrcRelIndex += charCount;
938                                 remainWidth -= width;
939                                 if (height > maxHeight)
940                                 {
941                                         maxHeight = height;
942                                 }
943                                 break;
944                         }
945                         else if (endType != TEXT_RETBY_LIMITLENGTH)
946                         {
947                                 ; //SysAssert(false);
948                         }
949
950                         textElementIndex++;
951                         pTextElement = __pCompositeText->GetElementAtElementIndex(textElementIndex);
952                         if (pTextElement == null)
953                         {
954                                 break;
955                         }
956
957                         remainWidth -= width;
958                         if (height > maxHeight)
959                         {
960                                 height = maxHeight;
961                         }
962
963                         strSrcRelIndex = pTextElement->GetValue(SET_TEXT_OFFSET);
964                         stringLength -= currentLength;
965                         textIndex += currentLength;
966                         currentLength = Math::Min(stringLength, pTextElement->GetValue(SET_TEXT_OFFSET) + pTextElement->GetTextLength() - strSrcRelIndex);
967                 }
968
969                 SysTryReturn(NID_GRP
970                                 , pTextElement
971                                 , null, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
972
973                 TextSimple* pSimpleTextElement = dynamic_cast < TextSimple* >(pTextElement);
974                 SysTryReturn(NID_GRP
975                                 , pSimpleTextElement
976                                 , null, E_SYSTEM, "[E_SYSTEM] Fail to cast text element.");
977
978                 wchar_t* pText = (wchar_t*)pSimpleTextElement->GetText();
979                 isNextKoreanStart = IsKorean(pText[0]);
980
981                 if (textIndex > 0)
982                 {
983                         WordTextWidthInfo* pNewWordWidthInfo = new (std::nothrow) WordTextWidthInfo;
984                         SysTryReturn(NID_GRP
985                                 , pNewWordWidthInfo
986                                 , null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
987
988                         pNewWordWidthInfo->type = TEXT_WIDTH_INFO_WORD;
989                         pNewWordWidthInfo->length = textIndex;
990                         pNewWordWidthInfo->maxHeight = height;
991                         pNewWordWidthInfo->width = limitWidth - remainWidth;
992
993                         bool isCacheChanged = false;
994
995                         if (__pCurrentWordWidthInfoNode == __pCachedWordWidthInfoNode)
996                         {
997                                 isCacheChanged = true;
998                         }
999
1000                         __pCurrentWordWidthInfoNode = TextSimpleList::InsertObjectBeforeNode(__pTextWidthInfoList, __pCurrentWordWidthInfoNode,
1001                                                                                                                 pNewWordWidthInfo);
1002
1003                         if (isCacheChanged)
1004                         {
1005                                 __pCachedWordWidthInfoNode = __pCurrentWordWidthInfoNode;
1006                         }
1007
1008                         pWordWidthInfo->length -= textIndex;
1009                         pWordWidthInfo->width -= pNewWordWidthInfo->width;
1010                         return pNewWordWidthInfo;
1011                 }
1012                 else
1013                 {
1014                         return pWordWidthInfo;
1015                 }
1016         }
1017         else
1018         {
1019                 int remainingWidth = currentWordWidth - limitWidth;
1020
1021                 TextElement* pTextElement = __pCurrentComposeTextElement;
1022                 int textElementIndex = __currentComposeTextElementIndex;
1023                 int strSrcRelIndex = __strCurrentRelIndex;
1024                 int textLength = currentWordLength;
1025                 int currentLength = __currentTextElementLength;
1026                 TextElement* pTextElementStack[10];
1027                 int textElementStackIndex = 0;
1028
1029                 pTextElementStack[0] = pTextElement;
1030
1031                 while (textLength > 0)
1032                 {
1033                         if (textLength <= currentLength)
1034                         {
1035                                 strSrcRelIndex += (textLength - 1);
1036                                 break;
1037                         }
1038
1039                         textLength -= currentLength;
1040
1041                         textElementIndex++;
1042                         pTextElement = __pCompositeText->GetElementAtElementIndex(textElementIndex);
1043                         if (pTextElement == null)
1044                         {
1045                                 break;
1046                         }
1047
1048                         strSrcRelIndex = pTextElement->GetValue(SET_TEXT_OFFSET);
1049                         currentLength = pTextElement->GetValue(SET_TEXT_OFFSET) + pTextElement->GetTextLength() - strSrcRelIndex;
1050
1051                         textElementStackIndex++;
1052                         pTextElementStack[textElementStackIndex] = pTextElement;
1053                 }
1054
1055                 SysTryReturn(NID_GRP
1056                                         , pTextElement
1057                                         , null, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
1058
1059                 int width = 0;
1060                 int height = 0;
1061                 int strSrcStartRelIndex = pTextElement->GetValue(SET_TEXT_OFFSET);
1062                 int widthBackward = 0;
1063                 int stringLengthBackward = 0;
1064                 int maxHeight = 0;
1065
1066                 while (0 < remainingWidth)
1067                 {
1068                         pTextElement->GetRegion(strSrcRelIndex, 1, width, height);
1069                         if (remainingWidth <= width)
1070                         {
1071                                 widthBackward += width;
1072                                 stringLengthBackward++;
1073                                 if (height > maxHeight)
1074                                 {
1075                                         maxHeight = height;
1076                                 }
1077                                 break;
1078                         }
1079
1080                         widthBackward += width;
1081                         stringLengthBackward++;
1082                         remainingWidth -= width;
1083
1084                         if (height > maxHeight)
1085                         {
1086                                 maxHeight = height;
1087                         }
1088
1089                         if (strSrcStartRelIndex < strSrcRelIndex)
1090                         {
1091                                 strSrcRelIndex--;
1092                         }
1093                         else
1094                         {
1095                                 textElementStackIndex--;
1096                                 SysTryReturn(NID_GRP
1097                                                         , textElementStackIndex >= 0
1098                                                         , null, E_SYSTEM, "[E_SYSTEM] Index must be greater than or equal to 0.");
1099
1100                                 pTextElement = pTextElementStack[textElementStackIndex];
1101                                 SysTryReturn(NID_GRP
1102                                                         , pTextElement
1103                                                         , null, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
1104
1105                                 strSrcStartRelIndex = pTextElement->GetValue(SET_TEXT_OFFSET);
1106                                 strSrcRelIndex = pTextElement->GetValue(SET_TEXT_OFFSET) + pTextElement->GetTextLength() - 1;
1107                         }
1108                 }
1109
1110                 TextSimple* pSimpleTextElement = dynamic_cast < TextSimple* >(pTextElement);
1111                 SysTryReturn(NID_GRP
1112                                 , pSimpleTextElement
1113                                 , null, E_SYSTEM, "[E_SYSTEM] Fail to cast text element.");
1114
1115                 wchar_t* pText = (wchar_t*)pSimpleTextElement->GetText();
1116                 isNextKoreanStart = IsKorean(pText[0]);
1117
1118                 if ((stringLengthBackward > 0) && (stringLengthBackward < pWordWidthInfo->length))
1119                 {
1120                         WordTextWidthInfo* pNewWordWidthInfo = new (std::nothrow) WordTextWidthInfo;
1121                         SysTryReturn(NID_GRP
1122                                         , pNewWordWidthInfo
1123                                         , null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
1124
1125                         pNewWordWidthInfo->type = TEXT_WIDTH_INFO_WORD;
1126                         pNewWordWidthInfo->length = stringLengthBackward;
1127                         pNewWordWidthInfo->maxHeight = height;
1128                         pNewWordWidthInfo->width = widthBackward;
1129
1130                         TextSimpleList::InsertObjectAfterNode(__pTextWidthInfoList, __pCurrentWordWidthInfoNode, pNewWordWidthInfo);
1131
1132                         pWordWidthInfo->length -= stringLengthBackward;
1133                         pWordWidthInfo->width -= widthBackward;
1134                 }
1135                 else
1136                 {
1137                         return pWordWidthInfo;
1138                 }
1139
1140                 return pWordWidthInfo;
1141         }
1142
1143         return null;
1144 }
1145
1146 WordTextWidthInfo*
1147 TextWidthManager::SplitWordWidthInfo(SimpleNode* pCurrentWordWidthInfoNode, TextElement* pCurrentTextElement,
1148                                                                                    int strCurrentRelIndex, int strCurrentLength, int limitWidth, bool& isNextKoreanStart)
1149 {
1150         WordTextWidthInfo* pWordWidthInfo = static_cast < WordTextWidthInfo* >(pCurrentWordWidthInfoNode->pObject);
1151         SysTryReturn(NID_GRP
1152                         , pWordWidthInfo
1153                         , null, E_SYSTEM, "[E_SYSTEM] Fail to get text width information.");
1154
1155         int currentWordWidth = pWordWidthInfo->width;
1156         int currentWordLength = pWordWidthInfo->length;
1157
1158         if ((currentWordWidth - limitWidth) >= (currentWordWidth >> 2))
1159         {
1160                 TextElement* pTextElement = pCurrentTextElement;
1161                 int strSrcRelIndex = strCurrentRelIndex;
1162                 int currentLength = Math::Min(__currentTextElementLength, currentWordLength);
1163                 int stringLength = currentWordLength;
1164                 int endType = TEXT_RETBY_NORMAL;
1165                 int remainWidth = limitWidth;
1166                 int charCount = 0;
1167                 int width = 0;
1168                 int height = 0;
1169                 int maxHeight = 0;
1170                 int stringIndex = 0;
1171                 int textElementIndex = __pCompositeText->GetElementIndexOf(*pCurrentTextElement);
1172                 SysTryReturn(NID_GRP
1173                                         , textElementIndex >= 0
1174                                         , null, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
1175
1176                 while (stringLength != 0)
1177                 {
1178                         endType = pTextElement->ForwardAnalyze(strSrcRelIndex, currentLength, remainWidth,
1179                                                                                                  TEXT_OBJECT_WRAP_TYPE_NONE, charCount, width, height);
1180
1181                         if (endType == TEXT_RETBY_LIMITWIDTH)
1182                         {
1183                                 stringIndex += charCount;
1184                                 strSrcRelIndex += charCount;
1185                                 remainWidth -= width;
1186                                 if (height > maxHeight)
1187                                 {
1188                                         maxHeight = height;
1189                                 }
1190                                 break;
1191                         }
1192                         else if (endType != TEXT_RETBY_LIMITLENGTH)
1193                         {
1194                                 ; //SysAssert(false);
1195                         }
1196
1197                         textElementIndex++;
1198                         pTextElement = __pCompositeText->GetElementAtElementIndex(textElementIndex);
1199                         if (pTextElement == null)
1200                         {
1201                                 break;
1202                         }
1203
1204                         remainWidth -= width;
1205
1206                         if (height > maxHeight)
1207                         {
1208                                 height = maxHeight;
1209                         }
1210
1211                         strSrcRelIndex = pTextElement->GetValue(SET_TEXT_OFFSET);
1212                         stringLength -= currentLength;
1213                         stringIndex += currentLength;
1214                         currentLength = Math::Min(stringLength, pTextElement->GetValue(
1215                                                                                    SET_TEXT_OFFSET) + pTextElement->GetTextLength() - strSrcRelIndex);
1216                 }
1217
1218                 SysTryReturn(NID_GRP
1219                                 , pTextElement
1220                                 , null, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
1221
1222                 TextSimple* pSimpleTextElement = dynamic_cast < TextSimple* >(pTextElement);
1223                 SysTryReturn(NID_GRP
1224                                 , pSimpleTextElement
1225                                 , null, E_SYSTEM, "[E_SYSTEM] Fail to cast text element.");
1226
1227                 wchar_t* pText = (wchar_t*)pSimpleTextElement->GetText();
1228                 isNextKoreanStart = IsKorean(pText[0]);
1229
1230                 if (stringIndex > 0)
1231                 {
1232                         WordTextWidthInfo* pNewWordWidthInfo = new (std::nothrow) WordTextWidthInfo;
1233                         SysTryReturn(NID_GRP
1234                                 , pNewWordWidthInfo
1235                                 , null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
1236
1237                         pNewWordWidthInfo->type = TEXT_WIDTH_INFO_WORD;
1238                         pNewWordWidthInfo->length = stringIndex;
1239                         pNewWordWidthInfo->maxHeight = height;
1240                         pNewWordWidthInfo->width = limitWidth - remainWidth;
1241
1242                         if (pCurrentWordWidthInfoNode == __pCachedWordWidthInfoNode)
1243                         {
1244                                 __pCachedWordWidthInfoNode = TextSimpleList::InsertObjectBeforeNode(__pTextWidthInfoList,
1245                                                                                                                                                         pCurrentWordWidthInfoNode, pNewWordWidthInfo);
1246                         }
1247                         else
1248                         {
1249                                 TextSimpleList::InsertObjectBeforeNode(__pTextWidthInfoList, pCurrentWordWidthInfoNode, pNewWordWidthInfo);
1250                         }
1251
1252                         pWordWidthInfo->length -= stringIndex;
1253                         pWordWidthInfo->width -= pNewWordWidthInfo->width;
1254                         return pNewWordWidthInfo;
1255                 }
1256                 else
1257                 {
1258                         return pWordWidthInfo;
1259                 }
1260         }
1261         else
1262         {
1263                 int remainingWidth = currentWordWidth - limitWidth;
1264
1265                 TextElement* pTextElement = __pCurrentComposeTextElement;
1266                 int textElementIndex = __currentComposeTextElementIndex;
1267                 int strSrcRelIndex = strCurrentRelIndex;
1268                 int textLength = currentWordLength;
1269                 int currentLength = __currentTextElementLength;
1270                 TextElement* pTextElementStack[10];
1271                 int textElementStackIndex = 0;
1272
1273                 pTextElementStack[0] = pTextElement;
1274
1275                 while (textLength > 0)
1276                 {
1277                         if (currentLength >= textLength)
1278                         {
1279                                 strSrcRelIndex += (textLength - 1);
1280                                 break;
1281                         }
1282
1283                         textLength -= currentLength;
1284                         textElementIndex++;
1285
1286                         pTextElement = __pCompositeText->GetElementAtElementIndex(textElementIndex);
1287                         if (pTextElement == null)
1288                         {
1289                                 break;
1290                         }
1291
1292                         strSrcRelIndex = pTextElement->GetValue(SET_TEXT_OFFSET);
1293                         currentLength = pTextElement->GetValue(SET_TEXT_OFFSET) + pTextElement->GetTextLength() - strSrcRelIndex;
1294
1295                         textElementStackIndex++;
1296                         pTextElementStack[textElementStackIndex] = pTextElement;
1297                 }
1298
1299                 SysTryReturn(NID_GRP
1300                                 , pTextElement
1301                                 , null, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
1302
1303                 int width = 0;
1304                 int height = 0;
1305                 int strSrcStartRelIndex = pTextElement->GetValue(SET_TEXT_OFFSET);
1306                 int widthBackward = 0;
1307                 int stringLengthBackward = 0;
1308                 int maxHeight = 0;
1309                 while (remainingWidth > 0)
1310                 {
1311                         pTextElement->GetRegion(strSrcRelIndex, 1, width, height);
1312                         if (remainingWidth <= width)
1313                         {
1314                                 widthBackward += width;
1315                                 stringLengthBackward++;
1316                                 if (height > maxHeight)
1317                                 {
1318                                         maxHeight = height;
1319                                 }
1320                                 break;
1321                         }
1322
1323                         widthBackward += width;
1324                         stringLengthBackward++;
1325                         remainingWidth -= width;
1326
1327                         if (height > maxHeight)
1328                         {
1329                                 maxHeight = height;
1330                         }
1331
1332                         if (strSrcStartRelIndex < strSrcRelIndex)
1333                         {
1334                                 strSrcRelIndex--;
1335                         }
1336                         else
1337                         {
1338                                 textElementStackIndex--;
1339                                 SysTryReturn(NID_GRP
1340                                                         , textElementStackIndex >= 0
1341                                                         , null, E_SYSTEM, "[E_SYSTEM] Index must be greater than or equal to 0.");
1342
1343                                 pTextElement = pTextElementStack[textElementStackIndex];
1344                                 SysTryReturn(NID_GRP
1345                                                         , pTextElement
1346                                                         , null, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
1347
1348                                 strSrcStartRelIndex = pTextElement->GetValue(SET_TEXT_OFFSET);
1349                                 strSrcRelIndex = pTextElement->GetValue(SET_TEXT_OFFSET) + pTextElement->GetTextLength() - 1;
1350                         }
1351                 }
1352
1353                 TextSimple* pSimpleTextElement = dynamic_cast < TextSimple* >(pTextElement);
1354                 SysTryReturn(NID_GRP
1355                                 , pSimpleTextElement
1356                                 , null, E_SYSTEM, "[E_SYSTEM] Fail to cast text element.");
1357
1358                 wchar_t* pText = (wchar_t*)pSimpleTextElement->GetText();
1359                 isNextKoreanStart = IsKorean(pText[0]);
1360
1361                 if ((stringLengthBackward > 0) && (stringLengthBackward < pWordWidthInfo->length))
1362                 {
1363                         WordTextWidthInfo* pNewWordWidthInfo = new (std::nothrow) WordTextWidthInfo;
1364                         SysTryReturn(NID_GRP
1365                                 , pNewWordWidthInfo
1366                                 , null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
1367
1368                         pNewWordWidthInfo->type = TEXT_WIDTH_INFO_WORD;
1369                         pNewWordWidthInfo->length = stringLengthBackward;
1370                         pNewWordWidthInfo->maxHeight = height;
1371                         pNewWordWidthInfo->width = widthBackward;
1372
1373                         TextSimpleList::InsertObjectAfterNode(__pTextWidthInfoList, pCurrentWordWidthInfoNode, pNewWordWidthInfo);
1374
1375                         pWordWidthInfo->length -= stringLengthBackward;
1376                         pWordWidthInfo->width -= widthBackward;
1377                 }
1378                 else
1379                 {
1380                         return pWordWidthInfo;
1381                 }
1382
1383                 return pWordWidthInfo;
1384         }
1385
1386         return null;
1387 }
1388
1389 bool
1390 TextWidthManager::Seek(int textLength)
1391 {
1392         if (__currentTextIndex + textLength > __length)
1393         {
1394                 return false;
1395         }
1396
1397         if (__currentTextIndex + textLength == __length)
1398         {
1399                 __pCurrentWordWidthInfoNode = null;
1400                 __pCurrentComposeTextElement = null;
1401                 __currentTextIndex += textLength;
1402                 return true;
1403         }
1404
1405         if (textLength == 0)
1406         {
1407                 return false;
1408         }
1409
1410         TextWidthCommonInfo* pCurrentTextWidthInfo = static_cast < TextWidthCommonInfo* >(__pCurrentWordWidthInfoNode->pObject);
1411         SysTryReturn(NID_GRP
1412                                 , pCurrentTextWidthInfo
1413                                 , false, E_SYSTEM, "[E_SYSTEM] Fail to get text width information.");
1414
1415         int strCurrentTextWidthInfoLength = GetTextWidthInfoLength(pCurrentTextWidthInfo);
1416
1417         if (__textOffsetOfCurrentWidthInfo != 0)
1418         {
1419                 return false;
1420         }
1421
1422         int length = textLength;
1423
1424         while (length > 0)
1425         {
1426                 length -= strCurrentTextWidthInfoLength;
1427
1428                 __pCurrentWordWidthInfoNode = __pCurrentWordWidthInfoNode->pNext;
1429                 pCurrentTextWidthInfo = static_cast < TextWidthCommonInfo* >(__pCurrentWordWidthInfoNode->pObject);
1430                 SysTryReturn(NID_GRP
1431                                         , pCurrentTextWidthInfo
1432                                         , false, E_SYSTEM, "[E_SYSTEM] Fail to get text width information.");
1433                 strCurrentTextWidthInfoLength = GetTextWidthInfoLength(pCurrentTextWidthInfo);
1434         }
1435
1436         length = textLength;
1437         TextElement* pTextElement = __pCurrentComposeTextElement;
1438         int textElementIndex = __currentComposeTextElementIndex;
1439         int strSrcRelIndex = __strCurrentRelIndex;
1440         int currentLength = __currentTextElementLength;
1441
1442         while (length > 0)
1443         {
1444                 if (currentLength > length)
1445                 {
1446                         strSrcRelIndex += length;
1447                         break;
1448                 }
1449
1450                 length -= currentLength;
1451
1452                 textElementIndex++;
1453                 pTextElement = __pCompositeText->GetElementAtElementIndex(textElementIndex);
1454                 if (pTextElement == null)
1455                 {
1456                         break;
1457                 }
1458
1459                 strSrcRelIndex = pTextElement->GetValue(SET_TEXT_OFFSET);
1460                 currentLength = pTextElement->GetValue(SET_TEXT_OFFSET) + pTextElement->GetTextLength() - strSrcRelIndex;
1461         }
1462
1463         SysTryReturn(NID_GRP
1464                                 , pTextElement
1465                                 , false, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
1466
1467         __pCurrentComposeTextElement = pTextElement;
1468         __strCurrentRelIndex = strSrcRelIndex;
1469         __currentTextElementLength = pTextElement->GetValue(SET_TEXT_OFFSET) + pTextElement->GetTextLength() - strSrcRelIndex;
1470         __currentTextIndex += textLength;
1471
1472         return true;
1473 }
1474
1475 bool
1476 TextWidthManager::AnalyzeCurrentUnKnownTextWidthInfo(int limitWidth)
1477 {
1478         SimpleNode* pCurrentWordWidthInfoNode = __pCurrentWordWidthInfoNode;
1479         UnknownTextWidthInfo* pCurrentUnknowTextWidthInfo = static_cast < UnknownTextWidthInfo* >(__pCurrentWordWidthInfoNode->pObject);
1480         SysTryReturn(NID_GRP
1481                         , pCurrentUnknowTextWidthInfo
1482                         , false, E_SYSTEM, "[E_SYSTEM] Fail to get text width information.");
1483
1484         int strCurrentTextWidthInfoLength = pCurrentUnknowTextWidthInfo->length;
1485
1486         TextElement* pTextElement = __pCurrentComposeTextElement;
1487         int textElementIndex = __currentComposeTextElementIndex;
1488         int strSrcRelIndex = __strCurrentRelIndex;
1489         int currentLength = __currentTextElementLength;
1490         int textLength = strCurrentTextWidthInfoLength;
1491         int width = 0;
1492         int height = 0;
1493
1494         TextElementType objectType;
1495
1496         bool getDone = false;
1497
1498         while (textLength > 0)
1499         {
1500                 objectType = pTextElement->GetType();
1501
1502                 switch (objectType)
1503                 {
1504                 case TEXT_ELEMENT_TYPE_TEXT:
1505                         // fall through
1506                 case TEXT_ELEMENT_TYPE_CUTLINK:
1507                 {
1508                         TextSimple* pSimpleTextElement = dynamic_cast < TextSimple* >(pTextElement);
1509                         SysTryReturn(NID_GRP
1510                                         , pSimpleTextElement
1511                                         , null, E_SYSTEM, "[E_SYSTEM] Fail to cast text element.");
1512
1513                         int wordType = 0;
1514                         int currentTextLength = 0;
1515
1516                         wordType = pSimpleTextElement->GetWordLength(strSrcRelIndex, currentTextLength);
1517                         if (wordType == WORD_ENTER)
1518                         {
1519                                 pCurrentUnknowTextWidthInfo->length -= currentTextLength;
1520
1521                                 pTextElement->GetRegion(strSrcRelIndex, 1, width, height);
1522
1523                                 EnterTextWidthInfo* pNewEnterTextWidthInfo = new (std::nothrow) EnterTextWidthInfo;
1524                                 SysTryReturn(NID_GRP
1525                                                 , pNewEnterTextWidthInfo
1526                                                 , false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
1527
1528                                 pNewEnterTextWidthInfo->type = TEXT_WIDTH_INFO_ENTER;
1529                                 pNewEnterTextWidthInfo->length = currentTextLength;
1530                                 pNewEnterTextWidthInfo->maxHeight = height;
1531
1532                                 if (pCurrentWordWidthInfoNode == __pCurrentWordWidthInfoNode)
1533                                 {
1534                                         bool changecachedInfo = false;
1535
1536                                         if (__pCurrentWordWidthInfoNode == __pCachedWordWidthInfoNode)
1537                                         {
1538                                                 changecachedInfo = true;
1539                                         }
1540
1541                                         __pCurrentWordWidthInfoNode =
1542                                                 TextSimpleList::InsertObjectBeforeNode(__pTextWidthInfoList, pCurrentWordWidthInfoNode,
1543                                                                                                                                 pNewEnterTextWidthInfo);
1544
1545                                         if (changecachedInfo)
1546                                         {
1547                                                 __pCachedWordWidthInfoNode = __pCurrentWordWidthInfoNode;
1548                                         }
1549                                 }
1550                                 else
1551                                 {
1552                                         TextSimpleList::InsertObjectBeforeNode(__pTextWidthInfoList, pCurrentWordWidthInfoNode,
1553                                                                                                                         pNewEnterTextWidthInfo);
1554                                 }
1555
1556                                 getDone = true;
1557                         }
1558                         else if (wordType == WORD_SPACE)
1559                         {
1560                                 pCurrentUnknowTextWidthInfo->length--;
1561
1562                                 pTextElement->GetRegion(strSrcRelIndex, 1, width, height);
1563
1564                                 SpaceTextWidthInfo* pNewSpaceTextWidthInfo = new (std::nothrow) SpaceTextWidthInfo;
1565                                 SysTryReturn(NID_GRP
1566                                                 , pNewSpaceTextWidthInfo
1567                                                 , false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
1568
1569                                 pNewSpaceTextWidthInfo->type = TEXT_WIDTH_INFO_SPACE;
1570                                 pNewSpaceTextWidthInfo->width = width;
1571                                 pNewSpaceTextWidthInfo->maxHeight = height;
1572
1573                                 if (pCurrentWordWidthInfoNode == __pCurrentWordWidthInfoNode)
1574                                 {
1575                                         bool changecachedInfo = false;
1576
1577                                         if (__pCurrentWordWidthInfoNode == __pCachedWordWidthInfoNode)
1578                                         {
1579                                                 changecachedInfo = true;
1580                                         }
1581
1582                                         __pCurrentWordWidthInfoNode =
1583                                                 TextSimpleList::InsertObjectBeforeNode(__pTextWidthInfoList, pCurrentWordWidthInfoNode,
1584                                                                                                                                 pNewSpaceTextWidthInfo);
1585
1586                                         if (changecachedInfo)
1587                                         {
1588                                                 __pCachedWordWidthInfoNode = __pCurrentWordWidthInfoNode;
1589                                         }
1590                                 }
1591                                 else
1592                                 {
1593                                         TextSimpleList::InsertObjectBeforeNode(__pTextWidthInfoList, pCurrentWordWidthInfoNode,
1594                                                                                                                         pNewSpaceTextWidthInfo);
1595                                 }
1596
1597                                 currentLength--;
1598                                 strSrcRelIndex++;
1599                                 limitWidth -= width;
1600                                 textLength--;
1601                         }
1602                         else
1603                         {
1604                                 if (currentTextLength > textLength)
1605                                 {
1606                                         currentTextLength = textLength;
1607                                 }
1608                                 pCurrentUnknowTextWidthInfo->length -= currentTextLength;
1609
1610                                 pTextElement->GetRegion(strSrcRelIndex, currentTextLength, width, height);
1611
1612                                 WordTextWidthInfo* pNewWordTextWidthInfo = new (std::nothrow) WordTextWidthInfo;
1613                                 SysTryReturn(NID_GRP
1614                                                 , pNewWordTextWidthInfo
1615                                                 , false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
1616
1617                                 pNewWordTextWidthInfo->type = TEXT_WIDTH_INFO_WORD;
1618                                 pNewWordTextWidthInfo->length = currentTextLength;
1619                                 pNewWordTextWidthInfo->width = width;
1620                                 pNewWordTextWidthInfo->maxHeight = height;
1621
1622                                 if (pCurrentWordWidthInfoNode == __pCurrentWordWidthInfoNode)
1623                                 {
1624                                         bool changecachedInfo = false;
1625
1626                                         if (__pCurrentWordWidthInfoNode == __pCachedWordWidthInfoNode)
1627                                         {
1628                                                 changecachedInfo = true;
1629                                         }
1630
1631                                         __pCurrentWordWidthInfoNode =
1632                                                 TextSimpleList::InsertObjectBeforeNode(__pTextWidthInfoList, pCurrentWordWidthInfoNode,
1633                                                                                                                                 pNewWordTextWidthInfo);
1634
1635                                         if (changecachedInfo)
1636                                         {
1637                                                 __pCachedWordWidthInfoNode = __pCurrentWordWidthInfoNode;
1638                                         }
1639                                 }
1640                                 else
1641                                 {
1642                                         TextSimpleList::InsertObjectBeforeNode(__pTextWidthInfoList, pCurrentWordWidthInfoNode,
1643                                                                                                                         pNewWordTextWidthInfo);
1644                                 }
1645
1646                                 currentLength -= currentTextLength;
1647                                 strSrcRelIndex += currentTextLength;
1648                                 limitWidth -= width;
1649                                 textLength -= currentTextLength;
1650                         }
1651                 }
1652                 break;
1653
1654                 case TEXT_ELEMENT_TYPE_IMAGE:
1655                 {
1656                         pTextElement->GetRegion(0, 1, width, height);
1657
1658                         pCurrentUnknowTextWidthInfo->length--;
1659
1660                         SymbolTextWidthInfo* pNewSymbolTextWidthInfo = new (std::nothrow) SymbolTextWidthInfo;
1661                         SysTryReturn(NID_GRP
1662                                         , pNewSymbolTextWidthInfo
1663                                         , false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
1664
1665                         pNewSymbolTextWidthInfo->type = TEXT_WIDTH_INFO_SYMBOL;
1666                         pNewSymbolTextWidthInfo->width = width;
1667                         pNewSymbolTextWidthInfo->maxHeight = height;
1668
1669                         if (pCurrentWordWidthInfoNode == __pCurrentWordWidthInfoNode)
1670                         {
1671                                 bool changecachedInfo = false;
1672
1673                                 if (__pCurrentWordWidthInfoNode == __pCachedWordWidthInfoNode)
1674                                 {
1675                                         changecachedInfo = true;
1676                                 }
1677
1678                                 __pCurrentWordWidthInfoNode =
1679                                         TextSimpleList::InsertObjectBeforeNode(__pTextWidthInfoList, pCurrentWordWidthInfoNode,
1680                                                                                                                         pNewSymbolTextWidthInfo);
1681
1682                                 if (changecachedInfo)
1683                                 {
1684                                         __pCachedWordWidthInfoNode = __pCurrentWordWidthInfoNode;
1685                                 }
1686                         }
1687                         else
1688                         {
1689                                 TextSimpleList::InsertObjectBeforeNode(__pTextWidthInfoList, pCurrentWordWidthInfoNode,
1690                                                                                                                 pNewSymbolTextWidthInfo);
1691                         }
1692
1693                         getDone = true;
1694                 }
1695                 break;
1696
1697                 default:
1698                         return false;
1699                 }
1700
1701                 if (limitWidth <= 0)
1702                 {
1703                         break;
1704                 }
1705
1706                 if (getDone)
1707                 {
1708                         break;
1709                 }
1710
1711                 if (currentLength <= 0)
1712                 {
1713                         textElementIndex++;
1714                         pTextElement = __pCompositeText->GetElementAtElementIndex(textElementIndex);
1715                         if (pTextElement == null)
1716                         {
1717                                 break;
1718                         }
1719
1720                         strSrcRelIndex = pTextElement->GetValue(SET_TEXT_OFFSET);
1721                         currentLength = pTextElement->GetValue(SET_TEXT_OFFSET) + pTextElement->GetTextLength() - strSrcRelIndex;
1722                 }
1723         }
1724
1725         if (pCurrentUnknowTextWidthInfo->length == 0)
1726         {
1727                 TextSimpleList::DeleteNode(__pTextWidthInfoList, pCurrentWordWidthInfoNode);
1728         }
1729
1730         return true;
1731 }
1732
1733 SimpleNode*
1734 TextWidthManager::AnalyzeUnKnownTextWidthInfo(SimpleNode* pCurrentWordWidthInfoNode, TextElement* pCurrentTextElement,
1735                                                                                                  int strCurrentRelIndex, int strCurrentLength, int limitWidth)
1736 {
1737         SimpleNode* pReturnWordWidthInfoNode = null;
1738         SimpleNode* p_current_word_width_info_node = pCurrentWordWidthInfoNode;
1739         int strCurrentTextWidthInfoLength = 0;
1740
1741         UnknownTextWidthInfo* pCurrentUnknowTextWidthInfo = static_cast < UnknownTextWidthInfo* >(pCurrentWordWidthInfoNode->pObject);
1742         SysTryReturn(NID_GRP
1743                                 , pCurrentUnknowTextWidthInfo
1744                                 , null, E_SYSTEM, "[E_SYSTEM] Fail to get text width information.");
1745         strCurrentTextWidthInfoLength = pCurrentUnknowTextWidthInfo->length;
1746
1747         TextElement* pTextElement = pCurrentTextElement;
1748         SysTryReturn(NID_GRP
1749                                 , pTextElement
1750                                 , null, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
1751
1752         int textElementIndex = __pCompositeText->GetElementIndexOf(*pCurrentTextElement);
1753         SysTryReturn(NID_GRP
1754                                 , textElementIndex >= 0
1755                                 , null, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
1756
1757         int strSrcRelIndex = strCurrentRelIndex;
1758         int currentLength = strCurrentLength;
1759         int textLength = strCurrentTextWidthInfoLength;
1760         TextElementType objectType;
1761         bool getDone = false;
1762         int width = 0;
1763         int height = 0;
1764
1765         while (textLength > 0)
1766         {
1767                 objectType = pTextElement->GetType();
1768
1769                 switch (objectType)
1770                 {
1771                 case TEXT_ELEMENT_TYPE_TEXT:
1772                         // fall through
1773                 case TEXT_ELEMENT_TYPE_CUTLINK:
1774                 {
1775                         TextSimple* pSimpleTextElement = dynamic_cast < TextSimple* >(pTextElement);
1776                         SysTryReturn(NID_GRP
1777                                         , pSimpleTextElement
1778                                         , null, E_SYSTEM, "[E_SYSTEM] Fail to cast text element.");
1779
1780                         int wordType = 0;
1781                         int currentTextLength = 0;
1782
1783                         wordType = pSimpleTextElement->GetWordLength(strSrcRelIndex, currentTextLength);
1784                         if (wordType == WORD_ENTER)
1785                         {
1786                                 pCurrentUnknowTextWidthInfo->length -= currentTextLength;
1787
1788                                 pTextElement->GetRegion(strSrcRelIndex, 1, width, height);
1789
1790                                 EnterTextWidthInfo* pNewEnterTextWidthInfo = new (std::nothrow) EnterTextWidthInfo;
1791                                 SysTryReturn(NID_GRP
1792                                                 , pNewEnterTextWidthInfo
1793                                                 , null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
1794
1795                                 pNewEnterTextWidthInfo->type = TEXT_WIDTH_INFO_ENTER;
1796                                 pNewEnterTextWidthInfo->length = currentTextLength;
1797                                 pNewEnterTextWidthInfo->maxHeight = height;
1798
1799                                 if (pReturnWordWidthInfoNode == null)
1800                                 {
1801                                         bool changecachedInfo = false;
1802
1803                                         if (p_current_word_width_info_node == __pCachedWordWidthInfoNode)
1804                                         {
1805                                                 changecachedInfo = true;
1806                                         }
1807
1808                                         pReturnWordWidthInfoNode =
1809                                                 TextSimpleList::InsertObjectBeforeNode(__pTextWidthInfoList, pCurrentWordWidthInfoNode,
1810                                                                                                                                 pNewEnterTextWidthInfo);
1811
1812                                         if (changecachedInfo)
1813                                         {
1814                                                 __pCachedWordWidthInfoNode = pReturnWordWidthInfoNode;
1815                                         }
1816                                 }
1817                                 else
1818                                 {
1819                                         TextSimpleList::InsertObjectBeforeNode(__pTextWidthInfoList, pCurrentWordWidthInfoNode,
1820                                                                                                                         pNewEnterTextWidthInfo);
1821                                 }
1822
1823                                 getDone = true;
1824                         }
1825                         else if (wordType == WORD_SPACE)
1826                         {
1827                                 pCurrentUnknowTextWidthInfo->length--;
1828
1829                                 pTextElement->GetRegion(strSrcRelIndex, 1, width, height);
1830
1831                                 SpaceTextWidthInfo* pNewSpaceTextWidthInfo = new (std::nothrow) SpaceTextWidthInfo;
1832                                 SysTryReturn(NID_GRP
1833                                                 , pNewSpaceTextWidthInfo
1834                                                 , null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
1835
1836                                 pNewSpaceTextWidthInfo->type = TEXT_WIDTH_INFO_SPACE;
1837                                 pNewSpaceTextWidthInfo->width = width;
1838                                 pNewSpaceTextWidthInfo->maxHeight = height;
1839
1840                                 if (pReturnWordWidthInfoNode == null)
1841                                 {
1842                                         bool changecachedInfo = false;
1843
1844                                         if (p_current_word_width_info_node == __pCachedWordWidthInfoNode)
1845                                         {
1846                                                 changecachedInfo = true;
1847                                         }
1848
1849                                         pReturnWordWidthInfoNode = TextSimpleList::InsertObjectBeforeNode(__pTextWidthInfoList, pCurrentWordWidthInfoNode,
1850                                                                                                                                 pNewSpaceTextWidthInfo);
1851
1852                                         if (changecachedInfo)
1853                                         {
1854                                                 __pCachedWordWidthInfoNode = pReturnWordWidthInfoNode;
1855                                         }
1856                                 }
1857                                 else
1858                                 {
1859                                         TextSimpleList::InsertObjectBeforeNode(__pTextWidthInfoList, pCurrentWordWidthInfoNode,
1860                                                                                                                         pNewSpaceTextWidthInfo);
1861                                 }
1862
1863                                 currentLength--;
1864                                 strSrcRelIndex++;
1865                                 limitWidth -= width;
1866                                 textLength--;
1867                         }
1868                         else
1869                         {
1870                                 if (textLength < currentTextLength)
1871                                 {
1872                                         currentTextLength = textLength;
1873                                 }
1874                                 pCurrentUnknowTextWidthInfo->length -= currentTextLength;
1875
1876                                 pTextElement->GetRegion(strSrcRelIndex, currentTextLength, width, height);
1877
1878                                 WordTextWidthInfo* pNewWordTextWidthInfo = new (std::nothrow) WordTextWidthInfo;
1879                                 SysTryReturn(NID_GRP
1880                                                 , pNewWordTextWidthInfo
1881                                                 , null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
1882
1883                                 pNewWordTextWidthInfo->type = TEXT_WIDTH_INFO_WORD;
1884                                 pNewWordTextWidthInfo->length = currentTextLength;
1885                                 pNewWordTextWidthInfo->width = width;
1886                                 pNewWordTextWidthInfo->maxHeight = height;
1887
1888                                 if (pReturnWordWidthInfoNode == null)
1889                                 {
1890                                         bool changecachedInfo = false;
1891
1892                                         if (p_current_word_width_info_node == __pCachedWordWidthInfoNode)
1893                                         {
1894                                                 changecachedInfo = true;
1895                                         }
1896
1897                                         pReturnWordWidthInfoNode =
1898                                                 TextSimpleList::InsertObjectBeforeNode(__pTextWidthInfoList, pCurrentWordWidthInfoNode,
1899                                                                                                                                 pNewWordTextWidthInfo);
1900
1901                                         if (changecachedInfo)
1902                                         {
1903                                                 __pCachedWordWidthInfoNode = pReturnWordWidthInfoNode;
1904                                         }
1905                                 }
1906                                 else
1907                                 {
1908                                         TextSimpleList::InsertObjectBeforeNode(__pTextWidthInfoList, pCurrentWordWidthInfoNode,
1909                                                                                                                         pNewWordTextWidthInfo);
1910                                 }
1911
1912                                 currentLength -= currentTextLength;
1913                                 strSrcRelIndex += currentTextLength;
1914                                 limitWidth -= width;
1915                                 textLength -= currentTextLength;
1916                         }
1917                 }
1918                 break;
1919
1920                 case TEXT_ELEMENT_TYPE_IMAGE:
1921                 {
1922                         pTextElement->GetRegion(0, 1, width, height);
1923
1924                         pCurrentUnknowTextWidthInfo->length--;
1925
1926                         SymbolTextWidthInfo* pNewSymbolTextWidthInfo = new (std::nothrow) SymbolTextWidthInfo;
1927                         SysTryReturn(NID_GRP
1928                                         , pNewSymbolTextWidthInfo
1929                                         , null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
1930
1931                         pNewSymbolTextWidthInfo->type = TEXT_WIDTH_INFO_SYMBOL;
1932                         pNewSymbolTextWidthInfo->width = width;
1933                         pNewSymbolTextWidthInfo->maxHeight = height;
1934
1935                         if (pReturnWordWidthInfoNode == null)
1936                         {
1937                                 bool changecachedInfo = false;
1938
1939                                 if (p_current_word_width_info_node == __pCachedWordWidthInfoNode)
1940                                 {
1941                                         changecachedInfo = true;
1942                                 }
1943
1944                                 pReturnWordWidthInfoNode = TextSimpleList::InsertObjectBeforeNode(__pTextWidthInfoList, pCurrentWordWidthInfoNode,
1945                                                                                                                         pNewSymbolTextWidthInfo);
1946
1947                                 if (changecachedInfo)
1948                                 {
1949                                         __pCachedWordWidthInfoNode = pReturnWordWidthInfoNode;
1950                                 }
1951                         }
1952                         else
1953                         {
1954                                 TextSimpleList::InsertObjectBeforeNode(__pTextWidthInfoList, pCurrentWordWidthInfoNode,
1955                                                                                                                 pNewSymbolTextWidthInfo);
1956                         }
1957
1958                         getDone = true;
1959                 }
1960                 break;
1961
1962                 default:
1963                         return false;
1964                 }
1965
1966                 if (limitWidth <= 0)
1967                 {
1968                         break;
1969                 }
1970
1971                 if (getDone)
1972                 {
1973                         break;
1974                 }
1975
1976                 if (currentLength <= 0)
1977                 {
1978                         textElementIndex++;
1979                         pTextElement = __pCompositeText->GetElementAtElementIndex(textElementIndex);
1980                         if (pTextElement == null)
1981                         {
1982                                 break;
1983                         }
1984
1985                         strSrcRelIndex = pTextElement->GetValue(SET_TEXT_OFFSET);
1986                         currentLength = pTextElement->GetValue(SET_TEXT_OFFSET) + pTextElement->GetTextLength() - strSrcRelIndex;
1987                 }
1988         }
1989
1990         if (pCurrentUnknowTextWidthInfo->length == 0)
1991         {
1992                 TextSimpleList::DeleteNode(__pTextWidthInfoList, pCurrentWordWidthInfoNode);
1993         }
1994
1995         return pReturnWordWidthInfoNode;
1996 }
1997
1998 bool
1999 TextWidthManager::AnalyzeNextTextWidthInfo(int limitWidth, bool& wordoverWidth, int& widthAnlyzed, int& strLengthAalyzed,
2000                                                                                                   int& heightAnalzyed, bool& isnextKorean, bool& meetCutlink)
2001 {
2002         widthAnlyzed = 0;
2003         strLengthAalyzed = 0;
2004         heightAnalzyed = 0;
2005         wordoverWidth = false;
2006         isnextKorean = false;
2007
2008         TextWidthCommonInfo* pCurrentCommonTextWidthInfo = static_cast < TextWidthCommonInfo* >(__pCurrentWordWidthInfoNode->pObject);
2009         SysTryReturn(NID_GRP
2010                                 , pCurrentCommonTextWidthInfo
2011                                 , false, E_SYSTEM, "[E_SYSTEM] Fail to get text width information.");
2012
2013         int strCurrentTextWidthInfoLength = GetTextWidthInfoLength(pCurrentCommonTextWidthInfo);
2014
2015         SimpleNode* pCurrentWordWidthInfoNode = __pCurrentWordWidthInfoNode->pNext;
2016         if (pCurrentWordWidthInfoNode == null)
2017         {
2018                 return false;
2019         }
2020
2021         pCurrentCommonTextWidthInfo = static_cast < TextWidthCommonInfo* >(pCurrentWordWidthInfoNode->pObject);
2022         SysTryReturn(NID_GRP
2023                         , pCurrentCommonTextWidthInfo
2024                         , null, E_SYSTEM, "[E_SYSTEM] Fail to get text width information.");
2025
2026         TextElement* pTextElement = __pCurrentComposeTextElement;
2027         int textElementIndex = __currentComposeTextElementIndex;
2028         int strSrcRelIndex = __strCurrentRelIndex;
2029         int strTextElementLength = __currentTextElementLength;
2030
2031         int seekLength = strCurrentTextWidthInfoLength;
2032
2033         while (seekLength > 0)
2034         {
2035                 if (seekLength < strTextElementLength)
2036                 {
2037                         strSrcRelIndex += seekLength;
2038                         strTextElementLength -= seekLength;
2039                         break;
2040                 }
2041
2042                 seekLength -= strTextElementLength;
2043
2044                 if (pTextElement->GetType() == TEXT_ELEMENT_TYPE_CUTLINK)
2045                 {
2046                         meetCutlink = true;
2047
2048                         textElementIndex++;
2049                         pTextElement = __pCompositeText->GetElementAtElementIndex(textElementIndex);
2050                         if (pTextElement == null)
2051                         {
2052                                 break;
2053                         }
2054
2055                         break;
2056                 }
2057
2058                 textElementIndex++;
2059                 pTextElement = __pCompositeText->GetElementAtElementIndex(textElementIndex);
2060                 if (pTextElement == null)
2061                 {
2062                         break;
2063                 }
2064
2065                 strSrcRelIndex = pTextElement->GetValue(SET_TEXT_OFFSET);
2066                 strTextElementLength = pTextElement->GetValue(SET_TEXT_OFFSET) + pTextElement->GetTextLength() - strSrcRelIndex;
2067
2068                 if (pTextElement->GetType() == TEXT_ELEMENT_TYPE_CUTLINK)
2069                 {
2070                         meetCutlink = true;
2071                         break;
2072                 }
2073         }
2074
2075         int widthAnalyzed = 0;
2076         int maxHeight = 0;
2077         int stringAnalzyed = 0;
2078         int widthLeft = limitWidth;
2079
2080         int type = pCurrentCommonTextWidthInfo->type;
2081
2082         while (((type == TEXT_WIDTH_INFO_WORD) || (type == TEXT_WIDTH_INFO_UNKNOWN)) && !meetCutlink)
2083         {
2084                         SysTryReturn(NID_GRP
2085                                 , pTextElement
2086                                 , false, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
2087
2088                 int stringtoGo = 0;
2089                 if (type == TEXT_WIDTH_INFO_WORD)
2090                 {
2091                         WordTextWidthInfo* pWordTtextWidthInfo = static_cast < WordTextWidthInfo* >(pCurrentCommonTextWidthInfo);
2092                         SysTryReturn(NID_GRP
2093                                         , pWordTtextWidthInfo
2094                                         , false, E_SYSTEM, "[E_SYSTEM] Fail to get text width information.");
2095
2096                         if (widthLeft < pWordTtextWidthInfo->width)
2097                         {
2098                                 if ((widthLeft <= 0) || (pTextElement->GetType() == TEXT_ELEMENT_TYPE_CUTLINK))
2099                                 {
2100                                         wordoverWidth = true;
2101                                         break;
2102                                 }
2103
2104                                 int textLengthBeforeSplit = GetTextWidthInfoLength(static_cast < TextWidthCommonInfo* >(pCurrentWordWidthInfoNode->pObject));
2105                                 pWordTtextWidthInfo = SplitWordWidthInfo(pCurrentWordWidthInfoNode, pTextElement, strSrcRelIndex,
2106                                                 strTextElementLength, widthLeft, isnextKorean);
2107
2108                                 if (textLengthBeforeSplit != pWordTtextWidthInfo->length)
2109                                 {
2110                                         widthAnalyzed += pWordTtextWidthInfo->width;
2111                                         stringAnalzyed += pWordTtextWidthInfo->length;
2112                                         if (pWordTtextWidthInfo->maxHeight > maxHeight)
2113                                         {
2114                                                 maxHeight = pWordTtextWidthInfo->maxHeight;
2115                                         }
2116                                 }
2117
2118                                 wordoverWidth = true;
2119                                 break;
2120                         }
2121                         else
2122                         {
2123                                 widthAnalyzed += pWordTtextWidthInfo->width;
2124                                 widthLeft -= pWordTtextWidthInfo->width;
2125                                 stringAnalzyed += pWordTtextWidthInfo->length;
2126                                 if (pWordTtextWidthInfo->maxHeight > maxHeight)
2127                                 {
2128                                         maxHeight = pWordTtextWidthInfo->maxHeight;
2129                                 }
2130
2131                                 stringtoGo = pWordTtextWidthInfo->length;
2132                         }
2133                 }
2134                 else
2135                 {
2136                         SimpleNode* pNewSimpleNode = AnalyzeUnKnownTextWidthInfo(pCurrentWordWidthInfoNode, pTextElement,
2137                                                                                                                                                                                                                                 strSrcRelIndex, strTextElementLength, widthLeft);
2138
2139                         SysTryReturn(NID_GRP
2140                                         , pNewSimpleNode
2141                                         , null, E_SYSTEM, "[E_SYSTEM] Fail to get text element node.");
2142
2143                         pCurrentWordWidthInfoNode = pNewSimpleNode;
2144                         pCurrentCommonTextWidthInfo = static_cast < TextWidthCommonInfo* >(pCurrentWordWidthInfoNode->pObject);
2145                         SysTryReturn(NID_GRP
2146                                         , pCurrentCommonTextWidthInfo
2147                                         , null, E_SYSTEM, "[E_SYSTEM] Fail to get text width information.");
2148
2149                         type = pCurrentCommonTextWidthInfo->type;
2150                 }
2151
2152                 if (stringtoGo > 0)
2153                 {
2154                         pCurrentWordWidthInfoNode = pCurrentWordWidthInfoNode->pNext;
2155                         if (pCurrentWordWidthInfoNode == null)
2156                         {
2157                                 break;
2158                         }
2159
2160                         pCurrentCommonTextWidthInfo = static_cast < TextWidthCommonInfo* >(pCurrentWordWidthInfoNode->pObject);
2161                         SysTryReturn(NID_GRP
2162                                         , pCurrentCommonTextWidthInfo
2163                                         , null, E_SYSTEM, "[E_SYSTEM] Fail to get text element node.");
2164
2165                         type = pCurrentCommonTextWidthInfo->type;
2166
2167                         seekLength = stringtoGo;
2168
2169                         while (seekLength > 0)
2170                         {
2171                                 if (seekLength < strTextElementLength)
2172                                 {
2173                                         strSrcRelIndex += seekLength;
2174                                         strTextElementLength -= seekLength;
2175                                         break;
2176                                 }
2177
2178                                 seekLength -= strTextElementLength;
2179
2180                                 if (pTextElement->GetType() == TEXT_ELEMENT_TYPE_CUTLINK)
2181                                 {
2182                                         textElementIndex++;
2183                                         pTextElement = __pCompositeText->GetElementAtElementIndex(textElementIndex);
2184                                         if (pTextElement == null)
2185                                         {
2186                                                 break;
2187                                         }
2188
2189                                         meetCutlink = true;
2190                                         break;
2191                                 }
2192
2193                                 textElementIndex++;
2194                                 pTextElement = __pCompositeText->GetElementAtElementIndex(textElementIndex);
2195                                 SysTryReturn(NID_GRP
2196                                                 , pTextElement
2197                                                 , null, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
2198
2199                                 strSrcRelIndex = pTextElement->GetValue(SET_TEXT_OFFSET);
2200                                 strTextElementLength = pTextElement->GetValue(SET_TEXT_OFFSET) + pTextElement->GetTextLength() - strSrcRelIndex;
2201
2202                                 if (pTextElement->GetType() == TEXT_ELEMENT_TYPE_CUTLINK)
2203                                 {
2204                                         meetCutlink = true;
2205                                         break;
2206                                 }
2207                         }
2208                 }
2209         }
2210
2211         widthAnlyzed = widthAnalyzed;
2212         strLengthAalyzed = stringAnalzyed;
2213         heightAnalzyed = maxHeight;
2214
2215         return true;
2216 }
2217
2218 bool
2219 TextWidthManager::UpdateCachedTextWidhtInfo(int textOffset, SimpleNode* pTextWidthInfoNode)
2220 {
2221         __pCachedWordWidthInfoNode = pTextWidthInfoNode;
2222         __textOffsetOfCachedWidthInfo = textOffset;
2223
2224         return true;
2225 }
2226
2227 SimpleNode*
2228 TextWidthManager::SearchTextWidthInfo(int textIndex, int& widthInfoTextOffset)
2229 {
2230         SimpleNode* pCurrentTextWidthInfoNode = __pCachedWordWidthInfoNode;
2231         int currentWidthInfoTextOffset = __textOffsetOfCachedWidthInfo;
2232
2233         if (pCurrentTextWidthInfoNode == null)
2234         {
2235                 pCurrentTextWidthInfoNode = TextSimpleList::GetNthNode(__pTextWidthInfoList, 0);
2236                 currentWidthInfoTextOffset = 0;
2237         }
2238
2239         if (pCurrentTextWidthInfoNode == null)
2240         {
2241                 widthInfoTextOffset = 0;
2242                 return null;
2243         }
2244
2245         TextWidthCommonInfo* pCurrentTextWidthInfo = static_cast < TextWidthCommonInfo* >(pCurrentTextWidthInfoNode->pObject);
2246         SysTryReturn(NID_GRP
2247                         , pCurrentTextWidthInfo
2248                         , null, E_SYSTEM, "[E_SYSTEM] Fail to get text width information.");
2249
2250         if (currentWidthInfoTextOffset < textIndex)
2251         {
2252                 int currentWidthInfoTextLength = GetTextWidthInfoLength(pCurrentTextWidthInfo);
2253
2254                 while (currentWidthInfoTextOffset + currentWidthInfoTextLength <= textIndex)
2255                 {
2256                         pCurrentTextWidthInfoNode = pCurrentTextWidthInfoNode->pNext;
2257                         SysTryReturn(NID_GRP
2258                                         , pCurrentTextWidthInfoNode
2259                                         , null, E_SYSTEM, "[E_SYSTEM] Fail to get text width.");
2260
2261                         currentWidthInfoTextOffset += currentWidthInfoTextLength;
2262                         pCurrentTextWidthInfo = static_cast < TextWidthCommonInfo* >(pCurrentTextWidthInfoNode->pObject);
2263                         SysTryReturn(NID_GRP
2264                                         , pCurrentTextWidthInfo
2265                                         , null, E_SYSTEM, "[E_SYSTEM] Fail to get text width information.");
2266
2267                         currentWidthInfoTextLength = GetTextWidthInfoLength(pCurrentTextWidthInfo);
2268                 }
2269         }
2270         else if (textIndex < currentWidthInfoTextOffset)
2271         {
2272                 pCurrentTextWidthInfoNode = pCurrentTextWidthInfoNode->pPrev;
2273
2274                 SysTryReturn(NID_GRP
2275                                 , pCurrentTextWidthInfoNode
2276                                 , null, E_SYSTEM, "[E_SYSTEM] Fail to get text width.");
2277
2278                 pCurrentTextWidthInfo = static_cast < TextWidthCommonInfo* >(pCurrentTextWidthInfoNode->pObject);
2279                 SysTryReturn(NID_GRP
2280                                 , pCurrentTextWidthInfo
2281                                 , null, E_SYSTEM, "[E_SYSTEM] Fail to get text width.");
2282
2283                 currentWidthInfoTextOffset -= GetTextWidthInfoLength(pCurrentTextWidthInfo);
2284
2285                 while (textIndex < currentWidthInfoTextOffset)
2286                 {
2287                         pCurrentTextWidthInfoNode = pCurrentTextWidthInfoNode->pPrev;
2288
2289                         SysTryReturn(NID_GRP
2290                                         , pCurrentTextWidthInfoNode
2291                                         , null, E_SYSTEM, "[E_SYSTEM] Fail to get text width.");
2292
2293                         pCurrentTextWidthInfo = static_cast < TextWidthCommonInfo* >(pCurrentTextWidthInfoNode->pObject);
2294                         SysTryReturn(NID_GRP
2295                                         , pCurrentTextWidthInfo
2296                                         , null, E_SYSTEM, "[E_SYSTEM] Fail to get text width.");
2297
2298                         currentWidthInfoTextOffset -= GetTextWidthInfoLength(pCurrentTextWidthInfo);
2299                 }
2300         }
2301
2302         widthInfoTextOffset = currentWidthInfoTextOffset;
2303
2304         return pCurrentTextWidthInfoNode;
2305 }
2306
2307 bool
2308 TextWidthManager::IsKorean(wchar_t ch)
2309 {
2310         bool r = false;
2311
2312         if (0xAC00 <= ch && ch <= 0xD7A3)
2313         {
2314                 r = true;
2315         }
2316         else if (0x3130 <= ch && ch <= 0x318F)
2317         {
2318                 r = true;
2319         }
2320         else if (0x1100 <= ch && ch <= 0x11FF)
2321         {
2322                 r = true;
2323         }
2324         else if (0X2E80 <= ch && ch <= 0x2FFF)
2325         {
2326                 r = true;
2327         }
2328         else if (0x3220 <= ch && ch <= 0x3243)
2329         {
2330                 r = true;
2331         }
2332         else if (0x3280 <= ch && ch <= 0x32CB)
2333         {
2334                 r = true;
2335         }
2336         else if (0x3400 <= ch && ch <= 0x4DBF)
2337         {
2338                 r = true;
2339         }
2340         else if (0x4E00 <= ch && ch <= 0x9FFF)
2341         {
2342                 r = true;
2343         }
2344         else if (0xF900 <= ch && ch <= 0xFAFF)
2345         {
2346                 r = true;
2347         }
2348
2349         return r;
2350 }
2351
2352 }}} // Tizen::Graphics::_Text