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