| | 106 | |
| | 107 | dimension_t character_dimensions(const unsigned c) |
| | 108 | { |
| | 109 | FT_Matrix matrix; |
| | 110 | FT_Vector pen; |
| | 111 | FT_Error error; |
| | 112 | |
| | 113 | FT_GlyphSlot slot = face_->glyph; |
| | 114 | |
| | 115 | pen.x = 0; |
| | 116 | pen.y = 0; |
| | 117 | |
| | 118 | FT_BBox glyph_bbox; |
| | 119 | FT_Glyph image; |
| | 120 | |
| | 121 | matrix.xx = (FT_Fixed)( 1 * 0x10000L ); |
| | 122 | matrix.xy = (FT_Fixed)( 0 * 0x10000L ); |
| | 123 | matrix.yx = (FT_Fixed)( 0 * 0x10000L ); |
| | 124 | matrix.yy = (FT_Fixed)( 1 * 0x10000L ); |
| | 125 | |
| | 126 | FT_Set_Transform (face_,&matrix,&pen); |
| | 127 | |
| | 128 | FT_UInt glyph_index = FT_Get_Char_Index( face_, c); |
| | 129 | |
| | 130 | error = FT_Load_Glyph (face_,glyph_index,FT_LOAD_NO_HINTING); |
| | 131 | if ( error ) |
| | 132 | return dimension_t(0, 0); |
| | 133 | |
| | 134 | error = FT_Get_Glyph( face_->glyph, &image); |
| | 135 | if ( error ) |
| | 136 | return dimension_t(0, 0); |
| | 137 | |
| | 138 | FT_Glyph_Get_CBox(image,ft_glyph_bbox_pixels, &glyph_bbox); |
| | 139 | FT_Done_Glyph(image); |
| | 140 | return dimension_t(slot->advance.x >> 6, glyph_bbox.yMax - glyph_bbox.yMin); |
| | 141 | } |
| | 143 | void get_string_info(string_info & info) |
| | 144 | { |
| | 145 | unsigned width = 0; |
| | 146 | unsigned height = 0; |
| | 147 | UErrorCode err = U_ZERO_ERROR; |
| | 148 | UnicodeString const& ustr = info.get_string(); |
| | 149 | const UChar * text = ustr.getBuffer(); |
| | 150 | UBiDi * bidi = ubidi_openSized(ustr.length(),0,&err); |
| | 151 | |
| | 152 | if (U_SUCCESS(err)) |
| | 153 | { |
| | 154 | ubidi_setPara(bidi,text,ustr.length(), UBIDI_DEFAULT_LTR,0,&err); |
| | 155 | |
| | 156 | if (U_SUCCESS(err)) |
| | 157 | { |
| | 158 | int32_t count = ubidi_countRuns(bidi,&err); |
| | 159 | int32_t logicalStart; |
| | 160 | int32_t length; |
| | 161 | |
| | 162 | for (int32_t i=0; i< count;++i) |
| | 163 | { |
| | 164 | if (UBIDI_LTR == ubidi_getVisualRun(bidi,i,&logicalStart,&length)) |
| | 165 | { |
| | 166 | do { |
| | 167 | UChar ch = text[logicalStart++]; |
| | 168 | dimension_t char_dim = character_dimensions(ch); |
| | 169 | info.add_info(ch, char_dim.first, char_dim.second); |
| | 170 | width += char_dim.first; |
| | 171 | height = char_dim.second > height ? char_dim.second : height; |
| | 172 | |
| | 173 | } while (--length > 0); |
| | 174 | } |
| | 175 | else |
| | 176 | { |
| | 177 | logicalStart += length; |
| | 178 | |
| | 179 | int32_t j=0,i=length; |
| | 180 | UnicodeString arabic; |
| | 181 | UChar * buf = arabic.getBuffer(length); |
| | 182 | do { |
| | 183 | UChar ch = text[--logicalStart]; |
| | 184 | buf[j++] = ch; |
| | 185 | } while (--i > 0); |
| | 186 | |
| | 187 | arabic.releaseBuffer(length); |
| | 188 | if ( *arabic.getBuffer() >= 0x0600 && *arabic.getBuffer() <= 0x06ff) |
| | 189 | { |
| | 190 | |
| | 191 | UnicodeString shaped; |
| | 192 | u_shapeArabic(arabic.getBuffer(),arabic.length(),shaped.getBuffer(arabic.length()),arabic.length(), |
| | 193 | U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR| |
| | 194 | U_SHAPE_TEXT_DIRECTION_VISUAL_LTR |
| | 195 | ,&err); |
| | 196 | |
| | 197 | shaped.releaseBuffer(arabic.length()); |
| | 198 | |
| | 199 | if (U_SUCCESS(err)) |
| | 200 | { |
| | 201 | for (int j=0;j<shaped.length();++j) |
| | 202 | { |
| | 203 | dimension_t char_dim = character_dimensions(shaped[j]); |
| | 204 | info.add_info(shaped[j], char_dim.first, char_dim.second); |
| | 205 | width += char_dim.first; |
| | 206 | height = char_dim.second > height ? char_dim.second : height; |
| | 207 | } |
| | 208 | } |
| | 209 | } |
| | 210 | } |
| | 211 | } |
| | 212 | } |
| | 213 | ubidi_close(bidi); |
| | 214 | } |
| | 215 | |
| | 216 | info.set_dimensions(width, height); |
| | 217 | } |
| 281 | | |
| 282 | | dimension_t character_dimensions(const unsigned c) |
| 283 | | { |
| 284 | | FT_Matrix matrix; |
| 285 | | FT_Vector pen; |
| 286 | | FT_Error error; |
| 287 | | |
| 288 | | FT_Face face = face_->get_face(); |
| 289 | | FT_GlyphSlot slot = face->glyph; |
| 290 | | |
| 291 | | pen.x = 0; |
| 292 | | pen.y = 0; |
| 293 | | |
| 294 | | FT_BBox glyph_bbox; |
| 295 | | FT_Glyph image; |
| 296 | | |
| 297 | | matrix.xx = (FT_Fixed)( 1 * 0x10000L ); |
| 298 | | matrix.xy = (FT_Fixed)( 0 * 0x10000L ); |
| 299 | | matrix.yx = (FT_Fixed)( 0 * 0x10000L ); |
| 300 | | matrix.yy = (FT_Fixed)( 1 * 0x10000L ); |
| 301 | | |
| 302 | | FT_Set_Transform (face,&matrix,&pen); |
| 303 | | |
| 304 | | FT_UInt glyph_index = FT_Get_Char_Index( face, c); |
| 305 | | |
| 306 | | error = FT_Load_Glyph (face,glyph_index,FT_LOAD_NO_HINTING); |
| 307 | | if ( error ) |
| 308 | | return dimension_t(0, 0); |
| 309 | | |
| 310 | | error = FT_Get_Glyph( face->glyph, &image); |
| 311 | | if ( error ) |
| 312 | | return dimension_t(0, 0); |
| 313 | | |
| 314 | | FT_Glyph_Get_CBox(image,ft_glyph_bbox_pixels, &glyph_bbox); |
| 315 | | FT_Done_Glyph(image); |
| 316 | | return dimension_t(slot->advance.x >> 6, glyph_bbox.yMax - glyph_bbox.yMin); |
| 317 | | } |
| 319 | | void get_string_info(string_info & info) |
| 320 | | { |
| 321 | | unsigned width = 0; |
| 322 | | unsigned height = 0; |
| 323 | | UErrorCode err = U_ZERO_ERROR; |
| 324 | | UnicodeString const& ustr = info.get_string(); |
| 325 | | const UChar * text = ustr.getBuffer(); |
| 326 | | UBiDi * bidi = ubidi_openSized(ustr.length(),0,&err); |
| 327 | | |
| 328 | | if (U_SUCCESS(err)) |
| 329 | | { |
| 330 | | ubidi_setPara(bidi,text,ustr.length(), UBIDI_DEFAULT_LTR,0,&err); |
| 331 | | |
| 332 | | if (U_SUCCESS(err)) |
| 333 | | { |
| 334 | | int32_t count = ubidi_countRuns(bidi,&err); |
| 335 | | int32_t logicalStart; |
| 336 | | int32_t length; |
| 337 | | |
| 338 | | for (int32_t i=0; i< count;++i) |
| 339 | | { |
| 340 | | if (UBIDI_LTR == ubidi_getVisualRun(bidi,i,&logicalStart,&length)) |
| 341 | | { |
| 342 | | do { |
| 343 | | UChar ch = text[logicalStart++]; |
| 344 | | dimension_t char_dim = character_dimensions(ch); |
| 345 | | info.add_info(ch, char_dim.first, char_dim.second); |
| 346 | | width += char_dim.first; |
| 347 | | height = char_dim.second > height ? char_dim.second : height; |
| 348 | | |
| 349 | | } while (--length > 0); |
| 350 | | } |
| 351 | | else |
| 352 | | { |
| 353 | | logicalStart += length; |
| 354 | | |
| 355 | | int32_t j=0,i=length; |
| 356 | | UnicodeString arabic; |
| 357 | | UChar * buf = arabic.getBuffer(length); |
| 358 | | do { |
| 359 | | UChar ch = text[--logicalStart]; |
| 360 | | buf[j++] = ch; |
| 361 | | } while (--i > 0); |
| 362 | | |
| 363 | | arabic.releaseBuffer(length); |
| 364 | | if ( *arabic.getBuffer() >= 0x0600 && *arabic.getBuffer() <= 0x06ff) |
| 365 | | { |
| 366 | | |
| 367 | | UnicodeString shaped; |
| 368 | | u_shapeArabic(arabic.getBuffer(),arabic.length(),shaped.getBuffer(arabic.length()),arabic.length(), |
| 369 | | U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR| |
| 370 | | U_SHAPE_TEXT_DIRECTION_VISUAL_LTR |
| 371 | | ,&err); |
| 372 | | |
| 373 | | shaped.releaseBuffer(arabic.length()); |
| 374 | | |
| 375 | | if (U_SUCCESS(err)) |
| 376 | | { |
| 377 | | for (int j=0;j<shaped.length();++j) |
| 378 | | { |
| 379 | | dimension_t char_dim = character_dimensions(shaped[j]); |
| 380 | | info.add_info(shaped[j], char_dim.first, char_dim.second); |
| 381 | | width += char_dim.first; |
| 382 | | height = char_dim.second > height ? char_dim.second : height; |
| 383 | | } |
| 384 | | } |
| 385 | | } |
| 386 | | } |
| 387 | | } |
| 388 | | } |
| 389 | | ubidi_close(bidi); |
| 390 | | } |
| 391 | | |
| 392 | | info.set_dimensions(width, height); |
| 393 | | } |
| 394 | | |