2 * Copyright 2012 Google, Inc. All Rights Reserved.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 * Google Author(s): Behdad Esfahbod, Maysum Panju
19 #ifndef GLYPHY_TEXTURE1D_FUNC
20 #define GLYPHY_TEXTURE1D_FUNC glyphy_texture1D_func
22 #ifndef GLYPHY_TEXTURE1D_EXTRA_DECLS
23 #define GLYPHY_TEXTURE1D_EXTRA_DECLS
25 #ifndef GLYPHY_TEXTURE1D_EXTRA_ARGS
26 #define GLYPHY_TEXTURE1D_EXTRA_ARGS
29 #ifndef GLYPHY_SDF_TEXTURE1D_FUNC
30 #define GLYPHY_SDF_TEXTURE1D_FUNC GLYPHY_TEXTURE1D_FUNC
32 #ifndef GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS
33 #define GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS GLYPHY_TEXTURE1D_EXTRA_DECLS
35 #ifndef GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS
36 #define GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS GLYPHY_TEXTURE1D_EXTRA_ARGS
38 #ifndef GLYPHY_SDF_TEXTURE1D
39 #define GLYPHY_SDF_TEXTURE1D(offset) GLYPHY_RGBA(GLYPHY_SDF_TEXTURE1D_FUNC (offset GLYPHY_TEXTURE1D_EXTRA_ARGS))
42 #ifndef GLYPHY_MAX_NUM_ENDPOINTS
43 #define GLYPHY_MAX_NUM_ENDPOINTS 32
46 glyphy_arc_list_t glyphy_arc_list (const vec2 p, const ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS)
48 int cell_offset = glyphy_arc_list_offset (p, nominal_size);
49 vec4 arc_list_data = GLYPHY_SDF_TEXTURE1D (cell_offset);
50 return glyphy_arc_list_decode (arc_list_data, nominal_size);
53 float glyphy_sdf (const vec2 p, const ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS)
55 glyphy_arc_list_t arc_list = glyphy_arc_list (p, nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS);
58 if (arc_list.num_endpoints == 0)
61 return GLYPHY_INFINITY * float(arc_list.side);
63 if (arc_list.num_endpoints == -1)
66 float angle = arc_list.line_angle;
67 vec2 n = vec2 (cos (angle), sin (angle));
68 return dot (p - (vec2(nominal_size) * .5), n) - arc_list.line_distance;
71 float side = float(arc_list.side);
72 float min_dist = GLYPHY_INFINITY;
73 glyphy_arc_t closest_arc;
75 glyphy_arc_endpoint_t endpoint_prev, endpoint;
76 endpoint_prev = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset), nominal_size);
77 for (int i = 1; i < GLYPHY_MAX_NUM_ENDPOINTS; i++)
79 if (i >= arc_list.num_endpoints)
83 endpoint = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset + i), nominal_size);
84 glyphy_arc_t a = glyphy_arc_t (endpoint_prev.p, endpoint.p, endpoint.d);
85 endpoint_prev = endpoint;
86 if (glyphy_isinf (a.d)) continue;
88 if (glyphy_arc_wedge_contains (a, p))
90 float sdist = glyphy_arc_wedge_signed_dist (a, p);
91 float udist = abs (sdist) * (1. - GLYPHY_EPSILON);
92 if (udist <= min_dist)
100 float udist = min (distance (p, a.p0), distance (p, a.p1));
101 if (udist < min_dist)
104 side = 0.; /* unsure */
107 else if (side == 0. && udist == min_dist)
109 /* If this new distance is the same as the current minimum,
110 * compare extended distances. Take the sign from the arc
111 * with larger extended distance. */
112 float old_ext_dist = glyphy_arc_extended_dist (closest_arc, p);
113 float new_ext_dist = glyphy_arc_extended_dist (a, p);
115 float ext_dist = abs (new_ext_dist) <= abs (old_ext_dist) ?
116 old_ext_dist : new_ext_dist;
118 #ifdef GLYPHY_SDF_PSEUDO_DISTANCE
119 /* For emboldening and stuff: */
120 min_dist = abs (ext_dist);
122 side = sign (ext_dist);
129 // Technically speaking this should not happen, but it does. So try to fix it.
130 float ext_dist = glyphy_arc_extended_dist (closest_arc, p);
131 side = sign (ext_dist);
134 return min_dist * side;
137 float glyphy_point_dist (const vec2 p, const ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS)
139 glyphy_arc_list_t arc_list = glyphy_arc_list (p, nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS);
141 float side = float(arc_list.side);
142 float min_dist = GLYPHY_INFINITY;
144 if (arc_list.num_endpoints == 0)
147 glyphy_arc_endpoint_t endpoint;
148 for (int i = 0; i < GLYPHY_MAX_NUM_ENDPOINTS; i++)
150 if (i >= arc_list.num_endpoints)
154 endpoint = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset + i), nominal_size);
155 if (glyphy_isinf (endpoint.d)) continue;
156 min_dist = min (min_dist, distance (p, endpoint.p));