1 /**************************************************************************** 2 * 3 * ftglyph.c 4 * 5 * FreeType convenience functions to handle glyphs (body). 6 * 7 * Copyright (C) 1996-2023 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 <freetype/internal/ftdebug.h> 32 33 #include <freetype/ftglyph.h> 34 #include <freetype/ftoutln.h> 35 #include <freetype/ftbitmap.h> 36 #include <freetype/internal/ftobjs.h> 37 #include <freetype/otsvg.h> 38 39 #include "ftbase.h" 40 41 42 /************************************************************************** 43 * 44 * The macro FT_COMPONENT is used in trace mode. It is an implicit 45 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log 46 * messages during execution. 47 */ 48 #undef FT_COMPONENT 49 #define FT_COMPONENT glyph 50 51 52 /*************************************************************************/ 53 /*************************************************************************/ 54 /**** ****/ 55 /**** FT_BitmapGlyph support ****/ 56 /**** ****/ 57 /*************************************************************************/ 58 /*************************************************************************/ 59 60 FT_CALLBACK_DEF( FT_Error ) ft_bitmap_glyph_init(FT_Glyph bitmap_glyph,FT_GlyphSlot slot)61 ft_bitmap_glyph_init( FT_Glyph bitmap_glyph, 62 FT_GlyphSlot slot ) 63 { 64 FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph; 65 FT_Error error = FT_Err_Ok; 66 FT_Library library = FT_GLYPH( glyph )->library; 67 68 69 if ( slot->format != FT_GLYPH_FORMAT_BITMAP ) 70 { 71 error = FT_THROW( Invalid_Glyph_Format ); 72 goto Exit; 73 } 74 75 glyph->left = slot->bitmap_left; 76 glyph->top = slot->bitmap_top; 77 78 /* do lazy copying whenever possible */ 79 if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) 80 { 81 glyph->bitmap = slot->bitmap; 82 slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; 83 } 84 else 85 { 86 FT_Bitmap_Init( &glyph->bitmap ); 87 error = FT_Bitmap_Copy( library, &slot->bitmap, &glyph->bitmap ); 88 } 89 90 Exit: 91 return error; 92 } 93 94 95 FT_CALLBACK_DEF( FT_Error ) ft_bitmap_glyph_copy(FT_Glyph bitmap_source,FT_Glyph bitmap_target)96 ft_bitmap_glyph_copy( FT_Glyph bitmap_source, 97 FT_Glyph bitmap_target ) 98 { 99 FT_Library library = bitmap_source->library; 100 FT_BitmapGlyph source = (FT_BitmapGlyph)bitmap_source; 101 FT_BitmapGlyph target = (FT_BitmapGlyph)bitmap_target; 102 103 104 target->left = source->left; 105 target->top = source->top; 106 107 return FT_Bitmap_Copy( library, &source->bitmap, &target->bitmap ); 108 } 109 110 111 FT_CALLBACK_DEF( void ) ft_bitmap_glyph_done(FT_Glyph bitmap_glyph)112 ft_bitmap_glyph_done( FT_Glyph bitmap_glyph ) 113 { 114 FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph; 115 FT_Library library = FT_GLYPH( glyph )->library; 116 117 118 FT_Bitmap_Done( library, &glyph->bitmap ); 119 } 120 121 122 FT_CALLBACK_DEF( void ) ft_bitmap_glyph_bbox(FT_Glyph bitmap_glyph,FT_BBox * cbox)123 ft_bitmap_glyph_bbox( FT_Glyph bitmap_glyph, 124 FT_BBox* cbox ) 125 { 126 FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph; 127 128 129 cbox->xMin = glyph->left * 64; 130 cbox->xMax = cbox->xMin + (FT_Pos)( glyph->bitmap.width * 64 ); 131 cbox->yMax = glyph->top * 64; 132 cbox->yMin = cbox->yMax - (FT_Pos)( glyph->bitmap.rows * 64 ); 133 } 134 135 FT_DEFINE_GLYPH(ft_bitmap_glyph_class,sizeof (FT_BitmapGlyphRec),FT_GLYPH_FORMAT_BITMAP,ft_bitmap_glyph_init,ft_bitmap_glyph_done,ft_bitmap_glyph_copy,NULL,ft_bitmap_glyph_bbox,NULL)136 FT_DEFINE_GLYPH( 137 ft_bitmap_glyph_class, 138 139 sizeof ( FT_BitmapGlyphRec ), 140 FT_GLYPH_FORMAT_BITMAP, 141 142 ft_bitmap_glyph_init, /* FT_Glyph_InitFunc glyph_init */ 143 ft_bitmap_glyph_done, /* FT_Glyph_DoneFunc glyph_done */ 144 ft_bitmap_glyph_copy, /* FT_Glyph_CopyFunc glyph_copy */ 145 NULL, /* FT_Glyph_TransformFunc glyph_transform */ 146 ft_bitmap_glyph_bbox, /* FT_Glyph_GetBBoxFunc glyph_bbox */ 147 NULL /* FT_Glyph_PrepareFunc glyph_prepare */ 148 ) 149 150 151 /*************************************************************************/ 152 /*************************************************************************/ 153 /**** ****/ 154 /**** FT_OutlineGlyph support ****/ 155 /**** ****/ 156 /*************************************************************************/ 157 /*************************************************************************/ 158 159 160 FT_CALLBACK_DEF( FT_Error ) 161 ft_outline_glyph_init( FT_Glyph outline_glyph, 162 FT_GlyphSlot slot ) 163 { 164 FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph; 165 FT_Error error = FT_Err_Ok; 166 FT_Library library = FT_GLYPH( glyph )->library; 167 FT_Outline* source = &slot->outline; 168 FT_Outline* target = &glyph->outline; 169 170 171 /* check format in glyph slot */ 172 if ( slot->format != FT_GLYPH_FORMAT_OUTLINE ) 173 { 174 error = FT_THROW( Invalid_Glyph_Format ); 175 goto Exit; 176 } 177 178 /* allocate new outline */ 179 error = FT_Outline_New( library, 180 (FT_UInt)source->n_points, 181 source->n_contours, 182 &glyph->outline ); 183 if ( error ) 184 goto Exit; 185 186 FT_Outline_Copy( source, target ); 187 188 Exit: 189 return error; 190 } 191 192 193 FT_CALLBACK_DEF( void ) ft_outline_glyph_done(FT_Glyph outline_glyph)194 ft_outline_glyph_done( FT_Glyph outline_glyph ) 195 { 196 FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph; 197 198 199 FT_Outline_Done( FT_GLYPH( glyph )->library, &glyph->outline ); 200 } 201 202 203 FT_CALLBACK_DEF( FT_Error ) ft_outline_glyph_copy(FT_Glyph outline_source,FT_Glyph outline_target)204 ft_outline_glyph_copy( FT_Glyph outline_source, 205 FT_Glyph outline_target ) 206 { 207 FT_OutlineGlyph source = (FT_OutlineGlyph)outline_source; 208 FT_OutlineGlyph target = (FT_OutlineGlyph)outline_target; 209 FT_Error error; 210 FT_Library library = FT_GLYPH( source )->library; 211 212 213 error = FT_Outline_New( library, 214 (FT_UInt)source->outline.n_points, 215 source->outline.n_contours, 216 &target->outline ); 217 if ( !error ) 218 FT_Outline_Copy( &source->outline, &target->outline ); 219 220 return error; 221 } 222 223 224 FT_CALLBACK_DEF( void ) ft_outline_glyph_transform(FT_Glyph outline_glyph,const FT_Matrix * matrix,const FT_Vector * delta)225 ft_outline_glyph_transform( FT_Glyph outline_glyph, 226 const FT_Matrix* matrix, 227 const FT_Vector* delta ) 228 { 229 FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph; 230 231 232 if ( matrix ) 233 FT_Outline_Transform( &glyph->outline, matrix ); 234 235 if ( delta ) 236 FT_Outline_Translate( &glyph->outline, delta->x, delta->y ); 237 } 238 239 240 FT_CALLBACK_DEF( void ) ft_outline_glyph_bbox(FT_Glyph outline_glyph,FT_BBox * bbox)241 ft_outline_glyph_bbox( FT_Glyph outline_glyph, 242 FT_BBox* bbox ) 243 { 244 FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph; 245 246 247 FT_Outline_Get_CBox( &glyph->outline, bbox ); 248 } 249 250 251 FT_CALLBACK_DEF( FT_Error ) ft_outline_glyph_prepare(FT_Glyph outline_glyph,FT_GlyphSlot slot)252 ft_outline_glyph_prepare( FT_Glyph outline_glyph, 253 FT_GlyphSlot slot ) 254 { 255 FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph; 256 257 258 slot->format = FT_GLYPH_FORMAT_OUTLINE; 259 slot->outline = glyph->outline; 260 slot->outline.flags &= ~FT_OUTLINE_OWNER; 261 262 return FT_Err_Ok; 263 } 264 265 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)266 FT_DEFINE_GLYPH( 267 ft_outline_glyph_class, 268 269 sizeof ( FT_OutlineGlyphRec ), 270 FT_GLYPH_FORMAT_OUTLINE, 271 272 ft_outline_glyph_init, /* FT_Glyph_InitFunc glyph_init */ 273 ft_outline_glyph_done, /* FT_Glyph_DoneFunc glyph_done */ 274 ft_outline_glyph_copy, /* FT_Glyph_CopyFunc glyph_copy */ 275 ft_outline_glyph_transform, /* FT_Glyph_TransformFunc glyph_transform */ 276 ft_outline_glyph_bbox, /* FT_Glyph_GetBBoxFunc glyph_bbox */ 277 ft_outline_glyph_prepare /* FT_Glyph_PrepareFunc glyph_prepare */ 278 ) 279 280 281 #ifdef FT_CONFIG_OPTION_SVG 282 283 /*************************************************************************/ 284 /*************************************************************************/ 285 /**** ****/ 286 /**** FT_SvgGlyph support ****/ 287 /**** ****/ 288 /*************************************************************************/ 289 /*************************************************************************/ 290 291 292 FT_CALLBACK_DEF( FT_Error ) 293 ft_svg_glyph_init( FT_Glyph svg_glyph, 294 FT_GlyphSlot slot ) 295 { 296 FT_ULong doc_length; 297 FT_SVG_Document document; 298 FT_SvgGlyph glyph = (FT_SvgGlyph)svg_glyph; 299 300 FT_Error error = FT_Err_Ok; 301 FT_Memory memory = FT_GLYPH( glyph )->library->memory; 302 303 304 if ( slot->format != FT_GLYPH_FORMAT_SVG ) 305 { 306 error = FT_THROW( Invalid_Glyph_Format ); 307 goto Exit; 308 } 309 310 if ( slot->other == NULL ) 311 { 312 error = FT_THROW( Invalid_Slot_Handle ); 313 goto Exit; 314 } 315 316 document = (FT_SVG_Document)slot->other; 317 318 if ( document->svg_document_length == 0 ) 319 { 320 error = FT_THROW( Invalid_Slot_Handle ); 321 goto Exit; 322 } 323 324 /* allocate a new document */ 325 doc_length = document->svg_document_length; 326 if ( FT_QALLOC( glyph->svg_document, doc_length ) ) 327 goto Exit; 328 glyph->svg_document_length = doc_length; 329 330 glyph->glyph_index = slot->glyph_index; 331 332 glyph->metrics = document->metrics; 333 glyph->units_per_EM = document->units_per_EM; 334 335 glyph->start_glyph_id = document->start_glyph_id; 336 glyph->end_glyph_id = document->end_glyph_id; 337 338 glyph->transform = document->transform; 339 glyph->delta = document->delta; 340 341 /* copy the document into glyph */ 342 FT_MEM_COPY( glyph->svg_document, document->svg_document, doc_length ); 343 344 Exit: 345 return error; 346 } 347 348 349 FT_CALLBACK_DEF( void ) ft_svg_glyph_done(FT_Glyph svg_glyph)350 ft_svg_glyph_done( FT_Glyph svg_glyph ) 351 { 352 FT_SvgGlyph glyph = (FT_SvgGlyph)svg_glyph; 353 FT_Memory memory = svg_glyph->library->memory; 354 355 356 /* just free the memory */ 357 FT_FREE( glyph->svg_document ); 358 } 359 360 361 FT_CALLBACK_DEF( FT_Error ) ft_svg_glyph_copy(FT_Glyph svg_source,FT_Glyph svg_target)362 ft_svg_glyph_copy( FT_Glyph svg_source, 363 FT_Glyph svg_target ) 364 { 365 FT_SvgGlyph source = (FT_SvgGlyph)svg_source; 366 FT_SvgGlyph target = (FT_SvgGlyph)svg_target; 367 368 FT_Error error = FT_Err_Ok; 369 FT_Memory memory = FT_GLYPH( source )->library->memory; 370 371 372 if ( svg_source->format != FT_GLYPH_FORMAT_SVG ) 373 { 374 error = FT_THROW( Invalid_Glyph_Format ); 375 goto Exit; 376 } 377 378 if ( source->svg_document_length == 0 ) 379 { 380 error = FT_THROW( Invalid_Slot_Handle ); 381 goto Exit; 382 } 383 384 target->glyph_index = source->glyph_index; 385 386 target->svg_document_length = source->svg_document_length; 387 388 target->metrics = source->metrics; 389 target->units_per_EM = source->units_per_EM; 390 391 target->start_glyph_id = source->start_glyph_id; 392 target->end_glyph_id = source->end_glyph_id; 393 394 target->transform = source->transform; 395 target->delta = source->delta; 396 397 /* allocate space for the SVG document */ 398 if ( FT_QALLOC( target->svg_document, target->svg_document_length ) ) 399 goto Exit; 400 401 /* copy the document */ 402 FT_MEM_COPY( target->svg_document, 403 source->svg_document, 404 target->svg_document_length ); 405 406 Exit: 407 return error; 408 } 409 410 411 FT_CALLBACK_DEF( void ) ft_svg_glyph_transform(FT_Glyph svg_glyph,const FT_Matrix * _matrix,const FT_Vector * _delta)412 ft_svg_glyph_transform( FT_Glyph svg_glyph, 413 const FT_Matrix* _matrix, 414 const FT_Vector* _delta ) 415 { 416 FT_SvgGlyph glyph = (FT_SvgGlyph)svg_glyph; 417 FT_Matrix* matrix = (FT_Matrix*)_matrix; 418 FT_Vector* delta = (FT_Vector*)_delta; 419 420 FT_Matrix tmp_matrix; 421 FT_Vector tmp_delta; 422 423 FT_Matrix a, b; 424 FT_Pos x, y; 425 426 427 if ( !matrix ) 428 { 429 tmp_matrix.xx = 0x10000; 430 tmp_matrix.xy = 0; 431 tmp_matrix.yx = 0; 432 tmp_matrix.yy = 0x10000; 433 434 matrix = &tmp_matrix; 435 } 436 437 if ( !delta ) 438 { 439 tmp_delta.x = 0; 440 tmp_delta.y = 0; 441 442 delta = &tmp_delta; 443 } 444 445 a = glyph->transform; 446 b = *matrix; 447 FT_Matrix_Multiply( &b, &a ); 448 449 x = ADD_LONG( ADD_LONG( FT_MulFix( matrix->xx, glyph->delta.x ), 450 FT_MulFix( matrix->xy, glyph->delta.y ) ), 451 delta->x ); 452 y = ADD_LONG( ADD_LONG( FT_MulFix( matrix->yx, glyph->delta.x ), 453 FT_MulFix( matrix->yy, glyph->delta.y ) ), 454 delta->y ); 455 456 glyph->delta.x = x; 457 glyph->delta.y = y; 458 459 glyph->transform = a; 460 } 461 462 463 FT_CALLBACK_DEF( FT_Error ) ft_svg_glyph_prepare(FT_Glyph svg_glyph,FT_GlyphSlot slot)464 ft_svg_glyph_prepare( FT_Glyph svg_glyph, 465 FT_GlyphSlot slot ) 466 { 467 FT_SvgGlyph glyph = (FT_SvgGlyph)svg_glyph; 468 469 FT_Error error = FT_Err_Ok; 470 FT_Memory memory = svg_glyph->library->memory; 471 472 FT_SVG_Document document = NULL; 473 474 475 if ( FT_NEW( document ) ) 476 return error; 477 478 document->svg_document = glyph->svg_document; 479 document->svg_document_length = glyph->svg_document_length; 480 481 document->metrics = glyph->metrics; 482 document->units_per_EM = glyph->units_per_EM; 483 484 document->start_glyph_id = glyph->start_glyph_id; 485 document->end_glyph_id = glyph->end_glyph_id; 486 487 document->transform = glyph->transform; 488 document->delta = glyph->delta; 489 490 slot->format = FT_GLYPH_FORMAT_SVG; 491 slot->glyph_index = glyph->glyph_index; 492 slot->other = document; 493 494 return error; 495 } 496 497 FT_DEFINE_GLYPH(ft_svg_glyph_class,sizeof (FT_SvgGlyphRec),FT_GLYPH_FORMAT_SVG,ft_svg_glyph_init,ft_svg_glyph_done,ft_svg_glyph_copy,ft_svg_glyph_transform,NULL,ft_svg_glyph_prepare)498 FT_DEFINE_GLYPH( 499 ft_svg_glyph_class, 500 501 sizeof ( FT_SvgGlyphRec ), 502 FT_GLYPH_FORMAT_SVG, 503 504 ft_svg_glyph_init, /* FT_Glyph_InitFunc glyph_init */ 505 ft_svg_glyph_done, /* FT_Glyph_DoneFunc glyph_done */ 506 ft_svg_glyph_copy, /* FT_Glyph_CopyFunc glyph_copy */ 507 ft_svg_glyph_transform, /* FT_Glyph_TransformFunc glyph_transform */ 508 NULL, /* FT_Glyph_GetBBoxFunc glyph_bbox */ 509 ft_svg_glyph_prepare /* FT_Glyph_PrepareFunc glyph_prepare */ 510 ) 511 512 #endif /* FT_CONFIG_OPTION_SVG */ 513 514 515 /*************************************************************************/ 516 /*************************************************************************/ 517 /**** ****/ 518 /**** FT_Glyph class and API ****/ 519 /**** ****/ 520 /*************************************************************************/ 521 /*************************************************************************/ 522 523 static FT_Error 524 ft_new_glyph( FT_Library library, 525 const FT_Glyph_Class* clazz, 526 FT_Glyph* aglyph ) 527 { 528 FT_Memory memory = library->memory; 529 FT_Error error; 530 FT_Glyph glyph = NULL; 531 532 533 *aglyph = NULL; 534 535 if ( !FT_ALLOC( glyph, clazz->glyph_size ) ) 536 { 537 glyph->library = library; 538 glyph->clazz = clazz; 539 glyph->format = clazz->glyph_format; 540 541 *aglyph = glyph; 542 } 543 544 return error; 545 } 546 547 548 /* documentation is in ftglyph.h */ 549 550 FT_EXPORT_DEF( FT_Error ) FT_Glyph_Copy(FT_Glyph source,FT_Glyph * target)551 FT_Glyph_Copy( FT_Glyph source, 552 FT_Glyph *target ) 553 { 554 FT_Glyph copy; 555 FT_Error error; 556 const FT_Glyph_Class* clazz; 557 558 559 /* check arguments */ 560 if ( !target || !source || !source->clazz ) 561 { 562 error = FT_THROW( Invalid_Argument ); 563 goto Exit; 564 } 565 566 *target = NULL; 567 568 if ( !source || !source->clazz ) 569 { 570 error = FT_THROW( Invalid_Argument ); 571 goto Exit; 572 } 573 574 clazz = source->clazz; 575 error = ft_new_glyph( source->library, clazz, © ); 576 if ( error ) 577 goto Exit; 578 579 copy->advance = source->advance; 580 copy->format = source->format; 581 582 if ( clazz->glyph_copy ) 583 error = clazz->glyph_copy( source, copy ); 584 585 if ( error ) 586 FT_Done_Glyph( copy ); 587 else 588 *target = copy; 589 590 Exit: 591 return error; 592 } 593 594 595 /* documentation is in ftglyph.h */ 596 597 FT_EXPORT( FT_Error ) FT_New_Glyph(FT_Library library,FT_Glyph_Format format,FT_Glyph * aglyph)598 FT_New_Glyph( FT_Library library, 599 FT_Glyph_Format format, 600 FT_Glyph *aglyph ) 601 { 602 const FT_Glyph_Class* clazz = NULL; 603 604 if ( !library || !aglyph ) 605 return FT_THROW( Invalid_Argument ); 606 607 /* if it is a bitmap, that's easy :-) */ 608 if ( format == FT_GLYPH_FORMAT_BITMAP ) 609 clazz = &ft_bitmap_glyph_class; 610 611 /* if it is an outline */ 612 else if ( format == FT_GLYPH_FORMAT_OUTLINE ) 613 clazz = &ft_outline_glyph_class; 614 615 #ifdef FT_CONFIG_OPTION_SVG 616 /* if it is an SVG glyph */ 617 else if ( format == FT_GLYPH_FORMAT_SVG ) 618 clazz = &ft_svg_glyph_class; 619 #endif 620 621 else 622 { 623 /* try to find a renderer that supports the glyph image format */ 624 FT_Renderer render = FT_Lookup_Renderer( library, format, 0 ); 625 626 627 if ( render ) 628 clazz = &render->glyph_class; 629 } 630 631 if ( !clazz ) 632 return FT_THROW( Invalid_Glyph_Format ); 633 634 /* create FT_Glyph object */ 635 return ft_new_glyph( library, clazz, aglyph ); 636 } 637 638 639 /* documentation is in ftglyph.h */ 640 641 FT_EXPORT_DEF( FT_Error ) FT_Get_Glyph(FT_GlyphSlot slot,FT_Glyph * aglyph)642 FT_Get_Glyph( FT_GlyphSlot slot, 643 FT_Glyph *aglyph ) 644 { 645 FT_Error error; 646 FT_Glyph glyph; 647 648 649 if ( !slot ) 650 return FT_THROW( Invalid_Slot_Handle ); 651 652 if ( !aglyph ) 653 return FT_THROW( Invalid_Argument ); 654 655 /* create FT_Glyph object */ 656 error = FT_New_Glyph( slot->library, slot->format, &glyph ); 657 if ( error ) 658 goto Exit; 659 660 /* copy advance while converting 26.6 to 16.16 format */ 661 if ( slot->advance.x >= 0x8000L * 64 || 662 slot->advance.x <= -0x8000L * 64 ) 663 { 664 FT_ERROR(( "FT_Get_Glyph: advance width too large\n" )); 665 error = FT_THROW( Invalid_Argument ); 666 goto Exit2; 667 } 668 if ( slot->advance.y >= 0x8000L * 64 || 669 slot->advance.y <= -0x8000L * 64 ) 670 { 671 FT_ERROR(( "FT_Get_Glyph: advance height too large\n" )); 672 error = FT_THROW( Invalid_Argument ); 673 goto Exit2; 674 } 675 676 glyph->advance.x = slot->advance.x * 1024; 677 glyph->advance.y = slot->advance.y * 1024; 678 679 /* now import the image from the glyph slot */ 680 error = glyph->clazz->glyph_init( glyph, slot ); 681 682 Exit2: 683 /* if an error occurred, destroy the glyph */ 684 if ( error ) 685 { 686 FT_Done_Glyph( glyph ); 687 *aglyph = NULL; 688 } 689 else 690 *aglyph = glyph; 691 692 Exit: 693 return error; 694 } 695 696 697 /* documentation is in ftglyph.h */ 698 699 FT_EXPORT_DEF( FT_Error ) FT_Glyph_Transform(FT_Glyph glyph,const FT_Matrix * matrix,const FT_Vector * delta)700 FT_Glyph_Transform( FT_Glyph glyph, 701 const FT_Matrix* matrix, 702 const FT_Vector* delta ) 703 { 704 FT_Error error = FT_Err_Ok; 705 706 707 if ( !glyph || !glyph->clazz ) 708 error = FT_THROW( Invalid_Argument ); 709 else 710 { 711 const FT_Glyph_Class* clazz = glyph->clazz; 712 713 714 if ( clazz->glyph_transform ) 715 { 716 /* transform glyph image */ 717 clazz->glyph_transform( glyph, matrix, delta ); 718 719 /* transform advance vector */ 720 if ( matrix ) 721 FT_Vector_Transform( &glyph->advance, matrix ); 722 } 723 else 724 error = FT_THROW( Invalid_Glyph_Format ); 725 } 726 return error; 727 } 728 729 730 /* documentation is in ftglyph.h */ 731 732 FT_EXPORT_DEF( void ) FT_Glyph_Get_CBox(FT_Glyph glyph,FT_UInt bbox_mode,FT_BBox * acbox)733 FT_Glyph_Get_CBox( FT_Glyph glyph, 734 FT_UInt bbox_mode, 735 FT_BBox *acbox ) 736 { 737 const FT_Glyph_Class* clazz; 738 739 740 if ( !acbox ) 741 return; 742 743 acbox->xMin = acbox->yMin = acbox->xMax = acbox->yMax = 0; 744 745 if ( !glyph || !glyph->clazz ) 746 return; 747 748 clazz = glyph->clazz; 749 if ( !clazz->glyph_bbox ) 750 return; 751 752 /* retrieve bbox in 26.6 coordinates */ 753 clazz->glyph_bbox( glyph, acbox ); 754 755 /* perform grid fitting if needed */ 756 if ( bbox_mode == FT_GLYPH_BBOX_GRIDFIT || 757 bbox_mode == FT_GLYPH_BBOX_PIXELS ) 758 { 759 acbox->xMin = FT_PIX_FLOOR( acbox->xMin ); 760 acbox->yMin = FT_PIX_FLOOR( acbox->yMin ); 761 acbox->xMax = FT_PIX_CEIL_LONG( acbox->xMax ); 762 acbox->yMax = FT_PIX_CEIL_LONG( acbox->yMax ); 763 } 764 765 /* convert to integer pixels if needed */ 766 if ( bbox_mode == FT_GLYPH_BBOX_TRUNCATE || 767 bbox_mode == FT_GLYPH_BBOX_PIXELS ) 768 { 769 acbox->xMin >>= 6; 770 acbox->yMin >>= 6; 771 acbox->xMax >>= 6; 772 acbox->yMax >>= 6; 773 } 774 } 775 776 777 /* documentation is in ftglyph.h */ 778 779 FT_EXPORT_DEF( FT_Error ) FT_Glyph_To_Bitmap(FT_Glyph * the_glyph,FT_Render_Mode render_mode,const FT_Vector * origin,FT_Bool destroy)780 FT_Glyph_To_Bitmap( FT_Glyph* the_glyph, 781 FT_Render_Mode render_mode, 782 const FT_Vector* origin, 783 FT_Bool destroy ) 784 { 785 FT_GlyphSlotRec dummy; 786 FT_GlyphSlot_InternalRec dummy_internal; 787 FT_Error error = FT_Err_Ok; 788 FT_Glyph b, glyph; 789 FT_BitmapGlyph bitmap = NULL; 790 const FT_Glyph_Class* clazz; 791 792 FT_Library library; 793 794 795 /* check argument */ 796 if ( !the_glyph ) 797 goto Bad; 798 glyph = *the_glyph; 799 if ( !glyph ) 800 goto Bad; 801 802 clazz = glyph->clazz; 803 library = glyph->library; 804 if ( !library || !clazz ) 805 goto Bad; 806 807 /* when called with a bitmap glyph, do nothing and return successfully */ 808 if ( clazz == &ft_bitmap_glyph_class ) 809 goto Exit; 810 811 if ( !clazz->glyph_prepare ) 812 goto Bad; 813 814 /* we render the glyph into a glyph bitmap using a `dummy' glyph slot */ 815 /* then calling FT_Render_Glyph_Internal() */ 816 817 FT_ZERO( &dummy ); 818 FT_ZERO( &dummy_internal ); 819 dummy.internal = &dummy_internal; 820 dummy.library = library; 821 dummy.format = clazz->glyph_format; 822 823 /* create result bitmap glyph */ 824 error = ft_new_glyph( library, &ft_bitmap_glyph_class, &b ); 825 if ( error ) 826 goto Exit; 827 bitmap = (FT_BitmapGlyph)b; 828 829 #if 1 830 /* if `origin' is set, translate the glyph image */ 831 if ( origin ) 832 FT_Glyph_Transform( glyph, NULL, origin ); 833 #else 834 FT_UNUSED( origin ); 835 #endif 836 837 /* prepare dummy slot for rendering */ 838 error = clazz->glyph_prepare( glyph, &dummy ); 839 if ( !error ) 840 error = FT_Render_Glyph_Internal( glyph->library, &dummy, render_mode ); 841 842 #ifdef FT_CONFIG_OPTION_SVG 843 if ( clazz == &ft_svg_glyph_class ) 844 { 845 FT_Memory memory = library->memory; 846 847 848 FT_FREE( dummy.other ); 849 } 850 #endif 851 852 #if 1 853 if ( !destroy && origin ) 854 { 855 FT_Vector v; 856 857 858 v.x = -origin->x; 859 v.y = -origin->y; 860 FT_Glyph_Transform( glyph, NULL, &v ); 861 } 862 #endif 863 864 if ( error ) 865 goto Exit; 866 867 /* in case of success, copy the bitmap to the glyph bitmap */ 868 error = ft_bitmap_glyph_init( (FT_Glyph)bitmap, &dummy ); 869 if ( error ) 870 goto Exit; 871 872 /* copy advance */ 873 bitmap->root.advance = glyph->advance; 874 875 if ( destroy ) 876 FT_Done_Glyph( glyph ); 877 878 *the_glyph = FT_GLYPH( bitmap ); 879 880 Exit: 881 if ( error && bitmap ) 882 FT_Done_Glyph( FT_GLYPH( bitmap ) ); 883 884 return error; 885 886 Bad: 887 error = FT_THROW( Invalid_Argument ); 888 goto Exit; 889 } 890 891 892 /* documentation is in ftglyph.h */ 893 894 FT_EXPORT_DEF( void ) FT_Done_Glyph(FT_Glyph glyph)895 FT_Done_Glyph( FT_Glyph glyph ) 896 { 897 if ( glyph ) 898 { 899 FT_Memory memory = glyph->library->memory; 900 const FT_Glyph_Class* clazz = glyph->clazz; 901 902 903 if ( clazz->glyph_done ) 904 clazz->glyph_done( glyph ); 905 906 FT_FREE( glyph ); 907 } 908 } 909 910 911 /* END */ 912