modified __DrawText for bidi
authorSungyeon Woo <s.woo@samsung.com>
Thu, 21 Mar 2013 07:46:12 +0000 (16:46 +0900)
committerSungyeon Woo <s.woo@samsung.com>
Fri, 22 Mar 2013 07:15:05 +0000 (16:15 +0900)
Change-Id: I7407403caf67779f98482d27b1a8020cbe05a94a
Signed-off-by: Sungyeon Woo <s.woo@samsung.com>
src/graphics/FGrp_Font.cpp
src/graphics/FGrp_Font.h
src/graphics/FGrp_FontBidiUtil.cpp
src/graphics/FGrp_FontBidiUtil.h

index a299f12..e6e17f9 100644 (file)
@@ -545,21 +545,6 @@ struct _TextFragment
        }
 };
 
-inline int _Abs(int value)
-{
-       return (value > 0) ? value : -value;
-}
-
-inline bool _IsLTR(FriBidiCharType charType)
-{
-       return (((charType & FRIBIDI_MASK_RTL) == 0) && ((charType & FRIBIDI_MASK_STRONG) != 0) && ((charType & FRIBIDI_MASK_LETTER) != 0));
-}
-
-inline bool _IsRTL(FriBidiCharType charType)
-{
-       return ((charType & FRIBIDI_MASK_RTL) != 0);
-}
-
 }
 
 
@@ -1151,7 +1136,7 @@ _Font::GetTextExtent(int width, const _Util::String& text, bool outline, int& co
                }
                else
                {
-                       _TextBidiPropertyWithReorder determinedBidiProperty(text.pStart, text.length);
+                       _TextBidiPropertyWithReorder determinedBidiProperty(text.pStart, determinedCount);
 
                        GapList determinedGapList;
 
@@ -1162,6 +1147,9 @@ _Font::GetTextExtent(int width, const _Util::String& text, bool outline, int& co
                                return r;
                        }
 
+                       left = 0;
+                       right = 0;
+
                        for (GapList::Iterator i = determinedGapList.Begin(); i != determinedGapList.End(); ++i)
                        {
                                left = (i->first < left) ? i->first : left;
@@ -1170,6 +1158,76 @@ _Font::GetTextExtent(int width, const _Util::String& text, bool outline, int& co
 
                        pcDim.SetSize(right - left, __fontAttrib.size.ToInt());
                        count = (determinedCount >= 0) ? determinedCount : 0;
+
+// for arabic collation element
+                       if (text.pStart + count != null)
+                       {
+                               if (count > 0 && text.pStart + count != null && _TextBidiUtil::IsCollationElement(*(text.pStart + (count - 1)), *(text.pStart + (count - 1) + 1)))
+                               {
+                                       //count - 1 < width
+                                       _TextBidiPropertyWithReorder tempBidiProperty1(text.pStart, count - 1);
+
+                                       GapList tempGapList1;
+
+                                       result r = this->__GetTextExtentList(tempBidiProperty1, tempGapList1);
+
+                                       if (r != E_SUCCESS)
+                                       {
+                                               return r;
+                                       }
+
+                                       left = 0;
+                                       right = 0;
+
+                                       for (GapList::Iterator i = tempGapList1.Begin(); i != tempGapList1.End(); ++i)
+                                       {
+                                               left = (i->first < left) ? i->first : left;
+                                               right = (i->second > right) ? i->second : right;
+                                       }
+
+                                       int tempWidth = (right - left) < width ? right - left : 0;
+
+                                       //count + 1 < width
+                                       _TextBidiPropertyWithReorder tempBidiProperty2(text.pStart, count + 1);
+
+                                       GapList tempGapList2;
+
+                                       r = this->__GetTextExtentList(tempBidiProperty2, tempGapList2);
+
+                                       if (r != E_SUCCESS)
+                                       {
+                                               return r;
+                                       }
+
+                                       left = 0;
+                                       right = 0;
+
+                                       for (GapList::Iterator i = tempGapList2.Begin(); i != tempGapList2.End(); ++i)
+                                       {
+                                               left = (i->first < left) ? i->first : left;
+                                               right = (i->second > right) ? i->second : right;
+                                       }
+
+                                       if (right - left < width)
+                                       {
+                                               if (right - left < tempWidth)
+                                               {
+                                                       pcDim.SetSize(tempWidth, __fontAttrib.size.ToInt());
+                                                       count -= 1;
+                                               }
+                                               else
+                                               {
+                                                       pcDim.SetSize(right - left, __fontAttrib.size.ToInt());
+                                                       count += 1;
+                                               }
+                                       }
+                                       else
+                                       {
+                                               pcDim.SetSize(tempWidth, __fontAttrib.size.ToInt());
+                                               count -= 1;
+                                       }
+                               }
+                       }
                }
 
                return E_SUCCESS;
@@ -1478,125 +1536,25 @@ _Font::__GetTextExtentList(const _Util::String& text, _Util::AccumList<_Util::Pa
 }
 
 result
-_Font::__GetTextExtentList(const _TextBidiPropertyWithReorder& bidiProperty, _Util::AccumList<_Util::Pair<int, int> >& outList) const
+_Font::__GetTextExtentList(_TextBidiPropertyWithReorder& bidiProperty, _Util::AccumList<_Util::Pair<int, int> >& outList) const
 {
-       _Util::AccumList<_TextBidiProperty> textList;
-
-#if 0 // old version (buggy)
-       if (bidiProperty.pEmbeddingLevels)
-       {
-               _Util::String originalText(bidiProperty.pEventText, bidiProperty.length);
-
-               const wchar_t* pBegin = originalText.pStart;
-               const wchar_t* pEnd = pBegin + originalText.length;
-
-               const wchar_t* pText = pBegin;
-               const FriBidiLevel* pEmbedLevel = &bidiProperty.pEmbeddingLevels[0];
-
-               bool isRtl = ((*pEmbedLevel & 0x01) != 0);
-
-               while (pText < pEnd)
-               {
-                       if (isRtl == ((*pEmbedLevel & 0x01) != 0))
-                       {
-                               ++pText;
-                               ++pEmbedLevel;
-                       }
-                       else
-                       {
-                               textList.Push(_TextBidiProperty(bidiProperty, pBegin - originalText.pStart, pText - pBegin));
-
-                               pBegin = pText;
-                               isRtl = !isRtl;
-                       }
-               }
+       _Util::AccumList<_Util::Pair<int, int> > tempList;
 
-               if (pBegin < pText)
-               {
-                       textList.Push(_TextBidiProperty(bidiProperty, pBegin - originalText.pStart, pText - pBegin));
-               }
-       }
-       else
-       {
-               _Util::String originalText(bidiProperty.pEventText, bidiProperty.length);
-               textList.Push(_TextBidiProperty(bidiProperty, 0, originalText.length));
-       }
-#else
        if (bidiProperty.pBidiIndex)
        {
-               _Util::String originalText(bidiProperty.pEventText, bidiProperty.length);
-
-               if (originalText.length <= 0)
-               {
-                       return E_SUCCESS;
-               }
-
-               const wchar_t* pBegin = originalText.pStart;
-               const wchar_t* pEnd = pBegin + originalText.length;
-
-               const wchar_t* pText = pBegin;
-               const FriBidiStrIndex* pStrIndexBegin = &bidiProperty.pBidiIndex[0];
-               const FriBidiStrIndex* pStrIndex = pStrIndexBegin;
-
-               const FriBidiCharType* pCharType = &bidiProperty.pCharType[0];
-
-               // (*pStrIndex) is always valid
-               bool isRtl = (*pStrIndex > 0) || ((*pCharType & FRIBIDI_MASK_RTL) != 0);
-
-               while (pText < pEnd)
-               {
-                       bool mustPush = (isRtl && _IsLTR(*pCharType)) || (!isRtl && _IsRTL(*pCharType));
-
-                       int step = (pStrIndex > pStrIndexBegin) ? *pStrIndex - *(pStrIndex-1) : 0;
-
-                       if ((!mustPush) && (_Abs(step) <= 1))
-                       {
-                               ++pText;
-                               ++pStrIndex;
-                               ++pCharType;
-                       }
-                       else
-                       {
-                               textList.Push(_TextBidiProperty(bidiProperty, pBegin - originalText.pStart, pText - pBegin));
-
-                               pStrIndexBegin = pStrIndex;
-                               pBegin = pText;
-                               isRtl = !isRtl;
-                       }
-               }
-
-               if (pBegin < pText)
-               {
-                       textList.Push(_TextBidiProperty(bidiProperty, pBegin - originalText.pStart, pText - pBegin));
-               }
-       }
-       else
-       {
-               _Util::String originalText(bidiProperty.pEventText, bidiProperty.length);
-               textList.Push(_TextBidiProperty(bidiProperty, 0, originalText.length));
-       }
-#endif
+               int xDest = 0;
+               int yDest = 0;
 
-       int xDest = 0;
-       int yDest = 0;
+               int length = bidiProperty.length;
 
-       bool isRtl = bidiProperty.isRtl;
+               _Font* pThis = const_cast <_Font*>(this);
 
-       _Font* pThis = const_cast <_Font*>(this);
-
-       pThis->ApplyAttribute();
+               pThis->ApplyAttribute();
 
-       _Util::AccumList<_Util::Pair<int, int> > tempList;
-
-       for (_Util::AccumList<_TextBidiProperty>::Iterator textSegment = textList.Begin(); textSegment != textList.End(); ++textSegment)
-       {
-               if (textSegment->pEventText == null || textSegment->length <= 0)
-               {
-                       continue;
-               }
+               const wchar_t* pReorderedText = bidiProperty.GetReorderedText();
 
-               const wchar_t* pTextFragmentBegin = textSegment->pEventText;
-               const wchar_t* pTextFragmentEnd = pTextFragmentBegin + textSegment->length;
+               const wchar_t* pTextFragmentBegin = pReorderedText;
+               const wchar_t* pTextFragmentEnd = pTextFragmentBegin + length;
 
                const wchar_t* pTextSegment = pTextFragmentBegin;
 
@@ -1635,13 +1593,7 @@ _Font::__GetTextExtentList(const _TextBidiPropertyWithReorder& bidiProperty, _Ut
                 *
                 */
 
-               typedef _Util::AccumList<_TextFragment>::Iterator TextFragmentIter;
-
-               TextFragmentIter textFragment = (textSegment->isRtl) ? textFragmentList.End() : textFragmentList.Begin() - 1;
-               TextFragmentIter endCondition = (textSegment->isRtl) ? textFragmentList.Begin() - 1 : textFragmentList.End();
-               int increasing = (textSegment->isRtl) ? -1 : 1;
-
-               while ((textFragment += increasing) != endCondition)
+               for (_Util::AccumList<_TextFragment>::Iterator textFragment = textFragmentList.Begin(); textFragment != textFragmentList.End(); ++textFragment)
                {
                        if (textFragment->pUsingFont == null || textFragment->textFragment.length <= 0)
                        {
@@ -1666,10 +1618,12 @@ _Font::__GetTextExtentList(const _TextBidiPropertyWithReorder& bidiProperty, _Ut
 
                        Tizen::Base::Collection::ArrayListT<_IFont::Glyph *> glyphList;
 
-                       GUnicodeScript script = g_unichar_get_script(textSegment->eventChar);
+                       const wchar_t firstChar = *textFragment->textFragment.pStart;
+
+                       GUnicodeScript script = _TextBidiUtil::GetUnicodeScript(firstChar);
                        // need to check if (script < 0 || script >= _sampleLanguageCount) ?
 
-                       textFragment->pUsingFont->GetGlyphList(textFragment->textFragment, glyphList, isRtl, script);
+                       textFragment->pUsingFont->GetGlyphList(textFragment->textFragment, glyphList, false, script);
 
                        int count = glyphList.GetCount();
 
@@ -1679,6 +1633,12 @@ _Font::__GetTextExtentList(const _TextBidiPropertyWithReorder& bidiProperty, _Ut
 
                                glyphList.GetAt(i, pGlyph);
 
+                               // bug fixed in test case of L"\x9a8\x20\x981\x9a0\x635"
+                               if (pGlyph->xAdvance == 0 && pGlyph->image.width == 0)
+                               {
+                                       continue;
+                               }
+
                                int prevX = xDest;
 
                                xDest += pGlyph->xAdvance.ToInt();
@@ -1703,12 +1663,9 @@ _Font::__GetTextExtentList(const _TextBidiPropertyWithReorder& bidiProperty, _Ut
                                delete pEnum;
                        }
                }
-
-               isRtl = !isRtl;
        }
 
        // reorder Bidi index
-#if 1
        {
                typedef _Util::Pair<int, int> Gap;
                typedef _Util::AccumList<Gap> GapList;
@@ -1717,71 +1674,26 @@ _Font::__GetTextExtentList(const _TextBidiPropertyWithReorder& bidiProperty, _Ut
 
                int index = 0;
 
-               for (GapList::Iterator dst = outList.Begin(); dst != outList.End() && index < bidiProperty.length; ++dst)
+               if (bidiProperty.length == int(tempList.Size()))
                {
-                       *dst = *(srcBegin + bidiProperty.pBidiIndex[index++]);
+                       for (GapList::Iterator dst = outList.Begin(); dst != outList.End(); ++dst)
+                       {
+                               *dst = *(srcBegin + bidiProperty.pBidiIndex[index++]);
+                       }
                }
-       }
-#else // under development
-       if (bidiProperty.length == tempList.Size())
-       {
-               typedef _Util::Pair<int, int> Gap;
-               typedef _Util::AccumList<Gap> GapList;
-
-               GapList::Iterator srcBegin = tempList.Begin();
-
-               int index = 0;
-
-               for (GapList::Iterator dst = outList.Begin(); dst != outList.End(); ++dst)
+               else if (bidiProperty.length > int(tempList.Size()))
                {
-                       *dst = *(srcBegin + bidiProperty.pBidiIndex[index++]);
+                       _TextBidiUtil::GetReorderedIndexList(bidiProperty, tempList, outList);
                }
-       }
-       else if (bidiProperty.length > tempList.Size())
-       {
-               typedef _Util::Pair<int, int> Gap;
-               typedef _Util::AccumList<Gap> GapList;
-
-               GapList revisedList;
-
+               else // if (bidiProperty.length < tempList.Size())
                {
-                       const wchar_t* pText = bidiProperty.pEventText;
-                       const wchar_t* const pTextEnd = pText + bidiProperty.length;
-
-                       GapList::Iterator tempListIter = tempList.Begin();
-
-                       while (pText < pTextEnd)
+               // under development
+                       for (GapList::Iterator dst = outList.Begin(); dst != outList.End() && index < bidiProperty.length; ++dst)
                        {
-                               revisedList.Push(*tempListIter);
-
-                               if (*pText == 0x0644)
-                               {
-                                       if (((pText+1) < pTextEnd) && *(pText+1) == 0x0627)
-                                       {
-                                               revisedList.Push(_Util::MakePair(tempListIter->first, tempListIter->first));
-                                               ++pText;
-                                       }
-                               }
-
-                               ++pText;
-                               ++tempListIter;
+                               *dst = *(srcBegin + bidiProperty.pBidiIndex[index++]);
                        }
                }
-
-               GapList::Iterator srcBegin = revisedList.Begin();
-
-               int index = 0;
-
-               for (GapList::Iterator dst = outList.Begin(); dst != outList.End(); ++dst)
-               {
-                       *dst = *(srcBegin + bidiProperty.pBidiIndex[index++]);
-               }
        }
-       else
-       {
-               SysAssert(false);
-       }
-#endif
 
        return E_SUCCESS;
 }
@@ -1907,428 +1819,198 @@ _Font::__DrawText(_Canvas& canvas, const Point& point, const Tizen::Base::String
 
        unsigned long canvasFgColor = canvas.__fgColor;
 
-#if 1
-       // Do not use _TextBidiProperty bidiProps(pText, length);
-       _TextBidiPropertyWithReorder bidiProps(pText, length);
+       _TextBidiPropertyWithReorder bidiProperty(pText, length);
 
-       if (bidiProps.HasBidi())
+       if (bidiProperty.HasBidi())
        {
-               _Util::AccumList<_TextBidiProperty> textList;
+               const wchar_t* pReorderedText = bidiProperty.GetReorderedText();
 
-#if 0 // old version (buggy)
-               if (bidiProps.pEmbeddingLevels)
-               {
-                       _Util::String originalText(text.GetPointer(), text.GetLength(), startIndex, length);
+               const wchar_t* pTextFragmentBegin = pReorderedText;
+               const wchar_t* pTextFragmentEnd = pTextFragmentBegin + length;
 
-                       const wchar_t* pBegin = originalText.pStart;
-                       const wchar_t* pEnd = pBegin + originalText.length;
+               const wchar_t* pTextSegment = pTextFragmentBegin;
 
-                       const wchar_t* pText = pBegin;
-                       const FriBidiLevel* pEmbedLevel = &bidiProps.pEmbeddingLevels[pText - text.GetPointer()];
+               _IFont* pBaseFont = this->__GetFont(*pTextSegment);
 
-                       bool isRtl = ((*pEmbedLevel & 0x01) != 0);
+               _Util::AccumList<_TextFragment> textFragmentList;
 
-                       while (pText < pEnd)
+               while (pTextSegment < pTextFragmentEnd)
+               {
+                       if (pBaseFont->CheckGlyph(*pTextSegment) == 0)
                        {
-                               if (isRtl == ((*pEmbedLevel & 0x01) != 0))
-                               {
-                                       ++pText;
-                                       ++pEmbedLevel;
-                               }
-                               else
+                               _IFont* pFallbackFont = this->__GetFont(*pTextSegment);
+
+                               if (pBaseFont != pFallbackFont)
                                {
-                                       textList.Push(_TextBidiProperty(bidiProps, pBegin - originalText.pStart, pText - pBegin));
+                                       textFragmentList.Push(_TextFragment(_Util::String(pTextFragmentBegin, pTextSegment - pTextFragmentBegin), pBaseFont));
 
-                                       pBegin = pText;
-                                       isRtl = !isRtl;
+                                       pTextFragmentBegin = pTextSegment;
+                                       pBaseFont = pFallbackFont;
                                }
                        }
 
-                       if (pBegin < pText)
-                       {
-                               textList.Push(_TextBidiProperty(bidiProps, pBegin - originalText.pStart, pText - pBegin));
-                       }
-               }
-               else
-               {
-                       _Util::String originalText(text.GetPointer(), text.GetLength(), startIndex, length);
-                       textList.Push(_TextBidiProperty(bidiProps, 0, originalText.length));
+                       ++pTextSegment;
                }
-#else
-               if (bidiProps.pBidiIndex)
-               {
-                       _Util::String originalText(text.GetPointer(), text.GetLength(), startIndex, length);
-
-                       if (originalText.length <= 0)
-                       {
-                               return E_SUCCESS;
-                       }
-
-                       const wchar_t* pBegin = originalText.pStart;
-                       const wchar_t* pEnd = pBegin + originalText.length;
 
-                       const wchar_t* pText = pBegin;
-                       const FriBidiStrIndex* pStrIndexBegin = &bidiProps.pBidiIndex[pText - text.GetPointer()];
-                       const FriBidiStrIndex* pStrIndex = pStrIndexBegin;
-
-                       const FriBidiCharType* pCharType = &bidiProps.pCharType[pText - text.GetPointer()];
+               textFragmentList.Push(_TextFragment(_Util::String(pTextFragmentBegin, pTextSegment - pTextFragmentBegin), pBaseFont));
 
-                       // (*pStrIndex) is always valid
-                       bool isRtl = (*pStrIndex > 0) || ((*pCharType & FRIBIDI_MASK_RTL) != 0);
+               /*
+                * - In case of LTR
+                * for (_Util::AccumList<_TextFragment>::Iterator textFragment = textFragmentList.Begin(); textFragment != textFragmentList.End(); ++textFragment)
+                *
+                * - In case of RTL
+                * for (_Util::AccumList<_TextFragment>::Iterator textFragment = textFragmentList.End(); textFragment != textFragmentList.Begin(); )
+                * {
+                *     --textFragment;
+                *
+                */
 
-                       while (pText < pEnd)
+               for (_Util::AccumList<_TextFragment>::Iterator textFragment = textFragmentList.Begin(); textFragment != textFragmentList.End(); ++textFragment)
+               {
+                       if (textFragment->pUsingFont == null || textFragment->textFragment.length <= 0)
                        {
-                               bool mustPush = (isRtl && _IsLTR(*pCharType)) || (!isRtl && _IsRTL(*pCharType));
+                               continue;
+                       }
 
-                               int step = (pStrIndex > pStrIndexBegin) ? *pStrIndex - *(pStrIndex-1) : 0;
+                       if (textFragment->pUsingFont != __pNativeFont)
+                       {
+                               _IFont::Attrib fontAttrib;
 
-                               if ((!mustPush) && (_Abs(step) <= 1))
-                               {
-                                       ++pText;
-                                       ++pStrIndex;
-                                       ++pCharType;
-                               }
-                               else
+                               if (textFragment->pUsingFont->GetAttrib(fontAttrib))
                                {
-                                       textList.Push(_TextBidiProperty(bidiProps, pBegin - originalText.pStart, pText - pBegin));
+                                       fontAttrib.size = __fontAttrib.size;
+                                       fontAttrib.style = _IFont::STYLE_NONE;
+                                       fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_BOLD) ? _IFont::STYLE_BOLD : 0;
+                                       fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_ITALIC) ? _IFont::STYLE_ITALIC : 0;
+                                       fontAttrib.style |= (__fontAttrib.underline) ? _IFont::STYLE_UNDERLINE : 0;
 
-                                       pStrIndexBegin = pStrIndex;
-                                       pBegin = pText;
-                                       isRtl = !isRtl;
+                                       textFragment->pUsingFont->SetAttrib(fontAttrib);
                                }
                        }
 
-                       if (pBegin < pText)
-                       {
-                               textList.Push(_TextBidiProperty(bidiProps, pBegin - originalText.pStart, pText - pBegin));
-                       }
-               }
-               else
-               {
-                       _Util::String originalText(text.GetPointer(), text.GetLength(), startIndex, length);
-                       textList.Push(_TextBidiProperty(bidiProps, 0, originalText.length));
-               }
-#endif
-
-               for (_Util::AccumList<_TextBidiProperty>::Iterator textSegment = textList.Begin(); textSegment != textList.End(); ++textSegment)
-               {
-                       if (textSegment->pEventText == null || textSegment->length <= 0)
-                       {
-                               continue;
-                       }
+                       Tizen::Base::Collection::ArrayListT<_IFont::Glyph *> glyphList;
 
-                       const wchar_t* pTextFragmentBegin = textSegment->pEventText;
-                       const wchar_t* pTextFragmentEnd = pTextFragmentBegin + textSegment->length;
+                       const wchar_t firstChar = *textFragment->textFragment.pStart;
 
-                       const wchar_t* pTextSegment = pTextFragmentBegin;
+                       GUnicodeScript script = _TextBidiUtil::GetUnicodeScript(firstChar);
 
-                       _IFont* pBaseFont = this->__GetFont(*pTextSegment);
+                       textFragment->pUsingFont->GetGlyphList(textFragment->textFragment, glyphList, false, script);
+                       // need to check if (script < 0 || script >= _sampleLanguageCount) ?
 
-                       _Util::AccumList<_TextFragment> textFragmentList;
+                       int count = glyphList.GetCount();
 
-                       while (pTextSegment < pTextFragmentEnd)
+                       for (int i = 0; i < count; i++)
                        {
-                               if (pBaseFont->CheckGlyph(*pTextSegment) == 0)
+                               /* for debugging
+                               static int s_index = 0;
+                               const unsigned long COLOR[6] =
                                {
-                                       _IFont* pFallbackFont = this->__GetFont(*pTextSegment);
+                                       0xFFFFFFFF,
+                                       0xFF40FF40,
+                                       0xFF40FFFF,
+                                       0xFFFF4040,
+                                       0xFFFF40FF,
+                                       0xFFFFFF40
+                               };
+                               unsigned long canvasFgColor = COLOR[s_index++ % 6];
+                               */
+
+                               typedef unsigned long TPixel;
+                               _IFont::Glyph *pGlyph = 0;
 
-                                       if (pBaseFont != pFallbackFont)
-                                       {
-                                               textFragmentList.Push(_TextFragment(_Util::String(pTextFragmentBegin, pTextSegment - pTextFragmentBegin), pBaseFont));
+                               TPixel srcR, srcG, srcB, srcA;
+                               TPixel dstR, dstG, dstB, dstA;
 
-                                               pTextFragmentBegin = pTextSegment;
-                                               pBaseFont = pFallbackFont;
-                                       }
-                               }
+                               srcA = (canvasFgColor >> 24) & 0xFF;
+                               srcA += (srcA >> 7);
+                               srcR = (canvasFgColor >> 16) & 0xFF;
+                               srcG = (canvasFgColor >> 8) & 0xFF;
+                               srcB = (canvasFgColor) & 0xFF;
 
-                               ++pTextSegment;
-                       }
+                               SystemPixel* pBufferStartAddr = null;
+                               int bufferPitch;
 
-                       textFragmentList.Push(_TextFragment(_Util::String(pTextFragmentBegin, pTextSegment - pTextFragmentBegin), pBaseFont));
-
-                       /*
-                        * - In case of LTR
-                        * for (_Util::AccumList<_TextFragment>::Iterator textFragment = textFragmentList.Begin(); textFragment != textFragmentList.End(); ++textFragment)
-                        *
-                        * - In case of RTL
-                        * for (_Util::AccumList<_TextFragment>::Iterator textFragment = textFragmentList.End(); textFragment != textFragmentList.Begin(); )
-                        * {
-                        *     --textFragment;
-                        *
-                        */
-                       typedef _Util::AccumList<_TextFragment>::Iterator TextFragmentIter;
-
-                       TextFragmentIter textFragment = (textSegment->isRtl) ? textFragmentList.End() : textFragmentList.Begin() - 1;
-                       TextFragmentIter endCondition = (textSegment->isRtl) ? textFragmentList.Begin() - 1 : textFragmentList.End();
-                       int increasing = (textSegment->isRtl) ? -1 : 1;
-
-                       while ((textFragment += increasing) != endCondition)
-                       {
-                               if (textFragment->pUsingFont == null || textFragment->textFragment.length <= 0)
-                               {
-                                       continue;
-                               }
+                               scratchPad.GetBuffer(pBufferStartAddr, bufferPitch);
 
-                               if (textFragment->pUsingFont != __pNativeFont)
+                               glyphList.GetAt(i, pGlyph);
+
+                               for (int h = 0; h < pGlyph->image.height; h++)
                                {
-                                       _IFont::Attrib fontAttrib;
+                                       int y = yDest - pGlyph->yOffset.ToInt() + h;
 
-                                       if (textFragment->pUsingFont->GetAttrib(fontAttrib))
+                                       if (y < clipY1)
                                        {
-                                               fontAttrib.size = __fontAttrib.size;
-                                               fontAttrib.style = _IFont::STYLE_NONE;
-                                               fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_BOLD) ? _IFont::STYLE_BOLD : 0;
-                                               fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_ITALIC) ? _IFont::STYLE_ITALIC : 0;
-                                               fontAttrib.style |= (__fontAttrib.underline) ? _IFont::STYLE_UNDERLINE : 0;
-
-                                               textFragment->pUsingFont->SetAttrib(fontAttrib);
+                                               continue;
                                        }
-                               }
-
-                               Tizen::Base::Collection::ArrayListT<_IFont::Glyph *> glyphList;
-
-                               GUnicodeScript script = g_unichar_get_script(textSegment->eventChar);
-                               // need to check if (script < 0 || script >= _sampleLanguageCount) ?
-
-                               textFragment->pUsingFont->GetGlyphList(textFragment->textFragment, glyphList, textSegment->isRtl, script);
 
-                               int count = glyphList.GetCount();
-
-                               for (int i = 0; i < count; i++)
-                               {
-                                       /* for debugging
-                                       static int s_index = 0;
-                                       const unsigned long COLOR[6] =
+                                       if (y >= clipY2)
                                        {
-                                               0xFFFFFFFF,
-                                               0xFF40FF40,
-                                               0xFF40FFFF,
-                                               0xFFFF4040,
-                                               0xFFFF40FF,
-                                               0xFFFFFF40
-                                       };
-                                       unsigned long canvasFgColor = COLOR[s_index++ % 6];
-                                       */
-
-                                       typedef unsigned long TPixel;
-                                       _IFont::Glyph *pGlyph = 0;
-
-                                       TPixel srcR, srcG, srcB, srcA;
-                                       TPixel dstR, dstG, dstB, dstA;
-
-                                       srcA = (canvasFgColor >> 24) & 0xFF;
-                                       srcA += (srcA >> 7);
-                                       srcR = (canvasFgColor >> 16) & 0xFF;
-                                       srcG = (canvasFgColor >> 8) & 0xFF;
-                                       srcB = (canvasFgColor) & 0xFF;
-
-                                       SystemPixel* pBufferStartAddr = null;
-                                       int bufferPitch;
-
-                                       scratchPad.GetBuffer(pBufferStartAddr, bufferPitch);
+                                               break;
+                                       }
 
-                                       glyphList.GetAt(i, pGlyph);
+                                       TPixel* pDest32 = pBufferStartAddr + y * bufferPitch + xDest + pGlyph->xOffset.ToInt();
 
-                                       for (int h = 0; h < pGlyph->image.height; h++)
+                                       for (int w = 0; w < pGlyph->image.width; w++)
                                        {
-                                               int y = yDest - pGlyph->yOffset.ToInt() + h;
+                                               int x = xDest + pGlyph->xOffset.ToInt() + w;
 
-                                               if (y < clipY1)
+                                               if (x < clipX1)
                                                {
+                                                       ++pDest32;
                                                        continue;
                                                }
 
-                                               if (y >= clipY2)
+                                               if (x >= clipX2)
                                                {
                                                        break;
                                                }
 
-                                               TPixel* pDest32 = pBufferStartAddr + y * bufferPitch + xDest + pGlyph->xOffset.ToInt();
+                                               unsigned long alpha = (unsigned long) (pGlyph->image.pBitmap[h * pGlyph->image.bytesPerLine + w]);
 
-                                               for (int w = 0; w < pGlyph->image.width; w++)
+                                               if (alpha > 0)
                                                {
-                                                       int x = xDest + pGlyph->xOffset.ToInt() + w;
+                                                       // equivalent to scratchPad.FillRect(x, y, 1, 1, fgColor, alpha);
+                                                       alpha = (alpha * srcA) >> 8;
+                                                       alpha += (alpha >> 7);
 
-                                                       if (x < clipX1)
-                                                       {
-                                                               ++pDest32;
-                                                               continue;
-                                                       }
+                                                       dstA = (*pDest32 >> 24) & 0xFF;
+                                                       dstR = (*pDest32 >> 16) & 0xFF;
+                                                       dstG = (*pDest32 >> 8) & 0xFF;
+                                                       dstB = (*pDest32) & 0xFF;
 
-                                                       if (x >= clipX2)
-                                                       {
-                                                               break;
-                                                       }
+                                                       dstA = BLEND_ALPHA_COMPONEMT(alpha, dstA);
+                                                       dstR = (dstR + (((srcR - dstR) * alpha) >> 8)) & 0xFF;
+                                                       dstG = (dstG + (((srcG - dstG) * alpha) >> 8)) & 0xFF;
+                                                       dstB = (dstB + (((srcB - dstB) * alpha) >> 8)) & 0xFF;
 
-                                                       unsigned long alpha = (unsigned long) (pGlyph->image.pBitmap[h * pGlyph->image.bytesPerLine + w]);
+                                                       *pDest32 = (dstA << 24) | (dstR << 16) | (dstG << 8) | dstB;
 
-                                                       if (alpha > 0)
-                                                       {
-                                                               // equivalent to scratchPad.FillRect(x, y, 1, 1, fgColor, alpha);
-                                                               alpha = (alpha * srcA) >> 8;
-                                                               alpha += (alpha >> 7);
-
-                                                               dstA = (*pDest32 >> 24) & 0xFF;
-                                                               dstR = (*pDest32 >> 16) & 0xFF;
-                                                               dstG = (*pDest32 >> 8) & 0xFF;
-                                                               dstB = (*pDest32) & 0xFF;
-
-                                                               dstA = BLEND_ALPHA_COMPONEMT(alpha, dstA);
-                                                               dstR = (dstR + (((srcR - dstR) * alpha) >> 8)) & 0xFF;
-                                                               dstG = (dstG + (((srcG - dstG) * alpha) >> 8)) & 0xFF;
-                                                               dstB = (dstB + (((srcB - dstB) * alpha) >> 8)) & 0xFF;
-
-                                                               *pDest32 = (dstA << 24) | (dstR << 16) | (dstG << 8) | dstB;
-
-                                                       }
-                                                       ++pDest32;
                                                }
+                                               ++pDest32;
                                        }
-
-                                       xDest += pGlyph->xAdvance.ToInt();
-                                       yDest += pGlyph->yAdvance.ToInt();
                                }
 
-                               scratchPad.RegisterFillRect(null);
-
-                               IEnumeratorT<_IFont::Glyph*>* pEnum = glyphList.GetEnumeratorN();
-
-                               if (pEnum)
-                               {
-                                       while (pEnum->MoveNext() == E_SUCCESS)
-                                       {
-                                               _IFont::Glyph* pGlyph;
-
-                                               pEnum->GetCurrent(pGlyph);
-                                               delete pGlyph;
-                                       }
-
-                                       delete pEnum;
-                               }
+                               xDest += pGlyph->xAdvance.ToInt();
+                               yDest += pGlyph->yAdvance.ToInt();
                        }
 
-                       bidiProps.isRtl = !bidiProps.isRtl;
-               }
-#else
-       GUnicodeScript script = g_unichar_get_script(*pText);
-       // need to check if (script < 0 || script >= _sampleLanguageCount) ?
-
-       // Temporary code for testing Arabic
-       if (script == G_UNICODE_SCRIPT_ARABIC)
-       {
-               _TextBidiProperty bidiProps(pText, length);
-
-               _IFont* pFont = this->__GetFont(*pText);
-
-               if (pFont == null)
-               {
-                       return E_SYSTEM;
-               }
+                       scratchPad.RegisterFillRect(null);
 
-               Tizen::Base::Collection::ArrayListT<_IFont::Glyph *> glyphList;
-
-               pFont->GetGlyphList(_Util::String(text.GetPointer(), text.GetLength(), startIndex, length), glyphList, bidiProps.isRtl, script);
-
-               int count = glyphList.GetCount();
-
-               for (int i = 0; i < count; i++)
-               {
-                       typedef unsigned long TPixel;
-                       _IFont::Glyph *pGlyph = 0;
-
-                       TPixel srcR, srcG, srcB, srcA;
-                       TPixel dstR, dstG, dstB, dstA;
-
-                       srcA = (canvasFgColor >> 24) & 0xFF;
-                       srcA += (srcA >> 7);
-                       srcR = (canvasFgColor >> 16) & 0xFF;
-                       srcG = (canvasFgColor >> 8) & 0xFF;
-                       srcB = (canvasFgColor) & 0xFF;
-
-                       SystemPixel* pBufferStartAddr = null;
-                       int bufferPitch;
-
-                       scratchPad.GetBuffer(pBufferStartAddr, bufferPitch);
-
-                       glyphList.GetAt(i, pGlyph);
+                       IEnumeratorT<_IFont::Glyph*>* pEnum = glyphList.GetEnumeratorN();
 
-                       for (int h = 0; h < pGlyph->image.height; h++)
+                       if (pEnum)
                        {
-                               int y = yDest - pGlyph->yOffset + h;
-
-                               if (y < 0)
-                               {
-                                       continue;
-                               }
-
-                               if (y >= scratchPad.GetHeight())
-                               {
-                                       break;
-                               }
-
-                               TPixel* pDest32 = pBufferStartAddr + y * bufferPitch + xDest + pGlyph->xOffset;
-
-                               for (int w = 0; w < pGlyph->image.width; w++)
+                               while (pEnum->MoveNext() == E_SUCCESS)
                                {
-                                       int x = xDest + pGlyph->xOffset + w;
-
-                                       if (x < 0)
-                                       {
-                                               ++pDest32;
-                                               continue;
-                                       }
-
-                                       if (x >= scratchPad.GetWidth())
-                                       {
-                                               break;
-                                       }
-
-                                       unsigned long alpha = (unsigned long) (pGlyph->image.pBitmap[h * pGlyph->image.bytesPerLine + w]);
-
-                                       if (alpha > 0)
-                                       {
-                                               // equivalent to scratchPad.FillRect(x, y, 1, 1, fgColor, alpha);
-                                               alpha = (alpha * srcA) >> 8;
-                                               alpha += (alpha >> 7);
-
-                                               dstA = (*pDest32 >> 24) & 0xFF;
-                                               dstR = (*pDest32 >> 16) & 0xFF;
-                                               dstG = (*pDest32 >> 8) & 0xFF;
-                                               dstB = (*pDest32) & 0xFF;
-
-                                               dstA = BLEND_ALPHA_COMPONEMT(alpha, dstA);
-                                               dstR = (dstR + (((srcR - dstR) * alpha) >> 8)) & 0xFF;
-                                               dstG = (dstG + (((srcG - dstG) * alpha) >> 8)) & 0xFF;
-                                               dstB = (dstB + (((srcB - dstB) * alpha) >> 8)) & 0xFF;
-
-                                               *pDest32 = (dstA << 24) | (dstR << 16) | (dstG << 8) | dstB;
+                                       _IFont::Glyph* pGlyph;
 
-                                       }
-                                       ++pDest32;
+                                       pEnum->GetCurrent(pGlyph);
+                                       delete pGlyph;
                                }
-                       }
-
-                       xDest += pGlyph->xAdvance.ToInt();
-                       yDest += pGlyph->yAdvance.ToInt();
-               }
 
-               scratchPad.RegisterFillRect(null);
-
-               IEnumeratorT<_IFont::Glyph*>* pEnum = glyphList.GetEnumeratorN();
-
-               if (pEnum)
-               {
-                       while (pEnum->MoveNext() == E_SUCCESS)
-                       {
-                               _IFont::Glyph* pGlyph;
-
-                               pEnum->GetCurrent(pGlyph);
-                               delete pGlyph;
+                               delete pEnum;
                        }
-
-                       delete pEnum;
                }
-#endif
        }
        else
        {
@@ -2353,6 +2035,7 @@ _Font::__DrawText(_Canvas& canvas, const Point& point, const Tizen::Base::String
                                fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_BOLD) ? _IFont::STYLE_BOLD : 0;
                                fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_ITALIC) ? _IFont::STYLE_ITALIC : 0;
                                fontAttrib.style |= (__fontAttrib.underline) ? _IFont::STYLE_UNDERLINE : 0;
+
                                rtn = pFont->SetAttrib(fontAttrib);
                                //SysTryReturn(NID_GRP, rtn, false, E_SYSTEM, "[E_SYSTEM] Failed to set font attribute");
                        }
index 28588bc..3836bad 100644 (file)
@@ -185,7 +185,7 @@ private:
        result __GetTextExtent(int width, const _Util::String& text, bool outline, int& count, Dimension& dim) const;
 
        result __GetTextExtentList(const _Util::String& text, _Util::AccumList<_Util::Pair<int, int> >& outList) const;
-       result __GetTextExtentList(const _TextBidiPropertyWithReorder& bidiProperty, _Util::AccumList<_Util::Pair<int, int> >& outList) const;
+       result __GetTextExtentList(_TextBidiPropertyWithReorder& bidiProperty, _Util::AccumList<_Util::Pair<int, int> >& outList) const;
 
 private:
        std::tr1::shared_ptr <_IFont> __sharedFont;
index 19e4498..a71e16d 100644 (file)
@@ -436,6 +436,7 @@ _TextBidiProperty::~_TextBidiProperty(void)
 _TextBidiPropertyWithReorder::_TextBidiPropertyWithReorder(const wchar_t* pText, int length)
        : _TextBidiProperty(pText, length)
        , pBidiIndex(0)
+       , __pReorderedText(0)
 {
        BidiParagraph* pBidiProperty = static_cast<BidiParagraph*>(this->pReserved);
 
@@ -453,12 +454,153 @@ _TextBidiPropertyWithReorder::_TextBidiPropertyWithReorder(const wchar_t* pText,
 _TextBidiPropertyWithReorder::_TextBidiPropertyWithReorder(const _TextBidiProperty& refBidiProperty, int offset, int length)
        : _TextBidiProperty(refBidiProperty, offset, length)
        , pBidiIndex(0)
+       , __pReorderedText(0)
 {
 }
 
+const wchar_t*
+_TextBidiPropertyWithReorder::GetReorderedText(void)
+{
+       if ((__pReorderedText == NULL) && (pEventText != NULL) && (pBidiIndex != NULL))
+       {
+               __pReorderedText = new (std::nothrow) wchar_t[length + 1];
+
+               if (__pReorderedText)
+               {
+                       wchar_t* pTempText = __pReorderedText;
+                       const wchar_t* pTempTextEnd = pTempText + length;
+                       const FriBidiStrIndex* pTempBidiIndex = pBidiIndex;
+
+                       while (pTempText < pTempTextEnd)
+                       {
+                               *pTempText++ = pEventText[*pTempBidiIndex++];
+                       }
+
+                       *pTempText = 0;
+               }
+       }
+
+       return __pReorderedText;
+}
+
 _TextBidiPropertyWithReorder::~_TextBidiPropertyWithReorder(void)
 {
-       delete pBidiIndex;
+       delete[] pBidiIndex;
+       delete[] __pReorderedText;
+}
+
+GUnicodeScript
+_TextBidiUtil::GetUnicodeScript(const wchar_t unicode)
+{
+       static const struct MatchingTable
+       {
+               wchar_t min;
+               wchar_t max;
+               GUnicodeScript script;
+       } MATCHING_TABLE[] =
+       {
+               { 0x0600, 0x06ff, G_UNICODE_SCRIPT_ARABIC }
+       };
+
+       static const MatchingTable* pTableEnd = &MATCHING_TABLE[0] + sizeof(MATCHING_TABLE) / sizeof(MATCHING_TABLE[0]);
+
+       const MatchingTable* pTable = &MATCHING_TABLE[0] - 1;
+
+       while (++pTable < pTableEnd)
+       {
+               if ((pTable->min <= unicode) && (pTable->max >= unicode))
+               {
+                       return pTable->script;
+               }
+       }
+
+       return g_unichar_get_script(unicode);
+}
+
+bool
+_TextBidiUtil::IsCollationElement(const wchar_t first, const wchar_t second)
+{
+       static const struct MatchingTable
+       {
+               wchar_t first;
+               wchar_t second;
+       } MATCHING_TABLE[] =
+       {
+               { 0x0644, 0x0627 }
+       };
+
+       static const MatchingTable* pTableEnd = &MATCHING_TABLE[0] + sizeof(MATCHING_TABLE) / sizeof(MATCHING_TABLE[0]);
+
+       const MatchingTable* pTable = &MATCHING_TABLE[0] - 1;
+
+       while (++pTable < pTableEnd)
+       {
+               if ((pTable->first != first) || (pTable->second != second))
+               {
+                       continue;
+               }
+
+               return true;
+       }
+
+       return false;
+}
+
+bool
+_TextBidiUtil::GetReorderedIndexList(const _TextBidiPropertyWithReorder& refBidiProperty, const _Util::AccumList<_Util::Pair<int, int> >& inputList, _Util::AccumList<_Util::Pair<int, int> >& outList)
+{
+       if ((refBidiProperty.pEventText != NULL) && (refBidiProperty.pBidiIndex != NULL))
+       {
+               int length = refBidiProperty.length;
+
+               int* pCoIndex = new int[length];
+
+               int coIndex = 0;
+
+               for (int i = 0; i < refBidiProperty.length; i++, coIndex++)
+               {
+                       if ((i + 1 < length) && IsCollationElement(refBidiProperty.pEventText[i], refBidiProperty.pEventText[i + 1]))
+                       {
+                               pCoIndex[i] = coIndex;
+                               pCoIndex[++i] = (1 << 24) | coIndex;
+                       }
+                       else
+                       {
+                               pCoIndex[i] = coIndex;
+                       }
+               }
+
+               typedef _Util::Pair<int, int> Gap;
+               typedef _Util::AccumList<Gap> GapList;
+
+               GapList::ConstIterator srcBegin = inputList.Begin();
+
+               int index = 0;
+
+               for (GapList::Iterator dst = outList.Begin(); dst != outList.End(); ++dst)
+               {
+                       // for safty
+                       if (index >= length)
+                       {
+                               break;
+                       }
+
+                       int coIx = pCoIndex[refBidiProperty.pBidiIndex[index++]];
+                       int jump = coIx >> 24;
+
+                       index += jump;
+
+                       coIx &= 0x00FFFFFF;
+
+                       *dst = *(srcBegin + coIx);
+               }
+
+               delete[] pCoIndex;
+
+               return true;
+       }
+
+       return false;
 }
 
 }} // Tizen::Graphics
index d7b174c..262080e 100644 (file)
@@ -25,7 +25,9 @@
 #define _FGRP_INTERNAL_FONT_BIDI_UTIL_H_
 
 #include <fribidi.h>
+#include <glib.h>
 
+#include "util/FGrp_UtilTemplate.h"
 
 namespace Tizen { namespace Graphics
 {
@@ -59,6 +61,20 @@ struct _TextBidiPropertyWithReorder
        _TextBidiPropertyWithReorder(const wchar_t* pText, int length);
        _TextBidiPropertyWithReorder(const _TextBidiProperty& refBidiProperty, int offset, int length);
        virtual ~_TextBidiPropertyWithReorder(void);
+
+       const wchar_t* GetReorderedText(void);
+
+private:
+       wchar_t* __pReorderedText;
+};
+
+struct _TextBidiUtil
+{
+       static GUnicodeScript GetUnicodeScript(const wchar_t unicode);
+
+       static bool IsCollationElement(const wchar_t first, const wchar_t second);
+
+       static bool GetReorderedIndexList(const _TextBidiPropertyWithReorder& refBidiProperty, const _Util::AccumList<_Util::Pair<int, int> >& inputList, _Util::AccumList<_Util::Pair<int, int> >& outList);
 };
 
 }} // Tizen::Graphics