Adaptor refactor
[platform/core/uifw/dali-adaptor.git] / third-party / glyphy / glyphy-arcs.cc
1 /*
2  * Copyright 2012 Google, Inc. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * Google Author(s): Behdad Esfahbod, Maysum Panju, Wojciech Baranowski
17  */
18
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 // Glyphy is written using C style casts
24 #pragma GCC diagnostic push
25 #pragma GCC diagnostic ignored "-Wold-style-cast"
26
27 #include "glyphy-common.hh"
28 #include "glyphy-geometry.hh"
29 #include "glyphy-arcs-bezier.hh"
30
31 using namespace GLyphy::Geometry;
32 using namespace GLyphy::ArcsBezier;
33
34
35
36 /*
37  * Approximate outlines with multiple arcs
38  */
39
40
41 struct glyphy_arc_accumulator_t {
42   unsigned int refcount;
43
44   double tolerance;
45   unsigned int d_bits;
46   glyphy_arc_endpoint_accumulator_callback_t  callback;
47   void                                       *user_data;
48
49   glyphy_point_t start_point;
50   glyphy_point_t current_point;
51   bool           need_moveto;
52   unsigned int   num_endpoints;
53   double max_error;
54   glyphy_bool_t success;
55 };
56
57
58 glyphy_arc_accumulator_t *
59 glyphy_arc_accumulator_create (void)
60 {
61   glyphy_arc_accumulator_t *acc = (glyphy_arc_accumulator_t *) calloc (1, sizeof (glyphy_arc_accumulator_t));
62   acc->refcount = 1;
63
64   acc->tolerance = 5e-4;
65   acc->d_bits = 8;
66   acc->callback = NULL;
67   acc->user_data = NULL;
68
69   glyphy_arc_accumulator_reset (acc);
70
71   return acc;
72 }
73
74 void
75 glyphy_arc_accumulator_reset (glyphy_arc_accumulator_t *acc)
76 {
77   acc->start_point = acc->current_point = Point (0, 0);
78   acc->need_moveto = true;
79   acc->num_endpoints = 0;
80   acc->max_error = 0;
81   acc->success = true;
82 }
83
84 void
85 glyphy_arc_accumulator_destroy (glyphy_arc_accumulator_t *acc)
86 {
87   if (!acc || --acc->refcount)
88     return;
89
90   free (acc);
91 }
92
93 /* Configure acc */
94
95 void
96 glyphy_arc_accumulator_set_tolerance (glyphy_arc_accumulator_t *acc,
97                                       double                    tolerance)
98 {
99   acc->tolerance = tolerance;
100 }
101
102 double
103 glyphy_arc_accumulator_get_tolerance (glyphy_arc_accumulator_t *acc)
104 {
105   return acc->tolerance;
106 }
107
108 void
109 glyphy_arc_accumulator_set_callback (glyphy_arc_accumulator_t *acc,
110                                      glyphy_arc_endpoint_accumulator_callback_t callback,
111                                      void                     *user_data)
112 {
113   acc->callback = callback;
114   acc->user_data = user_data;
115 }
116
117 void
118 glyphy_arc_accumulator_get_callback (glyphy_arc_accumulator_t  *acc,
119                                      glyphy_arc_endpoint_accumulator_callback_t *callback,
120                                      void                     **user_data)
121 {
122   *callback = acc->callback;
123   *user_data = acc->user_data;
124 }
125
126 /* Accumulation results */
127
128 double
129 glyphy_arc_accumulator_get_error (glyphy_arc_accumulator_t *acc)
130 {
131   return acc->max_error;
132 }
133
134 glyphy_bool_t
135 glyphy_arc_accumulator_successful (glyphy_arc_accumulator_t *acc)
136 {
137   return acc->success;
138 }
139
140
141 /* Accumulate */
142
143 static void
144 emit (glyphy_arc_accumulator_t *acc, const Point &p, double d)
145 {
146   glyphy_arc_endpoint_t endpoint = {p, d};
147   acc->success = acc->success && acc->callback (&endpoint, acc->user_data);
148   if (acc->success) {
149     acc->num_endpoints++;
150     acc->current_point = p;
151   }
152 }
153
154 static void
155 accumulate (glyphy_arc_accumulator_t *acc, const Point &p, double d)
156 {
157   if (Point (acc->current_point) == p)
158     return;
159   if (d == GLYPHY_INFINITY) {
160     /* Emit moveto lazily, for cleaner outlines */
161     acc->need_moveto = true;
162     acc->current_point = p;
163     return;
164   }
165   if (acc->need_moveto) {
166     emit (acc, acc->current_point, GLYPHY_INFINITY);
167     if (acc->success) {
168       acc->start_point = acc->current_point;
169       acc->need_moveto = false;
170     }
171   }
172   emit (acc, p, d);
173 }
174
175 static void
176 move_to (glyphy_arc_accumulator_t *acc, const Point &p)
177 {
178   if (!acc->num_endpoints || p != acc->current_point)
179     accumulate (acc, p, GLYPHY_INFINITY);
180 }
181
182 static void
183 arc_to (glyphy_arc_accumulator_t *acc, const Point &p1, double d)
184 {
185   accumulate (acc, p1, d);
186 }
187
188 static void
189 bezier (glyphy_arc_accumulator_t *acc, const Bezier &b)
190 {
191   double e;
192
193   std::vector<Arc> arcs;
194   typedef ArcBezierApproximatorQuantizedDefault _ArcBezierApproximator;
195   _ArcBezierApproximator appx (GLYPHY_MAX_D, acc->d_bits);
196   ArcsBezierApproximatorSpringSystem<_ArcBezierApproximator>
197     ::approximate_bezier_with_arcs (b, acc->tolerance, appx, arcs, &e);
198
199   acc->max_error = std::max (acc->max_error, e);
200
201   move_to (acc, b.p0);
202   for (unsigned int i = 0; i < arcs.size (); i++)
203     arc_to (acc, arcs[i].p1, arcs[i].d);
204 }
205
206 static void
207 close_path (glyphy_arc_accumulator_t *acc)
208 {
209   if (!acc->need_moveto && Point (acc->current_point) != Point (acc->start_point))
210     arc_to (acc, acc->start_point, 0);
211 }
212
213 void
214 glyphy_arc_accumulator_move_to (glyphy_arc_accumulator_t *acc,
215                                 const glyphy_point_t *p0)
216 {
217   move_to (acc, *p0);
218 }
219
220 void
221 glyphy_arc_accumulator_line_to (glyphy_arc_accumulator_t *acc,
222                                 const glyphy_point_t *p1)
223 {
224   arc_to (acc, *p1, 0);
225 }
226
227 void
228 glyphy_arc_accumulator_conic_to (glyphy_arc_accumulator_t *acc,
229                                  const glyphy_point_t *p1,
230                                  const glyphy_point_t *p2)
231 {
232   bezier (acc, Bezier (acc->current_point,
233                        Point (acc->current_point).lerp (2/3., *p1),
234                        Point (*p2).lerp (2/3., *p1),
235                        *p2));
236 }
237
238 void
239 glyphy_arc_accumulator_cubic_to (glyphy_arc_accumulator_t *acc,
240                                  const glyphy_point_t *p1,
241                                  const glyphy_point_t *p2,
242                                  const glyphy_point_t *p3)
243 {
244   bezier (acc, Bezier (acc->current_point, *p1, *p2, *p3));
245 }
246
247 void
248 glyphy_arc_accumulator_arc_to (glyphy_arc_accumulator_t *acc,
249                                const glyphy_point_t *p1,
250                                double         d)
251 {
252   arc_to (acc, *p1, d);
253 }
254
255 void
256 glyphy_arc_accumulator_close_path (glyphy_arc_accumulator_t *acc)
257 {
258   close_path (acc);
259 }
260
261
262
263 /*
264  * Outline extents from arc list
265  */
266
267
268 void
269 glyphy_arc_list_extents (const glyphy_arc_endpoint_t *endpoints,
270                          unsigned int                 num_endpoints,
271                          glyphy_extents_t            *extents)
272 {
273   Point p0 (0, 0);
274   glyphy_extents_clear (extents);
275   for (unsigned int i = 0; i < num_endpoints; i++) {
276     const glyphy_arc_endpoint_t &endpoint = endpoints[i];
277     if (endpoint.d == GLYPHY_INFINITY) {
278       p0 = endpoint.p;
279       continue;
280     }
281     Arc arc (p0, endpoint.p, endpoint.d);
282     p0 = endpoint.p;
283
284     glyphy_extents_t arc_extents;
285     arc.extents (arc_extents);
286     glyphy_extents_extend (extents, &arc_extents);
287   }
288 }
289
290 #pragma GCC diagnostic pop