Modified word wrap algorithm
authorYunji Park <yunji19.park@samsung.com>
Wed, 22 May 2013 06:02:10 +0000 (15:02 +0900)
committerYunji Park <yunji19.park@samsung.com>
Wed, 22 May 2013 06:02:10 +0000 (15:02 +0900)
Change-Id: I0ef60fd33ca5039afe329d867b90295123590f73

src/graphics/inc/FGrp_TextTextSimple.h
src/graphics/text/FGrp_TextTextSimple.cpp

index e7d0dc0..9885297 100644 (file)
@@ -132,14 +132,20 @@ public:
 
        bool IsBitmapDisplayMode(void) const;
 
+       bool IsLeadingCharacter(const wchar_t ch) const;
+
+       bool IsFollowingCharacter(const wchar_t ch) const;
+
+       bool IsDelimiter(const wchar_t ch) const;
+
 private:
        static int ConvertEnterToSpace(wchar_t* pDstText, const wchar_t* pSrcText, int textLength);
 
        bool IsKorean(const wchar_t* ch) const;
 
-       bool IsChinese(const wchar_t* ch) const;
+       bool IsChinese(const wchar_t ch) const;
 
-       bool IsJapanese(const wchar_t* ch) const;
+       bool IsJapanese(const wchar_t ch) const;
 
        int GetSentenceLength(const wchar_t* pText, int textLength, int& actualLength) const;
 
index de84ccb..97370cb 100644 (file)
@@ -341,34 +341,34 @@ TextSimple::IsKorean(const wchar_t* ch) const
 }
 
 bool
-TextSimple::IsChinese(const wchar_t* ch) const
+TextSimple::IsChinese(const wchar_t ch) const
 {
-       if (0X2E80 <= *ch && *ch <= 0x2FFF)
+       if (0X2E80 <= ch && ch <= 0x2FFF)
        {
                return true;
        }
 
-       else if (0x3220 <= *ch && *ch <= 0x3243)
+       else if (0x3220 <= ch && ch <= 0x3243)
        {
                return true;
        }
 
-       else if (0x3280 <= *ch && *ch <= 0x32CB)
+       else if (0x3280 <= ch && ch <= 0x32CB)
        {
                return true;
        }
 
-       else if (0x3400 <= *ch && *ch <= 0x4DBF)
+       else if (0x3400 <= ch && ch <= 0x4DBF)
        {
                return true;
        }
 
-       else if (0x4E00 <= *ch && *ch <= 0x9FFF)
+       else if (0x4E00 <= ch && ch <= 0x9FFF)
        {
                return true;
        }
 
-       else if (0xF900 <= *ch && *ch <= 0xFAFF)
+       else if (0xF900 <= ch && ch <= 0xFAFF)
        {
                return true;
        }
@@ -377,14 +377,14 @@ TextSimple::IsChinese(const wchar_t* ch) const
 }
 
 bool
-TextSimple::IsJapanese(const wchar_t* ch) const
+TextSimple::IsJapanese(const wchar_t ch) const
 {
-       if (0x3040 <= *ch && *ch <= 0x309F)
+       if (0x3040 <= ch && ch <= 0x309F)
        {
                return true;
        }
 
-       if (0x30A0 <= *ch && *ch <= 0x30FF)
+       if (0x30A0 <= ch && ch <= 0x30FF)
        {
                return true;
        }
@@ -1035,109 +1035,105 @@ TextSimple::GetWordWrapLengthEx(const wchar_t* pText, int textLength, int& actua
                pText++;
        }
 
-       bool hasFirstDot = false;
+       bool isCJ = false;\r
+       bool hasFollowingCharacter = false;\r
+       bool hasLeadingCharacter = false;
        int length = textLength;
        actualLength = textLength;
 
-       const wchar_t* pLastCharacter = pText - 1;
-       if (*pLastCharacter == TEXT_LINE_FEED || *pLastCharacter == TEXT_CARRIAGE_RETURN)
-       {
-               return TEXT_RETBY_LINEFEED;
-       }
-       else if (*pLastCharacter == (wchar_t)L' ' || *pLastCharacter == TEXT_JAPANESE_SPACE ||
-               *pLastCharacter == TEXT_OBJ_CHARACTER || *pLastCharacter == TEXT_JAPANESE_DOT|| *pLastCharacter ==  TEXT_JAPANESE_COMMA)
-       {
-               return TEXT_RETBY_NORMAL;
-       }
-
-       if ((*pText == TEXT_JAPANESE_DOT || *pText == TEXT_JAPANESE_COMMA)
-               && (IsChinese(pLastCharacter) || IsJapanese(pLastCharacter)))
-       {
-               hasFirstDot = true;
-       }
-
-       if (*pText == TEXT_OBJ_CHARACTER)
-       {
-               return TEXT_RETBY_NORMAL;
-       }
-       else if (*pText == (wchar_t)L' ' || *pText == TEXT_JAPANESE_SPACE)
-       {
-               actualLength--;
-               length--;
-               pText--;
-       }
-       else if (*pText == TEXT_LINE_FEED || *pText == TEXT_CARRIAGE_RETURN)
-       {
-               wchar_t mch = *pText;
-               pText--;
-
-               if (mch != *pText && (*pText == TEXT_LINE_FEED || *pText == TEXT_CARRIAGE_RETURN))
-               {
-                       actualLength++;
-                       length++;
-                       pText++;
-               }
-
-               return TEXT_RETBY_LINEFEED;
-       }
-       else if (IsChinese(pText) || IsJapanese(pText))
-       {
-               return TEXT_RETBY_NORMAL;
-       }
-
-       actualLength--;
-       length--;
-       pText--;
-
-       while ((length >= 0) && (*pText != 0))
-       {
-               if (*pText == (wchar_t)L' ' || *pText == TEXT_JAPANESE_SPACE || *pText == TEXT_OBJ_CHARACTER ||
-                       *pText == TEXT_JAPANESE_DOT || *pText == TEXT_JAPANESE_COMMA)
-               {
-                       actualLength++;
-                       length++;
-                       pText++;
-
-                       return TEXT_RETBY_NORMAL;
-               }
-               else if (*pText == TEXT_LINE_FEED || *pText == TEXT_CARRIAGE_RETURN)
-               {
-                       wchar_t mch = *pText;
-
-                       actualLength++;
-                       length++;
-                       pText++;
-
-                       if (mch != *pText && (*pText == TEXT_LINE_FEED || *pText == TEXT_CARRIAGE_RETURN))
-                       {
-                               actualLength++;
-                               length++;
-                               pText++;
-                       }
-
-                       return TEXT_RETBY_LINEFEED;
-               }
-
-               actualLength--;
-               length--;
-               pText--;
-       }
-
+       // 1. Find Last Character\r
+       const wchar_t* pLastCharacter = pText - 1;\r
+       if (*pLastCharacter == TEXT_LINE_FEED || *pLastCharacter == TEXT_CARRIAGE_RETURN)\r
+       {\r
+               return TEXT_RETBY_LINEFEED;\r
+       }\r
+       else if (IsDelimiter(*pLastCharacter) || *pLastCharacter == TEXT_OBJ_CHARACTER)\r
+       {\r
+               return TEXT_RETBY_NORMAL;\r
+       }\r
+\r
+       // 2. Set properties\r
+       if (IsChinese(*pLastCharacter) || IsJapanese(*pLastCharacter))\r
+       {\r
+               isCJ = true;\r
+       }\r
+       \r
+       if (IsLeadingCharacter(*pLastCharacter))\r
+       {\r
+               pLastCharacter--;\r
+               if (IsChinese(*pLastCharacter) || IsJapanese(*pLastCharacter))\r
+               {\r
+                       isCJ = true;\r
+                       hasFollowingCharacter = true;\r
+               }\r
+       }\r
+\r
+       if (isCJ && IsFollowingCharacter(*pText))\r
+       {\r
+               hasLeadingCharacter = true;\r
+       }\r
+\r
+       // 3. Find Line breaking position\r
+       if (*pText == TEXT_OBJ_CHARACTER)\r
+       {\r
+               return TEXT_RETBY_NORMAL;\r
+       }\r
+       else if (*pText == TEXT_LINE_FEED || *pText == TEXT_CARRIAGE_RETURN)\r
+       {\r
+               return TEXT_RETBY_LINEFEED;\r
+       }\r
+       else if (hasFollowingCharacter || hasLeadingCharacter)\r
+       {\r
+               actualLength--;\r
+               return TEXT_RETBY_NORMAL;\r
+       }\r
+       else if (IsChinese(*pText) || IsJapanese(*pText))\r
+       {\r
+               return TEXT_RETBY_NORMAL;\r
+       }
+
+       actualLength--;\r
+       length--;\r
+       pText--;\r
+\r
+       // 4. backSearching\r
+       while ((length >= 0) && (*pText != 0))\r
+       {\r
+               if (IsDelimiter(*pText) || *pText == TEXT_OBJ_CHARACTER)\r
+               {\r
+                       actualLength++;\r
+                       length++;\r
+                       pText++;\r
+\r
+                       return TEXT_RETBY_NORMAL;\r
+               }\r
+               else if (*pText == TEXT_LINE_FEED || *pText == TEXT_CARRIAGE_RETURN)\r
+               {\r
+                       actualLength++;\r
+                       length++;\r
+                       pText++;\r
+\r
+                       return TEXT_RETBY_LINEFEED;\r
+               }\r
+               else if (IsChinese(*pText) || IsJapanese(*pText))\r
+               {\r
+                       actualLength++;\r
+                       length++;\r
+                       pText++;\r
+\r
+                       return TEXT_RETBY_NORMAL;\r
+               }\r
+\r
+               actualLength--;\r
+               length--;\r
+               pText--;\r
+       }\r
+\r
        if (actualLength < 0)
        {
                actualLength = 0;
-       }
-
-       if (actualLength == 0)
-       {
-               if (hasFirstDot == true)
-               {
-                       actualLength = textLength - 1;
-               }
-
-               return TEXT_RETBY_LIMITLENGTH;
-       }
-
+       }\r
+\r
        return TEXT_RETBY_NORMAL;
 }
 
@@ -1437,7 +1433,236 @@ TextSimple::GetBaselineF(void) const
        _FontImpl* pFontImpl = _FontImpl::GetInstance(*pCurrentFont);
        SysTryReturn(NID_GRP, pFontImpl, -1, E_SYSTEM, "[E_SYSTEM] Fail to get native font instance.");
 
-       return pFontImpl->GetDescenderF();
+       float maxHeight = pFontImpl->GetMaxHeightF();\r
+\r
+       return maxHeight / 3.0f;
+}\r
+\r
+bool\r
+TextSimple::IsLeadingCharacter(const wchar_t ch) const\r
+{\r
+       bool isLeadingCharacter = false;\r
+\r
+       switch (ch)\r
+       {\r
+       case 0x0024:  //$   0x0024\r
+               // fall through\r
+       case 0x0028:  //(   0x0028\r
+               // fall through\r
+       case 0xff3b:  //[  0xff3b\r
+               // fall through\r
+       case 0x300c:  //「  0x300c\r
+               // fall through\r
+       case 0x300e:  //『  0x300e\r
+               // fall through\r
+       case 0x2018:  //‘  0x2018\r
+               // fall through\r
+       case 0x201c:  //“  0x201c\r
+               // fall through\r
+       case 0xff5b:  //{  0xff5b\r
+               // fall through\r
+       case 0x3010:  //【  0x3010\r
+               // fall through\r
+       case 0x3008:  //〈  0x3008\r
+               // fall through\r
+       case 0xffe5:  //¥  0xffe5\r
+               // fall through\r
+       case 0x00a5:  //¥   0x00a5\r
+               // fall through\r
+       case 0x300a:  //《  0x300a\r
+               // fall through\r
+       case 0xff08:  //(  0xff08\r
+               // fall through\r
+       case 0xff04:  //$  0xff04\r
+               // fall through\r
+       case 0x3014:  //〔  0x3014\r
+               // fall through\r
+       case 0xffe1:  //£  0xffe1\r
+               isLeadingCharacter = true;\r
+               break;\r
+       default:\r
+               break;\r
+       }\r
+       return isLeadingCharacter;\r
+}\r
+\r
+bool\r
+TextSimple::IsFollowingCharacter(const wchar_t ch) const\r
+{\r
+       bool isFollowingCharacter = false;\r
+\r
+       switch (ch)\r
+       {\r
+       case 0x0021:    // !\r
+               // fall through\r
+       case 0x0025:    // %\r
+               // fall through\r
+       case 0x0029:    // )\r
+               // fall through\r
+       case 0x002c:    // ,\r
+               // fall through\r
+       case 0x002e:    // .\r
+               // fall through\r
+       case 0x003f:    // ?\r
+               // fall through\r
+       case 0x005d:    // ]\r
+               // fall through\r
+       case 0x007d:    // }\r
+               // fall through\r
+       case 0x3002:    //。\r
+               // fall through\r
+       case 0xff61:    //。\r
+               // fall through\r
+       case 0x300d:    // 」\r
+               // fall through\r
+       case 0x3001:    // 、\r
+               // fall through\r
+       case 0xff0c:    //.\r
+               // fall through\r
+       case 0xff0e:    //.\r
+               // fall through\r
+       case 0xff64:    //、\r
+               // fall through\r
+       case 0xfe52:    //﹒\r
+               // fall through\r
+       case 0xff65:    //・\r
+               // fall through\r
+       case 0x30fb:    //・\r
+               // fall through\r
+       case 0x30a1:    //ァ\r
+               // fall through\r
+       case 0x30a3:    //ィ\r
+               // fall through\r
+       case 0x30a5:    //ゥ\r
+               // fall through\r
+       case 0x30a7:    //ェ\r
+               // fall through\r
+       case 0x30a9:    //ォ\r
+               // fall through\r
+       case 0x30c3:    //ッ\r
+               // fall through\r
+       case 0x30e3:    //ャ\r
+               // fall through\r
+       case 0x30e5:    //ュ\r
+               // fall through\r
+       case 0x30e7:    //ョ\r
+               // fall through\r
+       case 0x3049:    //ぉ\r
+               // fall through\r
+       case 0x3063:    //っ\r
+               // fall through\r
+       case 0x3083:    //ゃ\r
+               // fall through\r
+       case 0x3085:    //ゅ\r
+               // fall through\r
+       case 0x3087:    //ょ\r
+               // fall through\r
+       case 0x308e:    //ゎ\r
+               // fall through\r
+       case 0x30ee:    //ヮ\r
+               // fall through\r
+       case 0x30f5:    //ヵ\r
+               // fall through\r
+       case 0x30f6:    //ヶ\r
+               // fall through\r
+       case 0x30fd:    //ヽ\r
+               // fall through\r
+       case 0x30fe:    //ヾ\r
+               // fall through\r
+       case 0x30fc:    //ー\r
+               // fall through\r
+       case 0x3005:    //々\r
+               // fall through\r
+       case 0x2019:    //’\r
+               // fall through\r
+       case 0x3041:    //ぁ\r
+               // fall through\r
+       case 0x3043:    //ぃ\r
+               // fall through\r
+       case 0x3045:    //ぅ\r
+               // fall through\r
+       case 0x3047:    //ぇ\r
+               // fall through\r
+       case 0xff05:    //%\r
+               // fall through\r
+       case 0x00a2:    //¢\r
+               // fall through\r
+       case 0x30bd:    //ソ\r
+               // fall through\r
+       case 0x30be:    //ゾ\r
+               // fall through\r
+       case 0x2030:    //‰\r
+               // fall through\r
+       case 0x309b:    //゛\r
+               // fall through\r
+       case 0x309c:    //゜\r
+               // fall through\r
+       case 0x201d:    //”\r
+               // fall through\r
+       case 0x00b0:    //°\r
+               // fall through\r
+       case 0xff1a:    //:\r
+               // fall through\r
+       case 0xff1b:    //;\r
+               // fall through\r
+       case 0x003a:    //:\r
+               // fall through\r
+       case 0x003b:    //;\r
+               // fall through\r
+       case 0xff1f:    //?\r
+               // fall through\r
+       case 0xff01:    //!\r
+               // fall through\r
+       case 0xff09:    //)\r
+               // fall through\r
+       case 0x3009:    //〉\r
+               // fall through\r
+       case 0x300b:    //》\r
+               // fall through\r
+       case 0x300f:    //』\r
+               // fall through\r
+       case 0x3011:    //】\r
+               // fall through\r
+       case 0x3015:    //〕\r
+               // fall through\r
+       case 0xff3d:    //]\r
+               // fall through\r
+       case 0xff5d:    //}\r
+               // fall through\r
+       case 0xff63:    //」\r
+               isFollowingCharacter = true;\r
+               break;\r
+       default:\r
+               break;\r
+       }\r
+\r
+       return isFollowingCharacter;\r
+}\r
+\r
+bool\r
+TextSimple::IsDelimiter(const wchar_t ch) const\r
+{\r
+       bool isDelimiter = false;\r
+\r
+       switch (ch)\r
+       {\r
+       case 0x0020:    // \r
+               // fall through\r
+       case 0x3000:    // \r
+               // fall through\r
+       case 0x3001:    //、\r
+               // fall through\r
+       case 0x3002:    //。\r
+               isDelimiter = true;\r
+               break;\r
+       }\r
+\r
+       if (0xfe30 <= ch && ch <= 0xffe3)       // ︰~  ̄\r
+       {\r
+               isDelimiter = true;\r
+       }\r
+\r
+       return isDelimiter;\r
 }
 
 }}} // Tizen::Graphics::_Text