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