1 /**************************************************************************** 2 * 3 * ftglyph.c 4 * 5 * FreeType convenience functions to handle glyphs (body). 6 * 7 * Copyright (C) 1996-2022 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 FT_Done_Glyph( glyph ); 686 else 687 *aglyph = glyph; 688 689 Exit: 690 return error; 691 } 692 693 694 /* documentation is in ftglyph.h */ 695 696 FT_EXPORT_DEF( FT_Error ) FT_Glyph_Transform(FT_Glyph glyph,const FT_Matrix * matrix,const FT_Vector * delta)697 FT_Glyph_Transform( FT_Glyph glyph, 698 const FT_Matrix* matrix, 699 const FT_Vector* delta ) 700 { 701 FT_Error error = FT_Err_Ok; 702 703 704 if ( !glyph || !glyph->clazz ) 705 error = FT_THROW( Invalid_Argument ); 706 else 707 { 708 const FT_Glyph_Class* clazz = glyph->clazz; 709 710 711 if ( clazz->glyph_transform ) 712 { 713 /* transform glyph image */ 714 clazz->glyph_transform( glyph, matrix, delta ); 715 716 /* transform advance vector */ 717 if ( matrix ) 718 FT_Vector_Transform( &glyph->advance, matrix ); 719 } 720 else 721 error = FT_THROW( Invalid_Glyph_Format ); 722 } 723 return error; 724 } 725 726 727 /* documentation is in ftglyph.h */ 728 729 FT_EXPORT_DEF( void ) FT_Glyph_Get_CBox(FT_Glyph glyph,FT_UInt bbox_mode,FT_BBox * acbox)730 FT_Glyph_Get_CBox( FT_Glyph glyph, 731 FT_UInt bbox_mode, 732 FT_BBox *acbox ) 733 { 734 const FT_Glyph_Class* clazz; 735 736 737 if ( !acbox ) 738 return; 739 740 acbox->xMin = acbox->yMin = acbox->xMax = acbox->yMax = 0; 741 742 if ( !glyph || !glyph->clazz ) 743 return; 744 745 clazz = glyph->clazz; 746 if ( !clazz->glyph_bbox ) 747 return; 748 749 /* retrieve bbox in 26.6 coordinates */ 750 clazz->glyph_bbox( glyph, acbox ); 751 752 /* perform grid fitting if needed */ 753 if ( bbox_mode == FT_GLYPH_BBOX_GRIDFIT || 754 bbox_mode == FT_GLYPH_BBOX_PIXELS ) 755 { 756 acbox->xMin = FT_PIX_FLOOR( acbox->xMin ); 757 acbox->yMin = FT_PIX_FLOOR( acbox->yMin ); 758 acbox->xMax = FT_PIX_CEIL_LONG( acbox->xMax ); 759 acbox->yMax = FT_PIX_CEIL_LONG( acbox->yMax ); 760 } 761 762 /* convert to integer pixels if needed */ 763 if ( bbox_mode == FT_GLYPH_BBOX_TRUNCATE || 764 bbox_mode == FT_GLYPH_BBOX_PIXELS ) 765 { 766 acbox->xMin >>= 6; 767 acbox->yMin >>= 6; 768 acbox->xMax >>= 6; 769 acbox->yMax >>= 6; 770 } 771 } 772 773 774 /* documentation is in ftglyph.h */ 775 776 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)777 FT_Glyph_To_Bitmap( FT_Glyph* the_glyph, 778 FT_Render_Mode render_mode, 779 const FT_Vector* origin, 780 FT_Bool destroy ) 781 { 782 FT_GlyphSlotRec dummy; 783 FT_GlyphSlot_InternalRec dummy_internal; 784 FT_Error error = FT_Err_Ok; 785 FT_Glyph b, glyph; 786 FT_BitmapGlyph bitmap = NULL; 787 const FT_Glyph_Class* clazz; 788 789 FT_Library library; 790 791 792 /* check argument */ 793 if ( !the_glyph ) 794 goto Bad; 795 glyph = *the_glyph; 796 if ( !glyph ) 797 goto Bad; 798 799 clazz = glyph->clazz; 800 library = glyph->library; 801 if ( !library || !clazz ) 802 goto Bad; 803 804 /* when called with a bitmap glyph, do nothing and return successfully */ 805 if ( clazz == &ft_bitmap_glyph_class ) 806 goto Exit; 807 808 if ( !clazz->glyph_prepare ) 809 goto Bad; 810 811 /* we render the glyph into a glyph bitmap using a `dummy' glyph slot */ 812 /* then calling FT_Render_Glyph_Internal() */ 813 814 FT_ZERO( &dummy ); 815 FT_ZERO( &dummy_internal ); 816 dummy.internal = &dummy_internal; 817 dummy.library = library; 818 dummy.format = clazz->glyph_format; 819 820 /* create result bitmap glyph */ 821 error = ft_new_glyph( library, &ft_bitmap_glyph_class, &b ); 822 if ( error ) 823 goto Exit; 824 bitmap = (FT_BitmapGlyph)b; 825 826 #if 1 827 /* if `origin' is set, translate the glyph image */ 828 if ( origin ) 829 FT_Glyph_Transform( glyph, NULL, origin ); 830 #else 831 FT_UNUSED( origin ); 832 #endif 833 834 /* prepare dummy slot for rendering */ 835 error = clazz->glyph_prepare( glyph, &dummy ); 836 if ( !error ) 837 error = FT_Render_Glyph_Internal( glyph->library, &dummy, render_mode ); 838 839 #ifdef FT_CONFIG_OPTION_SVG 840 if ( clazz == &ft_svg_glyph_class ) 841 { 842 FT_Memory memory = library->memory; 843 844 845 FT_FREE( dummy.other ); 846 } 847 #endif 848 849 #if 1 850 if ( !destroy && origin ) 851 { 852 FT_Vector v; 853 854 855 v.x = -origin->x; 856 v.y = -origin->y; 857 FT_Glyph_Transform( glyph, NULL, &v ); 858 } 859 #endif 860 861 if ( error ) 862 goto Exit; 863 864 /* in case of success, copy the bitmap to the glyph bitmap */ 865 error = ft_bitmap_glyph_init( (FT_Glyph)bitmap, &dummy ); 866 if ( error ) 867 goto Exit; 868 869 /* copy advance */ 870 bitmap->root.advance = glyph->advance; 871 872 if ( destroy ) 873 FT_Done_Glyph( glyph ); 874 875 *the_glyph = FT_GLYPH( bitmap ); 876 877 Exit: 878 if ( error && bitmap ) 879 FT_Done_Glyph( FT_GLYPH( bitmap ) ); 880 881 return error; 882 883 Bad: 884 error = FT_THROW( Invalid_Argument ); 885 goto Exit; 886 } 887 888 889 /* documentation is in ftglyph.h */ 890 891 FT_EXPORT_DEF( void ) FT_Done_Glyph(FT_Glyph glyph)892 FT_Done_Glyph( FT_Glyph glyph ) 893 { 894 if ( glyph ) 895 { 896 FT_Memory memory = glyph->library->memory; 897 const FT_Glyph_Class* clazz = glyph->clazz; 898 899 900 if ( clazz->glyph_done ) 901 clazz->glyph_done( glyph ); 902 903 FT_FREE( glyph ); 904 } 905 } 906 907 908 /* END */ 909