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