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