citrun

watch C/C++ source code execute
Log | Files | Refs | LICENSE

commit 698b980c72473bc53c92a7cff8d50ca7289fe224
parent ed6fb4af7f2a6b15d18e32644d48fabcce1ab5d5
Author: Kyle Milz <milz@black.my.domain>
Date:   Sat, 13 Apr 2019 00:51:08 -0700

bin: remove custom compiled glyphy

Diffstat:
MJamrules | 2+-
Mbin/Jamfile | 10++++------
Dbin/glyphy/Jamfile | 15---------------
Dbin/glyphy/glyphy-arc-bezier.hh | 228-------------------------------------------------------------------------------
Dbin/glyphy/glyphy-arc.cc | 137-------------------------------------------------------------------------------
Dbin/glyphy/glyphy-arcs-bezier.hh | 153-------------------------------------------------------------------------------
Dbin/glyphy/glyphy-arcs.cc | 320-------------------------------------------------------------------------------
Dbin/glyphy/glyphy-blob.cc | 328-------------------------------------------------------------------------------
Dbin/glyphy/glyphy-common.glsl | 222-------------------------------------------------------------------------------
Dbin/glyphy/glyphy-common.hh | 62--------------------------------------------------------------
Dbin/glyphy/glyphy-extents.cc | 89-------------------------------------------------------------------------------
Dbin/glyphy/glyphy-freetype.h | 102-------------------------------------------------------------------------------
Dbin/glyphy/glyphy-geometry.hh | 742-------------------------------------------------------------------------------
Dbin/glyphy/glyphy-outline.cc | 327-------------------------------------------------------------------------------
Dbin/glyphy/glyphy-sdf.cc | 91-------------------------------------------------------------------------------
Dbin/glyphy/glyphy-sdf.glsl | 150-------------------------------------------------------------------------------
Dbin/glyphy/glyphy-shaders.cc | 39---------------------------------------
Dbin/glyphy/glyphy.h | 354-------------------------------------------------------------------------------
18 files changed, 5 insertions(+), 3366 deletions(-)

diff --git a/Jamrules b/Jamrules @@ -66,7 +66,7 @@ actions PkgConfig type pkg-config echo - gl_pkgs="osmesa glfw3 glew freetype2" + gl_pkgs="osmesa glfw3 glew glyphy freetype2" for pkg in $gl_pkgs; do echo -n "$pkg = " pkg-config --modversion $pkg || echo "NOT FOUND" diff --git a/bin/Jamfile b/bin/Jamfile @@ -71,13 +71,13 @@ Stringize gl_atlas_glsl.h : gl_atlas.glsl ; Stringize gl_vshader_glsl.h : gl_vshader.glsl ; Stringize gl_fshader_glsl.h : gl_fshader.glsl ; -ObjectC++Flags gl.cc gltest.cc $(GL_SRCS) : `pkg-config --cflags glfw3 glew freetype2` ; +ObjectC++Flags gl.cc gltest.cc $(GL_SRCS) : `pkg-config --cflags glyphy glfw3 glew freetype2` ; -LINKLIBS on citrun_gl += -lm $(GL_EXTRALIB) `pkg-config --libs glfw3 glew freetype2` ; -LINKLIBS on citrun_gltest += -lm `pkg-config --libs glfw3 osmesa freetype2` ; +LINKLIBS on citrun_gl += -lm $(GL_EXTRALIB) `pkg-config --libs glyphy glfw3 glew freetype2` ; +LINKLIBS on citrun_gltest += -lm `pkg-config --libs glyphy glfw3 osmesa freetype2` ; LINKLIBS on citrun_gltest += bin/glew-2.1.0/lib/libGLEW.a ; -LinkLibraries citrun_gl citrun_gltest : gl_common libglyphy ; +LinkLibraries citrun_gl citrun_gltest : gl_common ; Main citrun_gl : gl.cc ; Main citrun_gltest : gltest.cc ; @@ -87,5 +87,3 @@ Main citrun_gltest : gltest.cc ; # InstallShell $(PREFIX)/bin : citrun_report citrun_wrap ; InstallBin $(PREFIX)/bin : citrun_gl citrun_inst ; - -SubInclude TOP bin glyphy ; diff --git a/bin/glyphy/Jamfile b/bin/glyphy/Jamfile @@ -1,15 +0,0 @@ -SubDir TOP bin glyphy ; - -SubDirHdrs . ; -SubDirC++Flags -DPKGDATADIR="" ; - -Library libglyphy : glyphy-arc.cc - glyphy-arcs.cc - glyphy-blob.cc - glyphy-extents.cc - glyphy-outline.cc - glyphy-sdf.cc - glyphy-shaders.cc ; - -Stringize glyphy_common_glsl.h : glyphy-common.glsl ; -Stringize glyphy_sdf_glsl.h : glyphy-sdf.glsl ; diff --git a/bin/glyphy/glyphy-arc-bezier.hh b/bin/glyphy/glyphy-arc-bezier.hh @@ -1,228 +0,0 @@ -/* - * Copyright 2012,2013 Google, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Google Author(s): Behdad Esfahbod, Maysum Panju - */ - -#ifndef GLYPHY_ARC_BEZIER_HH -#define GLYPHY_ARC_BEZIER_HH - -#include "glyphy-common.hh" -#include "glyphy-geometry.hh" - -namespace GLyphy { -namespace ArcBezier { - -using namespace Geometry; - - -class MaxDeviationApproximatorExact -{ - public: - /* Returns 3 max(abs(d₀ t (1-t)² + d₁ t² (1-t)) for 0≤t≤1. */ - static double approximate_deviation (double d0, double d1) - { - double candidates[4] = {0,1}; - unsigned int num_candidates = 2; - if (d0 == d1) - candidates[num_candidates++] = .5; - else { - double delta = d0*d0 - d0*d1 + d1*d1; - double t2 = 1. / (3 * (d0 - d1)); - double t0 = (2 * d0 - d1) * t2; - if (delta == 0) - candidates[num_candidates++] = t0; - else if (delta > 0) { - /* This code can be optimized to avoid the sqrt if the solution - * is not feasible (ie. lies outside (0,1)). I have implemented - * that in cairo-spline.c:_cairo_spline_bound(). Can be reused - * here. - */ - double t1 = sqrt (delta) * t2; - candidates[num_candidates++] = t0 - t1; - candidates[num_candidates++] = t0 + t1; - } - } - - double e = 0; - for (unsigned int i = 0; i < num_candidates; i++) { - double t = candidates[i]; - double ee; - if (t < 0. || t > 1.) - continue; - ee = fabs (3 * t * (1-t) * (d0 * (1 - t) + d1 * t)); - e = std::max (e, ee); - } - - return e; - } -}; - - - -template <class MaxDeviationApproximator> -class ArcBezierErrorApproximatorBehdad -{ - public: - static double approximate_bezier_arc_error (const Bezier &b0, const Arc &a) - { - assert (b0.p0 == a.p0); - assert (b0.p3 == a.p1); - - double ea; - Bezier b1 = a.approximate_bezier (&ea); - - assert (b0.p0 == b1.p0); - assert (b0.p3 == b1.p3); - - Vector v0 = b1.p1 - b0.p1; - Vector v1 = b1.p2 - b0.p2; - - Vector b = (b0.p3 - b0.p0).normalized (); - v0 = v0.rebase (b); - v1 = v1.rebase (b); - - Vector v (MaxDeviationApproximator::approximate_deviation (v0.dx, v1.dx), - MaxDeviationApproximator::approximate_deviation (v0.dy, v1.dy)); - - /* Edge cases: If d*d is too close too large default to a weak bound. */ - if (a.d * a.d > 1. - 1e-4) - return ea + v.len (); - - /* If the wedge doesn't contain control points, default to weak bound. */ - if (!a.wedge_contains_point (b0.p1) || !a.wedge_contains_point (b0.p2)) - return ea + v.len (); - - /* If straight line, return the max ortho deviation. */ - if (fabs (a.d) < 1e-6) - return ea + v.dy; - - /* We made sure that fabs(a.d) < 1 */ - double tan_half_alpha = fabs (tan2atan (a.d)); - - double tan_v = v.dx / v.dy; - - double eb; - if (fabs (tan_v) <= tan_half_alpha) - return ea + v.len (); - - double c2 = (a.p1 - a.p0).len () * .5; - double r = a.radius (); - - eb = Vector (c2 + v.dx, c2 / tan_half_alpha + v.dy).len () - r; - assert (eb >= 0); - - return ea + eb; - } -}; - - - -template <class ArcBezierErrorApproximator> -class ArcBezierApproximatorMidpointSimple -{ - public: - static const Arc approximate_bezier_with_arc (const Bezier &b, double *error) - { - Arc a (b.p0, b.p3, b.midpoint (), false); - - *error = ArcBezierErrorApproximator::approximate_bezier_arc_error (b, a); - - return a; - } -}; - -template <class ArcBezierErrorApproximator> -class ArcBezierApproximatorMidpointTwoPart -{ - public: - static const Arc approximate_bezier_with_arc (const Bezier &b, double *error, double mid_t = .5) - { - Pair<Bezier > pair = b.split (mid_t); - Point m = pair.second.p0; - - Arc a0 (b.p0, m, b.p3, true); - Arc a1 (m, b.p3, b.p0, true); - - double e0 = ArcBezierErrorApproximator::approximate_bezier_arc_error (pair.first, a0); - double e1 = ArcBezierErrorApproximator::approximate_bezier_arc_error (pair.second, a1); - *error = std::max (e0, e1); - - return Arc (b.p0, b.p3, m, false); - } -}; - -template <class ArcBezierErrorApproximator> -class ArcBezierApproximatorQuantized -{ - public: - ArcBezierApproximatorQuantized (double _max_d = GLYPHY_INFINITY, unsigned int _d_bits = 0) : - max_d (_max_d), d_bits (_d_bits) {}; - - protected: - double max_d; - unsigned int d_bits; - - public: - const Arc approximate_bezier_with_arc (const Bezier &b, double *error) const - { - double mid_t = .5; - Arc a (b.p0, b.p3, b.point (mid_t), false); - Arc orig_a = a; - - if (std::isfinite (max_d)) { - assert (max_d >= 0); - if (fabs (a.d) > max_d) - a.d = a.d < 0 ? -max_d : max_d; - } - if (d_bits && max_d != 0) { - assert (std::isfinite (max_d)); - assert (fabs (a.d) <= max_d); - int mult = (1 << (d_bits - 1)) - 1; - int id = round (a.d / max_d * mult); - assert (-mult <= id && id <= mult); - a.d = id * max_d / mult; - assert (fabs (a.d) <= max_d); - } - - /* Error introduced by arc quantization */ - double ed = fabs (a.d - orig_a.d) * (a.p1 - a.p0).len () * .5; - - ArcBezierApproximatorMidpointTwoPart<ArcBezierErrorApproximator> - ::approximate_bezier_with_arc (b, error, mid_t); - - if (ed) { - *error += ed; - - /* Try a simple one-arc approx which works with the quantized arc. - * May produce smaller error bound. */ - double e = ArcBezierErrorApproximator::approximate_bezier_arc_error (b, a); - if (e < *error) - *error = e; - } - - return a; - } -}; - -typedef MaxDeviationApproximatorExact MaxDeviationApproximatorDefault; -typedef ArcBezierErrorApproximatorBehdad<MaxDeviationApproximatorDefault> ArcBezierErrorApproximatorDefault; -typedef ArcBezierApproximatorMidpointTwoPart<ArcBezierErrorApproximatorDefault> ArcBezierApproximatorDefault; -typedef ArcBezierApproximatorQuantized<ArcBezierErrorApproximatorDefault> ArcBezierApproximatorQuantizedDefault; - -} /* namespace ArcBezier */ -} /* namespace GLyphy */ - -#endif /* GLYPHY_ARC_BEZIER_HH */ diff --git a/bin/glyphy/glyphy-arc.cc b/bin/glyphy/glyphy-arc.cc @@ -1,137 +0,0 @@ -/* - * Copyright 2012 Google, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Google Author(s): Behdad Esfahbod, Maysum Panju, Wojciech Baranowski - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "glyphy-common.hh" -#include "glyphy-geometry.hh" -#include "glyphy-arc-bezier.hh" - -using namespace GLyphy::Geometry; -using namespace GLyphy::ArcBezier; - - - -/* - * Circular arcs - */ - - -/* Build from a conventional arc representation */ -void -glyphy_arc_from_conventional (const glyphy_point_t *center, - double radius, - double angle0, - double angle1, - glyphy_bool_t negative, - glyphy_arc_t *arc) -{ - *arc = Arc (*center, radius, angle0, angle1, negative); -}; - -/* Convert to a conventional arc representation */ -void -glyphy_arc_to_conventional (glyphy_arc_t arc, - glyphy_point_t *center /* may be NULL */, - double *radius /* may be NULL */, - double *angle0 /* may be NULL */, - double *angle1 /* may be NULL */, - glyphy_bool_t *negative /* may be NULL */) -{ - Arc a (arc); - if (radius) *radius = a.radius (); - if (center || angle0 || angle1) { - Point c = a.center (); - if (center) *center = c; - if (angle0) *angle0 = (a.p0 - c).angle (); - if (angle1) *angle1 = (a.p1 - c).angle (); - if (negative) *negative = a.d < 0; - } -} - -glyphy_bool_t -glyphy_arc_is_a_line (glyphy_arc_t arc) -{ - return arc.d == 0; -} - -void -glyphy_arc_extents (glyphy_arc_t arc, - glyphy_extents_t *extents) -{ - Arc(arc).extents (*extents); -} - - -/* - * Approximate single pieces of geometry to/from one arc - */ - - -void -glyphy_arc_from_line (const glyphy_point_t *p0, - const glyphy_point_t *p1, - glyphy_arc_t *arc) -{ - *arc = Arc (*p0, *p1, 0); -} - -void -glyphy_arc_from_conic (const glyphy_point_t *p0, - const glyphy_point_t *p1, - const glyphy_point_t *p2, - glyphy_arc_t *arc, - double *error) -{ - Point p1_ (Point (*p0).lerp (2/3., *p1)); - Point p2_ (Point (*p2).lerp (2/3., *p1)); - glyphy_arc_from_cubic (p0, - &p1_, - &p2_, - p2, - arc, - error); -} - -void -glyphy_arc_from_cubic (const glyphy_point_t *p0, - const glyphy_point_t *p1, - const glyphy_point_t *p2, - const glyphy_point_t *p3, - glyphy_arc_t *arc, - double *error) -{ - *arc = ArcBezierApproximatorDefault::approximate_bezier_with_arc (Bezier (*p0, *p1, *p2, *p3), error); -} - -void -glyphy_arc_to_cubic (const glyphy_arc_t *arc, - glyphy_point_t *p0, - glyphy_point_t *p1, - glyphy_point_t *p2, - glyphy_point_t *p3, - double *error) -{ - Bezier b = Arc (*arc).approximate_bezier (error); - *p0 = arc->p0; - *p1 = b.p1; - *p2 = b.p2; - *p3 = arc->p1; -} diff --git a/bin/glyphy/glyphy-arcs-bezier.hh b/bin/glyphy/glyphy-arcs-bezier.hh @@ -1,153 +0,0 @@ -/* - * Copyright 2012 Google, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Google Author(s): Behdad Esfahbod, Maysum Panju - */ - -#ifndef GLYPHY_ARCS_BEZIER_HH -#define GLYPHY_ARCS_BEZIER_HH - -#include "glyphy-common.hh" -#include "glyphy-geometry.hh" -#include "glyphy-arc-bezier.hh" - -namespace GLyphy { -namespace ArcsBezier { - -using namespace Geometry; -using namespace ArcBezier; - -template <class ArcBezierApproximator> -class ArcsBezierApproximatorSpringSystem -{ - static inline void calc_arcs (const Bezier &b, - const std::vector<double> &t, - const ArcBezierApproximator &appx, - std::vector<double> &e, - std::vector<Arc > &arcs, - double &max_e, double &min_e) - { - unsigned int n = t.size () - 1; - e.resize (n); - arcs.clear (); - max_e = 0; - min_e = GLYPHY_INFINITY; - for (unsigned int i = 0; i < n; i++) - { - Bezier segment = b.segment (t[i], t[i + 1]); - arcs.push_back (appx.approximate_bezier_with_arc (segment, &e[i])); - - max_e = std::max (max_e, e[i]); - min_e = std::min (min_e, e[i]); - } - } - - static inline void jiggle (const Bezier &b, - const ArcBezierApproximator &appx, - std::vector<double> &t, - std::vector<double> &e, - std::vector<Arc > &arcs, - double &max_e, double &min_e, - double tolerance, - unsigned int &n_jiggle) - { - unsigned int n = t.size () - 1; - double conditioner = tolerance * .01; - //fprintf (stderr, "candidate n %d max_e %g min_e %g\n", n, max_e, min_e); - unsigned int max_jiggle = log2 (n) + 1; - unsigned int s; - for (s = 0; s < max_jiggle; s++) - { - double total = 0; - for (unsigned int i = 0; i < n; i++) { - double l = t[i + 1] - t[i]; - double k_inv = l * pow (e[i] + conditioner, -.3); - total += k_inv; - e[i] = k_inv; - } - for (unsigned int i = 0; i < n; i++) { - double k_inv = e[i]; - double l = k_inv / total; - t[i + 1] = t[i] + l; - } - t[n] = 1.0; // Do this to get real 1.0, not .9999999999999998! - - calc_arcs (b, t, appx, e, arcs, max_e, min_e); - - //fprintf (stderr, "n %d jiggle %d max_e %g min_e %g\n", n, s, max_e, min_e); - - n_jiggle++; - if (max_e < tolerance || (2 * min_e - max_e > tolerance)) - break; - } - //if (s == max_jiggle) fprintf (stderr, "JIGGLE OVERFLOW n %d s %d\n", n, s); - } - - public: - static void approximate_bezier_with_arcs (const Bezier &b, - double tolerance, - const ArcBezierApproximator &appx, - std::vector<Arc> &arcs, - double *perror, - unsigned int max_segments = 100) - { - /* Handle fully-degenerate cases. */ - Vector v1 (b.p1 - b.p0); - Vector v2 (b.p2 - b.p0); - Vector v3 (b.p3 - b.p0); - if (fabs (v1.cross(v2)) < GLYPHY_EPSILON && fabs (v2.cross(v3)) < GLYPHY_EPSILON) - { - /* Curve has no area. If endpoints are NOT the same, replace with single - * line segment. Otherwise fully skip. */ - arcs.clear (); - if (b.p0 != b.p1) - arcs.push_back (Arc (b.p0, b.p1, 0)); - return; - } - - std::vector<double> t; - std::vector<double> e; - double max_e, min_e; - unsigned int n_jiggle = 0; - - /* Technically speaking we can bsearch for n. */ - for (unsigned int n = 1; n <= max_segments; n++) - { - t.resize (n + 1); - for (unsigned int i = 0; i < n; i++) - t[i] = double (i) / n; - t[n] = 1.0; // Do this out of the loop to get real 1.0, not .9999999999999998! - - calc_arcs (b, t, appx, e, arcs, max_e, min_e); - - for (unsigned int i = 0; i < n; i++) - if (e[i] <= tolerance) { - jiggle (b, appx, t, e, arcs, max_e, min_e, tolerance, n_jiggle); - break; - } - - if (max_e <= tolerance) - break; - } - if (perror) - *perror = max_e; - //fprintf (stderr, "n_jiggle %d\n", n_jiggle); - } -}; - -} /* namespace ArcsBezier */ -} /* namespace GLyphy */ - -#endif /* GLYPHY_ARCS_BEZIER_HH */ diff --git a/bin/glyphy/glyphy-arcs.cc b/bin/glyphy/glyphy-arcs.cc @@ -1,320 +0,0 @@ -/* - * Copyright 2012 Google, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Google Author(s): Behdad Esfahbod, Maysum Panju, Wojciech Baranowski - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "glyphy-common.hh" -#include "glyphy-geometry.hh" -#include "glyphy-arcs-bezier.hh" - -using namespace GLyphy::Geometry; -using namespace GLyphy::ArcsBezier; - - - -/* - * Approximate outlines with multiple arcs - */ - - -struct glyphy_arc_accumulator_t { - unsigned int refcount; - - double tolerance; - double max_d; - unsigned int d_bits; - glyphy_arc_endpoint_accumulator_callback_t callback; - void *user_data; - - glyphy_point_t start_point; - glyphy_point_t current_point; - bool need_moveto; - unsigned int num_endpoints; - double max_error; - glyphy_bool_t success; -}; - - -glyphy_arc_accumulator_t * -glyphy_arc_accumulator_create (void) -{ - glyphy_arc_accumulator_t *acc = (glyphy_arc_accumulator_t *) calloc (1, sizeof (glyphy_arc_accumulator_t)); - acc->refcount = 1; - - acc->tolerance = 5e-4; - acc->max_d = GLYPHY_MAX_D; - acc->d_bits = 8; - acc->callback = NULL; - acc->user_data = NULL; - - glyphy_arc_accumulator_reset (acc); - - return acc; -} - -void -glyphy_arc_accumulator_reset (glyphy_arc_accumulator_t *acc) -{ - acc->start_point = acc->current_point = Point (0, 0); - acc->need_moveto = true; - acc->num_endpoints = 0; - acc->max_error = 0; - acc->success = true; -} - -void -glyphy_arc_accumulator_destroy (glyphy_arc_accumulator_t *acc) -{ - if (!acc || --acc->refcount) - return; - - free (acc); -} - -glyphy_arc_accumulator_t * -glyphy_arc_accumulator_reference (glyphy_arc_accumulator_t *acc) -{ - if (acc) - acc->refcount++; - return acc; -} - - -/* Configure acc */ - -void -glyphy_arc_accumulator_set_tolerance (glyphy_arc_accumulator_t *acc, - double tolerance) -{ - acc->tolerance = tolerance; -} - -double -glyphy_arc_accumulator_get_tolerance (glyphy_arc_accumulator_t *acc) -{ - return acc->tolerance; -} - -void -glyphy_arc_accumulator_set_callback (glyphy_arc_accumulator_t *acc, - glyphy_arc_endpoint_accumulator_callback_t callback, - void *user_data) -{ - acc->callback = callback; - acc->user_data = user_data; -} - -void -glyphy_arc_accumulator_get_callback (glyphy_arc_accumulator_t *acc, - glyphy_arc_endpoint_accumulator_callback_t *callback, - void **user_data) -{ - *callback = acc->callback; - *user_data = acc->user_data; -} - -void -glyphy_arc_accumulator_set_d_metrics (glyphy_arc_accumulator_t *acc, - double max_d, - double d_bits) -{ - acc->max_d = max_d; - acc->d_bits = d_bits; -} - -void -glyphy_arc_accumulator_get_d_metrics (glyphy_arc_accumulator_t *acc, - double *max_d, - double *d_bits) -{ - *max_d = acc->max_d; - *d_bits = acc->d_bits; -} - - -/* Accumulation results */ - -unsigned int -glyphy_arc_accumulator_get_num_endpoints (glyphy_arc_accumulator_t *acc) -{ - return acc->num_endpoints; -} - -double -glyphy_arc_accumulator_get_error (glyphy_arc_accumulator_t *acc) -{ - return acc->max_error; -} - -glyphy_bool_t -glyphy_arc_accumulator_successful (glyphy_arc_accumulator_t *acc) -{ - return acc->success; -} - - -/* Accumulate */ - -static void -emit (glyphy_arc_accumulator_t *acc, const Point &p, double d) -{ - glyphy_arc_endpoint_t endpoint = {p, d}; - acc->success = acc->success && acc->callback (&endpoint, acc->user_data); - if (acc->success) { - acc->num_endpoints++; - acc->current_point = p; - } -} - -static void -accumulate (glyphy_arc_accumulator_t *acc, const Point &p, double d) -{ - if (Point (acc->current_point) == p) - return; - if (d == GLYPHY_INFINITY) { - /* Emit moveto lazily, for cleaner outlines */ - acc->need_moveto = true; - acc->current_point = p; - return; - } - if (acc->need_moveto) { - emit (acc, acc->current_point, GLYPHY_INFINITY); - if (acc->success) { - acc->start_point = acc->current_point; - acc->need_moveto = false; - } - } - emit (acc, p, d); -} - -static void -move_to (glyphy_arc_accumulator_t *acc, const Point &p) -{ - if (!acc->num_endpoints || p != acc->current_point) - accumulate (acc, p, GLYPHY_INFINITY); -} - -static void -arc_to (glyphy_arc_accumulator_t *acc, const Point &p1, double d) -{ - accumulate (acc, p1, d); -} - -static void -bezier (glyphy_arc_accumulator_t *acc, const Bezier &b) -{ - double e; - - std::vector<Arc> arcs; - typedef ArcBezierApproximatorQuantizedDefault _ArcBezierApproximator; - _ArcBezierApproximator appx (acc->max_d, acc->d_bits); - ArcsBezierApproximatorSpringSystem<_ArcBezierApproximator> - ::approximate_bezier_with_arcs (b, acc->tolerance, appx, arcs, &e); - - acc->max_error = std::max (acc->max_error, e); - - move_to (acc, b.p0); - for (unsigned int i = 0; i < arcs.size (); i++) - arc_to (acc, arcs[i].p1, arcs[i].d); -} - -static void -close_path (glyphy_arc_accumulator_t *acc) -{ - if (!acc->need_moveto && Point (acc->current_point) != Point (acc->start_point)) - arc_to (acc, acc->start_point, 0); -} - -void -glyphy_arc_accumulator_move_to (glyphy_arc_accumulator_t *acc, - const glyphy_point_t *p0) -{ - move_to (acc, *p0); -} - -void -glyphy_arc_accumulator_line_to (glyphy_arc_accumulator_t *acc, - const glyphy_point_t *p1) -{ - arc_to (acc, *p1, 0); -} - -void -glyphy_arc_accumulator_conic_to (glyphy_arc_accumulator_t *acc, - const glyphy_point_t *p1, - const glyphy_point_t *p2) -{ - bezier (acc, Bezier (acc->current_point, - Point (acc->current_point).lerp (2/3., *p1), - Point (*p2).lerp (2/3., *p1), - *p2)); -} - -void -glyphy_arc_accumulator_cubic_to (glyphy_arc_accumulator_t *acc, - const glyphy_point_t *p1, - const glyphy_point_t *p2, - const glyphy_point_t *p3) -{ - bezier (acc, Bezier (acc->current_point, *p1, *p2, *p3)); -} - -void -glyphy_arc_accumulator_arc_to (glyphy_arc_accumulator_t *acc, - const glyphy_point_t *p1, - double d) -{ - arc_to (acc, *p1, d); -} - -void -glyphy_arc_accumulator_close_path (glyphy_arc_accumulator_t *acc) -{ - close_path (acc); -} - - - -/* - * Outline extents from arc list - */ - - -void -glyphy_arc_list_extents (const glyphy_arc_endpoint_t *endpoints, - unsigned int num_endpoints, - glyphy_extents_t *extents) -{ - Point p0 (0, 0); - glyphy_extents_clear (extents); - for (unsigned int i = 0; i < num_endpoints; i++) { - const glyphy_arc_endpoint_t &endpoint = endpoints[i]; - if (endpoint.d == GLYPHY_INFINITY) { - p0 = endpoint.p; - continue; - } - Arc arc (p0, endpoint.p, endpoint.d); - p0 = endpoint.p; - - glyphy_extents_t arc_extents; - arc.extents (arc_extents); - glyphy_extents_extend (extents, &arc_extents); - } -} diff --git a/bin/glyphy/glyphy-blob.cc b/bin/glyphy/glyphy-blob.cc @@ -1,328 +0,0 @@ -/* - * Copyright 2012 Google, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Google Author(s): Behdad Esfahbod, Maysum Panju, Wojciech Baranowski - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "glyphy-common.hh" -#include "glyphy-geometry.hh" - -#define GRID_SIZE 24 - -using namespace GLyphy::Geometry; - - -#define UPPER_BITS(v,bits,total_bits) ((v) >> ((total_bits) - (bits))) -#define LOWER_BITS(v,bits,total_bits) ((v) & ((1 << (bits)) - 1)) - -#define MAX_X 4095 -#define MAX_Y 4095 - -static inline glyphy_rgba_t -arc_endpoint_encode (unsigned int ix, unsigned int iy, double d) -{ - glyphy_rgba_t v; - - /* 12 bits for each of x and y, 8 bits for d */ - assert (ix <= MAX_X); - assert (iy <= MAX_Y); - unsigned int id; - if (std::isinf (d)) - id = 0; - else { - assert (fabs (d) <= GLYPHY_MAX_D); - id = 128 + lround (d * 127 / GLYPHY_MAX_D); - } - assert (id < 256); - - v.r = id; - v.g = LOWER_BITS (ix, 8, 12); - v.b = LOWER_BITS (iy, 8, 12); - v.a = ((ix >> 8) << 4) | (iy >> 8); - return v; -} - -static inline glyphy_rgba_t -arc_list_encode (unsigned int offset, unsigned int num_points, int side) -{ - glyphy_rgba_t v; - v.r = 0; // unused for arc-list encoding - v.g = UPPER_BITS (offset, 8, 16); - v.b = LOWER_BITS (offset, 8, 16); - v.a = LOWER_BITS (num_points, 8, 8); - if (side < 0 && !num_points) - v.a = 255; - return v; -} - -static inline glyphy_rgba_t -line_encode (const Line &line) -{ - Line l = line.normalized (); - double angle = l.n.angle (); - double distance = l.c; - - int ia = lround (-angle / M_PI * 0x7FFF); - unsigned int ua = ia + 0x8000; - assert (0 == (ua & ~0xFFFF)); - - int id = lround (distance * 0x1FFF); - unsigned int ud = id + 0x4000; - assert (0 == (ud & ~0x7FFF)); - - /* Marker for line-encoded */ - ud |= 0x8000; - - glyphy_rgba_t v; - v.r = ud >> 8; - v.g = ud & 0xFF; - v.b = ua >> 8; - v.a = ua & 0xFF; - return v; -} - - -/* Given a cell, fills the vector closest_arcs with arcs that may be closest to some point in the cell. - * Uses idea that all close arcs to cell must be ~close to center of cell. - */ -static void -closest_arcs_to_cell (Point c0, Point c1, /* corners */ - double faraway, - const glyphy_arc_endpoint_t *endpoints, - unsigned int num_endpoints, - std::vector<glyphy_arc_endpoint_t> &near_endpoints, - int *side) -{ - // Find distance between cell center - Point c = c0.midpoint (c1); - double min_dist = glyphy_sdf_from_arc_list (endpoints, num_endpoints, &c, NULL); - - *side = min_dist >= 0 ? +1 : -1; - min_dist = fabs (min_dist); - std::vector<Arc> near_arcs; - - // If d is the distance from the center of the square to the nearest arc, then - // all nearest arcs to the square must be at most almost [d + half_diagonal] from the center. - double half_diagonal = (c - c0).len (); - double radius_squared = pow (min_dist + half_diagonal, 2); - if (min_dist - half_diagonal <= faraway) { - Point p0 (0, 0); - for (unsigned int i = 0; i < num_endpoints; i++) { - const glyphy_arc_endpoint_t &endpoint = endpoints[i]; - if (endpoint.d == GLYPHY_INFINITY) { - p0 = endpoint.p; - continue; - } - Arc arc (p0, endpoint.p, endpoint.d); - p0 = endpoint.p; - - if (arc.squared_distance_to_point (c) <= radius_squared) - near_arcs.push_back (arc); - } - } - - Point p1 = Point (0, 0); - for (unsigned i = 0; i < near_arcs.size (); i++) - { - Arc arc = near_arcs[i]; - - if (i == 0 || p1 != arc.p0) { - glyphy_arc_endpoint_t endpoint = {arc.p0, GLYPHY_INFINITY}; - near_endpoints.push_back (endpoint); - p1 = arc.p0; - } - - glyphy_arc_endpoint_t endpoint = {arc.p1, arc.d}; - near_endpoints.push_back (endpoint); - p1 = arc.p1; - } -} - - -glyphy_bool_t -glyphy_arc_list_encode_blob (const glyphy_arc_endpoint_t *endpoints, - unsigned int num_endpoints, - glyphy_rgba_t *blob, - unsigned int blob_size, - double faraway, - double avg_fetch_desired, - double *avg_fetch_achieved, - unsigned int *output_len, - unsigned int *nominal_width, /* 8bit */ - unsigned int *nominal_height, /* 8bit */ - glyphy_extents_t *pextents) -{ - glyphy_extents_t extents; - glyphy_extents_clear (&extents); - - glyphy_arc_list_extents (endpoints, num_endpoints, &extents); - - if (glyphy_extents_is_empty (&extents)) { - *pextents = extents; - if (!blob_size) - return false; - *blob = arc_list_encode (0, 0, +1); - *avg_fetch_achieved = 1; - *output_len = 1; - *nominal_width = *nominal_height = 1; - return true; - } - - /* Add antialiasing padding */ - extents.min_x -= faraway; - extents.min_y -= faraway; - extents.max_x += faraway; - extents.max_y += faraway; - - double glyph_width = extents.max_x - extents.min_x; - double glyph_height = extents.max_y - extents.min_y; - double unit = std::max (glyph_width, glyph_height); - - unsigned int grid_w = GRID_SIZE; - unsigned int grid_h = GRID_SIZE; - - if (glyph_width > glyph_height) { - while ((grid_h - 1) * unit / grid_w > glyph_height) - grid_h--; - glyph_height = grid_h * unit / grid_w; - extents.max_y = extents.min_y + glyph_height; - } else { - while ((grid_w - 1) * unit / grid_h > glyph_width) - grid_w--; - glyph_width = grid_w * unit / grid_h; - extents.max_x = extents.min_x + glyph_width; - } - - double cell_unit = unit / std::max (grid_w, grid_h); - - std::vector<glyphy_rgba_t> tex_data; - std::vector<glyphy_arc_endpoint_t> near_endpoints; - - unsigned int header_length = grid_w * grid_h; - unsigned int offset = header_length; - tex_data.resize (header_length); - Point origin = Point (extents.min_x, extents.min_y); - unsigned int total_arcs = 0; - - for (unsigned int row = 0; row < grid_h; row++) - for (unsigned int col = 0; col < grid_w; col++) - { - Point cp0 = origin + Vector ((col + 0) * cell_unit, (row + 0) * cell_unit); - Point cp1 = origin + Vector ((col + 1) * cell_unit, (row + 1) * cell_unit); - near_endpoints.clear (); - - int side; - closest_arcs_to_cell (cp0, cp1, - faraway, - endpoints, num_endpoints, - near_endpoints, - &side); - -#define QUANTIZE_X(X) (lround (MAX_X * ((X - extents.min_x) / glyph_width ))) -#define QUANTIZE_Y(Y) (lround (MAX_Y * ((Y - extents.min_y) / glyph_height))) -#define DEQUANTIZE_X(X) (double (X) / MAX_X * glyph_width + extents.min_x) -#define DEQUANTIZE_Y(Y) (double (Y) / MAX_Y * glyph_height + extents.min_y) -#define SNAP(P) (Point (DEQUANTIZE_X (QUANTIZE_X ((P).x)), DEQUANTIZE_Y (QUANTIZE_Y ((P).y)))) - - if (near_endpoints.size () == 2 && near_endpoints[1].d == 0) { - Point c (extents.min_x + glyph_width * .5, extents.min_y + glyph_height * .5); - Line line (SNAP (near_endpoints[0].p), SNAP (near_endpoints[1].p)); - line.c -= line.n * Vector (c); - line.c /= unit; - tex_data[row * grid_w + col] = line_encode (line); - continue; - } - - /* If the arclist is two arcs that can be combined in encoding if reordered, - * do that. */ - if (near_endpoints.size () == 4 && - std::isinf (near_endpoints[2].d) && - near_endpoints[0].p.x == near_endpoints[3].p.x && - near_endpoints[0].p.y == near_endpoints[3].p.y) - { - glyphy_arc_endpoint_t e0, e1, e2; - e0 = near_endpoints[2]; - e1 = near_endpoints[3]; - e2 = near_endpoints[1]; - near_endpoints.resize (0); - near_endpoints.push_back (e0); - near_endpoints.push_back (e1); - near_endpoints.push_back (e2); - } - - for (unsigned i = 0; i < near_endpoints.size (); i++) { - glyphy_arc_endpoint_t &endpoint = near_endpoints[i]; - tex_data.push_back (arc_endpoint_encode (QUANTIZE_X(endpoint.p.x), QUANTIZE_Y(endpoint.p.y), endpoint.d)); - } - - unsigned int current_endpoints = tex_data.size () - offset; - - if (current_endpoints) - { - /* See if we can fulfill this cell by using already-encoded arcs */ - const glyphy_rgba_t *needle = &tex_data[offset]; - unsigned int needle_len = current_endpoints; - const glyphy_rgba_t *haystack = &tex_data[header_length]; - unsigned int haystack_len = offset - header_length; - - bool found = false; - while (haystack_len >= needle_len) { - /* Trick: we don't care about first endpoint's d value, so skip one - * byte in comparison. This works because arc_encode() packs the - * d value in the first byte. */ - if (0 == memcmp (1 + (const char *) needle, - 1 + (const char *) haystack, - needle_len * sizeof (*needle) - 1)) { - found = true; - break; - } - haystack++; - haystack_len--; - } - if (found) { - unsigned int new_offset = haystack - &tex_data[0]; - tex_data.resize (offset); - haystack = needle = NULL; /* Invalidated by the resize. */ - offset = new_offset; - } - } - else - offset = 0; - - tex_data[row * grid_w + col] = arc_list_encode (offset, current_endpoints, side); - offset = tex_data.size (); - - total_arcs += current_endpoints; - } - - if (avg_fetch_achieved) - *avg_fetch_achieved = 1 + double (total_arcs) / (grid_w * grid_h); - - *pextents = extents; - - if (tex_data.size () > blob_size) - return false; - - memcpy (blob, &tex_data[0], tex_data.size () * sizeof(tex_data[0])); - *output_len = tex_data.size (); - *nominal_width = grid_w; - *nominal_height = grid_h; - - return true; -} diff --git a/bin/glyphy/glyphy-common.glsl b/bin/glyphy/glyphy-common.glsl @@ -1,222 +0,0 @@ -/* - * Copyright 2012 Google, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Google Author(s): Behdad Esfahbod, Maysum Panju - */ - - -#ifndef GLYPHY_INFINITY -# define GLYPHY_INFINITY 1e9 -#endif -#ifndef GLYPHY_EPSILON -# define GLYPHY_EPSILON 1e-5 -#endif - -#ifndef GLYPHY_RGBA -# ifdef GLYPHY_BGRA -# define GLYPHY_RGBA(v) glyphy_bgra (v) -# else -# define GLYPHY_RGBA(v) glyphy_rgba (v) -# endif -#endif - -vec4 -glyphy_rgba (const vec4 v) -{ - return v.rgba; -} - -vec4 -glyphy_bgra (const vec4 v) -{ - return v.bgra; -} - - -struct glyphy_arc_t { - vec2 p0; - vec2 p1; - float d; -}; - -struct glyphy_arc_endpoint_t { - /* Second arc endpoint */ - vec2 p; - /* Infinity if this endpoint does not form an arc with the previous - * endpoint. Ie. a "move_to". Test with glyphy_isinf(). - * Arc depth otherwise. */ - float d; -}; - -struct glyphy_arc_list_t { - /* Number of endpoints in the list. - * Will be zero if we're far away inside or outside, in which case side is set. - * Will be -1 if this arc-list encodes a single line, in which case line_* are set. */ - int num_endpoints; - - /* If num_endpoints is zero, this specifies whether we are inside (-1) - * or outside (+1). Otherwise we're unsure (0). */ - int side; - /* Offset to the arc-endpoints from the beginning of the glyph blob */ - int offset; - - /* A single line is all we care about. It's right here. */ - float line_angle; - float line_distance; /* From nominal glyph center */ -}; - -bool -glyphy_isinf (const float v) -{ - return abs (v) >= GLYPHY_INFINITY * .5; -} - -bool -glyphy_iszero (const float v) -{ - return abs (v) <= GLYPHY_EPSILON * 2.; -} - -vec2 -glyphy_ortho (const vec2 v) -{ - return vec2 (-v.y, v.x); -} - -int -glyphy_float_to_byte (const float v) -{ - return int (v * (256. - GLYPHY_EPSILON)); -} - -ivec4 -glyphy_vec4_to_bytes (const vec4 v) -{ - return ivec4 (v * (256. - GLYPHY_EPSILON)); -} - -ivec2 -glyphy_float_to_two_nimbles (const float v) -{ - int f = glyphy_float_to_byte (v); - return ivec2 (f / 16, int(mod (float(f), 16.))); -} - -/* returns tan (2 * atan (d)) */ -float -glyphy_tan2atan (const float d) -{ - return 2. * d / (1. - d * d); -} - -glyphy_arc_endpoint_t -glyphy_arc_endpoint_decode (const vec4 v, const ivec2 nominal_size) -{ - vec2 p = (vec2 (glyphy_float_to_two_nimbles (v.a)) + v.gb) / 16.; - float d = v.r; - if (d == 0.) - d = GLYPHY_INFINITY; - else -#define GLYPHY_MAX_D .5 - d = float(glyphy_float_to_byte (d) - 128) * GLYPHY_MAX_D / 127.; -#undef GLYPHY_MAX_D - return glyphy_arc_endpoint_t (p * vec2(nominal_size), d); -} - -vec2 -glyphy_arc_center (const glyphy_arc_t a) -{ - return mix (a.p0, a.p1, .5) + - glyphy_ortho (a.p1 - a.p0) / (2. * glyphy_tan2atan (a.d)); -} - -bool -glyphy_arc_wedge_contains (const glyphy_arc_t a, const vec2 p) -{ - float d2 = glyphy_tan2atan (a.d); - return dot (p - a.p0, (a.p1 - a.p0) * mat2(1, d2, -d2, 1)) >= 0. && - dot (p - a.p1, (a.p1 - a.p0) * mat2(1, -d2, d2, 1)) <= 0.; -} - -float -glyphy_arc_wedge_signed_dist_shallow (const glyphy_arc_t a, const vec2 p) -{ - vec2 v = normalize (a.p1 - a.p0); - float line_d = dot (p - a.p0, glyphy_ortho (v)); - if (a.d == 0.) - return line_d; - - float d0 = dot ((p - a.p0), v); - if (d0 < 0.) - return sign (line_d) * distance (p, a.p0); - float d1 = dot ((a.p1 - p), v); - if (d1 < 0.) - return sign (line_d) * distance (p, a.p1); - float r = 2. * a.d * (d0 * d1) / (d0 + d1); - if (r * line_d > 0.) - return sign (line_d) * min (abs (line_d + r), min (distance (p, a.p0), distance (p, a.p1))); - return line_d + r; -} - -float -glyphy_arc_wedge_signed_dist (const glyphy_arc_t a, const vec2 p) -{ - if (abs (a.d) <= .03) - return glyphy_arc_wedge_signed_dist_shallow (a, p); - vec2 c = glyphy_arc_center (a); - return sign (a.d) * (distance (a.p0, c) - distance (p, c)); -} - -float -glyphy_arc_extended_dist (const glyphy_arc_t a, const vec2 p) -{ - /* Note: this doesn't handle points inside the wedge. */ - vec2 m = mix (a.p0, a.p1, .5); - float d2 = glyphy_tan2atan (a.d); - if (dot (p - m, a.p1 - m) < 0.) - return dot (p - a.p0, normalize ((a.p1 - a.p0) * mat2(+d2, -1, +1, +d2))); - else - return dot (p - a.p1, normalize ((a.p1 - a.p0) * mat2(-d2, -1, +1, -d2))); -} - -int -glyphy_arc_list_offset (const vec2 p, const ivec2 nominal_size) -{ - ivec2 cell = ivec2 (clamp (floor (p), vec2 (0.,0.), vec2(nominal_size - 1))); - return cell.y * nominal_size.x + cell.x; -} - -glyphy_arc_list_t -glyphy_arc_list_decode (const vec4 v, const ivec2 nominal_size) -{ - glyphy_arc_list_t l; - ivec4 iv = glyphy_vec4_to_bytes (v); - l.side = 0; /* unsure */ - if (iv.r == 0) { /* arc-list encoded */ - l.offset = (iv.g * 256) + iv.b; - l.num_endpoints = iv.a; - if (l.num_endpoints == 255) { - l.num_endpoints = 0; - l.side = -1; - } else if (l.num_endpoints == 0) - l.side = +1; - } else { /* single line encoded */ - l.num_endpoints = -1; - l.line_distance = float(((iv.r - 128) * 256 + iv.g) - 0x4000) / float (0x1FFF) - * max (float (nominal_size.x), float (nominal_size.y)); - l.line_angle = float(-((iv.b * 256 + iv.a) - 0x8000)) / float (0x7FFF) * 3.14159265358979; - } - return l; -} diff --git a/bin/glyphy/glyphy-common.hh b/bin/glyphy/glyphy-common.hh @@ -1,62 +0,0 @@ -/* - * Copyright 2012 Google, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Google Author(s): Behdad Esfahbod, Maysum Panju - */ - -#ifndef GLYPHY_COMMON_HH -#define GLYPHY_COMMON_HH - -#include <glyphy.h> - -#define _USE_MATH_DEFINES // Used on Windows to bring in math constants. -#include <cmath> -#include <math.h> -#include <string.h> -#include <assert.h> -#include <stdio.h> -#include <vector> -#include <algorithm> -#include <iostream> - -#ifndef GLYPHY_EPSILON -# define GLYPHY_EPSILON 1e-5 -#endif -#ifndef GLYPHY_INFINITY -# define GLYPHY_INFINITY INFINITY -#endif - - -static inline bool -iszero (double v) -{ - return fabs (v) < 2 * GLYPHY_EPSILON; -} - - -#define GLYPHY_MAX_D .5 - -#undef ARRAY_LENGTH -#define ARRAY_LENGTH(__array) ((signed int) (sizeof (__array) / sizeof (__array[0]))) - -#define _ASSERT_STATIC1(_line, _cond) typedef int _static_assert_on_line_##_line##_failed[(_cond)?1:-1] -#define _ASSERT_STATIC0(_line, _cond) _ASSERT_STATIC1 (_line, (_cond)) -#define ASSERT_STATIC(_cond) _ASSERT_STATIC0 (__LINE__, (_cond)) - -#ifdef __ANDROID__ -#define log2(x) (log(x) / log(2.0)) -#endif - -#endif /* GLYPHY_COMMON_HH */ diff --git a/bin/glyphy/glyphy-extents.cc b/bin/glyphy/glyphy-extents.cc @@ -1,89 +0,0 @@ -/* - * Copyright 2012 Google, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Google Author(s): Behdad Esfahbod - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "glyphy-common.hh" - - -void -glyphy_extents_clear (glyphy_extents_t *extents) -{ - extents->min_x = GLYPHY_INFINITY; - extents->min_y = GLYPHY_INFINITY; - extents->max_x = -GLYPHY_INFINITY; - extents->max_y = -GLYPHY_INFINITY; -} - -glyphy_bool_t -glyphy_extents_is_empty (const glyphy_extents_t *extents) -{ - return std::isinf (extents->min_x); -} - -void -glyphy_extents_add (glyphy_extents_t *extents, - const glyphy_point_t *p) -{ - if (glyphy_extents_is_empty (extents)) { - extents->min_x = extents->max_x = p->x; - extents->min_y = extents->max_y = p->y; - return; - } - extents->min_x = std::min (extents->min_x, p->x); - extents->min_y = std::min (extents->min_y, p->y); - extents->max_x = std::max (extents->max_x, p->x); - extents->max_y = std::max (extents->max_y, p->y); -} - -void -glyphy_extents_extend (glyphy_extents_t *extents, - const glyphy_extents_t *other) -{ - if (glyphy_extents_is_empty (other)) - return; - if (glyphy_extents_is_empty (extents)) { - *extents = *other; - return; - } - extents->min_x = std::min (extents->min_x, other->min_x); - extents->min_y = std::min (extents->min_y, other->min_y); - extents->max_x = std::max (extents->max_x, other->max_x); - extents->max_y = std::max (extents->max_y, other->max_y); -} - -glyphy_bool_t -glyphy_extents_includes (const glyphy_extents_t *extents, - const glyphy_point_t *p) -{ - return extents->min_x <= p->x && p->x <= extents->max_x && - extents->min_y <= p->y && p->y <= extents->max_y; -} - -void -glyphy_extents_scale (glyphy_extents_t *extents, - double x_scale, - double y_scale) -{ - extents->min_x *= x_scale; - extents->max_x *= x_scale; - extents->min_y *= y_scale; - extents->max_y *= y_scale; -} diff --git a/bin/glyphy/glyphy-freetype.h b/bin/glyphy/glyphy-freetype.h @@ -1,102 +0,0 @@ -/* - * Copyright 2012 Google, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Google Author(s): Behdad Esfahbod, Maysum Panju - */ - -/* Intentionally doesn't have include guards */ - -#include "glyphy.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -#include <ft2build.h> -#include FT_FREETYPE_H -#include FT_OUTLINE_H - - - -#ifndef GLYPHY_FREETYPE_PREFIX -#define GLYPHY_FREETYPE_PREFIX glyphy_freetype_ -#endif - -#ifndef glyphy_freetype -#define glyphy_freetype(name) GLYPHY_PASTE (GLYPHY_FREETYPE_PREFIX, name) -#endif - - - -static int -glyphy_freetype(move_to) (FT_Vector *to, - glyphy_arc_accumulator_t *acc) -{ - glyphy_point_t p1 = {(double) to->x, (double) to->y}; - glyphy_arc_accumulator_close_path (acc); - glyphy_arc_accumulator_move_to (acc, &p1); - return glyphy_arc_accumulator_successful (acc) ? FT_Err_Ok : FT_Err_Out_Of_Memory; -} - -static int -glyphy_freetype(line_to) (FT_Vector *to, - glyphy_arc_accumulator_t *acc) -{ - glyphy_point_t p1 = {(double) to->x, (double) to->y}; - glyphy_arc_accumulator_line_to (acc, &p1); - return glyphy_arc_accumulator_successful (acc) ? FT_Err_Ok : FT_Err_Out_Of_Memory; -} - -static int -glyphy_freetype(conic_to) (FT_Vector *control, FT_Vector *to, - glyphy_arc_accumulator_t *acc) -{ - glyphy_point_t p1 = {(double) control->x, (double) control->y}; - glyphy_point_t p2 = {(double) to->x, (double) to->y}; - glyphy_arc_accumulator_conic_to (acc, &p1, &p2); - return glyphy_arc_accumulator_successful (acc) ? FT_Err_Ok : FT_Err_Out_Of_Memory; -} - -static int -glyphy_freetype(cubic_to) (FT_Vector *control1, FT_Vector *control2, FT_Vector *to, - glyphy_arc_accumulator_t *acc) -{ - glyphy_point_t p1 = {(double) control1->x, (double) control1->y}; - glyphy_point_t p2 = {(double) control2->x, (double) control2->y}; - glyphy_point_t p3 = {(double) to->x, (double) to->y}; - glyphy_arc_accumulator_cubic_to (acc, &p1, &p2, &p3); - return glyphy_arc_accumulator_successful (acc) ? FT_Err_Ok : FT_Err_Out_Of_Memory; -} - -static FT_Error -glyphy_freetype(outline_decompose) (const FT_Outline *outline, - glyphy_arc_accumulator_t *acc) -{ - const FT_Outline_Funcs outline_funcs = { - (FT_Outline_MoveToFunc) glyphy_freetype(move_to), - (FT_Outline_LineToFunc) glyphy_freetype(line_to), - (FT_Outline_ConicToFunc) glyphy_freetype(conic_to), - (FT_Outline_CubicToFunc) glyphy_freetype(cubic_to), - 0, /* shift */ - 0, /* delta */ - }; - - return FT_Outline_Decompose ((FT_Outline *) outline, &outline_funcs, acc); -} - -#ifdef __cplusplus -} -#endif diff --git a/bin/glyphy/glyphy-geometry.hh b/bin/glyphy/glyphy-geometry.hh @@ -1,742 +0,0 @@ -/* - * Copyright 2012,2013 Google, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Google Author(s): Behdad Esfahbod, Maysum Panju - */ - -#ifndef GLYPHY_GEOMETRY_HH -#define GLYPHY_GEOMETRY_HH - -#include "glyphy-common.hh" - -namespace GLyphy { -namespace Geometry { - -template <typename Type> struct Pair; -struct Vector; -struct SignedVector; -struct Point; -struct Line; -struct Segment; -struct Arc; -struct Bezier; - -/* returns tan (2 * atan (d)) */ -inline double tan2atan (double d) { return 2 * d / (1 - d*d); } - -/* returns sin (2 * atan (d)) */ -inline double sin2atan (double d) { return 2 * d / (1 + d*d); } - -/* returns cos (2 * atan (d)) */ -inline double cos2atan (double d) { return (1 - d*d) / (1 + d*d); } - -template <typename Type> -struct Pair { - typedef Type ElementType; - - inline Pair (const Type &first_, const Type &second_) : first (first_), second (second_) {} - - Type first, second; -}; - -struct Point : glyphy_point_t { - inline Point (double x_, double y_) { x = x_; y = y_; } - inline explicit Point (const Vector &v); - inline Point (const glyphy_point_t &p) { *(glyphy_point_t *)this = p; } - - inline bool operator == (const Point &p) const; - inline bool operator != (const Point &p) const; - inline Point& operator+= (const Vector &v); - inline Point& operator-= (const Vector &v); - inline const Point operator+ (const Vector &v) const; - inline const Point operator- (const Vector &v) const; - inline const Vector operator- (const Point &p) const; - inline const Point midpoint (const Point &p) const; - inline const Line bisector (const Point &p) const; - inline double distance_to_point (const Point &p) const; /* distance to point! */ - inline double squared_distance_to_point (const Point &p) const; /* square of distance to point! */ - - inline bool is_finite (void) const; - inline const Point lerp (const double &a, const Point &p) const; -}; - -struct Vector { - inline Vector (double dx_, double dy_) : dx (dx_), dy (dy_) {} - inline explicit Vector (const Point &p) : dx (p.x), dy (p.y) {} - - inline bool operator == (const Vector &v) const; - inline bool operator != (const Vector &v) const; - inline const Vector operator+ (void) const; - inline const Vector operator- (void) const; - inline Vector& operator+= (const Vector &v); - inline Vector& operator-= (const Vector &v); - inline Vector& operator*= (const double &s); - inline Vector& operator/= (const double &s); - inline const Vector operator+ (const Vector &v) const; - inline const Vector operator- (const Vector &v) const; - inline const Vector operator* (const double &s) const; - inline const Vector operator/ (const double &s) const; - inline double operator* (const Vector &v) const; /* dot product */ - inline const Point operator+ (const Point &p) const; - - inline bool is_nonzero (void) const; - inline double len (void) const; - inline double len2 (void) const; - inline const Vector normalized (void) const; - inline const Vector ortho (void) const; - inline const Vector normal (void) const; /* ortho().normalized() */ - inline double angle (void) const; - - inline double cross (const Vector &other) const; - inline const Vector rebase (const Vector &bx, const Vector &by) const; - inline const Vector rebase (const Vector &bx) const; - - double dx, dy; -}; - -struct SignedVector : Vector { - inline SignedVector (const Vector &v, bool negative_) : Vector (v), negative (negative_) {} - - inline bool operator == (const SignedVector &v) const; - inline bool operator != (const SignedVector &v) const; - inline const SignedVector operator- (void) const; - - bool negative; -}; - -struct Line { - inline Line (double a_, double b_, double c_) : n (a_, b_), c (c_) {} - inline Line (Vector n_, double c_) : n (n_), c (c_) {} - inline Line (const Point &p0, const Point &p1) : - n ((p1 - p0).ortho ()), c (n * Vector (p0)) {} - - inline const Point operator+ (const Line &l) const; /* line intersection! */ - inline const SignedVector operator- (const Point &p) const; /* shortest vector from point to line */ - - - inline const Line normalized (void) const; - inline const Vector normal (void) const; - - Vector n; /* line normal */ - double c; /* n.dx*x + n.dy*y = c */ -}; - -struct Segment { - inline Segment (const Point &p0_, const Point &p1_) : - p0 (p0_), p1 (p1_) {} - - inline const SignedVector operator- (const Point &p) const; /* shortest vector from point to ***line*** */ - inline double distance_to_point (const Point &p) const; /* shortest distance from point to segment */ - inline double squared_distance_to_point (const Point &p) const; /* shortest distance squared from point to segment */ - inline bool contains_in_span (const Point &p) const; /* is p in the stripe formed by sliding this segment? */ - inline double max_distance_to_arc (const Arc &a) const; - - - Point p0; - Point p1; -}; - - - -struct Arc { - inline Arc (const Point &p0_, const Point &p1_, const Point &pm, bool complement) : - p0 (p0_), p1 (p1_), - d (p0_ == pm || p1_ == pm ? 0 : - tan (((p1_-pm).angle () - (p0_-pm).angle ()) / 2 - (complement ? 0 : M_PI_2))) {} - inline Arc (const Point &p0_, const Point &p1_, const double &d_) : - p0 (p0_), p1 (p1_), d (d_) {} - inline Arc (const Point &center, double radius, const double &a0, const double &a1, bool complement) : - p0 (center + Vector (cos(a0),sin(a0)) * radius), - p1 (center + Vector (cos(a1),sin(a1)) * radius), - d (tan ((a1 - a0) / 4 - (complement ? 0 : M_PI_2))) {} - inline Arc (const glyphy_arc_t &a) : p0 (a.p0), p1 (a.p1), d (a.d) {} - inline operator glyphy_arc_t (void) const { glyphy_arc_t a = {p0, p1, d}; return a; } - - inline bool operator == (const Arc &a) const; - inline bool operator != (const Arc &a) const; - inline const SignedVector operator- (const Point &p) const; /* shortest vector from point to arc */ - - inline double radius (void) const; - inline const Point center (void) const; - inline const Pair<Vector> tangents (void) const; - - inline Bezier approximate_bezier (double *error) const; - - inline bool wedge_contains_point (const Point &p) const; - inline double distance_to_point (const Point &p) const; - inline double squared_distance_to_point (const Point &p) const; - inline double extended_dist (const Point &p) const; - - inline void extents (glyphy_extents_t &extents) const; - - Point p0, p1; - double d; /* Depth */ -}; - -struct Bezier { - inline Bezier (const Point &p0_, const Point &p1_, - const Point &p2_, const Point &p3_) : - p0 (p0_), p1 (p1_), p2 (p2_), p3 (p3_) {} - - inline const Point point (const double &t) const; - inline const Point midpoint (void) const; - inline const Vector tangent (const double &t) const; - inline const Vector d_tangent (const double &t) const; - inline double curvature (const double &t) const; - inline const Pair<Bezier> split (const double &t) const; - inline const Pair<Bezier> halve (void) const; - inline const Bezier segment (const double &t0, const double &t1) const; - - Point p0, p1, p2, p3; -}; - - -/* Implementations */ - - -/* Point */ - -inline Point::Point (const Vector &v) { - x = v.dx; - y = v.dy; -} -inline bool Point::operator == (const Point &p) const { - return x == p.x && y == p.y; -} -inline bool Point::operator != (const Point &p) const { - return !(*this == p); -} -inline Point& Point::operator+= (const Vector &v) { - x += v.dx; - y += v.dy; - return *this; -} -inline Point& Point::operator-= (const Vector &v) { - x -= v.dx; - y -= v.dy; - return *this; -} -inline const Point Point::operator+ (const Vector &v) const { - return Point (*this) += v; -} -inline const Point Point::operator- (const Vector &v) const { - return Point (*this) -= v; -} -inline const Vector Point::operator- (const Point &p) const { - return Vector (x - p.x, y - p.y); -} - -inline const Point Point::midpoint (const Point &p) const { - return *this + (p - *this) / 2; -} -inline const Line Point::bisector (const Point &p) const { - Vector d = p - *this; - return Line (d.dx * 2, d.dy * 2, d * Vector (p) + d * Vector (*this)); -} - -inline double Point::distance_to_point (const Point &p) const { - return ((*this) - p).len (); -} - -inline double Point::squared_distance_to_point (const Point &p) const { - return ((*this) - p).len2 (); -} - -inline bool Point::is_finite (void) const { - return std::isfinite (x) && std::isfinite (y); -} -inline const Point Point::lerp (const double &a, const Point &p) const { - /* The following two cases are special-cased to get better floating - * point stability. We require that points that are the same be - * bit-equal. */ - if (a == 0) return *this; - if (a == 1.0) return p; - return Point ((1-a) * x + a * p.x, (1-a) * y + a * p.y); -} - - -/* Vector */ - -inline bool Vector::operator == (const Vector &v) const { - return dx == v.dx && dy == v.dy; -} -inline bool Vector::operator != (const Vector &v) const { - return !(*this == v); -} -inline const Vector Vector::operator+ (void) const { - return *this; -} -inline const Vector Vector::operator- (void) const { - return Vector (-dx, -dy); -} -inline Vector& Vector::operator+= (const Vector &v) { - dx += v.dx; - dy += v.dy; - return *this; -} -inline Vector& Vector::operator-= (const Vector &v) { - dx -= v.dx; - dy -= v.dy; - return *this; -} -inline Vector& Vector::operator*= (const double &s) { - dx *= s; - dy *= s; - return *this; -} -inline Vector& Vector::operator/= (const double &s) { - dx /= s; - dy /= s; - return *this; -} -inline const Vector Vector::operator+ (const Vector &v) const { - return Vector (*this) += v; -} -inline const Vector Vector::operator- (const Vector &v) const { - return Vector (*this) -= v; -} -inline const Vector Vector::operator* (const double &s) const { - return Vector (*this) *= s; -} -inline const Vector operator* (const double &s, const Vector &v) { - return v * s; -} -inline const Vector Vector::operator/ (const double &s) const { - return Vector (*this) /= s; -} -inline double Vector::operator* (const Vector &v) const { /* dot product */ - return dx * v.dx + dy * v.dy; -} -inline const Point Vector::operator+ (const Point &p) const { - return p + *this; -} - -inline bool Vector::is_nonzero (void) const { - return dx || dy; -} -inline double Vector::len (void) const { - return hypot (dx, dy); -} -inline double Vector::len2 (void) const { - return dx * dx + dy * dy; -} -inline const Vector Vector::normalized (void) const { - double d = len (); - return d ? *this / d : *this; -} -inline const Vector Vector::ortho (void) const { - return Vector (-dy, dx); -} -inline const Vector Vector::normal (void) const { - return ortho ().normalized (); -} -inline double Vector::angle (void) const { - return atan2 (dy, dx); -} - -inline double Vector::cross (const Vector &other) const { - return dx * other.dy - dy * other.dx; -} -inline const Vector Vector::rebase (const Vector &bx, - const Vector &by) const { - return Vector (*this * bx, *this * by); -} -inline const Vector Vector::rebase (const Vector &bx) const { - return rebase (bx, bx.ortho ()); -} - - -/* SignedVector */ - -inline bool SignedVector::operator == (const SignedVector &v) const { - return (const Vector &)(*this) == (const Vector &)(v) && negative == v.negative; -} -inline bool SignedVector::operator != (const SignedVector &v) const { - return !(*this == v); -} -inline const SignedVector SignedVector::operator- (void) const { - return SignedVector (-(const Vector &)(*this), !negative); -} - - -/* Line */ - -inline const Point Line::operator+ (const Line &l) const { - double det = n.dx * l.n.dy - n.dy * l.n.dx; - if (!det) - return Point (GLYPHY_INFINITY, GLYPHY_INFINITY); - return Point ((c * l.n.dy - n.dy * l.c) / det, - (n.dx * l.c - c * l.n.dx) / det); -} -inline const SignedVector Line::operator- (const Point &p) const { - double mag = -(n * Vector (p) - c) / n.len (); - return SignedVector (n.normalized () * mag, mag < 0); /******************************************************************************************* FIX. *************************************/ -} - -inline const SignedVector operator- (const Point &p, const Line &l) { - return -(l - p); -} - -inline const Line Line::normalized (void) const { - double d = n.len (); - return d ? Line (n / d, c / d) : *this; -} -inline const Vector Line::normal (void) const { - return n; -} - -/* Segment */ -inline const SignedVector Segment::operator- (const Point &p) const { - /* shortest vector from point to line */ - return p - Line (p1, p0); /************************************************************************************************** Should the order (p1, p0) depend on d?? ***********************/ -} - -/* Segment */ -inline bool Segment::contains_in_span (const Point &p) const { - if (p0 == p1) - return false; - - /* shortest vector from point to line */ - Line temp (p0, p1); - double mag = -(temp.n * Vector (p) - temp.c) / temp.n.len (); - Vector y (temp.n.normalized () * mag); - Point z = y + p; - - // Check if z is between p0 and p1. - - if (fabs (p1.y - p0.y) > fabs (p1.x - p0.x)) { - return ((z.y - p0.y > 0 && p1.y - p0.y > z.y - p0.y) || - (z.y - p0.y < 0 && p1.y - p0.y < z.y - p0.y)); - } - else { - return ((0 < z.x - p0.x && z.x - p0.x < p1.x - p0.x) || - (0 > z.x - p0.x && z.x - p0.x > p1.x - p0.x)); - } -} - -inline double Segment::distance_to_point (const Point &p) const { - if (p0 == p1) - return 0; - - // Check if z is between p0 and p1. - Line temp (p0, p1); - if (contains_in_span (p)) - return -(temp.n * Vector (p) - temp.c) / temp.n.len (); - - double dist_p_p0 = p.distance_to_point (p0); - double dist_p_p1 = p.distance_to_point (p1); - return (dist_p_p0 < dist_p_p1 ? dist_p_p0 : dist_p_p1) * (-(temp.n * Vector (p) - temp.c) < 0 ? -1 : 1); -} - - -inline double Segment::squared_distance_to_point (const Point &p) const { - if (p0 == p1) - return 0; - - // Check if z is between p0 and p1. - Line temp (p0, p1); - if (contains_in_span (p)) - return (temp.n * Vector (p) - temp.c) * (temp.n * Vector (p) - temp.c) / (temp.n * temp.n); - - double dist_p_p0 = p.squared_distance_to_point (p0); - double dist_p_p1 = p.squared_distance_to_point (p1); - return (dist_p_p0 < dist_p_p1 ? dist_p_p0 : dist_p_p1); -} - - -inline double Segment::max_distance_to_arc (const Arc &a) const { - double max_distance = fabs(a.distance_to_point(p0)) ; - return max_distance > fabs(a.distance_to_point(p1)) ? max_distance : fabs(a.distance_to_point(p1)) ; -} - - - -/* Arc */ - -inline bool Arc::operator == (const Arc &a) const { - return p0 == a.p0 && p1 == a.p1 && d == a.d; -} -inline bool Arc::operator != (const Arc &a) const { - return !(*this == a); -} - - -inline const SignedVector Arc::operator- (const Point &p) const { - - if (fabs(d) < 1e-5) { - Segment arc_segment (p0, p1); - return arc_segment - p; - } - if (wedge_contains_point (p)){ - Vector difference = (center () - p).normalized () * fabs (p.distance_to_point (center ()) - radius ()); - - return SignedVector (difference, ((p - center ()).len () < radius ()) ^ (d < 0)); - } - double d0 = p.squared_distance_to_point (p0); - double d1 = p.squared_distance_to_point (p1); - - Arc other_arc (p0, p1, (1.0 + d) / (1.0 - d)); /********************************* NOT Robust. But works? *****************/ - Vector normal = center () - (d0 < d1 ? p0 : p1) ; - - if (normal.len() == 0) - return SignedVector (Vector (0, 0), true); /************************************ Check sign of this S.D. *************/ - - return SignedVector (Line (normal.dx, normal.dy, normal * Vector ((d0 < d1 ? p0 : p1))) - p, !other_arc.wedge_contains_point(p)); -} - -inline const SignedVector operator- (const Point &p, const Arc &a) { - return -(a - p); -} - - - -inline double Arc::radius (void) const -{ - return fabs ((p1 - p0).len () / (2 * sin2atan (d))); -} - -inline const Point Arc::center (void) const -{ - return (p0.midpoint (p1)) + (p1 - p0).ortho () / (2 * tan2atan (d)); -} - -inline const Pair<Vector> Arc::tangents (void) const -{ - Vector dp = (p1 - p0) * .5; - Vector pp = dp.ortho () * -sin2atan (d); - dp = dp * cos2atan (d); - return Pair<Vector> (dp + pp, dp - pp); -} - - - -inline Bezier Arc::approximate_bezier (double *error) const -{ - Vector dp = p1 - p0; - Vector pp = dp.ortho (); - - if (error) - *error = dp.len () * pow (fabs (d), 5) / (54 * (1 + d*d)); - - dp *= ((1 - d*d) / 3); - pp *= (2 * d / 3); - - Point p0s = p0 + dp - pp; - Point p1s = p1 - dp - pp; - - return Bezier (p0, p0s, p1s, p1); -} - - -inline bool Arc::wedge_contains_point (const Point &p) const -{ - Pair<Vector> t = tangents (); - if (fabs (d) <= 1) - return (p - p0) * t.first >= 0 && (p - p1) * t.second <= 0; - else - return (p - p0) * t.first >= 0 || (p - p1) * t.second <= 0; -} - - -/* Distance may not always be positive, but will be to an endpoint whenever necessary. */ -inline double Arc::distance_to_point (const Point &p) const { - if (fabs(d) < 1e-5) { - Segment arc_segment (p0, p1); - return arc_segment.distance_to_point (p); - } - - SignedVector difference = *this - p; - - if (wedge_contains_point (p) && fabs(d) > 1e-5) - return fabs (p.distance_to_point (center ()) - radius ()) * (difference.negative ? -1 : 1); - double d1 = p.squared_distance_to_point (p0); - double d2 = p.squared_distance_to_point (p1); - return (d1 < d2 ? sqrt(d1) : sqrt(d2)) * (difference.negative ? -1 : 1); -} - -/* Distance will be to an endpoint whenever necessary. */ -inline double Arc::squared_distance_to_point (const Point &p) const { - if (fabs(d) < 1e-5) { - Segment arc_segment (p0, p1); - return arc_segment.squared_distance_to_point (p); - } - - //SignedVector difference = *this - p; - - if (wedge_contains_point (p) && fabs(d) > 1e-5) { - double answer = p.distance_to_point (center ()) - radius (); - return answer * answer; - } - double d1 = p.squared_distance_to_point (p0); - double d2 = p.squared_distance_to_point (p1); - return (d1 < d2 ? d1 : d2); -} - -inline double Arc::extended_dist (const Point &p) const { - Point m = p0.lerp (.5, p1); - Vector dp = p1 - p0; - Vector pp = dp.ortho (); - float d2 = tan2atan (d); - if ((p - m) * (p1 - m) < 0) - return (p - p0) * (pp + dp * d2).normalized (); - else - return (p - p1) * (pp - dp * d2).normalized (); -} - -inline void Arc::extents (glyphy_extents_t &extents) const { - glyphy_extents_clear (&extents); - glyphy_extents_add (&extents, &p0); - glyphy_extents_add (&extents, &p1); - Point c = center (); - double r = radius (); - Point p[4] = {c + r * Vector (-1, 0), - c + r * Vector (+1, 0), - c + r * Vector ( 0, -1), - c + r * Vector ( 0, +1)}; - for (unsigned int i = 0; i < 4; i++) - if (wedge_contains_point (p[i])) - glyphy_extents_add (&extents, &p[i]); -} - - -/* Bezier */ - -inline const Point Bezier::point (const double &t) const { - Point p01 = p0.lerp (t, p1); - Point p12 = p1.lerp (t, p2); - Point p23 = p2.lerp (t, p3); - Point p012 = p01.lerp (t, p12); - Point p123 = p12.lerp (t, p23); - Point p0123 = p012.lerp (t, p123); - return p0123; -} - -inline const Point Bezier::midpoint (void) const -{ - Point p01 = p0.midpoint (p1); - Point p12 = p1.midpoint (p2); - Point p23 = p2.midpoint (p3); - Point p012 = p01.midpoint (p12); - Point p123 = p12.midpoint (p23); - Point p0123 = p012.midpoint (p123); - return p0123; -} - -inline const Vector Bezier::tangent (const double &t) const -{ - double t_2_0 = t * t; - double t_0_2 = (1 - t) * (1 - t); - - double _1__4t_1_0_3t_2_0 = 1 - 4 * t + 3 * t_2_0; - double _2t_1_0_3t_2_0 = 2 * t - 3 * t_2_0; - - return Vector (-3 * p0.x * t_0_2 - +3 * p1.x * _1__4t_1_0_3t_2_0 - +3 * p2.x * _2t_1_0_3t_2_0 - +3 * p3.x * t_2_0, - -3 * p0.y * t_0_2 - +3 * p1.y * _1__4t_1_0_3t_2_0 - +3 * p2.y * _2t_1_0_3t_2_0 - +3 * p3.y * t_2_0); -} - -inline const Vector Bezier::d_tangent (const double &t) const { - return Vector (6 * ((-p0.x + 3*p1.x - 3*p2.x + p3.x) * t + (p0.x - 2*p1.x + p2.x)), - 6 * ((-p0.y + 3*p1.y - 3*p2.y + p3.y) * t + (p0.y - 2*p1.y + p2.y))); -} - -inline double Bezier::curvature (const double &t) const { - Vector dpp = tangent (t).ortho (); - Vector ddp = d_tangent (t); - /* normal vector len squared */ - double len = dpp.len (); - double curvature = (dpp * ddp) / (len * len * len); - return curvature; -} - -inline const Pair<Bezier > Bezier::split (const double &t) const { - Point p01 = p0.lerp (t, p1); - Point p12 = p1.lerp (t, p2); - Point p23 = p2.lerp (t, p3); - Point p012 = p01.lerp (t, p12); - Point p123 = p12.lerp (t, p23); - Point p0123 = p012.lerp (t, p123); - return Pair<Bezier> (Bezier (p0, p01, p012, p0123), - Bezier (p0123, p123, p23, p3)); -} - -inline const Pair<Bezier > Bezier::halve (void) const -{ - Point p01 = p0.midpoint (p1); - Point p12 = p1.midpoint (p2); - Point p23 = p2.midpoint (p3); - Point p012 = p01.midpoint (p12); - Point p123 = p12.midpoint (p23); - Point p0123 = p012.midpoint (p123); - return Pair<Bezier> (Bezier (p0, p01, p012, p0123), - Bezier (p0123, p123, p23, p3)); -} - -inline const Bezier Bezier::segment (const double &t0, const double &t1) const -{ - Point p01 = p0.lerp (t0, p1); - Point p12 = p1.lerp (t0, p2); - Point p23 = p2.lerp (t0, p3); - Point p012 = p01.lerp (t0, p12); - Point p123 = p12.lerp (t0, p23); - Point p0123 = p012.lerp (t0, p123); - - Point q01 = p0.lerp (t1, p1); - Point q12 = p1.lerp (t1, p2); - Point q23 = p2.lerp (t1, p3); - Point q012 = q01.lerp (t1, q12); - Point q123 = q12.lerp (t1, q23); - Point q0123 = q012.lerp (t1, q123); - - return Bezier (p0123, - p0123 + (p123 - p0123) * ((t1 - t0) / (1 - t0)), - q0123 + (q012 - q0123) * ((t1 - t0) / t1), - q0123); -} - - -/* insertion operator */ - - -static inline std::ostream& operator<<(std::ostream& os, const Point& p) -{ - os << "Point(" << p.x << "," << p.y << ")"; - return os; -} -static inline std::ostream& operator<<(std::ostream& os, const Vector& v) -{ - os << "Vector(" << v.dx << "," << v.dy << ")"; - return os; -} -static inline std::ostream& operator<<(std::ostream& os, const Arc& a) -{ - os << "Arc(" << a.p0 << ", " << a.p1 << ", " << a.d << ")"; - return os; -} -static inline std::ostream& operator<<(std::ostream& os, const Bezier& b) -{ - os << "Bezier(" << b.p0 << ", " << b.p1 << ", " << b.p2 << ", " << b.p3 << ")"; - return os; -} - -} /* namespace Geometry */ -} /* namespace GLyphy */ - -#endif /* GLYPHY_GEOMETRY_HH */ diff --git a/bin/glyphy/glyphy-outline.cc b/bin/glyphy/glyphy-outline.cc @@ -1,327 +0,0 @@ -/* - * Copyright 2012 Google, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Google Author(s): Behdad Esfahbod - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "glyphy-common.hh" -#include "glyphy-geometry.hh" - -using namespace GLyphy::Geometry; - - -void -glyphy_outline_reverse (glyphy_arc_endpoint_t *endpoints, - unsigned int num_endpoints) -{ - if (!num_endpoints) - return; - - // Shift the d's first - double d0 = endpoints[0].d; - for (unsigned int i = 0; i < num_endpoints - 1; i++) - endpoints[i].d = endpoints[i + 1].d == GLYPHY_INFINITY ? GLYPHY_INFINITY : -endpoints[i + 1].d; - endpoints[num_endpoints - 1].d = d0; - - // Reverse - for (unsigned int i = 0, j = num_endpoints - 1; i < j; i++, j--) { - glyphy_arc_endpoint_t t = endpoints[i]; - endpoints[i] = endpoints[j]; - endpoints[j] = t; - } -} - - -static bool -winding (const glyphy_arc_endpoint_t *endpoints, - unsigned int num_endpoints) -{ - /* - * Algorithm: - * - * - Approximate arcs with triangles passing through the mid- and end-points, - * - Calculate the area of the contour, - * - Return sign. - */ - - double area = 0; - for (unsigned int i = 1; i < num_endpoints; i++) - { - const glyphy_point_t &p0 = endpoints[i - 1].p; - const glyphy_point_t &p1 = endpoints[i].p; - double d = endpoints[i].d; - - assert (d != GLYPHY_INFINITY); - - area += Vector(p0).cross (Vector(p1)); - area -= .5 * d * (Point(p1) - Point(p0)).len2 (); - } - return area < 0; -} - - -static int -categorize (double v, double ref) -{ - return v < ref - GLYPHY_EPSILON ? -1 : v > ref + GLYPHY_EPSILON ? +1 : 0; -} - -static bool -is_zero (double v) -{ - return fabs (v) < GLYPHY_EPSILON; -} - -static bool -even_odd (const glyphy_arc_endpoint_t *c_endpoints, - unsigned int num_c_endpoints, - const glyphy_arc_endpoint_t *endpoints, - unsigned int num_endpoints) -{ - /* - * Algorithm: - * - * - For a point on the contour, draw a halfline in a direction - * (eg. decreasing x) to infinity, - * - Count how many times it crosses all other contours, - * - Pay special attention to points falling exactly on the halfline, - * specifically, they count as +.5 or -.5, depending the direction - * of crossing. - * - * All this counting is extremely tricky: - * - * - Floating point equality cannot be relied on here, - * - Lots of arc analysis needed, - * - Without having a point that we know falls /inside/ the contour, - * there are legitimate cases that we simply cannot handle using - * this algorithm. For example, imagine the following glyph shape: - * - * +---------+ - * | +-----+ | - * | \ / | - * | \ / | - * +----o----+ - * - * If the glyph is defined as two outlines, and when analysing the - * inner outline we happen to pick the point denoted by 'o' for - * analysis, there simply is no way to differentiate this case from - * the following case: - * - * +---------+ - * | | - * | | - * | | - * +----o----+ - * / \ - * / \ - * +-----+ - * - * However, in one, the triangle should be filled in, and in the other - * filled out. - * - * One way to work around this may be to do the analysis for all endpoints - * on the outline and take majority. But even that can fail in more - * extreme yet legitimate cases, such as this one: - * - * +--+--+ - * | / \ | - * |/ \| - * + + - * |\ /| - * | \ / | - * +--o--+ - * - * The only correct algorithm I can think of requires a point that falls - * fully inside the outline. While we can try finding such a point (not - * dissimilar to the winding algorithm), it's beyond what I'm willing to - * implement right now. - */ - - const Point p = c_endpoints[0].p; - - double count = 0; - Point p0 (0, 0); - for (unsigned int i = 0; i < num_endpoints; i++) { - const glyphy_arc_endpoint_t &endpoint = endpoints[i]; - if (endpoint.d == GLYPHY_INFINITY) { - p0 = endpoint.p; - continue; - } - Arc arc (p0, endpoint.p, endpoint.d); - p0 = endpoint.p; - - /* - * Skip our own contour - */ - if (&endpoint >= c_endpoints && &endpoint < c_endpoints + num_c_endpoints) - continue; - - /* End-point y's compared to the ref point; lt, eq, or gt */ - unsigned s0 = categorize (arc.p0.y, p.y); - unsigned s1 = categorize (arc.p1.y, p.y); - - if (is_zero (arc.d)) - { - /* Line */ - - if (!s0 || !s1) - { - /* - * Add +.5 / -.5 for each endpoint on the halfline, depending on - * crossing direction. - */ - Pair<Vector> t = arc.tangents (); - if (!s0 && arc.p0.x < p.x + GLYPHY_EPSILON) - count += .5 * categorize (t.first.dy, 0); - if (!s1 && arc.p1.x < p.x + GLYPHY_EPSILON) - count += .5 * categorize (t.second.dy, 0); - continue; - } - - if (s0 == s1) - continue; // Segment fully above or below the halfline - - // Find x pos that the line segment would intersect the half-line. - double x = arc.p0.x + (arc.p1.x - arc.p0.x) * ((p.y - arc.p0.y) / (arc.p1.y - arc.p0.y)); - - if (x >= p.x - GLYPHY_EPSILON) - continue; // Does not intersect halfline - - count++; // Add one for full crossing - continue; - } - else - { - /* Arc */ - - if (!s0 || !s1) - { - /* - * Add +.5 / -.5 for each endpoint on the halfline, depending on - * crossing direction. - */ - Pair<Vector> t = arc.tangents (); - - /* Arc-specific logic: - * If the tangent has dy==0, use the other endpoint's - * y value to decide which way the arc will be heading. - */ - if (is_zero (t.first.dy)) - t.first.dy = +categorize (arc.p1.y, p.y); - if (is_zero (t.second.dy)) - t.second.dy = -categorize (arc.p0.y, p.y); - - if (!s0 && arc.p0.x < p.x + GLYPHY_EPSILON) - count += .5 * categorize (t.first.dy, 0); - if (!s1 && arc.p1.x < p.x + GLYPHY_EPSILON) - count += .5 * categorize (t.second.dy, 0); - } - - Point c = arc.center (); - double r = arc.radius (); - if (c.x - r >= p.x) - continue; // No chance - /* Solve for arc crossing line with y = p.y */ - double dy = p.y - c.y; - double x2 = r * r - dy * dy; - if (x2 <= GLYPHY_EPSILON) - continue; // Negative delta, no crossing - double dx = sqrt (x2); - /* There's two candidate points on the arc with the same y as the - * ref point. */ - Point pp[2] = { Point (c.x - dx, p.y), - Point (c.x + dx, p.y) }; - -#define POINTS_EQ(a,b) (is_zero (a.x - b.x) && is_zero (a.y - b.y)) - for (unsigned int i = 0; i < ARRAY_LENGTH (pp); i++) - { - /* Make sure we don't double-count endpoints that fall on the - * halfline as we already accounted for those above */ - if (!POINTS_EQ (pp[i], arc.p0) && !POINTS_EQ (pp[i], arc.p1) && - pp[i].x < p.x - GLYPHY_EPSILON && arc.wedge_contains_point (pp[i])) - count++; // Add one for full crossing - } -#undef POINTS_EQ - } - } - - return !(int (floor (count)) & 1); -} - -static bool -process_contour (glyphy_arc_endpoint_t *endpoints, - unsigned int num_endpoints, - const glyphy_arc_endpoint_t *all_endpoints, - unsigned int num_all_endpoints, - bool inverse) -{ - /* - * Algorithm: - * - * - Find the winding direction and even-odd number, - * - If the two disagree, reverse the contour, inplace. - */ - - if (!num_endpoints) - return false; - - if (num_endpoints < 3) { - abort (); // Don't expect this - return false; // Need at least two arcs - } - if (Point (endpoints[0].p) != Point (endpoints[num_endpoints-1].p)) { - abort (); // Don't expect this - return false; // Need a closed contour - } - - if (inverse ^ - winding (endpoints, num_endpoints) ^ - even_odd (endpoints, num_endpoints, all_endpoints, num_all_endpoints)) - { - glyphy_outline_reverse (endpoints, num_endpoints); - return true; - } - - return false; -} - -/* Returns true if outline was modified */ -glyphy_bool_t -glyphy_outline_winding_from_even_odd (glyphy_arc_endpoint_t *endpoints, - unsigned int num_endpoints, - glyphy_bool_t inverse) -{ - /* - * Algorithm: - * - * - Process one contour at a time. - */ - - unsigned int start = 0; - bool ret = false; - for (unsigned int i = 1; i < num_endpoints; i++) { - const glyphy_arc_endpoint_t &endpoint = endpoints[i]; - if (endpoint.d == GLYPHY_INFINITY) { - ret = ret | process_contour (endpoints + start, i - start, endpoints, num_endpoints, bool (inverse)); - start = i; - } - } - ret = ret | process_contour (endpoints + start, num_endpoints - start, endpoints, num_endpoints, bool (inverse)); - return ret; -} diff --git a/bin/glyphy/glyphy-sdf.cc b/bin/glyphy/glyphy-sdf.cc @@ -1,91 +0,0 @@ -/* - * Copyright 2012 Google, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Google Author(s): Behdad Esfahbod, Maysum Panju, Wojciech Baranowski - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "glyphy-common.hh" -#include "glyphy-geometry.hh" - -using namespace GLyphy::Geometry; - -/* - * TODO - * - * Sync this with the shader sdf - */ - -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 /* may be NULL; TBD not implemented yet */) -{ - Point c = *p; - Point p0 (0, 0); - Arc closest_arc (p0, p0, 0); - double min_dist = GLYPHY_INFINITY; - int side = 0; - for (unsigned int i = 0; i < num_endpoints; i++) { - const glyphy_arc_endpoint_t &endpoint = endpoints[i]; - if (endpoint.d == GLYPHY_INFINITY) { - p0 = endpoint.p; - continue; - } - Arc arc (p0, endpoint.p, endpoint.d); - p0 = endpoint.p; - - if (arc.wedge_contains_point (c)) { - double sdist = arc.distance_to_point (c); /* TODO This distance has the wrong sign. Fix */ - double udist = fabs (sdist) * (1 - GLYPHY_EPSILON); - if (udist <= min_dist) { - min_dist = udist; - side = sdist >= 0 ? -1 : +1; - } - } else { - double udist = std::min ((arc.p0 - c).len (), (arc.p1 - c).len ()); - if (udist < min_dist) { - min_dist = udist; - side = 0; /* unsure */ - closest_arc = arc; - } else if (side == 0 && udist == min_dist) { - /* If this new distance is the same as the current minimum, - * compare extended distances. Take the sign from the arc - * with larger extended distance. */ - double old_ext_dist = closest_arc.extended_dist (c); - double new_ext_dist = arc.extended_dist (c); - - double ext_dist = fabs (new_ext_dist) <= fabs (old_ext_dist) ? - old_ext_dist : new_ext_dist; - - /* For emboldening and stuff: */ - // min_dist = fabs (ext_dist); - side = ext_dist >= 0 ? +1 : -1; - } - } - } - - if (side == 0) { - // Technically speaking this should not happen, but it does. So try to fix it. - double ext_dist = closest_arc.extended_dist (c); - side = ext_dist >= 0 ? +1 : -1; - } - - return side * min_dist; -} diff --git a/bin/glyphy/glyphy-sdf.glsl b/bin/glyphy/glyphy-sdf.glsl @@ -1,150 +0,0 @@ -/* - * Copyright 2012 Google, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Google Author(s): Behdad Esfahbod, Maysum Panju - */ - -#ifndef GLYPHY_TEXTURE1D_FUNC -#define GLYPHY_TEXTURE1D_FUNC glyphy_texture1D_func -#endif -#ifndef GLYPHY_TEXTURE1D_EXTRA_DECLS -#define GLYPHY_TEXTURE1D_EXTRA_DECLS -#endif -#ifndef GLYPHY_TEXTURE1D_EXTRA_ARGS -#define GLYPHY_TEXTURE1D_EXTRA_ARGS -#endif - -#ifndef GLYPHY_SDF_TEXTURE1D_FUNC -#define GLYPHY_SDF_TEXTURE1D_FUNC GLYPHY_TEXTURE1D_FUNC -#endif -#ifndef GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS -#define GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS GLYPHY_TEXTURE1D_EXTRA_DECLS -#endif -#ifndef GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS -#define GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS GLYPHY_TEXTURE1D_EXTRA_ARGS -#endif -#ifndef GLYPHY_SDF_TEXTURE1D -#define GLYPHY_SDF_TEXTURE1D(offset) GLYPHY_RGBA(GLYPHY_SDF_TEXTURE1D_FUNC (offset GLYPHY_TEXTURE1D_EXTRA_ARGS)) -#endif - -#ifndef GLYPHY_MAX_NUM_ENDPOINTS -#define GLYPHY_MAX_NUM_ENDPOINTS 32 -#endif - -glyphy_arc_list_t -glyphy_arc_list (const vec2 p, const ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) -{ - int cell_offset = glyphy_arc_list_offset (p, nominal_size); - vec4 arc_list_data = GLYPHY_SDF_TEXTURE1D (cell_offset); - return glyphy_arc_list_decode (arc_list_data, nominal_size); -} - -float -glyphy_sdf (const vec2 p, const ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) -{ - glyphy_arc_list_t arc_list = glyphy_arc_list (p, nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS); - - /* Short-circuits */ - if (arc_list.num_endpoints == 0) { - /* far-away cell */ - return GLYPHY_INFINITY * float(arc_list.side); - } if (arc_list.num_endpoints == -1) { - /* single-line */ - float angle = arc_list.line_angle; - vec2 n = vec2 (cos (angle), sin (angle)); - return dot (p - (vec2(nominal_size) * .5), n) - arc_list.line_distance; - } - - float side = float(arc_list.side); - float min_dist = GLYPHY_INFINITY; - glyphy_arc_t closest_arc; - - glyphy_arc_endpoint_t endpoint_prev, endpoint; - endpoint_prev = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset), nominal_size); - for (int i = 1; i < GLYPHY_MAX_NUM_ENDPOINTS; i++) - { - if (i >= arc_list.num_endpoints) { - break; - } - endpoint = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset + i), nominal_size); - glyphy_arc_t a = glyphy_arc_t (endpoint_prev.p, endpoint.p, endpoint.d); - endpoint_prev = endpoint; - if (glyphy_isinf (a.d)) continue; - - if (glyphy_arc_wedge_contains (a, p)) - { - float sdist = glyphy_arc_wedge_signed_dist (a, p); - float udist = abs (sdist) * (1. - GLYPHY_EPSILON); - if (udist <= min_dist) { - min_dist = udist; - side = sdist <= 0. ? -1. : +1.; - } - } else { - float udist = min (distance (p, a.p0), distance (p, a.p1)); - if (udist < min_dist) { - min_dist = udist; - side = 0.; /* unsure */ - closest_arc = a; - } else if (side == 0. && udist == min_dist) { - /* If this new distance is the same as the current minimum, - * compare extended distances. Take the sign from the arc - * with larger extended distance. */ - float old_ext_dist = glyphy_arc_extended_dist (closest_arc, p); - float new_ext_dist = glyphy_arc_extended_dist (a, p); - - float ext_dist = abs (new_ext_dist) <= abs (old_ext_dist) ? - old_ext_dist : new_ext_dist; - -#ifdef GLYPHY_SDF_PSEUDO_DISTANCE - /* For emboldening and stuff: */ - min_dist = abs (ext_dist); -#endif - side = sign (ext_dist); - } - } - } - - if (side == 0.) { - // Technically speaking this should not happen, but it does. So try to fix it. - float ext_dist = glyphy_arc_extended_dist (closest_arc, p); - side = sign (ext_dist); - } - - return min_dist * side; -} - -float -glyphy_point_dist (const vec2 p, const ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) -{ - glyphy_arc_list_t arc_list = glyphy_arc_list (p, nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS); - - float side = float(arc_list.side); - float min_dist = GLYPHY_INFINITY; - - if (arc_list.num_endpoints == 0) - return min_dist; - - glyphy_arc_endpoint_t endpoint; - for (int i = 0; i < GLYPHY_MAX_NUM_ENDPOINTS; i++) - { - if (i >= arc_list.num_endpoints) { - break; - } - endpoint = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset + i), nominal_size); - if (glyphy_isinf (endpoint.d)) continue; - min_dist = min (min_dist, distance (p, endpoint.p)); - } - return min_dist; -} diff --git a/bin/glyphy/glyphy-shaders.cc b/bin/glyphy/glyphy-shaders.cc @@ -1,39 +0,0 @@ -/* - * Copyright 2012 Google, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Google Author(s): Behdad Esfahbod, Maysum Panju, Wojciech Baranowski - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "glyphy-common.hh" - -/* - * Shader source code - */ - -/* TODO path separator */ -#define SHADER_PATH(File) PKGDATADIR "/" File - -#include "glyphy_common_glsl.h" -#include "glyphy_sdf_glsl.h" - -const char * glyphy_common_shader_source (void) { return glyphy_common_glsl; } -const char * glyphy_sdf_shader_source (void) { return glyphy_sdf_glsl; } - -const char * glyphy_common_shader_source_path (void) { return SHADER_PATH ("glyphy-common.glsl"); } -const char * glyphy_sdf_shader_source_path (void) { return SHADER_PATH ("glyphy-sdf.glsl"); } diff --git a/bin/glyphy/glyphy.h b/bin/glyphy/glyphy.h @@ -1,354 +0,0 @@ -/* - * Copyright 2012 Google, Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Google Author(s): Behdad Esfahbod, Maysum Panju - */ - -#ifndef GLYPHY_H -#define GLYPHY_H - - -#ifdef __cplusplus -extern "C" { -#endif - - -#define GLYPHY_PASTE_ARGS(prefix, name) prefix ## name -#define GLYPHY_PASTE(prefix, name) GLYPHY_PASTE_ARGS (prefix, name) - - - -typedef int glyphy_bool_t; - - -typedef struct { - double x; - double y; -} glyphy_point_t; - - - -/* - * Geometry extents - */ - -typedef struct { - double min_x; - double min_y; - double max_x; - double max_y; -} glyphy_extents_t; - -void -glyphy_extents_clear (glyphy_extents_t *extents); - -glyphy_bool_t -glyphy_extents_is_empty (const glyphy_extents_t *extents); - -void -glyphy_extents_add (glyphy_extents_t *extents, - const glyphy_point_t *p); - -void -glyphy_extents_extend (glyphy_extents_t *extents, - const glyphy_extents_t *other); - -glyphy_bool_t -glyphy_extents_includes (const glyphy_extents_t *extents, - const glyphy_point_t *p); - -void -glyphy_extents_scale (glyphy_extents_t *extents, - double x_scale, - double y_scale); - - - -/* - * Circular arcs - */ - - -typedef struct { - glyphy_point_t p0; - glyphy_point_t p1; - double d; -} glyphy_arc_t; - - -/* Build from a conventional arc representation */ -void -glyphy_arc_from_conventional (const glyphy_point_t *center, - double radius, - double angle0, - double angle1, - glyphy_bool_t negative, - glyphy_arc_t *arc); - -/* Convert to a conventional arc representation */ -void -glyphy_arc_to_conventional (glyphy_arc_t arc, - glyphy_point_t *center /* may be NULL */, - double *radius /* may be NULL */, - double *angle0 /* may be NULL */, - double *angle1 /* may be NULL */, - glyphy_bool_t *negative /* may be NULL */); - -glyphy_bool_t -glyphy_arc_is_a_line (glyphy_arc_t arc); - -void -glyphy_arc_extents (glyphy_arc_t arc, - glyphy_extents_t *extents); - - - -/* - * Approximate single pieces of geometry to/from one arc - */ - - -void -glyphy_arc_from_line (const glyphy_point_t *p0, - const glyphy_point_t *p1, - glyphy_arc_t *arc); - -void -glyphy_arc_from_conic (const glyphy_point_t *p0, - const glyphy_point_t *p1, - const glyphy_point_t *p2, - glyphy_arc_t *arc, - double *error); - -void -glyphy_arc_from_cubic (const glyphy_point_t *p0, - const glyphy_point_t *p1, - const glyphy_point_t *p2, - const glyphy_point_t *p3, - glyphy_arc_t *arc, - double *error); - -void -glyphy_arc_to_cubic (const glyphy_arc_t *arc, - glyphy_point_t *p0, - glyphy_point_t *p1, - glyphy_point_t *p2, - glyphy_point_t *p3, - double *error); - - - -/* - * Approximate outlines with multiple arcs - */ - - -typedef struct { - glyphy_point_t p; - double d; -} glyphy_arc_endpoint_t; - -typedef glyphy_bool_t (*glyphy_arc_endpoint_accumulator_callback_t) (glyphy_arc_endpoint_t *endpoint, - void *user_data); - - -typedef struct glyphy_arc_accumulator_t glyphy_arc_accumulator_t; - -glyphy_arc_accumulator_t * -glyphy_arc_accumulator_create (void); - -void -glyphy_arc_accumulator_destroy (glyphy_arc_accumulator_t *acc); - -glyphy_arc_accumulator_t * -glyphy_arc_accumulator_reference (glyphy_arc_accumulator_t *acc); - - -void -glyphy_arc_accumulator_reset (glyphy_arc_accumulator_t *acc); - - -/* Configure accumulator */ - -void -glyphy_arc_accumulator_set_tolerance (glyphy_arc_accumulator_t *acc, - double tolerance); - -double -glyphy_arc_accumulator_get_tolerance (glyphy_arc_accumulator_t *acc); - -void -glyphy_arc_accumulator_set_callback (glyphy_arc_accumulator_t *acc, - glyphy_arc_endpoint_accumulator_callback_t callback, - void *user_data); - -void -glyphy_arc_accumulator_get_callback (glyphy_arc_accumulator_t *acc, - glyphy_arc_endpoint_accumulator_callback_t *callback, - void **user_data); - -void -glyphy_arc_accumulator_set_d_metrics (glyphy_arc_accumulator_t *acc, - double max_d, - double d_bits); - -void -glyphy_arc_accumulator_get_d_metrics (glyphy_arc_accumulator_t *acc, - double *max_d, - double *d_bits); - - -/* Accumulation results */ - -unsigned int -glyphy_arc_accumulator_get_num_endpoints (glyphy_arc_accumulator_t *acc); - -double -glyphy_arc_accumulator_get_error (glyphy_arc_accumulator_t *acc); - -glyphy_bool_t -glyphy_arc_accumulator_successful (glyphy_arc_accumulator_t *acc); - - -/* Accumulate */ - -void -glyphy_arc_accumulator_move_to (glyphy_arc_accumulator_t *acc, - const glyphy_point_t *p0); - -void -glyphy_arc_accumulator_line_to (glyphy_arc_accumulator_t *acc, - const glyphy_point_t *p1); - -void -glyphy_arc_accumulator_conic_to (glyphy_arc_accumulator_t *acc, - const glyphy_point_t *p1, - const glyphy_point_t *p2); - -void -glyphy_arc_accumulator_cubic_to (glyphy_arc_accumulator_t *acc, - const glyphy_point_t *p1, - const glyphy_point_t *p2, - const glyphy_point_t *p3); - -void -glyphy_arc_accumulator_arc_to (glyphy_arc_accumulator_t *acc, - const glyphy_point_t *p1, - double d); - -void -glyphy_arc_accumulator_close_path (glyphy_arc_accumulator_t *acc); - -void -glyphy_arc_list_extents (const glyphy_arc_endpoint_t *endpoints, - unsigned int num_endpoints, - glyphy_extents_t *extents); - - - -/* - * Modify outlines for proper consumption - */ - -void -glyphy_outline_reverse (glyphy_arc_endpoint_t *endpoints, - unsigned int num_endpoints); - -/* Returns true if outline was modified */ -glyphy_bool_t -glyphy_outline_winding_from_even_odd (glyphy_arc_endpoint_t *endpoints, - unsigned int num_endpoints, - glyphy_bool_t inverse); - - - -/* - * Encode an arc outline into binary blob for fast SDF calculation - */ - - -typedef struct { - unsigned char r; - unsigned char g; - unsigned char b; - unsigned char a; -} glyphy_rgba_t; - - -/* TODO make this callback-based also? */ -/* TODO rename to glyphy_blob_encode? */ -glyphy_bool_t -glyphy_arc_list_encode_blob (const glyphy_arc_endpoint_t *endpoints, - unsigned int num_endpoints, - glyphy_rgba_t *blob, - unsigned int blob_size, - double faraway, - double avg_fetch_desired, - double *avg_fetch_achieved, - unsigned int *output_len, - unsigned int *nominal_width, /* 6bit */ - unsigned int *nominal_height, /* 6bit */ - glyphy_extents_t *extents); - -/* TBD _decode_blob */ - - - -/* - * Calculate signed-distance-field from (encoded) arc list - */ - - -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 /* may be NULL; TBD not implemented yet */); - -/* TBD */ -double -glyphy_sdf_from_blob (const glyphy_rgba_t *blob, - unsigned int nominal_width, - unsigned int nominal_height, - const glyphy_point_t *p, - glyphy_point_t *closest_p /* may be NULL; TBD not implemented yet */); - - - -/* - * Shader source code - */ - - -/* TODO make this enum-based? */ - -const char * -glyphy_common_shader_source (void); - -const char * -glyphy_common_shader_source_path (void); - -const char * -glyphy_sdf_shader_source (void); - -const char * -glyphy_sdf_shader_source_path (void); - - -#ifdef __cplusplus -} -#endif - -#endif /* GLYPHY_H */