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
20 #ifndef GLYPHY_INFINITY
21 #define GLYPHY_INFINITY 1e9
23 #ifndef GLYPHY_EPSILON
24 #define GLYPHY_EPSILON 1e-5
29 #define GLYPHY_RGBA(v) glyphy_bgra (v)
31 #define GLYPHY_RGBA(v) glyphy_rgba (v)
35 vec4 glyphy_rgba (const vec4 v)
40 vec4 glyphy_bgra (const vec4 v)
52 struct glyphy_arc_endpoint_t
54 /* Second arc endpoint */
56 /* Infinity if this endpoint does not form an arc with the previous
57 * endpoint. Ie. a \"move_to\". Test with glyphy_isinf().
58 * Arc depth otherwise. */
62 struct glyphy_arc_list_t
64 /* Number of endpoints in the list.
65 * Will be zero if we're far away inside or outside, in which case side is set.
66 * Will be -1 if this arc-list encodes a single line, in which case line_* are set. */
69 /* If num_endpoints is zero, this specifies whether we are inside (-1)
70 * or outside (+1). Otherwise we're unsure (0). */
72 /* Offset to the arc-endpoints from the beginning of the glyph blob */
75 /* A single line is all we care about. It's right here. */
77 float line_distance; /* From nominal glyph center */
80 bool glyphy_isinf (const float v)
82 return abs (v) >= GLYPHY_INFINITY * .5;
85 bool glyphy_iszero (const float v)
87 return abs (v) <= GLYPHY_EPSILON * 2.;
90 vec2 glyphy_ortho (const vec2 v)
92 return vec2 (-v.y, v.x);
95 int glyphy_float_to_byte (const float v)
97 return int (v * (256. - GLYPHY_EPSILON));
100 ivec4 glyphy_vec4_to_bytes (const vec4 v)
102 return ivec4 (v * (256. - GLYPHY_EPSILON));
105 ivec2 glyphy_float_to_two_nimbles (const float v)
107 int f = glyphy_float_to_byte (v);
108 return ivec2 (f / 16, int(mod (float(f), 16.)));
111 /* returns tan (2 * atan (d)) */
112 float glyphy_tan2atan (const float d)
114 return 2. * d / (1. - d * d);
117 glyphy_arc_endpoint_t glyphy_arc_endpoint_decode(const vec4 v, const ivec2 nominal_size)
119 vec2 p = (vec2 (glyphy_float_to_two_nimbles (v.a)) + v.gb) / 16.;
124 #define GLYPHY_MAX_D .5
125 d = float(glyphy_float_to_byte (d) - 128) * GLYPHY_MAX_D / 127.;
127 return glyphy_arc_endpoint_t (p * vec2(nominal_size), d);
130 vec2 glyphy_arc_center (const glyphy_arc_t a)
132 return mix (a.p0, a.p1, .5) +
133 glyphy_ortho (a.p1 - a.p0) / (2. * glyphy_tan2atan (a.d));
136 bool glyphy_arc_wedge_contains (const glyphy_arc_t a, const vec2 p)
138 float d2 = glyphy_tan2atan (a.d);
139 return dot (p - a.p0, (a.p1 - a.p0) * mat2(1, d2, -d2, 1)) >= 0. &&
140 dot (p - a.p1, (a.p1 - a.p0) * mat2(1, -d2, d2, 1)) <= 0.;
143 float glyphy_arc_wedge_signed_dist_shallow (const glyphy_arc_t a, const vec2 p)
145 vec2 v = normalize (a.p1 - a.p0);
146 float line_d = dot (p - a.p0, glyphy_ortho (v));
150 float d0 = dot ((p - a.p0), v);
152 return sign (line_d) * distance (p, a.p0);
153 float d1 = dot ((a.p1 - p), v);
155 return sign (line_d) * distance (p, a.p1);
156 float r = 2. * a.d * (d0 * d1) / (d0 + d1);
158 return sign (line_d) * min (abs (line_d + r), min (distance (p, a.p0), distance (p, a.p1)));
162 float glyphy_arc_wedge_signed_dist (const glyphy_arc_t a, const vec2 p)
164 if (abs (a.d) <= .03)
165 return glyphy_arc_wedge_signed_dist_shallow (a, p);
166 vec2 c = glyphy_arc_center (a);
167 return sign (a.d) * (distance (a.p0, c) - distance (p, c));
170 float glyphy_arc_extended_dist (const glyphy_arc_t a, const vec2 p)
172 /* Note: this doesn't handle points inside the wedge. */
173 vec2 m = mix (a.p0, a.p1, .5);
174 float d2 = glyphy_tan2atan (a.d);
175 if (dot (p - m, a.p1 - m) < 0.)
176 return dot (p - a.p0, normalize ((a.p1 - a.p0) * mat2(+d2, -1, +1, +d2)));
178 return dot (p - a.p1, normalize ((a.p1 - a.p0) * mat2(-d2, -1, +1, -d2)));
181 int glyphy_arc_list_offset (const vec2 p, const ivec2 nominal_size)
183 ivec2 cell = ivec2 (clamp (floor (p), vec2 (0.,0.), vec2(nominal_size - 1)));
184 return cell.y * nominal_size.x + cell.x;
187 glyphy_arc_list_t glyphy_arc_list_decode (const vec4 v, const ivec2 nominal_size)
190 ivec4 iv = glyphy_vec4_to_bytes (v);
191 l.side = 0; /* unsure */
193 { /* arc-list encoded */
194 l.offset = (iv.g * 256) + iv.b;
195 l.num_endpoints = iv.a;
196 if (l.num_endpoints == 255)
201 else if (l.num_endpoints == 0)
205 { /* single line encoded */
206 l.num_endpoints = -1;
207 l.line_distance = ( float(iv.r)/32. + 0.01*float(iv.g)/82.0 - 6.) * max (float (nominal_size.x), float (nominal_size.y));
208 l.line_angle = ( -float(iv.b)/40.74 - float( iv.a )*0.0001 )-3.142;