2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
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
9 // http://floralicense.org/license/
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_FontBidiManager.cpp
20 * @brief This is the cpp file for _FontMemoryManager class.
30 #include "FGrp_FontBidiManager.h"
34 typedef wchar_t Eina_Unicode;
36 typedef FriBidiCharType EvasBiDiCharType;
37 typedef FriBidiLevel EvasBiDiLevel;
38 typedef FriBidiParType EvasBiDiParType;
40 #define EVAS_BIDI_PARAGRAPH_NEUTRAL FRIBIDI_PAR_ON
41 #define EVAS_BIDI_PARAGRAPH_LTR FRIBIDI_PAR_LTR
42 #define EVAS_BIDI_PARAGRAPH_RTL FRIBIDI_PAR_RTL
43 #define EVAS_BIDI_PARAGRAPH_WLTR FRIBIDI_PAR_WLTR
44 #define EVAS_BIDI_PARAGRAPH_WRTL FRIBIDI_PAR_WRTL
46 #define EVAS_BIDI_PARAGRAPH_DIRECTION_IS_RTL(x) \
48 ((x->direction == EVAS_BIDI_PARAGRAPH_RTL) || \
49 (x->direction == EVAS_BIDI_PARAGRAPH_WRTL))) ? \
50 EINA_TRUE : EINA_FALSE)
52 typedef struct _Evas_BiDi_Paragraph_Props {
53 EvasBiDiCharType *char_types; /* BiDi char types */
54 EvasBiDiLevel *embedding_levels; /* BiDi embedding levels */
55 int refcount; /* The number of references to this object */
56 EvasBiDiParType direction;
57 } Evas_BiDi_Paragraph_Props;
59 ////////////////////////////////////////////////////////////////////////////////
61 typedef int Eina_Bool;
69 #define _SAFE_FREE(x) \
79 evas_bidi_is_rtl_str(const Eina_Unicode *str)
81 EvasBiDiCharType type;
88 type = fribidi_get_bidi_type((FriBidiChar) *str);
89 if (FRIBIDI_IS_LETTER(type) && FRIBIDI_IS_RTL(type))
98 eina_unicode_strlen(const Eina_Unicode *str)
102 const Eina_Unicode* pEnd = str;
107 return (pEnd - str - 1);
116 evas_bidi_paragraph_props_clean(Evas_BiDi_Paragraph_Props *bidi_props)
118 _SAFE_FREE(bidi_props->embedding_levels);
119 _SAFE_FREE(bidi_props->char_types);
122 Evas_BiDi_Paragraph_Props *
123 evas_bidi_paragraph_props_new(void)
125 Evas_BiDi_Paragraph_Props *ret;
126 ret = (Evas_BiDi_Paragraph_Props *)calloc(1, sizeof(Evas_BiDi_Paragraph_Props));
127 ret->direction = EVAS_BIDI_PARAGRAPH_NEUTRAL;
134 evas_bidi_paragraph_props_unref(Evas_BiDi_Paragraph_Props *bidi_props)
136 if (!bidi_props) return;
139 if (--bidi_props->refcount == 0)
141 evas_bidi_paragraph_props_clean(bidi_props);
149 Evas_BiDi_Paragraph_Props *
150 evas_bidi_paragraph_props_get(const Eina_Unicode *eina_ustr, size_t len, int *segment_idxs)
152 Evas_BiDi_Paragraph_Props *bidi_props = NULL;
153 EvasBiDiCharType *char_types = NULL;
154 EvasBiDiLevel *embedding_levels = NULL;
155 const FriBidiChar *ustr;
156 FriBidiChar *base_ustr = NULL;
162 if (!evas_bidi_is_rtl_str(eina_ustr)) /* No need to handle bidi */
168 len = eina_unicode_strlen(eina_ustr);
169 /* The size of fribidichar s different than eina_unicode, convert */
170 #ifdef EVAS_FRIBIDI_EINA_UNICODE_UNEQUAL
171 base_ustr = calloc(len + 1, sizeof(FriBidiChar));
172 base_ustr = _evas_bidi_unicode_to_fribidichar(base_ustr, eina_ustr);
175 ustr = (const FriBidiChar *) eina_ustr;
178 bidi_props = evas_bidi_paragraph_props_new();
180 /* Prep work for reordering */
181 char_types = (EvasBiDiCharType *) malloc(sizeof(EvasBiDiCharType) * len);
187 fribidi_get_bidi_types(ustr, len, char_types);
189 embedding_levels = (EvasBiDiLevel *)malloc(sizeof(EvasBiDiLevel) * len);
190 if (!embedding_levels)
200 EvasBiDiLevel base_level = 0;
201 EvasBiDiParType direction;
203 for (itr = segment_idxs ; *itr > 0 ; itr++)
205 direction = EVAS_BIDI_PARAGRAPH_NEUTRAL;
206 if (!fribidi_get_par_embedding_levels(char_types + pos,
209 embedding_levels + pos))
215 /* Only on the first run */
216 if (itr == segment_idxs)
218 bidi_props->direction = direction;
219 /* adjust base_level to be 1 for rtl paragraphs, and 0 for
222 EVAS_BIDI_PARAGRAPH_DIRECTION_IS_RTL(bidi_props) ? 1 : 0;
225 /* We want those chars at the override points to be on the base
226 * level and we also remove -2 cause we later increment them,
227 * just for simpler code paths */
228 embedding_levels[*itr] = base_level - 2;
232 direction = EVAS_BIDI_PARAGRAPH_NEUTRAL;
233 if (!fribidi_get_par_embedding_levels(char_types + pos,
236 embedding_levels + pos))
242 /* Increment all levels by 2 to emulate embedding. */
244 EvasBiDiLevel *bitr = embedding_levels, *end;
246 for ( ; bitr < end ; bitr++)
254 if (!fribidi_get_par_embedding_levels(char_types, len,
255 &bidi_props->direction, embedding_levels))
264 if (bidi_props->embedding_levels)
266 free(bidi_props->embedding_levels);
268 bidi_props->embedding_levels = embedding_levels;
272 if (bidi_props->char_types)
274 free(bidi_props->char_types);
276 bidi_props->char_types = char_types;
278 if (base_ustr) free(base_ustr);
285 if (char_types) free(char_types);
286 if (embedding_levels) free(embedding_levels);
287 if (base_ustr) free(base_ustr);
288 if (bidi_props) evas_bidi_paragraph_props_unref(bidi_props); /* Clean up the bidi props */
298 typedef int EvasBiDiStrIndex;
301 evas_bidi_props_reorder_line(Eina_Unicode *eina_ustr, size_t start, size_t len, const Evas_BiDi_Paragraph_Props *props, EvasBiDiStrIndex **_v_to_l)
303 EvasBiDiStrIndex *v_to_l = NULL;
304 FriBidiChar *ustr = NULL, *base_ustr = NULL;
311 /* The size of fribidichar is different than eina_unicode, convert */
312 #ifdef EVAS_FRIBIDI_EINA_UNICODE_UNEQUAL
313 base_ustr = ustr = calloc(len + 1, sizeof(FriBidiChar));
314 ustr = _evas_bidi_unicode_to_fribidichar(ustr, eina_ustr);
316 ustr = (FriBidiChar *) eina_ustr;
323 v_to_l = *_v_to_l = (EvasBiDiStrIndex *) calloc(len, sizeof(EvasBiDiStrIndex));
328 /* init the array for fribidi */
329 for (i = 0 ; i < len ; i++)
336 EvasBiDiLevel *emb_lvl;
337 emb_lvl = (EvasBiDiLevel *) malloc((start + len) * sizeof(EvasBiDiLevel));
338 memcpy(emb_lvl, props->embedding_levels,
339 (start + len) * sizeof(EvasBiDiLevel));
340 /* We pass v_to_l - start, because fribidi assumes start is the offset
341 * from the start of v_to_l as well, not just the props. */
342 if (!fribidi_reorder_line (FRIBIDI_FLAGS_DEFAULT, props->char_types,
343 len, start, props->direction, emb_lvl, ustr, v_to_l - start))
352 /* The size of fribidichar is different than eina_unicode, convert */
353 #ifdef EVAS_FRIBIDI_EINA_UNICODE_UNEQUAL
354 _evas_bidi_fribidichar_to_unicode(eina_ustr, base_ustr);
360 if (base_ustr) free(base_ustr);
367 ////////////////////////////////////////////////////////////////////////////////
369 namespace Tizen { namespace Graphics
372 _FontBidiProps::_FontBidiProps(const wchar_t* pText, int length)
375 , pEmbeddingLevels(0)
376 , baseDirection(FRIBIDI_PAR_ON)
379 Evas_BiDi_Paragraph_Props* pEvasBidiProps = evas_bidi_paragraph_props_get(pText, length, 0);
383 this->pEventText = (FriBidiChar *)pText;
384 this->pCharType = pEvasBidiProps->char_types;
385 this->pEmbeddingLevels = pEvasBidiProps->embedding_levels;
386 this->baseDirection = pEvasBidiProps->direction;
389 evas_bidi_paragraph_props_unref(pEvasBidiProps);
393 }} // Tizen::Graphics