1 /***************************************************************************/ 2 /* */ 3 /* ftglyph.c */ 4 /* */ 5 /* FreeType convenience functions to handle glyphs (body). */ 6 /* */ 7 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2007, 2008, 2010 by */ 8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 9 /* */ 10 /* This file is part of the FreeType project, and may only be used, */ 11 /* modified, and distributed under the terms of the FreeType project */ 12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13 /* this file you indicate that you have read the license and */ 14 /* understand and accept it fully. */ 15 /* */ 16 /***************************************************************************/ 17 18 /*************************************************************************/ 19 /* */ 20 /* This file contains the definition of several convenience functions */ 21 /* that can be used by client applications to easily retrieve glyph */ 22 /* bitmaps and outlines from a given face. */ 23 /* */ 24 /* These functions should be optional if you are writing a font server */ 25 /* or text layout engine on top of FreeType. However, they are pretty */ 26 /* handy for many other simple uses of the library. */ 27 /* */ 28 /*************************************************************************/ 29 30 31 #include <ft2build.h> 32 #include FT_GLYPH_H 33 #include FT_OUTLINE_H 34 #include FT_BITMAP_H 35 #include FT_INTERNAL_OBJECTS_H 36 37 #include "basepic.h" 38 39 /*************************************************************************/ 40 /* */ 41 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 42 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 43 /* messages during execution. */ 44 /* */ 45 #undef FT_COMPONENT 46 #define FT_COMPONENT trace_glyph 47 48 49 /*************************************************************************/ 50 /*************************************************************************/ 51 /**** ****/ 52 /**** FT_BitmapGlyph support ****/ 53 /**** ****/ 54 /*************************************************************************/ 55 /*************************************************************************/ 56 57 FT_CALLBACK_DEF( FT_Error ) 58 ft_bitmap_glyph_init( FT_Glyph bitmap_glyph, 59 FT_GlyphSlot slot ) 60 { 61 FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph; 62 FT_Error error = FT_Err_Ok; 63 FT_Library library = FT_GLYPH( glyph )->library; 64 65 66 if ( slot->format != FT_GLYPH_FORMAT_BITMAP ) 67 { 68 error = FT_Err_Invalid_Glyph_Format; 69 goto Exit; 70 } 71 72 glyph->left = slot->bitmap_left; 73 glyph->top = slot->bitmap_top; 74 75 /* do lazy copying whenever possible */ 76 if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) 77 { 78 glyph->bitmap = slot->bitmap; 79 slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; 80 } 81 else 82 { 83 FT_Bitmap_New( &glyph->bitmap ); 84 error = FT_Bitmap_Copy( library, &slot->bitmap, &glyph->bitmap ); 85 } 86 87 Exit: 88 return error; 89 } 90 91 92 FT_CALLBACK_DEF( FT_Error ) 93 ft_bitmap_glyph_copy( FT_Glyph bitmap_source, 94 FT_Glyph bitmap_target ) 95 { 96 FT_Library library = bitmap_source->library; 97 FT_BitmapGlyph source = (FT_BitmapGlyph)bitmap_source; 98 FT_BitmapGlyph target = (FT_BitmapGlyph)bitmap_target; 99 100 101 target->left = source->left; 102 target->top = source->top; 103 104 return FT_Bitmap_Copy( library, &source->bitmap, &target->bitmap ); 105 } 106 107 108 FT_CALLBACK_DEF( void ) 109 ft_bitmap_glyph_done( FT_Glyph bitmap_glyph ) 110 { 111 FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph; 112 FT_Library library = FT_GLYPH( glyph )->library; 113 114 115 FT_Bitmap_Done( library, &glyph->bitmap ); 116 } 117 118 119 FT_CALLBACK_DEF( void ) 120 ft_bitmap_glyph_bbox( FT_Glyph bitmap_glyph, 121 FT_BBox* cbox ) 122 { 123 FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph; 124 125 126 cbox->xMin = glyph->left << 6; 127 cbox->xMax = cbox->xMin + ( glyph->bitmap.width << 6 ); 128 cbox->yMax = glyph->top << 6; 129 cbox->yMin = cbox->yMax - ( glyph->bitmap.rows << 6 ); 130 } 131 132 133 FT_DEFINE_GLYPH(ft_bitmap_glyph_class, 134 sizeof ( FT_BitmapGlyphRec ), 135 FT_GLYPH_FORMAT_BITMAP, 136 137 ft_bitmap_glyph_init, 138 ft_bitmap_glyph_done, 139 ft_bitmap_glyph_copy, 140 0, /* FT_Glyph_TransformFunc */ 141 ft_bitmap_glyph_bbox, 142 0 /* FT_Glyph_PrepareFunc */ 143 ) 144 145 146 /*************************************************************************/ 147 /*************************************************************************/ 148 /**** ****/ 149 /**** FT_OutlineGlyph support ****/ 150 /**** ****/ 151 /*************************************************************************/ 152 /*************************************************************************/ 153 154 155 FT_CALLBACK_DEF( FT_Error ) 156 ft_outline_glyph_init( FT_Glyph outline_glyph, 157 FT_GlyphSlot slot ) 158 { 159 FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph; 160 FT_Error error = FT_Err_Ok; 161 FT_Library library = FT_GLYPH( glyph )->library; 162 FT_Outline* source = &slot->outline; 163 FT_Outline* target = &glyph->outline; 164 165 166 /* check format in glyph slot */ 167 if ( slot->format != FT_GLYPH_FORMAT_OUTLINE ) 168 { 169 error = FT_Err_Invalid_Glyph_Format; 170 goto Exit; 171 } 172 173 /* allocate new outline */ 174 error = FT_Outline_New( library, source->n_points, source->n_contours, 175 &glyph->outline ); 176 if ( error ) 177 goto Exit; 178 179 FT_Outline_Copy( source, target ); 180 181 Exit: 182 return error; 183 } 184 185 186 FT_CALLBACK_DEF( void ) 187 ft_outline_glyph_done( FT_Glyph outline_glyph ) 188 { 189 FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph; 190 191 192 FT_Outline_Done( FT_GLYPH( glyph )->library, &glyph->outline ); 193 } 194 195 196 FT_CALLBACK_DEF( FT_Error ) 197 ft_outline_glyph_copy( FT_Glyph outline_source, 198 FT_Glyph outline_target ) 199 { 200 FT_OutlineGlyph source = (FT_OutlineGlyph)outline_source; 201 FT_OutlineGlyph target = (FT_OutlineGlyph)outline_target; 202 FT_Error error; 203 FT_Library library = FT_GLYPH( source )->library; 204 205 206 error = FT_Outline_New( library, source->outline.n_points, 207 source->outline.n_contours, &target->outline ); 208 if ( !error ) 209 FT_Outline_Copy( &source->outline, &target->outline ); 210 211 return error; 212 } 213 214 215 FT_CALLBACK_DEF( void ) 216 ft_outline_glyph_transform( FT_Glyph outline_glyph, 217 const FT_Matrix* matrix, 218 const FT_Vector* delta ) 219 { 220 FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph; 221 222 223 if ( matrix ) 224 FT_Outline_Transform( &glyph->outline, matrix ); 225 226 if ( delta ) 227 FT_Outline_Translate( &glyph->outline, delta->x, delta->y ); 228 } 229 230 231 FT_CALLBACK_DEF( void ) 232 ft_outline_glyph_bbox( FT_Glyph outline_glyph, 233 FT_BBox* bbox ) 234 { 235 FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph; 236 237 238 FT_Outline_Get_CBox( &glyph->outline, bbox ); 239 } 240 241 242 FT_CALLBACK_DEF( FT_Error ) 243 ft_outline_glyph_prepare( FT_Glyph outline_glyph, 244 FT_GlyphSlot slot ) 245 { 246 FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph; 247 248 249 slot->format = FT_GLYPH_FORMAT_OUTLINE; 250 slot->outline = glyph->outline; 251 slot->outline.flags &= ~FT_OUTLINE_OWNER; 252 253 return FT_Err_Ok; 254 } 255 256 257 FT_DEFINE_GLYPH( ft_outline_glyph_class, 258 sizeof ( FT_OutlineGlyphRec ), 259 FT_GLYPH_FORMAT_OUTLINE, 260 261 ft_outline_glyph_init, 262 ft_outline_glyph_done, 263 ft_outline_glyph_copy, 264 ft_outline_glyph_transform, 265 ft_outline_glyph_bbox, 266 ft_outline_glyph_prepare 267 ) 268 269 270 /*************************************************************************/ 271 /*************************************************************************/ 272 /**** ****/ 273 /**** FT_Glyph class and API ****/ 274 /**** ****/ 275 /*************************************************************************/ 276 /*************************************************************************/ 277 278 static FT_Error 279 ft_new_glyph( FT_Library library, 280 const FT_Glyph_Class* clazz, 281 FT_Glyph* aglyph ) 282 { 283 FT_Memory memory = library->memory; 284 FT_Error error; 285 FT_Glyph glyph = NULL; 286 287 288 *aglyph = 0; 289 290 if ( !FT_ALLOC( glyph, clazz->glyph_size ) ) 291 { 292 glyph->library = library; 293 glyph->clazz = clazz; 294 glyph->format = clazz->glyph_format; 295 296 *aglyph = glyph; 297 } 298 299 return error; 300 } 301 302 303 /* documentation is in ftglyph.h */ 304 305 FT_EXPORT_DEF( FT_Error ) 306 FT_Glyph_Copy( FT_Glyph source, 307 FT_Glyph *target ) 308 { 309 FT_Glyph copy; 310 FT_Error error; 311 const FT_Glyph_Class* clazz; 312 313 314 /* check arguments */ 315 if ( !target ) 316 { 317 error = FT_Err_Invalid_Argument; 318 goto Exit; 319 } 320 321 *target = 0; 322 323 if ( !source || !source->clazz ) 324 { 325 error = FT_Err_Invalid_Argument; 326 goto Exit; 327 } 328 329 clazz = source->clazz; 330 error = ft_new_glyph( source->library, clazz, © ); 331 if ( error ) 332 goto Exit; 333 334 copy->advance = source->advance; 335 copy->format = source->format; 336 337 if ( clazz->glyph_copy ) 338 error = clazz->glyph_copy( source, copy ); 339 340 if ( error ) 341 FT_Done_Glyph( copy ); 342 else 343 *target = copy; 344 345 Exit: 346 return error; 347 } 348 349 350 /* documentation is in ftglyph.h */ 351 352 FT_EXPORT_DEF( FT_Error ) 353 FT_Get_Glyph( FT_GlyphSlot slot, 354 FT_Glyph *aglyph ) 355 { 356 FT_Library library; 357 FT_Error error; 358 FT_Glyph glyph; 359 360 const FT_Glyph_Class* clazz = 0; 361 362 363 if ( !slot ) 364 return FT_Err_Invalid_Slot_Handle; 365 366 library = slot->library; 367 368 if ( !aglyph ) 369 return FT_Err_Invalid_Argument; 370 371 /* if it is a bitmap, that's easy :-) */ 372 if ( slot->format == FT_GLYPH_FORMAT_BITMAP ) 373 clazz = FT_BITMAP_GLYPH_CLASS_GET; 374 375 /* if it is an outline */ 376 else if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) 377 clazz = FT_OUTLINE_GLYPH_CLASS_GET; 378 379 else 380 { 381 /* try to find a renderer that supports the glyph image format */ 382 FT_Renderer render = FT_Lookup_Renderer( library, slot->format, 0 ); 383 384 385 if ( render ) 386 clazz = &render->glyph_class; 387 } 388 389 if ( !clazz ) 390 { 391 error = FT_Err_Invalid_Glyph_Format; 392 goto Exit; 393 } 394 395 /* create FT_Glyph object */ 396 error = ft_new_glyph( library, clazz, &glyph ); 397 if ( error ) 398 goto Exit; 399 400 /* copy advance while converting it to 16.16 format */ 401 glyph->advance.x = slot->advance.x << 10; 402 glyph->advance.y = slot->advance.y << 10; 403 404 /* now import the image from the glyph slot */ 405 error = clazz->glyph_init( glyph, slot ); 406 407 /* if an error occurred, destroy the glyph */ 408 if ( error ) 409 FT_Done_Glyph( glyph ); 410 else 411 *aglyph = glyph; 412 413 Exit: 414 return error; 415 } 416 417 418 /* documentation is in ftglyph.h */ 419 420 FT_EXPORT_DEF( FT_Error ) 421 FT_Glyph_Transform( FT_Glyph glyph, 422 FT_Matrix* matrix, 423 FT_Vector* delta ) 424 { 425 const FT_Glyph_Class* clazz; 426 FT_Error error = FT_Err_Ok; 427 428 429 if ( !glyph || !glyph->clazz ) 430 error = FT_Err_Invalid_Argument; 431 else 432 { 433 clazz = glyph->clazz; 434 if ( clazz->glyph_transform ) 435 { 436 /* transform glyph image */ 437 clazz->glyph_transform( glyph, matrix, delta ); 438 439 /* transform advance vector */ 440 if ( matrix ) 441 FT_Vector_Transform( &glyph->advance, matrix ); 442 } 443 else 444 error = FT_Err_Invalid_Glyph_Format; 445 } 446 return error; 447 } 448 449 450 /* documentation is in ftglyph.h */ 451 452 FT_EXPORT_DEF( void ) 453 FT_Glyph_Get_CBox( FT_Glyph glyph, 454 FT_UInt bbox_mode, 455 FT_BBox *acbox ) 456 { 457 const FT_Glyph_Class* clazz; 458 459 460 if ( !acbox ) 461 return; 462 463 acbox->xMin = acbox->yMin = acbox->xMax = acbox->yMax = 0; 464 465 if ( !glyph || !glyph->clazz ) 466 return; 467 else 468 { 469 clazz = glyph->clazz; 470 if ( !clazz->glyph_bbox ) 471 return; 472 else 473 { 474 /* retrieve bbox in 26.6 coordinates */ 475 clazz->glyph_bbox( glyph, acbox ); 476 477 /* perform grid fitting if needed */ 478 if ( bbox_mode == FT_GLYPH_BBOX_GRIDFIT || 479 bbox_mode == FT_GLYPH_BBOX_PIXELS ) 480 { 481 acbox->xMin = FT_PIX_FLOOR( acbox->xMin ); 482 acbox->yMin = FT_PIX_FLOOR( acbox->yMin ); 483 acbox->xMax = FT_PIX_CEIL( acbox->xMax ); 484 acbox->yMax = FT_PIX_CEIL( acbox->yMax ); 485 } 486 487 /* convert to integer pixels if needed */ 488 if ( bbox_mode == FT_GLYPH_BBOX_TRUNCATE || 489 bbox_mode == FT_GLYPH_BBOX_PIXELS ) 490 { 491 acbox->xMin >>= 6; 492 acbox->yMin >>= 6; 493 acbox->xMax >>= 6; 494 acbox->yMax >>= 6; 495 } 496 } 497 } 498 return; 499 } 500 501 502 /* documentation is in ftglyph.h */ 503 504 FT_EXPORT_DEF( FT_Error ) 505 FT_Glyph_To_Bitmap( FT_Glyph* the_glyph, 506 FT_Render_Mode render_mode, 507 FT_Vector* origin, 508 FT_Bool destroy ) 509 { 510 FT_GlyphSlotRec dummy; 511 FT_GlyphSlot_InternalRec dummy_internal; 512 FT_Error error = FT_Err_Ok; 513 FT_Glyph glyph; 514 FT_BitmapGlyph bitmap = NULL; 515 const FT_Glyph_Class* clazz; 516 517 /* FT_BITMAP_GLYPH_CLASS_GET derefers `library' in PIC mode */ 518 FT_Library library; 519 520 521 /* check argument */ 522 if ( !the_glyph ) 523 goto Bad; 524 glyph = *the_glyph; 525 if ( !glyph ) 526 goto Bad; 527 528 clazz = glyph->clazz; 529 library = glyph->library; 530 if ( !library || !clazz ) 531 goto Bad; 532 533 /* when called with a bitmap glyph, do nothing and return successfully */ 534 if ( clazz == FT_BITMAP_GLYPH_CLASS_GET ) 535 goto Exit; 536 537 if ( !clazz->glyph_prepare ) 538 goto Bad; 539 540 /* we render the glyph into a glyph bitmap using a `dummy' glyph slot */ 541 /* then calling FT_Render_Glyph_Internal() */ 542 543 FT_MEM_ZERO( &dummy, sizeof ( dummy ) ); 544 FT_MEM_ZERO( &dummy_internal, sizeof ( dummy_internal ) ); 545 dummy.internal = &dummy_internal; 546 dummy.library = library; 547 dummy.format = clazz->glyph_format; 548 549 /* create result bitmap glyph */ 550 error = ft_new_glyph( library, FT_BITMAP_GLYPH_CLASS_GET, 551 (FT_Glyph*)(void*)&bitmap ); 552 if ( error ) 553 goto Exit; 554 555 #if 1 556 /* if `origin' is set, translate the glyph image */ 557 if ( origin ) 558 FT_Glyph_Transform( glyph, 0, origin ); 559 #else 560 FT_UNUSED( origin ); 561 #endif 562 563 /* prepare dummy slot for rendering */ 564 error = clazz->glyph_prepare( glyph, &dummy ); 565 if ( !error ) 566 error = FT_Render_Glyph_Internal( glyph->library, &dummy, render_mode ); 567 568 #if 1 569 if ( !destroy && origin ) 570 { 571 FT_Vector v; 572 573 574 v.x = -origin->x; 575 v.y = -origin->y; 576 FT_Glyph_Transform( glyph, 0, &v ); 577 } 578 #endif 579 580 if ( error ) 581 goto Exit; 582 583 /* in case of success, copy the bitmap to the glyph bitmap */ 584 error = ft_bitmap_glyph_init( (FT_Glyph)bitmap, &dummy ); 585 if ( error ) 586 goto Exit; 587 588 /* copy advance */ 589 bitmap->root.advance = glyph->advance; 590 591 if ( destroy ) 592 FT_Done_Glyph( glyph ); 593 594 *the_glyph = FT_GLYPH( bitmap ); 595 596 Exit: 597 if ( error && bitmap ) 598 FT_Done_Glyph( FT_GLYPH( bitmap ) ); 599 600 return error; 601 602 Bad: 603 error = FT_Err_Invalid_Argument; 604 goto Exit; 605 } 606 607 608 /* documentation is in ftglyph.h */ 609 610 FT_EXPORT_DEF( void ) 611 FT_Done_Glyph( FT_Glyph glyph ) 612 { 613 if ( glyph ) 614 { 615 FT_Memory memory = glyph->library->memory; 616 const FT_Glyph_Class* clazz = glyph->clazz; 617 618 619 if ( clazz->glyph_done ) 620 clazz->glyph_done( glyph ); 621 622 FT_FREE( glyph ); 623 } 624 } 625 626 627 /* END */ 628