2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0/
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.
19 * @file FGrp_FontBidiUtil.cpp
20 * @brief This is the cpp file for the bidi utilities.
26 #include <unique_ptr.h>
29 #include "FGrp_FontBidiUtil.h"
38 FriBidiCharType* pCharTypes;
39 FriBidiLevel* pEmbeddingLevels;
40 FriBidiParType direction;
43 BidiParagraph(size_t length)
44 : pString(new (std::nothrow) wchar_t[length + 1])
45 , pCharTypes(new (std::nothrow) FriBidiCharType[length])
46 , pEmbeddingLevels(new (std::nothrow) FriBidiLevel[length])
47 , direction(FRIBIDI_PAR_LTR)//FRIBIDI_PAR_ON)
48 , bufferLength(length)
50 if (pString == NULL || pCharTypes == NULL || pEmbeddingLevels == NULL)
53 delete[] pEmbeddingLevels;
57 pEmbeddingLevels = NULL;
66 delete[] pEmbeddingLevels;
72 return (pString != NULL && pCharTypes != NULL && pEmbeddingLevels != NULL);
76 #define IS_DIRECTION_RTL(x) (((x->direction == FRIBIDI_PAR_RTL) || (x->direction == FRIBIDI_PAR_WRTL)) ? true : false)
78 ////////////////////////////////////////////////////////////////////////////////
81 _IsRtl(const wchar_t* pString, int length)
85 for ( ; *pString && length-- > 0 ; ++pString)
87 FriBidiCharType type = fribidi_get_bidi_type((FriBidiChar) *pString);
89 GUnicodeScript script = g_unichar_get_script(*pString);
91 if (FRIBIDI_IS_LETTER(type) && FRIBIDI_IS_RTL(type))
95 else if (script == G_UNICODE_SCRIPT_DEVANAGARI || script == G_UNICODE_SCRIPT_BENGALI)
106 _GetStringLength(const wchar_t* pString)
110 const wchar_t* pEnd = pString;
115 return (pEnd - pString - 1);
123 template <typename DstCode, typename SrcCode>
125 _ConvertCharacterCode(DstCode* pDst, const SrcCode* pSrc, int length)
129 while (*pSrc && length-- > 0)
141 _GetBidiParagraphProperty(const wchar_t* pText, size_t len, int* pSegmentIndex, Tizen::Graphics::_TextBidiProperty::BidiHint hint)
143 #define CHECK_IF(cond) if (!(cond)) return NULL
145 // precondition check
147 CHECK_IF((pText) && _IsRtl(pText, len));
149 size_t textLength = _GetStringLength(pText);
150 len = (len < textLength) ? len : textLength;
153 const FriBidiChar* pTestString = NULL;
154 std::unique_ptr<FriBidiChar[]> AutoDeleteString;
155 std::unique_ptr<BidiParagraph> bidiProperty(new (std::nothrow) BidiParagraph(len));
158 CHECK_IF(bidiProperty.get() && bidiProperty->IsValid());
160 // in case of different size of each wide character
161 if (sizeof(wchar_t) == sizeof(FriBidiChar))
163 pTestString = (const FriBidiChar *) pText;
167 AutoDeleteString.reset(new (std::nothrow) FriBidiChar[len + 1]);
169 CHECK_IF(AutoDeleteString.get());
171 _ConvertCharacterCode<FriBidiChar, wchar_t>(AutoDeleteString.get(), pText, len);
173 pTestString = AutoDeleteString.get();
177 * 0x110 FRIBIDI_TYPE_LTR;
178 * 0x111 FRIBIDI_TYPE_RTL;
179 * 0x113 FRIBIDI_TYPE_AL;
180 * 0x220 FRIBIDI_TYPE_EN;
183 fribidi_get_bidi_types(pTestString, len, bidiProperty->pCharTypes);
188 FriBidiLevel baseLevel = 0;
190 for (int* itr = pSegmentIndex ; *itr > 0 ; itr++)
192 FriBidiParType direction = FRIBIDI_PAR_ON;
193 CHECK_IF(fribidi_get_par_embedding_levels(bidiProperty->pCharTypes + pos, *itr - pos, &direction, bidiProperty->pEmbeddingLevels + pos));
195 // Only on the first run
196 if (itr == pSegmentIndex)
198 bidiProperty->direction = direction;
199 // adjust baseLevel to be 1 for rtl paragraphs, and 0 for ltr paragraphs.
200 baseLevel = IS_DIRECTION_RTL(bidiProperty) ? 1 : 0;
203 // We want those chars at the override points to be on the base
204 // level and we also remove -2 cause we later increment them,
205 // just for simpler code paths
206 bidiProperty->pEmbeddingLevels[*itr] = baseLevel - 2;
211 FriBidiParType direction = FRIBIDI_PAR_ON;
212 CHECK_IF(fribidi_get_par_embedding_levels(bidiProperty->pCharTypes + pos, len - pos, &direction, bidiProperty->pEmbeddingLevels + pos));
215 // Increment all levels by 2 to emulate embedding.
217 FriBidiLevel* pEmbeddingLevel = bidiProperty->pEmbeddingLevels;
218 FriBidiLevel* pEmbeddingLevelEnd = pEmbeddingLevel + len;
220 for ( ; pEmbeddingLevel < pEmbeddingLevelEnd ; ++pEmbeddingLevel)
222 *pEmbeddingLevel += 2;
228 FriBidiParType direction = FRIBIDI_PAR_ON;
230 if ((Tizen::Graphics::_TextBidiUtil::IsTextBidiBaseLtr()))
234 case Tizen::Graphics::_TextBidiProperty::BIDI_HINT_LTR:
235 direction = FRIBIDI_PAR_LTR;
237 case Tizen::Graphics::_TextBidiProperty::BIDI_HINT_RTL:
238 direction = FRIBIDI_PAR_RTL;
241 for (size_t i = 0; i < len; i++)
243 if (FRIBIDI_IS_STRONG(bidiProperty->pCharTypes[i]))
245 if (FRIBIDI_IS_RTL(bidiProperty->pCharTypes[i]))
247 direction = FRIBIDI_PAR_RTL;
251 direction = FRIBIDI_PAR_LTR;
264 case Tizen::Graphics::_TextBidiProperty::BIDI_HINT_LTR:
265 direction = FRIBIDI_PAR_RTL;
267 case Tizen::Graphics::_TextBidiProperty::BIDI_HINT_RTL:
268 direction = FRIBIDI_PAR_LTR;
271 for (size_t i = 0; i < len; i++)
273 if (FRIBIDI_IS_STRONG(bidiProperty->pCharTypes[i]))
275 if (FRIBIDI_IS_RTL(bidiProperty->pCharTypes[i]))
277 direction = FRIBIDI_PAR_LTR;
281 direction = FRIBIDI_PAR_RTL;
291 bidiProperty->direction = direction;
293 CHECK_IF(fribidi_get_par_embedding_levels(bidiProperty->pCharTypes, len, &bidiProperty->direction, bidiProperty->pEmbeddingLevels));
296 return bidiProperty.release();
302 _GetBidiShapeString(BidiParagraph* pBidiProps)
304 #define CHECK_IF(cond) if (!(cond)) return 0
306 FriBidiChar* pTestString = NULL;
307 std::unique_ptr<FriBidiChar[]> autoDeleteString;
309 const size_t textLength = pBidiProps->bufferLength;
311 if (pBidiProps->pString)
313 if (sizeof(wchar_t) == sizeof(FriBidiChar))
315 pTestString = (FriBidiChar *) pBidiProps->pString;
319 autoDeleteString.reset(new (std::nothrow) FriBidiChar[textLength + 1]);
321 CHECK_IF(autoDeleteString.get());
323 _ConvertCharacterCode<FriBidiChar, wchar_t>(autoDeleteString.get(), pBidiProps->pString, pBidiProps->bufferLength);
325 pTestString = autoDeleteString.get();
328 std::unique_ptr<FriBidiJoiningType[]> pJoinTypes(new (std::nothrow) FriBidiJoiningType[textLength]);
330 if (!pJoinTypes.get())
332 return pBidiProps->pString;
335 fribidi_get_joining_types(pTestString, textLength, pJoinTypes.get());
337 fribidi_join_arabic(pBidiProps->pCharTypes, textLength, pBidiProps->pEmbeddingLevels, pJoinTypes.get());
339 fribidi_shape(FRIBIDI_FLAGS_DEFAULT | FRIBIDI_FLAGS_ARABIC, pBidiProps->pEmbeddingLevels, textLength, pJoinTypes.get(), pTestString);
341 if (sizeof(wchar_t) == sizeof(FriBidiChar))
343 pBidiProps->pString = (wchar_t *) pTestString;
347 _ConvertCharacterCode<wchar_t, FriBidiChar>(pBidiProps->pString, pTestString, textLength);
351 return pBidiProps->pString;
361 * Reorders ustr according to the bidi props.
363 * @param pText the string to reorder. - Null is ok, will just populate the map.
364 * @param start the start of the line
365 * @param len the length of the line
366 * @param bidiProperty the paragraph props to reorder according to
367 * @param pOutVToL The visual to logical map to populate - if NULL it won't populate it.
370 _ReorderBidiLine(wchar_t* pText, size_t start, size_t len, const BidiParagraph& bidiProperty, FriBidiStrIndex** pOutVToL)
372 #define CHECK_IF(cond) if (!(cond)) return false
374 FriBidiChar* pTestString = NULL;
375 std::unique_ptr<FriBidiChar[]> AutoDeleteString;
376 std::unique_ptr<FriBidiStrIndex[]> vToL;
378 const size_t textLength = len;
382 if (sizeof(wchar_t) == sizeof(FriBidiChar))
384 pTestString = (FriBidiChar *) pText;
388 AutoDeleteString.reset(new (std::nothrow) FriBidiChar[textLength + 1]);
390 CHECK_IF(AutoDeleteString.get());
392 _ConvertCharacterCode<FriBidiChar, wchar_t>(AutoDeleteString.get(), pText, textLength);
394 pTestString = AutoDeleteString.get();
400 vToL.reset(new (std::nothrow) FriBidiStrIndex[textLength]);
402 CHECK_IF(vToL.get());
404 // init the array for fribidi
406 FriBidiStrIndex* pRefIndex = vToL.get();
408 for (size_t i = 0 ; i < textLength ; i++)
416 std::unique_ptr<FriBidiLevel[]> embeddingLevel(new (std::nothrow) FriBidiLevel[start + textLength]);
417 FriBidiLevel* pRefEmbeddingLevel = embeddingLevel.get();
419 CHECK_IF(pRefEmbeddingLevel);
421 memcpy(pRefEmbeddingLevel, bidiProperty.pEmbeddingLevels, (start + textLength) * sizeof(FriBidiLevel));
425 // We pass vToL.get() - start, because fribidi assumes start is the offset from the start of vToL.get() as well, not just the props.
426 CHECK_IF(fribidi_reorder_line(FRIBIDI_FLAGS_DEFAULT, bidiProperty.pCharTypes, textLength, start, bidiProperty.direction, pRefEmbeddingLevel, pTestString, vToL.get() - start));
430 CHECK_IF(fribidi_reorder_line(FRIBIDI_FLAGS_DEFAULT, bidiProperty.pCharTypes, textLength, start, bidiProperty.direction, pRefEmbeddingLevel, pTestString, NULL));
436 if (sizeof(wchar_t) != sizeof(FriBidiChar))
438 _ConvertCharacterCode<wchar_t, FriBidiChar>(pText, AutoDeleteString.get(), textLength);
444 *pOutVToL = vToL.release();
454 ////////////////////////////////////////////////////////////////////////////////
456 namespace Tizen { namespace Graphics
459 _TextBidiProperty::_TextBidiProperty(const wchar_t* pText, int length, BidiHint hint)
462 , pEmbeddingLevels(0)
464 , baseDirection(FRIBIDI_PAR_ON)
469 BidiParagraph* pBidiProperty = _GetBidiParagraphProperty(pText, length, NULL, hint);
474 this->pEventText = NULL;
476 memcpy(pBidiProperty->pString, pText, length * sizeof(wchar_t));
477 pBidiProperty->pString[length] = 0;
479 this->pEventText = _GetBidiShapeString(pBidiProperty);
481 this->pCharType = pBidiProperty->pCharTypes;
482 this->pEmbeddingLevels = pBidiProperty->pEmbeddingLevels;
483 this->eventChar = (this->pEventText) ? *this->pEventText : 0;
484 this->baseDirection = pBidiProperty->direction;
485 this->isRtl = (this->pCharType) ? ((*this->pCharType & FRIBIDI_MASK_RTL) != 0) : false;
486 this->length = length;
488 this->pReserved = static_cast<void*>(pBidiProperty);
492 this->pEventText = pText;
493 this->eventChar = (this->pEventText) ? *this->pEventText : 0;
494 this->length = length;
498 _TextBidiProperty::_TextBidiProperty(const _TextBidiProperty& refBidiProperty, int offset, int length)
501 , pEmbeddingLevels(0)
503 , baseDirection(FRIBIDI_PAR_ON)
508 const wchar_t* pBegin = refBidiProperty.pEventText + offset;
509 const wchar_t* pEnd = pBegin + length;
511 pBegin = (pBegin > refBidiProperty.pEventText) ? pBegin : refBidiProperty.pEventText;
512 pEnd = (refBidiProperty.pEventText + refBidiProperty.length < pEnd) ? refBidiProperty.pEventText + refBidiProperty.length : pEnd;
516 offset = pBegin - refBidiProperty.pEventText;
517 length = pEnd - pBegin;
519 this->pEventText = refBidiProperty.pEventText + offset;
520 this->pCharType = refBidiProperty.pCharType + offset;
521 this->pEmbeddingLevels = refBidiProperty.pEmbeddingLevels + offset;
522 this->eventChar = (this->pEventText) ? *this->pEventText : 0;
523 this->baseDirection = refBidiProperty.baseDirection;
524 this->isRtl = (this->pEmbeddingLevels) ? ((*this->pEmbeddingLevels & 0x01) != 0) : false;
525 this->length = length;
530 const FriBidiCharType* pBegin = this->pCharType;
531 const FriBidiCharType* pEnd = pBegin + length;
533 while (pBegin < pEnd)
535 if (*pBegin & FRIBIDI_MASK_LETTER)
537 this->eventChar = *(this->pEventText + (pBegin - this->pCharType));
547 _TextBidiProperty::~_TextBidiProperty(void)
551 delete static_cast<BidiParagraph*>(pReserved);
556 _TextBidiProperty::HasComplexText(void) const
558 return ((pReserved != 0) || (!_TextBidiUtil::IsTextBidiBaseLtr()));
561 _TextBidiPropertyWithReorder::_TextBidiPropertyWithReorder(const wchar_t* pText, int length, BidiHint hint)
562 : _TextBidiProperty(pText, length, hint)
564 , __pReorderedText(0)
566 BidiParagraph* pBidiProperty = static_cast<BidiParagraph*>(this->pReserved);
570 FriBidiStrIndex* pTempIndex = 0;
572 if (_ReorderBidiLine(NULL, 0, length, *pBidiProperty, &pTempIndex))
574 pBidiIndex = pTempIndex;
579 _TextBidiPropertyWithReorder::_TextBidiPropertyWithReorder(const _TextBidiProperty& refBidiProperty, int offset, int length)
580 : _TextBidiProperty(refBidiProperty, offset, length)
582 , __pReorderedText(0)
587 _TextBidiPropertyWithReorder::GetReorderedText(void)
589 if ((__pReorderedText == NULL) && (pEventText != NULL) && (pBidiIndex != NULL))
591 __pReorderedText = new (std::nothrow) wchar_t[length + 1];
593 if (__pReorderedText)
595 wchar_t* pTempText = __pReorderedText;
596 const wchar_t* pTempTextEnd = pTempText + length;
597 const FriBidiStrIndex* pTempBidiIndex = pBidiIndex;
599 while (pTempText < pTempTextEnd)
601 *pTempText++ = pEventText[*pTempBidiIndex++];
607 return __pReorderedText;
615 _TextBidiPropertyWithReorder::~_TextBidiPropertyWithReorder(void)
618 delete[] __pReorderedText;
622 _TextBidiUtil::GetUnicodeScript(const wchar_t unicode)
624 static const struct MatchingTable
628 GUnicodeScript script;
631 { 0x0600, 0x06ff, G_UNICODE_SCRIPT_ARABIC }
634 static const MatchingTable* pTableEnd = &MATCHING_TABLE[0] + sizeof(MATCHING_TABLE) / sizeof(MATCHING_TABLE[0]);
636 const MatchingTable* pTable = &MATCHING_TABLE[0] - 1;
638 while (++pTable < pTableEnd)
640 if ((pTable->min <= unicode) && (pTable->max >= unicode))
642 return pTable->script;
646 return g_unichar_get_script(unicode);
650 _TextBidiUtil::IsCollationElement(const wchar_t first, const wchar_t second)
652 static const struct MatchingTable
658 { 0x0644, 0x0622 }, // arabic letter
662 { 0x092F, 0x093C }, // Devanagari letter
673 { 0x09C7, 0x09BE }, // Bengali letter
678 { 0x0020, 0x064B }, // arabic sign
694 static const MatchingTable* pTableEnd = &MATCHING_TABLE[0] + sizeof(MATCHING_TABLE) / sizeof(MATCHING_TABLE[0]);
696 const MatchingTable* pTable = &MATCHING_TABLE[0] - 1;
698 while (++pTable < pTableEnd)
700 if ((pTable->first != first) || (pTable->second != second))
712 _TextBidiUtil::GetReorderedIndexList(const _TextBidiPropertyWithReorder& refBidiProperty, const _Util::AccumList<_Util::Pair<int, int> >& inputList, _Util::AccumList<_Util::Pair<int, int> >& outList)
714 if ((refBidiProperty.pEventText != NULL) && (refBidiProperty.pBidiIndex != NULL))
716 int length = refBidiProperty.length;
718 int* pCoIndex = new int[length];
722 for (int i = 0; i < refBidiProperty.length; i++, coIndex++)
724 if ((i + 1 < length) && IsCollationElement(refBidiProperty.pEventText[i], refBidiProperty.pEventText[i + 1]))
726 pCoIndex[i] = coIndex;
727 pCoIndex[++i] = (1 << 24) | coIndex;
731 pCoIndex[i] = coIndex;
735 typedef _Util::Pair<int, int> Gap;
736 typedef _Util::AccumList<Gap> GapList;
738 GapList::Iterator dstBegin = outList.Begin();
742 for (GapList::ConstIterator src = inputList.Begin(); src != inputList.End(); ++src)
750 int coIx = pCoIndex[refBidiProperty.pBidiIndex[index++]];
751 int jump = coIx >> 24;
757 *(dstBegin + coIx) = *src;
770 bool _isLtrBase = true;
774 _TextBidiUtil::SetTextBidiBase(bool isLtr)
780 _TextBidiUtil::IsTextBidiBaseLtr(void)
785 }} // Tizen::Graphics
788 ////////////////////////////////////////////////////////////////////////////////
794 namespace Tizen { namespace Graphics
797 _FontGlyphList::_FontGlyphList(const _Util::String& reorderedText, void* pFace, int script)
799 FT_Face face = FT_Face(pFace);
801 hb_font_t* hSubFont = NULL;
802 hb_buffer_t* hBuffer = NULL;
805 hb_font_t *hFont = hb_ft_font_create(face, NULL);
806 hSubFont = hb_font_create_sub_font(hFont);
807 hb_font_destroy (hFont);
810 hBuffer = hb_buffer_create();
811 hb_buffer_set_unicode_funcs(hBuffer, hb_unicode_funcs_get_default());
813 hb_buffer_set_script(hBuffer, hb_glib_script_to_script(GUnicodeScript(script)));
815 hb_buffer_set_direction(hBuffer, (_TextBidiUtil::IsTextBidiBaseLtr()) ? HB_DIRECTION_LTR : HB_DIRECTION_RTL);
817 int textLength = reorderedText.length;
819 if (sizeof(wchar_t) == sizeof(uint32_t))
821 hb_buffer_add_utf32(hBuffer, (const uint32_t*)reorderedText.pStart, textLength, 0, textLength);
825 uint32_t* pDst = new (std::nothrow) uint32_t[textLength + 1];
830 const wchar_t* pSrc = reorderedText.pStart;
832 uint32_t* pDstBegin = pDst;
833 uint32_t* pDstEnd = pDstBegin + textLength;
835 while (pDstBegin < pDstEnd)
837 *pDstBegin++ = *pSrc++;
843 hb_buffer_add_utf32(hBuffer, pDst, textLength, 0, textLength);
849 hb_shape(hSubFont, hBuffer, NULL, 0);
851 this->__glyphCount = hb_buffer_get_length(hBuffer);
853 if (int(this->__glyphCount) == textLength)
855 this->__pGlyphAuxInfo = new (std::nothrow) GlyphAuxInfo[this->__glyphCount];
857 if (this->__pGlyphAuxInfo)
859 hb_glyph_position_t* pPosition = hb_buffer_get_glyph_positions(hBuffer, NULL);
860 hb_glyph_info_t* pInfo = hb_buffer_get_glyph_infos(hBuffer, NULL);
862 GlyphAuxInfo* pAuxInfo = &this->__pGlyphAuxInfo[0];
863 GlyphAuxInfo* pAuxInfoEnd = pAuxInfo + this->__glyphCount;
865 while (pAuxInfo < pAuxInfoEnd)
867 pAuxInfo->isAvailable = true;
868 pAuxInfo->glyphIndex = pInfo->codepoint;
869 pAuxInfo->xOffset.Reset(pPosition->x_offset);
870 pAuxInfo->yOffset.Reset(pPosition->y_offset);
871 pAuxInfo->xAdvance.Reset(pPosition->x_advance);
872 pAuxInfo->yAdvance.Reset(pPosition->y_advance);
880 else if (int(this->__glyphCount) < textLength)
882 int tempCount = this->__glyphCount;
884 this->__glyphCount = textLength;
886 this->__pGlyphAuxInfo = new (std::nothrow) GlyphAuxInfo[textLength];
888 if (this->__pGlyphAuxInfo)
890 memset(static_cast<void*>(this->__pGlyphAuxInfo), 0, sizeof(GlyphAuxInfo) * this->__glyphCount);
892 hb_glyph_position_t* pPosition = hb_buffer_get_glyph_positions(hBuffer, NULL);
893 hb_glyph_info_t* pInfo = hb_buffer_get_glyph_infos(hBuffer, NULL);
895 GlyphAuxInfo* pAuxInfo = &this->__pGlyphAuxInfo[0];
896 GlyphAuxInfo* pAuxInfoEnd = pAuxInfo + textLength;
900 while (pAuxInfo < pAuxInfoEnd && textIndex < tempCount)
902 pAuxInfo->isAvailable = true;
903 pAuxInfo->glyphIndex = pInfo->codepoint;
904 pAuxInfo->xOffset.Reset(pPosition->x_offset);
905 pAuxInfo->yOffset.Reset(pPosition->y_offset);
906 pAuxInfo->xAdvance.Reset(pPosition->x_advance);
907 pAuxInfo->yAdvance.Reset(pPosition->y_advance);
909 bool isCollationElement = false;
911 if (script == G_UNICODE_SCRIPT_ARABIC)
913 isCollationElement = ((textIndex + 1 < textLength) && _TextBidiUtil::IsCollationElement(*(reorderedText.pStart + textIndex + 1), *(reorderedText.pStart + textIndex)));
917 isCollationElement = ((textIndex + 1 < textLength) && _TextBidiUtil::IsCollationElement(*(reorderedText.pStart + textIndex), *(reorderedText.pStart + textIndex + 1)));
920 if (isCollationElement)
925 pAuxInfo->isAvailable = false;
935 else if (int(this->__glyphCount) > textLength)
937 this->__pGlyphAuxInfo = new (std::nothrow) GlyphAuxInfo[this->__glyphCount];
939 if (this->__pGlyphAuxInfo)
941 memset(static_cast<void*>(this->__pGlyphAuxInfo), 0, sizeof(GlyphAuxInfo) * this->__glyphCount);
943 hb_glyph_position_t* pPosition = hb_buffer_get_glyph_positions(hBuffer, NULL);
944 hb_glyph_info_t* pInfo = hb_buffer_get_glyph_infos(hBuffer, NULL);
946 GlyphAuxInfo* pAuxInfo = &this->__pGlyphAuxInfo[0];
947 GlyphAuxInfo* pAuxInfoEnd = pAuxInfo + this->__glyphCount;
951 while (pAuxInfo < pAuxInfoEnd)
953 pAuxInfo->isAvailable = true;
954 pAuxInfo->glyphIndex = pInfo->codepoint;
955 pAuxInfo->xOffset.Reset(pPosition->x_offset);
956 pAuxInfo->yOffset.Reset(pPosition->y_offset);
957 pAuxInfo->xAdvance.Reset(pPosition->x_advance);
958 pAuxInfo->yAdvance.Reset(pPosition->y_advance);
960 bool isCollationElement = false;
962 if (script == G_UNICODE_SCRIPT_ARABIC)
964 isCollationElement = ((textIndex + 1 < textLength) && _TextBidiUtil::IsCollationElement(*(reorderedText.pStart + textIndex + 1), *(reorderedText.pStart + textIndex)));
968 isCollationElement = ((textIndex + 1 < textLength) && _TextBidiUtil::IsCollationElement(*(reorderedText.pStart + textIndex), *(reorderedText.pStart + textIndex + 1)));
971 if (isCollationElement)
975 pAuxInfo->isAvailable = false;
986 hb_buffer_destroy(hBuffer);
987 hb_font_destroy(hSubFont);
990 _FontGlyphList::~_FontGlyphList(void)
992 delete[] __pGlyphAuxInfo;
995 unsigned int _FontGlyphList::GetCount(void) const
1000 const _FontGlyphList::GlyphAuxInfo& _FontGlyphList::GetGlyphAuxInfo(unsigned int index) const
1002 static const GlyphAuxInfo nullInfo =
1004 false, 0, _Util::FixedPoint26_6(0), _Util::FixedPoint26_6(0), _Util::FixedPoint26_6(0), _Util::FixedPoint26_6(0)
1007 return (index < __glyphCount) ? __pGlyphAuxInfo[index] : nullInfo;
1010 }} // Tizen::Graphics