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