Fix SVACE issue
[platform/core/uifw/dali-adaptor.git] / text / dali / internal / 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
63   /**
64    * In the original file, a pointer 'acc' returned from 'calloc' may be NULL, and it is dereferenced.
65    * To prevent Null Pointer Dereference, we add to check NULL value here.
66    */
67   if( acc )
68   {
69     acc->refcount = 1;
70
71     acc->tolerance = 5e-4;
72     acc->d_bits = 8;
73     acc->callback = NULL;
74     acc->user_data = NULL;
75
76     glyphy_arc_accumulator_reset (acc);
77   }
78
79   return acc;
80 }
81
82 void
83 glyphy_arc_accumulator_reset (glyphy_arc_accumulator_t *acc)
84 {
85   acc->start_point = acc->current_point = Point (0, 0);
86   acc->need_moveto = true;
87   acc->num_endpoints = 0;
88   acc->max_error = 0;
89   acc->success = true;
90 }
91
92 void
93 glyphy_arc_accumulator_destroy (glyphy_arc_accumulator_t *acc)
94 {
95   if (!acc || --acc->refcount)
96     return;
97
98   free (acc);
99 }
100
101 /* Configure acc */
102
103 void
104 glyphy_arc_accumulator_set_tolerance (glyphy_arc_accumulator_t *acc,
105                                       double                    tolerance)
106 {
107   acc->tolerance = tolerance;
108 }
109
110 double
111 glyphy_arc_accumulator_get_tolerance (glyphy_arc_accumulator_t *acc)
112 {
113   return acc->tolerance;
114 }
115
116 void
117 glyphy_arc_accumulator_set_callback (glyphy_arc_accumulator_t *acc,
118                                      glyphy_arc_endpoint_accumulator_callback_t callback,
119                                      void                     *user_data)
120 {
121   acc->callback = callback;
122   acc->user_data = user_data;
123 }
124
125 void
126 glyphy_arc_accumulator_get_callback (glyphy_arc_accumulator_t  *acc,
127                                      glyphy_arc_endpoint_accumulator_callback_t *callback,
128                                      void                     **user_data)
129 {
130   *callback = acc->callback;
131   *user_data = acc->user_data;
132 }
133
134 /* Accumulation results */
135
136 double
137 glyphy_arc_accumulator_get_error (glyphy_arc_accumulator_t *acc)
138 {
139   return acc->max_error;
140 }
141
142 glyphy_bool_t
143 glyphy_arc_accumulator_successful (glyphy_arc_accumulator_t *acc)
144 {
145   return acc->success;
146 }
147
148
149 /* Accumulate */
150
151 static void
152 emit (glyphy_arc_accumulator_t *acc, const Point &p, double d)
153 {
154   glyphy_arc_endpoint_t endpoint = {p, d};
155   acc->success = acc->success && acc->callback (&endpoint, acc->user_data);
156   if (acc->success) {
157     acc->num_endpoints++;
158     acc->current_point = p;
159   }
160 }
161
162 static void
163 accumulate (glyphy_arc_accumulator_t *acc, const Point &p, double d)
164 {
165   if (Point (acc->current_point) == p)
166     return;
167   if (d == GLYPHY_INFINITY) {
168     /* Emit moveto lazily, for cleaner outlines */
169     acc->need_moveto = true;
170     acc->current_point = p;
171     return;
172   }
173   if (acc->need_moveto) {
174     emit (acc, acc->current_point, GLYPHY_INFINITY);
175     if (acc->success) {
176       acc->start_point = acc->current_point;
177       acc->need_moveto = false;
178     }
179   }
180   emit (acc, p, d);
181 }
182
183 static void
184 move_to (glyphy_arc_accumulator_t *acc, const Point &p)
185 {
186   if (!acc->num_endpoints || p != acc->current_point)
187     accumulate (acc, p, GLYPHY_INFINITY);
188 }
189
190 static void
191 arc_to (glyphy_arc_accumulator_t *acc, const Point &p1, double d)
192 {
193   accumulate (acc, p1, d);
194 }
195
196 static void
197 bezier (glyphy_arc_accumulator_t *acc, const Bezier &b)
198 {
199   double e;
200
201   std::vector<Arc> arcs;
202   typedef ArcBezierApproximatorQuantizedDefault _ArcBezierApproximator;
203   _ArcBezierApproximator appx (GLYPHY_MAX_D, acc->d_bits);
204   ArcsBezierApproximatorSpringSystem<_ArcBezierApproximator>
205     ::approximate_bezier_with_arcs (b, acc->tolerance, appx, arcs, &e);
206
207   acc->max_error = std::max (acc->max_error, e);
208
209   move_to (acc, b.p0);
210   for (unsigned int i = 0; i < arcs.size (); i++)
211     arc_to (acc, arcs[i].p1, arcs[i].d);
212 }
213
214 static void
215 close_path (glyphy_arc_accumulator_t *acc)
216 {
217   if (!acc->need_moveto && Point (acc->current_point) != Point (acc->start_point))
218     arc_to (acc, acc->start_point, 0);
219 }
220
221 void
222 glyphy_arc_accumulator_move_to (glyphy_arc_accumulator_t *acc,
223                                 const glyphy_point_t *p0)
224 {
225   move_to (acc, *p0);
226 }
227
228 void
229 glyphy_arc_accumulator_line_to (glyphy_arc_accumulator_t *acc,
230                                 const glyphy_point_t *p1)
231 {
232   arc_to (acc, *p1, 0);
233 }
234
235 void
236 glyphy_arc_accumulator_conic_to (glyphy_arc_accumulator_t *acc,
237                                  const glyphy_point_t *p1,
238                                  const glyphy_point_t *p2)
239 {
240   bezier (acc, Bezier (acc->current_point,
241                        Point (acc->current_point).lerp (2/3., *p1),
242                        Point (*p2).lerp (2/3., *p1),
243                        *p2));
244 }
245
246 void
247 glyphy_arc_accumulator_cubic_to (glyphy_arc_accumulator_t *acc,
248                                  const glyphy_point_t *p1,
249                                  const glyphy_point_t *p2,
250                                  const glyphy_point_t *p3)
251 {
252   bezier (acc, Bezier (acc->current_point, *p1, *p2, *p3));
253 }
254
255 void
256 glyphy_arc_accumulator_arc_to (glyphy_arc_accumulator_t *acc,
257                                const glyphy_point_t *p1,
258                                double         d)
259 {
260   arc_to (acc, *p1, d);
261 }
262
263 void
264 glyphy_arc_accumulator_close_path (glyphy_arc_accumulator_t *acc)
265 {
266   close_path (acc);
267 }
268
269
270
271 /*
272  * Outline extents from arc list
273  */
274
275
276 void
277 glyphy_arc_list_extents (const glyphy_arc_endpoint_t *endpoints,
278                          unsigned int                 num_endpoints,
279                          glyphy_extents_t            *extents)
280 {
281   Point p0 (0, 0);
282   glyphy_extents_clear (extents);
283   for (unsigned int i = 0; i < num_endpoints; i++) {
284     const glyphy_arc_endpoint_t &endpoint = endpoints[i];
285     if (endpoint.d == GLYPHY_INFINITY) {
286       p0 = endpoint.p;
287       continue;
288     }
289     Arc arc (p0, endpoint.p, endpoint.d);
290     p0 = endpoint.p;
291
292     glyphy_extents_t arc_extents;
293     arc.extents (arc_extents);
294     glyphy_extents_extend (extents, &arc_extents);
295   }
296 }
297
298 #pragma GCC diagnostic pop