1 /**************************************************************************** 2 * 3 * ftstroke.h 4 * 5 * FreeType path stroker (specification). 6 * 7 * Copyright (C) 2002-2019 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 #ifndef FTSTROKE_H_ 20 #define FTSTROKE_H_ 21 22 #include <ft2build.h> 23 #include FT_OUTLINE_H 24 #include FT_GLYPH_H 25 26 27 FT_BEGIN_HEADER 28 29 30 /************************************************************************** 31 * 32 * @section: 33 * glyph_stroker 34 * 35 * @title: 36 * Glyph Stroker 37 * 38 * @abstract: 39 * Generating bordered and stroked glyphs. 40 * 41 * @description: 42 * This component generates stroked outlines of a given vectorial glyph. 43 * It also allows you to retrieve the 'outside' and/or the 'inside' 44 * borders of the stroke. 45 * 46 * This can be useful to generate 'bordered' glyph, i.e., glyphs 47 * displayed with a coloured (and anti-aliased) border around their 48 * shape. 49 * 50 * @order: 51 * FT_Stroker 52 * 53 * FT_Stroker_LineJoin 54 * FT_Stroker_LineCap 55 * FT_StrokerBorder 56 * 57 * FT_Outline_GetInsideBorder 58 * FT_Outline_GetOutsideBorder 59 * 60 * FT_Glyph_Stroke 61 * FT_Glyph_StrokeBorder 62 * 63 * FT_Stroker_New 64 * FT_Stroker_Set 65 * FT_Stroker_Rewind 66 * FT_Stroker_ParseOutline 67 * FT_Stroker_Done 68 * 69 * FT_Stroker_BeginSubPath 70 * FT_Stroker_EndSubPath 71 * 72 * FT_Stroker_LineTo 73 * FT_Stroker_ConicTo 74 * FT_Stroker_CubicTo 75 * 76 * FT_Stroker_GetBorderCounts 77 * FT_Stroker_ExportBorder 78 * FT_Stroker_GetCounts 79 * FT_Stroker_Export 80 * 81 */ 82 83 84 /************************************************************************** 85 * 86 * @type: 87 * FT_Stroker 88 * 89 * @description: 90 * Opaque handle to a path stroker object. 91 */ 92 typedef struct FT_StrokerRec_* FT_Stroker; 93 94 95 /************************************************************************** 96 * 97 * @enum: 98 * FT_Stroker_LineJoin 99 * 100 * @description: 101 * These values determine how two joining lines are rendered in a 102 * stroker. 103 * 104 * @values: 105 * FT_STROKER_LINEJOIN_ROUND :: 106 * Used to render rounded line joins. Circular arcs are used to join 107 * two lines smoothly. 108 * 109 * FT_STROKER_LINEJOIN_BEVEL :: 110 * Used to render beveled line joins. The outer corner of the joined 111 * lines is filled by enclosing the triangular region of the corner 112 * with a straight line between the outer corners of each stroke. 113 * 114 * FT_STROKER_LINEJOIN_MITER_FIXED :: 115 * Used to render mitered line joins, with fixed bevels if the miter 116 * limit is exceeded. The outer edges of the strokes for the two 117 * segments are extended until they meet at an angle. If the segments 118 * meet at too sharp an angle (such that the miter would extend from 119 * the intersection of the segments a distance greater than the product 120 * of the miter limit value and the border radius), then a bevel join 121 * (see above) is used instead. This prevents long spikes being 122 * created. `FT_STROKER_LINEJOIN_MITER_FIXED` generates a miter line 123 * join as used in PostScript and PDF. 124 * 125 * FT_STROKER_LINEJOIN_MITER_VARIABLE :: 126 * FT_STROKER_LINEJOIN_MITER :: 127 * Used to render mitered line joins, with variable bevels if the miter 128 * limit is exceeded. The intersection of the strokes is clipped at a 129 * line perpendicular to the bisector of the angle between the strokes, 130 * at the distance from the intersection of the segments equal to the 131 * product of the miter limit value and the border radius. This 132 * prevents long spikes being created. 133 * `FT_STROKER_LINEJOIN_MITER_VARIABLE` generates a mitered line join 134 * as used in XPS. `FT_STROKER_LINEJOIN_MITER` is an alias for 135 * `FT_STROKER_LINEJOIN_MITER_VARIABLE`, retained for backward 136 * compatibility. 137 */ 138 typedef enum FT_Stroker_LineJoin_ 139 { 140 FT_STROKER_LINEJOIN_ROUND = 0, 141 FT_STROKER_LINEJOIN_BEVEL = 1, 142 FT_STROKER_LINEJOIN_MITER_VARIABLE = 2, 143 FT_STROKER_LINEJOIN_MITER = FT_STROKER_LINEJOIN_MITER_VARIABLE, 144 FT_STROKER_LINEJOIN_MITER_FIXED = 3 145 146 } FT_Stroker_LineJoin; 147 148 149 /************************************************************************** 150 * 151 * @enum: 152 * FT_Stroker_LineCap 153 * 154 * @description: 155 * These values determine how the end of opened sub-paths are rendered in 156 * a stroke. 157 * 158 * @values: 159 * FT_STROKER_LINECAP_BUTT :: 160 * The end of lines is rendered as a full stop on the last point 161 * itself. 162 * 163 * FT_STROKER_LINECAP_ROUND :: 164 * The end of lines is rendered as a half-circle around the last point. 165 * 166 * FT_STROKER_LINECAP_SQUARE :: 167 * The end of lines is rendered as a square around the last point. 168 */ 169 typedef enum FT_Stroker_LineCap_ 170 { 171 FT_STROKER_LINECAP_BUTT = 0, 172 FT_STROKER_LINECAP_ROUND, 173 FT_STROKER_LINECAP_SQUARE 174 175 } FT_Stroker_LineCap; 176 177 178 /************************************************************************** 179 * 180 * @enum: 181 * FT_StrokerBorder 182 * 183 * @description: 184 * These values are used to select a given stroke border in 185 * @FT_Stroker_GetBorderCounts and @FT_Stroker_ExportBorder. 186 * 187 * @values: 188 * FT_STROKER_BORDER_LEFT :: 189 * Select the left border, relative to the drawing direction. 190 * 191 * FT_STROKER_BORDER_RIGHT :: 192 * Select the right border, relative to the drawing direction. 193 * 194 * @note: 195 * Applications are generally interested in the 'inside' and 'outside' 196 * borders. However, there is no direct mapping between these and the 197 * 'left' and 'right' ones, since this really depends on the glyph's 198 * drawing orientation, which varies between font formats. 199 * 200 * You can however use @FT_Outline_GetInsideBorder and 201 * @FT_Outline_GetOutsideBorder to get these. 202 */ 203 typedef enum FT_StrokerBorder_ 204 { 205 FT_STROKER_BORDER_LEFT = 0, 206 FT_STROKER_BORDER_RIGHT 207 208 } FT_StrokerBorder; 209 210 211 /************************************************************************** 212 * 213 * @function: 214 * FT_Outline_GetInsideBorder 215 * 216 * @description: 217 * Retrieve the @FT_StrokerBorder value corresponding to the 'inside' 218 * borders of a given outline. 219 * 220 * @input: 221 * outline :: 222 * The source outline handle. 223 * 224 * @return: 225 * The border index. @FT_STROKER_BORDER_RIGHT for empty or invalid 226 * outlines. 227 */ 228 FT_EXPORT( FT_StrokerBorder ) 229 FT_Outline_GetInsideBorder( FT_Outline* outline ); 230 231 232 /************************************************************************** 233 * 234 * @function: 235 * FT_Outline_GetOutsideBorder 236 * 237 * @description: 238 * Retrieve the @FT_StrokerBorder value corresponding to the 'outside' 239 * borders of a given outline. 240 * 241 * @input: 242 * outline :: 243 * The source outline handle. 244 * 245 * @return: 246 * The border index. @FT_STROKER_BORDER_LEFT for empty or invalid 247 * outlines. 248 */ 249 FT_EXPORT( FT_StrokerBorder ) 250 FT_Outline_GetOutsideBorder( FT_Outline* outline ); 251 252 253 /************************************************************************** 254 * 255 * @function: 256 * FT_Stroker_New 257 * 258 * @description: 259 * Create a new stroker object. 260 * 261 * @input: 262 * library :: 263 * FreeType library handle. 264 * 265 * @output: 266 * astroker :: 267 * A new stroker object handle. `NULL` in case of error. 268 * 269 * @return: 270 * FreeType error code. 0~means success. 271 */ 272 FT_EXPORT( FT_Error ) 273 FT_Stroker_New( FT_Library library, 274 FT_Stroker *astroker ); 275 276 277 /************************************************************************** 278 * 279 * @function: 280 * FT_Stroker_Set 281 * 282 * @description: 283 * Reset a stroker object's attributes. 284 * 285 * @input: 286 * stroker :: 287 * The target stroker handle. 288 * 289 * radius :: 290 * The border radius. 291 * 292 * line_cap :: 293 * The line cap style. 294 * 295 * line_join :: 296 * The line join style. 297 * 298 * miter_limit :: 299 * The miter limit for the `FT_STROKER_LINEJOIN_MITER_FIXED` and 300 * `FT_STROKER_LINEJOIN_MITER_VARIABLE` line join styles, expressed as 301 * 16.16 fixed-point value. 302 * 303 * @note: 304 * The radius is expressed in the same units as the outline coordinates. 305 * 306 * This function calls @FT_Stroker_Rewind automatically. 307 */ 308 FT_EXPORT( void ) 309 FT_Stroker_Set( FT_Stroker stroker, 310 FT_Fixed radius, 311 FT_Stroker_LineCap line_cap, 312 FT_Stroker_LineJoin line_join, 313 FT_Fixed miter_limit ); 314 315 316 /************************************************************************** 317 * 318 * @function: 319 * FT_Stroker_Rewind 320 * 321 * @description: 322 * Reset a stroker object without changing its attributes. You should 323 * call this function before beginning a new series of calls to 324 * @FT_Stroker_BeginSubPath or @FT_Stroker_EndSubPath. 325 * 326 * @input: 327 * stroker :: 328 * The target stroker handle. 329 */ 330 FT_EXPORT( void ) 331 FT_Stroker_Rewind( FT_Stroker stroker ); 332 333 334 /************************************************************************** 335 * 336 * @function: 337 * FT_Stroker_ParseOutline 338 * 339 * @description: 340 * A convenience function used to parse a whole outline with the stroker. 341 * The resulting outline(s) can be retrieved later by functions like 342 * @FT_Stroker_GetCounts and @FT_Stroker_Export. 343 * 344 * @input: 345 * stroker :: 346 * The target stroker handle. 347 * 348 * outline :: 349 * The source outline. 350 * 351 * opened :: 352 * A boolean. If~1, the outline is treated as an open path instead of 353 * a closed one. 354 * 355 * @return: 356 * FreeType error code. 0~means success. 357 * 358 * @note: 359 * If `opened` is~0 (the default), the outline is treated as a closed 360 * path, and the stroker generates two distinct 'border' outlines. 361 * 362 * If `opened` is~1, the outline is processed as an open path, and the 363 * stroker generates a single 'stroke' outline. 364 * 365 * This function calls @FT_Stroker_Rewind automatically. 366 */ 367 FT_EXPORT( FT_Error ) 368 FT_Stroker_ParseOutline( FT_Stroker stroker, 369 FT_Outline* outline, 370 FT_Bool opened ); 371 372 373 /************************************************************************** 374 * 375 * @function: 376 * FT_Stroker_BeginSubPath 377 * 378 * @description: 379 * Start a new sub-path in the stroker. 380 * 381 * @input: 382 * stroker :: 383 * The target stroker handle. 384 * 385 * to :: 386 * A pointer to the start vector. 387 * 388 * open :: 389 * A boolean. If~1, the sub-path is treated as an open one. 390 * 391 * @return: 392 * FreeType error code. 0~means success. 393 * 394 * @note: 395 * This function is useful when you need to stroke a path that is not 396 * stored as an @FT_Outline object. 397 */ 398 FT_EXPORT( FT_Error ) 399 FT_Stroker_BeginSubPath( FT_Stroker stroker, 400 FT_Vector* to, 401 FT_Bool open ); 402 403 404 /************************************************************************** 405 * 406 * @function: 407 * FT_Stroker_EndSubPath 408 * 409 * @description: 410 * Close the current sub-path in the stroker. 411 * 412 * @input: 413 * stroker :: 414 * The target stroker handle. 415 * 416 * @return: 417 * FreeType error code. 0~means success. 418 * 419 * @note: 420 * You should call this function after @FT_Stroker_BeginSubPath. If the 421 * subpath was not 'opened', this function 'draws' a single line segment 422 * to the start position when needed. 423 */ 424 FT_EXPORT( FT_Error ) 425 FT_Stroker_EndSubPath( FT_Stroker stroker ); 426 427 428 /************************************************************************** 429 * 430 * @function: 431 * FT_Stroker_LineTo 432 * 433 * @description: 434 * 'Draw' a single line segment in the stroker's current sub-path, from 435 * the last position. 436 * 437 * @input: 438 * stroker :: 439 * The target stroker handle. 440 * 441 * to :: 442 * A pointer to the destination point. 443 * 444 * @return: 445 * FreeType error code. 0~means success. 446 * 447 * @note: 448 * You should call this function between @FT_Stroker_BeginSubPath and 449 * @FT_Stroker_EndSubPath. 450 */ 451 FT_EXPORT( FT_Error ) 452 FT_Stroker_LineTo( FT_Stroker stroker, 453 FT_Vector* to ); 454 455 456 /************************************************************************** 457 * 458 * @function: 459 * FT_Stroker_ConicTo 460 * 461 * @description: 462 * 'Draw' a single quadratic Bezier in the stroker's current sub-path, 463 * from the last position. 464 * 465 * @input: 466 * stroker :: 467 * The target stroker handle. 468 * 469 * control :: 470 * A pointer to a Bezier control point. 471 * 472 * to :: 473 * A pointer to the destination point. 474 * 475 * @return: 476 * FreeType error code. 0~means success. 477 * 478 * @note: 479 * You should call this function between @FT_Stroker_BeginSubPath and 480 * @FT_Stroker_EndSubPath. 481 */ 482 FT_EXPORT( FT_Error ) 483 FT_Stroker_ConicTo( FT_Stroker stroker, 484 FT_Vector* control, 485 FT_Vector* to ); 486 487 488 /************************************************************************** 489 * 490 * @function: 491 * FT_Stroker_CubicTo 492 * 493 * @description: 494 * 'Draw' a single cubic Bezier in the stroker's current sub-path, from 495 * the last position. 496 * 497 * @input: 498 * stroker :: 499 * The target stroker handle. 500 * 501 * control1 :: 502 * A pointer to the first Bezier control point. 503 * 504 * control2 :: 505 * A pointer to second Bezier control point. 506 * 507 * to :: 508 * A pointer to the destination point. 509 * 510 * @return: 511 * FreeType error code. 0~means success. 512 * 513 * @note: 514 * You should call this function between @FT_Stroker_BeginSubPath and 515 * @FT_Stroker_EndSubPath. 516 */ 517 FT_EXPORT( FT_Error ) 518 FT_Stroker_CubicTo( FT_Stroker stroker, 519 FT_Vector* control1, 520 FT_Vector* control2, 521 FT_Vector* to ); 522 523 524 /************************************************************************** 525 * 526 * @function: 527 * FT_Stroker_GetBorderCounts 528 * 529 * @description: 530 * Call this function once you have finished parsing your paths with the 531 * stroker. It returns the number of points and contours necessary to 532 * export one of the 'border' or 'stroke' outlines generated by the 533 * stroker. 534 * 535 * @input: 536 * stroker :: 537 * The target stroker handle. 538 * 539 * border :: 540 * The border index. 541 * 542 * @output: 543 * anum_points :: 544 * The number of points. 545 * 546 * anum_contours :: 547 * The number of contours. 548 * 549 * @return: 550 * FreeType error code. 0~means success. 551 * 552 * @note: 553 * When an outline, or a sub-path, is 'closed', the stroker generates two 554 * independent 'border' outlines, named 'left' and 'right'. 555 * 556 * When the outline, or a sub-path, is 'opened', the stroker merges the 557 * 'border' outlines with caps. The 'left' border receives all points, 558 * while the 'right' border becomes empty. 559 * 560 * Use the function @FT_Stroker_GetCounts instead if you want to retrieve 561 * the counts associated to both borders. 562 */ 563 FT_EXPORT( FT_Error ) 564 FT_Stroker_GetBorderCounts( FT_Stroker stroker, 565 FT_StrokerBorder border, 566 FT_UInt *anum_points, 567 FT_UInt *anum_contours ); 568 569 570 /************************************************************************** 571 * 572 * @function: 573 * FT_Stroker_ExportBorder 574 * 575 * @description: 576 * Call this function after @FT_Stroker_GetBorderCounts to export the 577 * corresponding border to your own @FT_Outline structure. 578 * 579 * Note that this function appends the border points and contours to your 580 * outline, but does not try to resize its arrays. 581 * 582 * @input: 583 * stroker :: 584 * The target stroker handle. 585 * 586 * border :: 587 * The border index. 588 * 589 * outline :: 590 * The target outline handle. 591 * 592 * @note: 593 * Always call this function after @FT_Stroker_GetBorderCounts to get 594 * sure that there is enough room in your @FT_Outline object to receive 595 * all new data. 596 * 597 * When an outline, or a sub-path, is 'closed', the stroker generates two 598 * independent 'border' outlines, named 'left' and 'right'. 599 * 600 * When the outline, or a sub-path, is 'opened', the stroker merges the 601 * 'border' outlines with caps. The 'left' border receives all points, 602 * while the 'right' border becomes empty. 603 * 604 * Use the function @FT_Stroker_Export instead if you want to retrieve 605 * all borders at once. 606 */ 607 FT_EXPORT( void ) 608 FT_Stroker_ExportBorder( FT_Stroker stroker, 609 FT_StrokerBorder border, 610 FT_Outline* outline ); 611 612 613 /************************************************************************** 614 * 615 * @function: 616 * FT_Stroker_GetCounts 617 * 618 * @description: 619 * Call this function once you have finished parsing your paths with the 620 * stroker. It returns the number of points and contours necessary to 621 * export all points/borders from the stroked outline/path. 622 * 623 * @input: 624 * stroker :: 625 * The target stroker handle. 626 * 627 * @output: 628 * anum_points :: 629 * The number of points. 630 * 631 * anum_contours :: 632 * The number of contours. 633 * 634 * @return: 635 * FreeType error code. 0~means success. 636 */ 637 FT_EXPORT( FT_Error ) 638 FT_Stroker_GetCounts( FT_Stroker stroker, 639 FT_UInt *anum_points, 640 FT_UInt *anum_contours ); 641 642 643 /************************************************************************** 644 * 645 * @function: 646 * FT_Stroker_Export 647 * 648 * @description: 649 * Call this function after @FT_Stroker_GetBorderCounts to export all 650 * borders to your own @FT_Outline structure. 651 * 652 * Note that this function appends the border points and contours to your 653 * outline, but does not try to resize its arrays. 654 * 655 * @input: 656 * stroker :: 657 * The target stroker handle. 658 * 659 * outline :: 660 * The target outline handle. 661 */ 662 FT_EXPORT( void ) 663 FT_Stroker_Export( FT_Stroker stroker, 664 FT_Outline* outline ); 665 666 667 /************************************************************************** 668 * 669 * @function: 670 * FT_Stroker_Done 671 * 672 * @description: 673 * Destroy a stroker object. 674 * 675 * @input: 676 * stroker :: 677 * A stroker handle. Can be `NULL`. 678 */ 679 FT_EXPORT( void ) 680 FT_Stroker_Done( FT_Stroker stroker ); 681 682 683 /************************************************************************** 684 * 685 * @function: 686 * FT_Glyph_Stroke 687 * 688 * @description: 689 * Stroke a given outline glyph object with a given stroker. 690 * 691 * @inout: 692 * pglyph :: 693 * Source glyph handle on input, new glyph handle on output. 694 * 695 * @input: 696 * stroker :: 697 * A stroker handle. 698 * 699 * destroy :: 700 * A Boolean. If~1, the source glyph object is destroyed on success. 701 * 702 * @return: 703 * FreeType error code. 0~means success. 704 * 705 * @note: 706 * The source glyph is untouched in case of error. 707 * 708 * Adding stroke may yield a significantly wider and taller glyph 709 * depending on how large of a radius was used to stroke the glyph. You 710 * may need to manually adjust horizontal and vertical advance amounts to 711 * account for this added size. 712 */ 713 FT_EXPORT( FT_Error ) 714 FT_Glyph_Stroke( FT_Glyph *pglyph, 715 FT_Stroker stroker, 716 FT_Bool destroy ); 717 718 719 /************************************************************************** 720 * 721 * @function: 722 * FT_Glyph_StrokeBorder 723 * 724 * @description: 725 * Stroke a given outline glyph object with a given stroker, but only 726 * return either its inside or outside border. 727 * 728 * @inout: 729 * pglyph :: 730 * Source glyph handle on input, new glyph handle on output. 731 * 732 * @input: 733 * stroker :: 734 * A stroker handle. 735 * 736 * inside :: 737 * A Boolean. If~1, return the inside border, otherwise the outside 738 * border. 739 * 740 * destroy :: 741 * A Boolean. If~1, the source glyph object is destroyed on success. 742 * 743 * @return: 744 * FreeType error code. 0~means success. 745 * 746 * @note: 747 * The source glyph is untouched in case of error. 748 * 749 * Adding stroke may yield a significantly wider and taller glyph 750 * depending on how large of a radius was used to stroke the glyph. You 751 * may need to manually adjust horizontal and vertical advance amounts to 752 * account for this added size. 753 */ 754 FT_EXPORT( FT_Error ) 755 FT_Glyph_StrokeBorder( FT_Glyph *pglyph, 756 FT_Stroker stroker, 757 FT_Bool inside, 758 FT_Bool destroy ); 759 760 /* */ 761 762 FT_END_HEADER 763 764 #endif /* FTSTROKE_H_ */ 765 766 767 /* END */ 768 769 770 /* Local Variables: */ 771 /* coding: utf-8 */ 772 /* End: */ 773