• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef OT_GLYF_PATH_BUILDER_HH
2 #define OT_GLYF_PATH_BUILDER_HH
3 
4 
5 #include "../../hb.hh"
6 
7 
8 namespace OT {
9 namespace glyf_impl {
10 
11 
12 struct path_builder_t
13 {
14   hb_font_t *font;
15   hb_draw_session_t *draw_session;
16 
17   struct optional_point_t
18   {
optional_point_tOT::glyf_impl::path_builder_t::optional_point_t19     optional_point_t () {}
optional_point_tOT::glyf_impl::path_builder_t::optional_point_t20     optional_point_t (float x_, float y_) : has_data (true), x (x_), y (y_) {}
operator boolOT::glyf_impl::path_builder_t::optional_point_t21     operator bool () const { return has_data; }
22 
23     bool has_data = false;
24     float x = 0.;
25     float y = 0.;
26 
lerpOT::glyf_impl::path_builder_t::optional_point_t27     optional_point_t lerp (optional_point_t p, float t)
28     { return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); }
29   } first_oncurve, first_offcurve, last_offcurve;
30 
path_builder_tOT::glyf_impl::path_builder_t31   path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_)
32   {
33     font = font_;
34     draw_session = &draw_session_;
35     first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
36   }
37 
38   /* based on https://github.com/RazrFalcon/ttf-parser/blob/4f32821/src/glyf.rs#L287
39      See also:
40      * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html
41      * https://stackoverflow.com/a/20772557 */
consume_pointOT::glyf_impl::path_builder_t42   void consume_point (const contour_point_t &point)
43   {
44     bool is_on_curve = point.flag & glyf_impl::SimpleGlyph::FLAG_ON_CURVE;
45     optional_point_t p (font->em_fscalef_x (point.x), font->em_fscalef_y (point.y));
46     if (!first_oncurve)
47     {
48       if (is_on_curve)
49       {
50 	first_oncurve = p;
51 	draw_session->move_to (p.x, p.y);
52       }
53       else
54       {
55 	if (first_offcurve)
56 	{
57 	  optional_point_t mid = first_offcurve.lerp (p, .5f);
58 	  first_oncurve = mid;
59 	  last_offcurve = p;
60 	  draw_session->move_to (mid.x, mid.y);
61 	}
62 	else
63 	  first_offcurve = p;
64       }
65     }
66     else
67     {
68       if (last_offcurve)
69       {
70 	if (is_on_curve)
71 	{
72 	  draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
73 				     p.x, p.y);
74 	  last_offcurve = optional_point_t ();
75 	}
76 	else
77 	{
78 	  optional_point_t mid = last_offcurve.lerp (p, .5f);
79 	  draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
80 				     mid.x, mid.y);
81 	  last_offcurve = p;
82 	}
83       }
84       else
85       {
86 	if (is_on_curve)
87 	  draw_session->line_to (p.x, p.y);
88 	else
89 	  last_offcurve = p;
90       }
91     }
92 
93     if (point.is_end_point)
94     {
95       if (first_offcurve && last_offcurve)
96       {
97 	optional_point_t mid = last_offcurve.lerp (first_offcurve, .5f);
98 	draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
99 				   mid.x, mid.y);
100 	last_offcurve = optional_point_t ();
101 	/* now check the rest */
102       }
103 
104       if (first_offcurve && first_oncurve)
105 	draw_session->quadratic_to (first_offcurve.x, first_offcurve.y,
106 				   first_oncurve.x, first_oncurve.y);
107       else if (last_offcurve && first_oncurve)
108 	draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
109 				   first_oncurve.x, first_oncurve.y);
110       else if (first_oncurve)
111 	draw_session->line_to (first_oncurve.x, first_oncurve.y);
112       else if (first_offcurve)
113       {
114 	float x = first_offcurve.x, y = first_offcurve.y;
115 	draw_session->move_to (x, y);
116 	draw_session->quadratic_to (x, y, x, y);
117       }
118 
119       /* Getting ready for the next contour */
120       first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
121       draw_session->close_path ();
122     }
123   }
points_endOT::glyf_impl::path_builder_t124   void points_end () {}
125 
is_consuming_contour_pointsOT::glyf_impl::path_builder_t126   bool is_consuming_contour_points () { return true; }
get_phantoms_sinkOT::glyf_impl::path_builder_t127   contour_point_t *get_phantoms_sink () { return nullptr; }
128 };
129 
130 
131 } /* namespace glyf_impl */
132 } /* namespace OT */
133 
134 
135 #endif /* OT_GLYF_PATH_BUILDER_HH */
136