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 #include "glyphy-common.hh"
24 #include "glyphy-geometry.hh"
25 
26 using namespace GLyphy::Geometry;
27 
28 /*
29  * TODO
30  *
31  * Sync this with the shader sdf
32  */
33 
34 double
glyphy_sdf_from_arc_list(const glyphy_arc_endpoint_t * endpoints,unsigned int num_endpoints,const glyphy_point_t * p,glyphy_point_t * closest_p)35 glyphy_sdf_from_arc_list (const glyphy_arc_endpoint_t *endpoints,
36 			  unsigned int                 num_endpoints,
37 			  const glyphy_point_t        *p,
38 			  glyphy_point_t              *closest_p /* may be NULL; TBD not implemented yet */)
39 {
40   Point c = *p;
41   Point p0 (0, 0);
42   Arc closest_arc (p0, p0, 0);
43   double min_dist = GLYPHY_INFINITY;
44   int side = 0;
45   for (unsigned int i = 0; i < num_endpoints; i++) {
46     const glyphy_arc_endpoint_t &endpoint = endpoints[i];
47     if (endpoint.d == GLYPHY_INFINITY) {
48       p0 = endpoint.p;
49       continue;
50     }
51     Arc arc (p0, endpoint.p, endpoint.d);
52     p0 = endpoint.p;
53 
54     if (arc.wedge_contains_point (c)) {
55       double sdist = arc.distance_to_point (c); /* TODO This distance has the wrong sign.  Fix */
56       double udist = fabs (sdist) * (1 - GLYPHY_EPSILON);
57       if (udist <= min_dist) {
58         min_dist = udist;
59 	side = sdist >= 0 ? -1 : +1;
60       }
61     } else {
62       double udist = std::min ((arc.p0 - c).len (), (arc.p1 - c).len ());
63       if (udist < min_dist) {
64         min_dist = udist;
65 	side = 0; /* unsure */
66 	closest_arc = arc;
67       } else if (side == 0 && udist == min_dist) {
68 	/* If this new distance is the same as the current minimum,
69 	 * compare extended distances.  Take the sign from the arc
70 	 * with larger extended distance. */
71 	double old_ext_dist = closest_arc.extended_dist (c);
72 	double new_ext_dist = arc.extended_dist (c);
73 
74 	double ext_dist = fabs (new_ext_dist) <= fabs (old_ext_dist) ?
75 			  old_ext_dist : new_ext_dist;
76 
77 	/* For emboldening and stuff: */
78 	// min_dist = fabs (ext_dist);
79 	side = ext_dist >= 0 ? +1 : -1;
80       }
81     }
82   }
83 
84   if (side == 0) {
85     // Technically speaking this should not happen, but it does.  So try to fix it.
86     double ext_dist = closest_arc.extended_dist (c);
87     side = ext_dist >= 0 ? +1 : -1;
88   }
89 
90   return side * min_dist;
91 }
92