From a80c04fce6b9f58f90495fb3d2266886ab148600 Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Wed, 9 May 2012 18:08:58 -0400 Subject: [PATCH 01/35] Geometry code to check for arc (and segment) intersections. Runs, but not tested yet. --- demo/jabberwocky.h | 2 +- src/glyphy-blob.cc | 2 +- src/glyphy-geometry.hh | 75 ++++++++++++++++++++++++++++++++++++++++++ src/glyphy-outline.cc | 2 ++ src/glyphy-sdf.glsl | 4 ++- 5 files changed, 82 insertions(+), 3 deletions(-) diff --git a/demo/jabberwocky.h b/demo/jabberwocky.h index c24f210e..e3cbc582 100644 --- a/demo/jabberwocky.h +++ b/demo/jabberwocky.h @@ -5,7 +5,7 @@ static const char *jabberwocky = " And the mome raths outgrabe.\n" "\n" "\"Beware the Jabberwock, my son!\n" -" The jaws that bite, the claws that catch!\n" +" The jaws thąt bite, the çląws that ©atch!\n" "Beware the Jubjub bird, and shun\n" " The frumious Bandersnatch!\"\n" "He took his vorpal sword in hand:\n" diff --git a/src/glyphy-blob.cc b/src/glyphy-blob.cc index 90beb6f4..d532f601 100644 --- a/src/glyphy-blob.cc +++ b/src/glyphy-blob.cc @@ -120,7 +120,7 @@ closest_arcs_to_cell (Point c0, Point c1, /* corners */ // 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); + 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++) { diff --git a/src/glyphy-geometry.hh b/src/glyphy-geometry.hh index f78104ed..37d109bc 100644 --- a/src/glyphy-geometry.hh +++ b/src/glyphy-geometry.hh @@ -137,6 +137,8 @@ struct 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; + inline bool contains_point (const Point &p) const; + inline bool intersects_segment (const Segment &s) const; Point p0; @@ -173,6 +175,8 @@ struct Arc { 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 bool intersects_arc (const Arc &a) const; + inline bool intersects_segment (const Segment &s) const; inline void extents (glyphy_extents_t &extents) const; @@ -372,6 +376,7 @@ inline const Point Line::operator+ (const Line &l) const { 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. *************************************/ @@ -453,6 +458,35 @@ inline double Segment::max_distance_to_arc (const Arc &a) const { return max_distance > fabs(a.distance_to_point(p1)) ? max_distance : fabs(a.distance_to_point(p1)) ; } +inline bool Segment::contains_point (const Point &p) const { + return (p0.distance_to_point (p) + p1.distance_to_point (p) == p0.distance_to_point(p1)); +} + +inline bool Segment::intersects_segment (const Segment &s) const { + /* Can't make lines if segments are degenerate. Handle this case with triangle equality. */ + if (p0 == p1) + return s.contains_point (p0); + if (s.p0 == s.p1) + return contains_point (s.p0); + + Line line1 (p0, p1); + Line line2 (s.p0, s.p1); + + /* If segments are parallel, we have another special case. */ + Vector normal = line1.normal (); + if (normal == line2.normal ()) { + if (normal.dx * p0.x + normal.dy + p0.y != normal.dx + s.p0.x + normal.dy + s.p0.y) /* TODO: Can we write using dot product? */ + return false; + + /* Lines are coincident. */ + return (contains_point (s.p0) || contains_point (s.p1) || s.contains_point (p0) || s.contains_point (p1)); + } + + + Point p = line1 + line2; + return contains_in_span (p) && s.contains_in_span (p); + +} /* Arc */ @@ -582,6 +616,47 @@ inline double Arc::extended_dist (const Point &p) const { return (p - p1) * (pp - dp * d2).normalized (); } +inline bool Arc::intersects_segment (const Segment &s) const { + if (fabs(d) < 1e-5) { + Segment arc_segment (p0, p1); + return s.intersects_segment (arc_segment); + } + + Point c1 = center (); + double a = (s.p0.x - s.p1.x) * (s.p0.x - s.p1.x) + (s.p0.y - s.p1.y) * (s.p0.y - s.p1.y); + double b = 2 * ((s.p1.x - s.p0.x) * (s.p0.x - c1.x) + (s.p1.y - s.p0.y) * (s.p0.y - c1.y)); + double c = c1.x * c1.x + c1.y * c1.y + s.p0.x + s.p0.x + s.p1.y * s.p1.y - 2 * (c1.x * s.p0.x + c1.y * s.p0.y) - radius () * radius (); + double d = b * b - 4 * a * c; + if (d < 0) + return false; + + double u = /* W... get it?! */ (-1 * b + sqrt (d)) / (2 * a); + Point p (s.p0.x + u * (s.p0.x - s.p1.x), s.p0.y + u * (s.p0.y - s.p1.y)); + if ((0 <= u && u <= 1) && wedge_contains_point(p)) + return true; + u = (-1 * b - sqrt (d)) / (2 * a); + p = Point (s.p0.x + u * (s.p0.x - s.p1.x), s.p0.y + u * (s.p0.y - s.p1.y)); + return ((0 <= u && u <= 1) && wedge_contains_point(p)); +} + +inline bool Arc::intersects_arc (const Arc &a) const { + if (fabs(d) < 1e-5) { + Segment arc_segment (p0, p1); + return intersects_segment (arc_segment); + } + + Point c1 = center (); + Point c2 = a.center (); + double d = c1.distance_to_point (c2); + double b = (radius () * radius () - a.radius () * a.radius () + d * d) / (2 * d); + double h = sqrt( radius () * radius () - b * b); + Point p (c1.x + b * (c2.x - c1.x) / b, c1.y + b * (c2.y - c1.y) / b); + Point p1 (p.x + h * (c2.y - c1.y) / d, p.x - h * (c2.x - c1.x) / d); + Point p2 (p.x - h * (c2.y - c1.y) / d, p.x + h * (c2.x - c1.x) / d); + + return (wedge_contains_point (p1) && a.wedge_contains_point (p1)) || (wedge_contains_point (p2) && a.wedge_contains_point (p2)); +} + inline void Arc::extents (glyphy_extents_t &extents) const { glyphy_extents_clear (&extents); glyphy_extents_add (&extents, &p0); diff --git a/src/glyphy-outline.cc b/src/glyphy-outline.cc index bc612e00..9bccb39b 100644 --- a/src/glyphy-outline.cc +++ b/src/glyphy-outline.cc @@ -361,5 +361,7 @@ glyphy_outline_winding_from_even_odd (glyphy_arc_endpoint_t *endpoints, } } ret = ret | process_contour (endpoints + start, num_endpoints - start, endpoints, num_endpoints, bool (inverse)); + + printf("."); return ret; } diff --git a/src/glyphy-sdf.glsl b/src/glyphy-sdf.glsl index 73ad26e0..c1d3bcc1 100644 --- a/src/glyphy-sdf.glsl +++ b/src/glyphy-sdf.glsl @@ -73,15 +73,17 @@ glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) 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_isinf (a.d)) continue; if (glyphy_arc_wedge_contains (a, p)) { From cbde1810912d69721dccaa0b2f8c1c3063eea934 Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Fri, 11 May 2012 15:54:55 -0400 Subject: [PATCH 02/35] Revised arc interesection detection functions. Does not always work if intersection is at an endpoint, though. --- src/glyphy-geometry.hh | 21 ++++++++++++++------- src/glyphy-outline.cc | 26 ++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/src/glyphy-geometry.hh b/src/glyphy-geometry.hh index 37d109bc..7cd06a5e 100644 --- a/src/glyphy-geometry.hh +++ b/src/glyphy-geometry.hh @@ -625,23 +625,30 @@ inline bool Arc::intersects_segment (const Segment &s) const { Point c1 = center (); double a = (s.p0.x - s.p1.x) * (s.p0.x - s.p1.x) + (s.p0.y - s.p1.y) * (s.p0.y - s.p1.y); double b = 2 * ((s.p1.x - s.p0.x) * (s.p0.x - c1.x) + (s.p1.y - s.p0.y) * (s.p0.y - c1.y)); - double c = c1.x * c1.x + c1.y * c1.y + s.p0.x + s.p0.x + s.p1.y * s.p1.y - 2 * (c1.x * s.p0.x + c1.y * s.p0.y) - radius () * radius (); + double c = (c1.x * c1.x) + (c1.y * c1.y) + (s.p0.x * s.p0.x) + (s.p0.y * s.p0.y) - 2 * (c1.x * s.p0.x + c1.y * s.p0.y) - radius () * radius (); double d = b * b - 4 * a * c; if (d < 0) return false; double u = /* W... get it?! */ (-1 * b + sqrt (d)) / (2 * a); - Point p (s.p0.x + u * (s.p0.x - s.p1.x), s.p0.y + u * (s.p0.y - s.p1.y)); + Point p (s.p0.x + u * (s.p1.x - s.p0.x), s.p0.y + u * (s.p1.y - s.p0.y)); + if ((0 <= u && u <= 1) && wedge_contains_point(p)) return true; u = (-1 * b - sqrt (d)) / (2 * a); - p = Point (s.p0.x + u * (s.p0.x - s.p1.x), s.p0.y + u * (s.p0.y - s.p1.y)); + p = Point (s.p0.x + u * (s.p1.x - s.p0.x), s.p0.y + u * (s.p1.y - s.p0.y)); return ((0 <= u && u <= 1) && wedge_contains_point(p)); } inline bool Arc::intersects_arc (const Arc &a) const { - if (fabs(d) < 1e-5) { + + if (fabs (d) < 1e-5) { Segment arc_segment (p0, p1); + return a.intersects_segment (arc_segment); + } + + if (fabs (a.d) < 1e-5) { + Segment arc_segment (a.p0, a.p1); return intersects_segment (arc_segment); } @@ -650,9 +657,9 @@ inline bool Arc::intersects_arc (const Arc &a) const { double d = c1.distance_to_point (c2); double b = (radius () * radius () - a.radius () * a.radius () + d * d) / (2 * d); double h = sqrt( radius () * radius () - b * b); - Point p (c1.x + b * (c2.x - c1.x) / b, c1.y + b * (c2.y - c1.y) / b); - Point p1 (p.x + h * (c2.y - c1.y) / d, p.x - h * (c2.x - c1.x) / d); - Point p2 (p.x - h * (c2.y - c1.y) / d, p.x + h * (c2.x - c1.x) / d); + Point p (c1.x + b * (c2.x - c1.x) / d, c1.y + b * (c2.y - c1.y) / d); + Point p1 (p.x + h * (c2.y - c1.y) / d, p.y - h * (c2.x - c1.x) / d); + Point p2 (p.x - h * (c2.y - c1.y) / d, p.y + h * (c2.x - c1.x) / d); return (wedge_contains_point (p1) && a.wedge_contains_point (p1)) || (wedge_contains_point (p2) && a.wedge_contains_point (p2)); } diff --git a/src/glyphy-outline.cc b/src/glyphy-outline.cc index 9bccb39b..30dab2d2 100644 --- a/src/glyphy-outline.cc +++ b/src/glyphy-outline.cc @@ -315,7 +315,6 @@ process_contour (glyphy_arc_endpoint_t *endpoints, * - Find the winding direction and even-odd number, * - If the two disagree, reverse the contour, inplace. */ - if (!num_endpoints) return false; @@ -339,6 +338,24 @@ process_contour (glyphy_arc_endpoint_t *endpoints, return false; } +/* Returns true if given arc intersects a previously seen contour. */ +glyphy_bool_t +arc_intersects_contour (Arc &a, + glyphy_arc_endpoint_t *endpoints, + unsigned int start) +{ + for (unsigned int i = 1; i < start; i++) { + const glyphy_arc_endpoint_t ethis = endpoints[i - 1]; + const glyphy_arc_endpoint_t enext = endpoints[i]; + Arc current_arc (ethis.p, enext.p, enext.d); + if (current_arc.intersects_arc (a)) { + // printf("The arc [(%f,%f), (%f,%f), %f], center (%f,%f), radius=%f, on a previous contour ", current_arc.p0.x, current_arc.p0.y, current_arc.p1.x, current_arc.p1.y, current_arc.d, current_arc.center ().x, current_arc.center ().y, current_arc.radius ()); + return true; + } + } + return false; +} + /* Returns true if outline was modified */ glyphy_bool_t glyphy_outline_winding_from_even_odd (glyphy_arc_endpoint_t *endpoints, @@ -354,6 +371,12 @@ glyphy_outline_winding_from_even_odd (glyphy_arc_endpoint_t *endpoints, unsigned int start = 0; bool ret = false; for (unsigned int i = 1; i < num_endpoints; i++) { + const glyphy_arc_endpoint_t ethis = endpoints[i - 1]; + const glyphy_arc_endpoint_t enext = endpoints[i]; + Arc current_arc (ethis.p, enext.p, enext.d); +/* if (arc_intersects_contour (current_arc, endpoints, start)) + printf("intersects the arc [(%f,%f), (%f,%f), %f], center (%f,%f), radius=%f.\n", current_arc.p0.x, current_arc.p0.y, current_arc.p1.x, current_arc.p1.y, current_arc.d, current_arc.center ().x, current_arc.center ().y, current_arc.radius ()); + */ 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)); @@ -362,6 +385,5 @@ glyphy_outline_winding_from_even_odd (glyphy_arc_endpoint_t *endpoints, } ret = ret | process_contour (endpoints + start, num_endpoints - start, endpoints, num_endpoints, bool (inverse)); - printf("."); return ret; } From 77654e9b4ecfb6c2b1705d1a7dd83d47a5130fd1 Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Wed, 16 May 2012 14:59:57 -0400 Subject: [PATCH 03/35] Intersection check of segment interior with endpoints should work. --- src/glyphy-geometry.hh | 8 ++++---- src/glyphy-outline.cc | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/glyphy-geometry.hh b/src/glyphy-geometry.hh index 7cd06a5e..6e8498c5 100644 --- a/src/glyphy-geometry.hh +++ b/src/glyphy-geometry.hh @@ -414,12 +414,12 @@ inline bool Segment::contains_in_span (const Point &p) const { // 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)); + 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)); + 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)); } } diff --git a/src/glyphy-outline.cc b/src/glyphy-outline.cc index 30dab2d2..504d6445 100644 --- a/src/glyphy-outline.cc +++ b/src/glyphy-outline.cc @@ -348,10 +348,10 @@ arc_intersects_contour (Arc &a, const glyphy_arc_endpoint_t ethis = endpoints[i - 1]; const glyphy_arc_endpoint_t enext = endpoints[i]; Arc current_arc (ethis.p, enext.p, enext.d); - if (current_arc.intersects_arc (a)) { - // printf("The arc [(%f,%f), (%f,%f), %f], center (%f,%f), radius=%f, on a previous contour ", current_arc.p0.x, current_arc.p0.y, current_arc.p1.x, current_arc.p1.y, current_arc.d, current_arc.center ().x, current_arc.center ().y, current_arc.radius ()); - return true; - } +// if (current_arc.intersects_arc (a)) { +// printf("The arc [(%f,%f), (%f,%f), %f], center (%f,%f), radius=%f, on a previous contour ", current_arc.p0.x, current_arc.p0.y, current_arc.p1.x, current_arc.p1.y, current_arc.d, current_arc.center ().x, current_arc.center ().y, current_arc.radius ()); +// return true; +// } } return false; } @@ -374,9 +374,9 @@ glyphy_outline_winding_from_even_odd (glyphy_arc_endpoint_t *endpoints, const glyphy_arc_endpoint_t ethis = endpoints[i - 1]; const glyphy_arc_endpoint_t enext = endpoints[i]; Arc current_arc (ethis.p, enext.p, enext.d); -/* if (arc_intersects_contour (current_arc, endpoints, start)) + if (arc_intersects_contour (current_arc, endpoints, start)) printf("intersects the arc [(%f,%f), (%f,%f), %f], center (%f,%f), radius=%f.\n", current_arc.p0.x, current_arc.p0.y, current_arc.p1.x, current_arc.p1.y, current_arc.d, current_arc.center ().x, current_arc.center ().y, current_arc.radius ()); - */ + 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)); From 9167fce5b66918b7c26b6504c132d8a0d221b0fc Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Thu, 17 May 2012 17:30:25 -0400 Subject: [PATCH 04/35] Changed intersect functions to return intersection points, rather than boolean values. Lots of assumptions, e.g. at most one intersection point. Known bug: problem if arc intersects segment at arc endpoint. Why is u=nan? --- src/glyphy-geometry.hh | 70 +++++++++++++++++++++++++++++------------- src/glyphy-outline.cc | 69 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 109 insertions(+), 30 deletions(-) diff --git a/src/glyphy-geometry.hh b/src/glyphy-geometry.hh index 6e8498c5..f2e940e9 100644 --- a/src/glyphy-geometry.hh +++ b/src/glyphy-geometry.hh @@ -138,7 +138,7 @@ struct 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; inline bool contains_point (const Point &p) const; - inline bool intersects_segment (const Segment &s) const; + inline Point intersects_segment (const Segment &s) const; Point p0; @@ -175,8 +175,8 @@ struct Arc { 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 bool intersects_arc (const Arc &a) const; - inline bool intersects_segment (const Segment &s) const; + inline Point intersects_arc (const Arc &a) const; + inline Point intersects_segment (const Segment &s) const; inline void extents (glyphy_extents_t &extents) const; @@ -462,12 +462,14 @@ inline bool Segment::contains_point (const Point &p) const { return (p0.distance_to_point (p) + p1.distance_to_point (p) == p0.distance_to_point(p1)); } -inline bool Segment::intersects_segment (const Segment &s) const { +inline Point Segment::intersects_segment (const Segment &s) const { /* Can't make lines if segments are degenerate. Handle this case with triangle equality. */ - if (p0 == p1) - return s.contains_point (p0); - if (s.p0 == s.p1) - return contains_point (s.p0); + if (s.contains_point (p0)) // Includes case p0 == p1 + return p0; + if (contains_point (s.p0)) // Includes case s.p0 == s.p1 + return s.p0; + if (p0 == p1 || s.p0 == s.p1) + return Point (GLYPHY_INFINITY, GLYPHY_INFINITY); Line line1 (p0, p1); Line line2 (s.p0, s.p1); @@ -476,15 +478,25 @@ inline bool Segment::intersects_segment (const Segment &s) const { Vector normal = line1.normal (); if (normal == line2.normal ()) { if (normal.dx * p0.x + normal.dy + p0.y != normal.dx + s.p0.x + normal.dy + s.p0.y) /* TODO: Can we write using dot product? */ - return false; + return Point (GLYPHY_INFINITY, GLYPHY_INFINITY); //false; /* Lines are coincident. */ - return (contains_point (s.p0) || contains_point (s.p1) || s.contains_point (p0) || s.contains_point (p1)); + if (contains_point (s.p0)) + return s.p0; + if (contains_point (s.p1)) + return s.p1; + if (s.contains_point (p0)) + return p0; + if (s.contains_point (p1)) // Is this case necessary? I don't think so. + return p1; + return Point (GLYPHY_INFINITY, GLYPHY_INFINITY); //(contains_point (s.p0) || contains_point (s.p1) || s.contains_point (p0) || s.contains_point (p1)); } Point p = line1 + line2; - return contains_in_span (p) && s.contains_in_span (p); + if (contains_in_span (p) && s.contains_in_span (p)) + return p; + return Point (GLYPHY_INFINITY, GLYPHY_INFINITY); //contains_in_span (p) && s.contains_in_span (p); } @@ -565,6 +577,9 @@ inline Bezier Arc::approximate_bezier (double *error) const inline bool Arc::wedge_contains_point (const Point &p) const { // TODO this doesn't handle fabs(d) > 1. + if (p == p0 || p == p1) + return true; + Pair t = tangents (); return (p - p0) * t.first >= 0 && (p - p1) * t.second <= 0; @@ -616,7 +631,8 @@ inline double Arc::extended_dist (const Point &p) const { return (p - p1) * (pp - dp * d2).normalized (); } -inline bool Arc::intersects_segment (const Segment &s) const { +/* TODO: Handle possibility that there are two intersection points. */ +inline Point Arc::intersects_segment (const Segment &s) const { if (fabs(d) < 1e-5) { Segment arc_segment (p0, p1); return s.intersects_segment (arc_segment); @@ -626,21 +642,27 @@ inline bool Arc::intersects_segment (const Segment &s) const { double a = (s.p0.x - s.p1.x) * (s.p0.x - s.p1.x) + (s.p0.y - s.p1.y) * (s.p0.y - s.p1.y); double b = 2 * ((s.p1.x - s.p0.x) * (s.p0.x - c1.x) + (s.p1.y - s.p0.y) * (s.p0.y - c1.y)); double c = (c1.x * c1.x) + (c1.y * c1.y) + (s.p0.x * s.p0.x) + (s.p0.y * s.p0.y) - 2 * (c1.x * s.p0.x + c1.y * s.p0.y) - radius () * radius (); - double d = b * b - 4 * a * c; - if (d < 0) - return false; + double disc = b * b - 4 * a * c; + if (disc < 0) + return Point (GLYPHY_INFINITY, GLYPHY_INFINITY); //false; + + /* Sometimes, u = nan. Can't explain that. */ - double u = /* W... get it?! */ (-1 * b + sqrt (d)) / (2 * a); + double u = /* W... get it?! */ (-1 * b + sqrt (disc)) / (2 * a); Point p (s.p0.x + u * (s.p1.x - s.p0.x), s.p0.y + u * (s.p1.y - s.p0.y)); - if ((0 <= u && u <= 1) && wedge_contains_point(p)) - return true; - u = (-1 * b - sqrt (d)) / (2 * a); + return p; //true; + + u = -1 * b / a - u; //(-1 * b - sqrt (d)) / (2 * a); p = Point (s.p0.x + u * (s.p1.x - s.p0.x), s.p0.y + u * (s.p1.y - s.p0.y)); - return ((0 <= u && u <= 1) && wedge_contains_point(p)); + if ((0 <= u && u <= 1) && wedge_contains_point(p)) + return p; //true; + + return Point (GLYPHY_INFINITY, GLYPHY_INFINITY); //((0 <= u && u <= 1) && wedge_contains_point(p)); } -inline bool Arc::intersects_arc (const Arc &a) const { +/* TODO: Handle possibility that there are two intersection points. */ +inline Point Arc::intersects_arc (const Arc &a) const { if (fabs (d) < 1e-5) { Segment arc_segment (p0, p1); @@ -661,7 +683,11 @@ inline bool Arc::intersects_arc (const Arc &a) const { Point p1 (p.x + h * (c2.y - c1.y) / d, p.y - h * (c2.x - c1.x) / d); Point p2 (p.x - h * (c2.y - c1.y) / d, p.y + h * (c2.x - c1.x) / d); - return (wedge_contains_point (p1) && a.wedge_contains_point (p1)) || (wedge_contains_point (p2) && a.wedge_contains_point (p2)); + if (wedge_contains_point (p1) && a.wedge_contains_point (p1)) + return p1; + if (wedge_contains_point (p2) && a.wedge_contains_point (p2)) + return p2; + return Point (GLYPHY_INFINITY, GLYPHY_INFINITY); //(wedge_contains_point (p1) && a.wedge_contains_point (p1)) || (wedge_contains_point (p2) && a.wedge_contains_point (p2)); } inline void Arc::extents (glyphy_extents_t &extents) const { diff --git a/src/glyphy-outline.cc b/src/glyphy-outline.cc index 504d6445..7ce3ed19 100644 --- a/src/glyphy-outline.cc +++ b/src/glyphy-outline.cc @@ -339,7 +339,7 @@ process_contour (glyphy_arc_endpoint_t *endpoints, } /* Returns true if given arc intersects a previously seen contour. */ -glyphy_bool_t +Point arc_intersects_contour (Arc &a, glyphy_arc_endpoint_t *endpoints, unsigned int start) @@ -348,12 +348,12 @@ arc_intersects_contour (Arc &a, const glyphy_arc_endpoint_t ethis = endpoints[i - 1]; const glyphy_arc_endpoint_t enext = endpoints[i]; Arc current_arc (ethis.p, enext.p, enext.d); -// if (current_arc.intersects_arc (a)) { -// printf("The arc [(%f,%f), (%f,%f), %f], center (%f,%f), radius=%f, on a previous contour ", current_arc.p0.x, current_arc.p0.y, current_arc.p1.x, current_arc.p1.y, current_arc.d, current_arc.center ().x, current_arc.center ().y, current_arc.radius ()); -// return true; -// } + if (current_arc.intersects_arc (a) != Point (GLYPHY_INFINITY, GLYPHY_INFINITY)) { + printf("The arc [(%f,%f), (%f,%f), %f], center (%f,%f), radius=%f, on a previous contour ", current_arc.p0.x, current_arc.p0.y, current_arc.p1.x, current_arc.p1.y, current_arc.d, current_arc.center ().x, current_arc.center ().y, current_arc.radius ()); + return current_arc.intersects_arc (a); //true; + } } - return false; + return Point (GLYPHY_INFINITY, GLYPHY_INFINITY);//false; } /* Returns true if outline was modified */ @@ -374,8 +374,9 @@ glyphy_outline_winding_from_even_odd (glyphy_arc_endpoint_t *endpoints, const glyphy_arc_endpoint_t ethis = endpoints[i - 1]; const glyphy_arc_endpoint_t enext = endpoints[i]; Arc current_arc (ethis.p, enext.p, enext.d); - if (arc_intersects_contour (current_arc, endpoints, start)) - printf("intersects the arc [(%f,%f), (%f,%f), %f], center (%f,%f), radius=%f.\n", current_arc.p0.x, current_arc.p0.y, current_arc.p1.x, current_arc.p1.y, current_arc.d, current_arc.center ().x, current_arc.center ().y, current_arc.radius ()); + Point intersection = arc_intersects_contour (current_arc, endpoints, start); + if (intersection != Point (GLYPHY_INFINITY, GLYPHY_INFINITY)) + printf("intersects the arc [(%f,%f), (%f,%f), %f], center (%f,%f), radius=%f at the point (%f,%f).\n", current_arc.p0.x, current_arc.p0.y, current_arc.p1.x, current_arc.p1.y, current_arc.d, current_arc.center ().x, current_arc.center ().y, current_arc.radius (), intersection.x, intersection.y); const glyphy_arc_endpoint_t &endpoint = endpoints[i]; if (endpoint.d == GLYPHY_INFINITY) { @@ -385,5 +386,57 @@ glyphy_outline_winding_from_even_odd (glyphy_arc_endpoint_t *endpoints, } ret = ret | process_contour (endpoints + start, num_endpoints - start, endpoints, num_endpoints, bool (inverse)); + // glyphy_remove_overlaps (*endpoints, num_endpoints); + return ret; } + +/* Returns true if outline was modified +glyphy_bool_t +glyphy_remove_overlaps (glyphy_arc_endpoint_t *endpoints, + unsigned int num_endpoints) +{ + + unsigned int first_contour_end = 0; + bool ret = false; + + for (unsigned int i = 1; i < num_endpoints; i++) { + const glyphy_arc_endpoint_t ethis = endpoints[i - 1]; + const glyphy_arc_endpoint_t enext = endpoints[i]; + Arc current_arc (ethis.p, enext.p, enext.d); + + // Comments. + + // Add the first contour completely. + + // For each new contour: + + // Try adding edges; either find an intersection with old contour, or return to start. + + // If there is an intersection, pick the outside side. + + // [*] Start adding edges in new contour along this direction. + + // Add edges until we find a new intersection. + + // Trace the original contour, deleting edges, until we find a new intersection. + + // If the new intersection is the starting intersection, then yay. + + // Otherwise, return to [*]. + + if (arc_intersects_contour (current_arc, endpoints, first_contour_end)) + printf("intersects the arc [(%f,%f), (%f,%f), %f], center (%f,%f), radius=%f.\n", current_arc.p0.x, current_arc.p0.y, current_arc.p1.x, current_arc.p1.y, current_arc.d, current_arc.center ().x, current_arc.center ().y, current_arc.radius ()); + + 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; +} */ + + From a7051bd6598d10b3515750b55d3e6d7829de2a2b Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Fri, 18 May 2012 14:43:11 -0400 Subject: [PATCH 05/35] Removed glyph-overlap attempt; will have to restart with new approach. --- src/glyphy-geometry.hh | 4 ++++ src/glyphy-outline.cc | 48 ------------------------------------------ 2 files changed, 4 insertions(+), 48 deletions(-) diff --git a/src/glyphy-geometry.hh b/src/glyphy-geometry.hh index f2e940e9..06221003 100644 --- a/src/glyphy-geometry.hh +++ b/src/glyphy-geometry.hh @@ -637,8 +637,11 @@ inline Point Arc::intersects_segment (const Segment &s) const { Segment arc_segment (p0, p1); return s.intersects_segment (arc_segment); } +// if (fabs(d) > 1e5) +// printf("WEIRDNESS. Arc from (%f,%f) to (%f,%f) with d=%f.\n", p0.x, p0.y, p1.x, p1.y, d); Point c1 = center (); +// printf("Centre at (%f,%f), radius is %f, depth is %f.\n", c1.x, c1.y, radius (), d); double a = (s.p0.x - s.p1.x) * (s.p0.x - s.p1.x) + (s.p0.y - s.p1.y) * (s.p0.y - s.p1.y); double b = 2 * ((s.p1.x - s.p0.x) * (s.p0.x - c1.x) + (s.p1.y - s.p0.y) * (s.p0.y - c1.y)); double c = (c1.x * c1.x) + (c1.y * c1.y) + (s.p0.x * s.p0.x) + (s.p0.y * s.p0.y) - 2 * (c1.x * s.p0.x + c1.y * s.p0.y) - radius () * radius (); @@ -649,6 +652,7 @@ inline Point Arc::intersects_segment (const Segment &s) const { /* Sometimes, u = nan. Can't explain that. */ double u = /* W... get it?! */ (-1 * b + sqrt (disc)) / (2 * a); +// printf("a=%f, b=%f, c=%f, disc=%f\n u=%f\n", a, b, c, disc, u); Point p (s.p0.x + u * (s.p1.x - s.p0.x), s.p0.y + u * (s.p1.y - s.p0.y)); if ((0 <= u && u <= 1) && wedge_contains_point(p)) return p; //true; diff --git a/src/glyphy-outline.cc b/src/glyphy-outline.cc index 7ce3ed19..d045ae4f 100644 --- a/src/glyphy-outline.cc +++ b/src/glyphy-outline.cc @@ -391,52 +391,4 @@ glyphy_outline_winding_from_even_odd (glyphy_arc_endpoint_t *endpoints, return ret; } -/* Returns true if outline was modified -glyphy_bool_t -glyphy_remove_overlaps (glyphy_arc_endpoint_t *endpoints, - unsigned int num_endpoints) -{ - - unsigned int first_contour_end = 0; - bool ret = false; - - for (unsigned int i = 1; i < num_endpoints; i++) { - const glyphy_arc_endpoint_t ethis = endpoints[i - 1]; - const glyphy_arc_endpoint_t enext = endpoints[i]; - Arc current_arc (ethis.p, enext.p, enext.d); - - // Comments. - - // Add the first contour completely. - - // For each new contour: - - // Try adding edges; either find an intersection with old contour, or return to start. - - // If there is an intersection, pick the outside side. - - // [*] Start adding edges in new contour along this direction. - - // Add edges until we find a new intersection. - - // Trace the original contour, deleting edges, until we find a new intersection. - - // If the new intersection is the starting intersection, then yay. - - // Otherwise, return to [*]. - - if (arc_intersects_contour (current_arc, endpoints, first_contour_end)) - printf("intersects the arc [(%f,%f), (%f,%f), %f], center (%f,%f), radius=%f.\n", current_arc.p0.x, current_arc.p0.y, current_arc.p1.x, current_arc.p1.y, current_arc.d, current_arc.center ().x, current_arc.center ().y, current_arc.radius ()); - - 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; -} */ - From 9ff48eecde5483786b77003b1f7fd04e777f1940 Mon Sep 17 00:00:00 2001 From: mhpanju Date: Fri, 18 May 2012 19:11:46 +0000 Subject: [PATCH 06/35] Added a check for arc endpoint/segment intersection. --- src/glyphy-geometry.hh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/glyphy-geometry.hh b/src/glyphy-geometry.hh index 06221003..8434d821 100644 --- a/src/glyphy-geometry.hh +++ b/src/glyphy-geometry.hh @@ -639,6 +639,11 @@ inline Point Arc::intersects_segment (const Segment &s) const { } // if (fabs(d) > 1e5) // printf("WEIRDNESS. Arc from (%f,%f) to (%f,%f) with d=%f.\n", p0.x, p0.y, p1.x, p1.y, d); + + if (s.contains_point (p0)) + return p0; + if (s.contains_point (p1)) + return p1; Point c1 = center (); // printf("Centre at (%f,%f), radius is %f, depth is %f.\n", c1.x, c1.y, radius (), d); From 46429c43dc73c4dcbc1b08a968e741c63fb46c32 Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Tue, 22 May 2012 10:04:44 -0400 Subject: [PATCH 07/35] Updated "segment contains point" method. Updated check for parallel lines. --- src/glyphy-geometry.hh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/glyphy-geometry.hh b/src/glyphy-geometry.hh index 8434d821..95b3e57f 100644 --- a/src/glyphy-geometry.hh +++ b/src/glyphy-geometry.hh @@ -459,7 +459,7 @@ inline double Segment::max_distance_to_arc (const Arc &a) const { } inline bool Segment::contains_point (const Point &p) const { - return (p0.distance_to_point (p) + p1.distance_to_point (p) == p0.distance_to_point(p1)); + return (distance_to_point (p) == 0); } inline Point Segment::intersects_segment (const Segment &s) const { @@ -476,7 +476,8 @@ inline Point Segment::intersects_segment (const Segment &s) const { /* If segments are parallel, we have another special case. */ Vector normal = line1.normal (); - if (normal == line2.normal ()) { + if (normal * line2.normal ().perpendicular () == 0) { + printf ("Parallel lines: (%f,%f)-(%f,%f) and (%f,%f)-(%f,%f).\n", p0.x, p0.y, p1.x, p1.y, s.p0.x, s.p0.y, s.p1.x, s.p1.y); if (normal.dx * p0.x + normal.dy + p0.y != normal.dx + s.p0.x + normal.dy + s.p0.y) /* TODO: Can we write using dot product? */ return Point (GLYPHY_INFINITY, GLYPHY_INFINITY); //false; From a2e13ad89c7e812cf80363b3b02d1a42c376adaf Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Tue, 22 May 2012 17:19:04 -0400 Subject: [PATCH 08/35] Lots of work on rearrange_endpoints, which should change order that contours are drawn. Need to fix subsequent contours though. --- src/glyphy-geometry.hh | 4 +- src/glyphy-outline.cc | 111 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 105 insertions(+), 10 deletions(-) diff --git a/src/glyphy-geometry.hh b/src/glyphy-geometry.hh index 95b3e57f..39a0f224 100644 --- a/src/glyphy-geometry.hh +++ b/src/glyphy-geometry.hh @@ -476,8 +476,10 @@ inline Point Segment::intersects_segment (const Segment &s) const { /* If segments are parallel, we have another special case. */ Vector normal = line1.normal (); + if (normal * line2.normal ().perpendicular () == 0) { - printf ("Parallel lines: (%f,%f)-(%f,%f) and (%f,%f)-(%f,%f).\n", p0.x, p0.y, p1.x, p1.y, s.p0.x, s.p0.y, s.p1.x, s.p1.y); + + /* This is NOT a great check. However, it might do for now - maybe it's not necessary. */ if (normal.dx * p0.x + normal.dy + p0.y != normal.dx + s.p0.x + normal.dy + s.p0.y) /* TODO: Can we write using dot product? */ return Point (GLYPHY_INFINITY, GLYPHY_INFINITY); //false; diff --git a/src/glyphy-outline.cc b/src/glyphy-outline.cc index d045ae4f..21280213 100644 --- a/src/glyphy-outline.cc +++ b/src/glyphy-outline.cc @@ -342,9 +342,10 @@ process_contour (glyphy_arc_endpoint_t *endpoints, Point arc_intersects_contour (Arc &a, glyphy_arc_endpoint_t *endpoints, - unsigned int start) + unsigned int start, + unsigned int end) { - for (unsigned int i = 1; i < start; i++) { + for (unsigned int i = start; i < end; i++) { const glyphy_arc_endpoint_t ethis = endpoints[i - 1]; const glyphy_arc_endpoint_t enext = endpoints[i]; Arc current_arc (ethis.p, enext.p, enext.d); @@ -356,6 +357,95 @@ arc_intersects_contour (Arc &a, return Point (GLYPHY_INFINITY, GLYPHY_INFINITY);//false; } + +/* Returns true if the contour in endpoints[start...end-1] intersects any arc in endpoints[0...start-1]. */ +glyphy_bool_t +contour_intersects_contour_list (glyphy_arc_endpoint_t *endpoints, + unsigned int start, + unsigned int end) +{ + /* Compare every arc pair in the two contours. TODO: Be more efficient (sanity check first.) */ + for (unsigned int i = start + 1; i < end; i++) { + const glyphy_arc_endpoint_t ethis = endpoints[i - 1]; + const glyphy_arc_endpoint_t enext = endpoints[i]; + Arc a (ethis.p, enext.p, enext.d); + + for (unsigned int j = 1; j < start; j++) { + // if (endpoints[j].d != GLYPHY_INFINITY) ????????????????????????????????????????????????????? + const glyphy_arc_endpoint_t ethis2 = endpoints[j - 1]; + const glyphy_arc_endpoint_t enext2 = endpoints[j]; + Arc current_arc (ethis2.p, enext2.p, enext2.d); + + if (current_arc.intersects_arc (a) != Point (GLYPHY_INFINITY, GLYPHY_INFINITY)) { + printf("Contours intersect.\n"); + return true; + } + } + } + printf("Contours do not intersect.\n"); + return false; +} + +glyphy_bool_t +rearrange_contours (glyphy_arc_endpoint_t *endpoints, + unsigned int num_endpoints, + glyphy_arc_endpoint_t *rearranged_endpoints) +{ + + + /* Copy first contour unchanged. */ + unsigned int i = 0; + printf("Enter the REARRANGE function..\n"); + printf("Endpoint [0] is (%f,%f),%f.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d); + while (endpoints[i + 1].d != GLYPHY_INFINITY && i + 1 < num_endpoints) { + rearranged_endpoints [i] = endpoints [i]; + printf("Added endpoint (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); + i++; + } + rearranged_endpoints [i] = endpoints [i]; + + printf("Added final endpoint (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); + i++; + + + /* Add new contours one-by-one. + * If the new contour intersects a contour at the top of the rearranged list, add it to the bottom. + * Otherwise, add it to the top. + */ + unsigned int top = i; + unsigned int bottom = num_endpoints; + unsigned int start = i; + + while (top < bottom ) { + printf("Now, i = %d, top = %d, start = %d; bottom = %d, num_endpoints = %d.\n", i, top, start, bottom, num_endpoints); + printf("Currently at (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); + + while (endpoints[i + 1].d != GLYPHY_INFINITY && i + 1 < num_endpoints ) { + printf("New contour includes (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); + i++; + } + printf("Added final endpoint (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); + i++; + + + if (contour_intersects_contour_list (endpoints, start, i)) { // TODO check for +-1 offsets + for (unsigned int j = start; j < i; j++) + rearranged_endpoints[bottom - (i - start + 1) + j] = endpoints[j]; + bottom = bottom - (i - start); + } + else { + for (unsigned int j = start; j < i; j++) + rearranged_endpoints[top + j] = endpoints[j]; // THIS IS WRONGGGGGGGGGGGGGGGGGGGGGGGGGGG + top = top + (i - start); + } + start = i; + } + + return true; +} + + + /* Returns true if outline was modified */ glyphy_bool_t glyphy_outline_winding_from_even_odd (glyphy_arc_endpoint_t *endpoints, @@ -371,12 +461,12 @@ glyphy_outline_winding_from_even_odd (glyphy_arc_endpoint_t *endpoints, unsigned int start = 0; bool ret = false; for (unsigned int i = 1; i < num_endpoints; i++) { - const glyphy_arc_endpoint_t ethis = endpoints[i - 1]; - const glyphy_arc_endpoint_t enext = endpoints[i]; - Arc current_arc (ethis.p, enext.p, enext.d); - Point intersection = arc_intersects_contour (current_arc, endpoints, start); - if (intersection != Point (GLYPHY_INFINITY, GLYPHY_INFINITY)) - printf("intersects the arc [(%f,%f), (%f,%f), %f], center (%f,%f), radius=%f at the point (%f,%f).\n", current_arc.p0.x, current_arc.p0.y, current_arc.p1.x, current_arc.p1.y, current_arc.d, current_arc.center ().x, current_arc.center ().y, current_arc.radius (), intersection.x, intersection.y); + // const glyphy_arc_endpoint_t ethis = endpoints[i - 1]; + // const glyphy_arc_endpoint_t enext = endpoints[i]; + // Arc current_arc (ethis.p, enext.p, enext.d); + // Point intersection = arc_intersects_contour (current_arc, endpoints, 1, start); + // if (intersection != Point (GLYPHY_INFINITY, GLYPHY_INFINITY)) + // printf("intersects the arc [(%f,%f), (%f,%f), %f], center (%f,%f), radius=%f at the point (%f,%f).\n", current_arc.p0.x, current_arc.p0.y, current_arc.p1.x, current_arc.p1.y, current_arc.d, current_arc.center ().x, current_arc.center ().y, current_arc.radius (), intersection.x, intersection.y); const glyphy_arc_endpoint_t &endpoint = endpoints[i]; if (endpoint.d == GLYPHY_INFINITY) { @@ -386,9 +476,12 @@ glyphy_outline_winding_from_even_odd (glyphy_arc_endpoint_t *endpoints, } ret = ret | process_contour (endpoints + start, num_endpoints - start, endpoints, num_endpoints, bool (inverse)); - // glyphy_remove_overlaps (*endpoints, num_endpoints); + glyphy_arc_endpoint_t rearranged_endpoints [num_endpoints]; + //rearrange_contours (endpoints, num_endpoints, rearranged_endpoints); return ret; } + + From 8c789d9d6e730c30f2a55d164bc815e8aa3dd391 Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Wed, 23 May 2012 16:51:53 -0400 Subject: [PATCH 09/35] Rearrange contours works, sorts contours by some intersection rule. --- demo/jabberwocky.h | 2 +- src/glyphy-outline.cc | 47 ++++++++++++++++++++++++++----------------- 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/demo/jabberwocky.h b/demo/jabberwocky.h index e3cbc582..8cebef52 100644 --- a/demo/jabberwocky.h +++ b/demo/jabberwocky.h @@ -5,7 +5,7 @@ static const char *jabberwocky = " And the mome raths outgrabe.\n" "\n" "\"Beware the Jabberwock, my son!\n" -" The jaws thąt bite, the çląws that ©atch!\n" +" The jaws ţhąt bite, thę çląwş that ©atch!\n" "Beware the Jubjub bird, and shun\n" " The frumious Bandersnatch!\"\n" "He took his vorpal sword in hand:\n" diff --git a/src/glyphy-outline.cc b/src/glyphy-outline.cc index 21280213..c1c52b83 100644 --- a/src/glyphy-outline.cc +++ b/src/glyphy-outline.cc @@ -377,12 +377,12 @@ contour_intersects_contour_list (glyphy_arc_endpoint_t *endpoints, Arc current_arc (ethis2.p, enext2.p, enext2.d); if (current_arc.intersects_arc (a) != Point (GLYPHY_INFINITY, GLYPHY_INFINITY)) { - printf("Contours intersect.\n"); + // printf("Contours intersect.\n"); return true; } } } - printf("Contours do not intersect.\n"); +// printf("Contours do not intersect.\n"); return false; } @@ -392,19 +392,24 @@ rearrange_contours (glyphy_arc_endpoint_t *endpoints, glyphy_arc_endpoint_t *rearranged_endpoints) { - + if (num_endpoints == 0) + return true; + /* Copy first contour unchanged. */ + unsigned int i = 0; - printf("Enter the REARRANGE function..\n"); - printf("Endpoint [0] is (%f,%f),%f.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d); - while (endpoints[i + 1].d != GLYPHY_INFINITY && i + 1 < num_endpoints) { - rearranged_endpoints [i] = endpoints [i]; - printf("Added endpoint (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); +// printf("Enter the REARRANGE function.. num_endpoints=%d.\n", num_endpoints); +// printf("Endpoint [0] is (%f,%f),%f.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d); + while (i + 1 < num_endpoints && endpoints[i + 1].d != GLYPHY_INFINITY) { + rearranged_endpoints [i] = glyphy_arc_endpoint_t (endpoints[i]); +// printf("Added endpoint (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); +// printf(" REARRANGED[%d] = (%f,%f),%f.\n", i, endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d); i++; } rearranged_endpoints [i] = endpoints [i]; - printf("Added final endpoint (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); + // printf("Added final endpoint (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); + // printf(" REARRANGED[%d] = (%f,%f),%f.\n", i, endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d); i++; @@ -417,30 +422,36 @@ rearrange_contours (glyphy_arc_endpoint_t *endpoints, unsigned int start = i; while (top < bottom ) { - printf("Now, i = %d, top = %d, start = %d; bottom = %d, num_endpoints = %d.\n", i, top, start, bottom, num_endpoints); - printf("Currently at (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); + // printf("Now, i = %d, top = %d, start = %d; bottom = %d, num_endpoints = %d.\n", i, top, start, bottom, num_endpoints); + // printf("Currently at (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); while (endpoints[i + 1].d != GLYPHY_INFINITY && i + 1 < num_endpoints ) { - printf("New contour includes (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); + // printf("New contour includes (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); i++; } - printf("Added final endpoint (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); + // printf("Added final endpoint (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); i++; if (contour_intersects_contour_list (endpoints, start, i)) { // TODO check for +-1 offsets - for (unsigned int j = start; j < i; j++) - rearranged_endpoints[bottom - (i - start + 1) + j] = endpoints[j]; + for (unsigned int j = start; j < i; j++) { + rearranged_endpoints[bottom - i + j] = endpoints[j]; + // printf(" REARRANGED[%d] = (%f,%f),%f.\n", bottom - i + j, endpoints[j].p.x, endpoints[j].p.y, endpoints[j].d); + } bottom = bottom - (i - start); } else { - for (unsigned int j = start; j < i; j++) - rearranged_endpoints[top + j] = endpoints[j]; // THIS IS WRONGGGGGGGGGGGGGGGGGGGGGGGGGGG + for (unsigned int j = start; j < i; j++) { + rearranged_endpoints[top + j - start] = endpoints[j]; + // printf(" REARRANGED[%d] = (%f,%f),%f.\n", top + j - start, endpoints[j].p.x, endpoints[j].p.y, endpoints[j].d); + } top = top + (i - start); } start = i; } + + return true; } @@ -477,7 +488,7 @@ glyphy_outline_winding_from_even_odd (glyphy_arc_endpoint_t *endpoints, ret = ret | process_contour (endpoints + start, num_endpoints - start, endpoints, num_endpoints, bool (inverse)); glyphy_arc_endpoint_t rearranged_endpoints [num_endpoints]; - //rearrange_contours (endpoints, num_endpoints, rearranged_endpoints); + rearrange_contours (endpoints, num_endpoints, rearranged_endpoints); return ret; } From 9ba70e21d65c958b368fdee50c8e951bd82bc974 Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Thu, 24 May 2012 17:43:43 -0400 Subject: [PATCH 10/35] Moved code around; rearranging endpoints now done in glyphy-blob. Contour intersection now checks roughly before doing too many calculations. --- src/glyphy-blob.cc | 134 ++++++++++++++++++++++++++++++++++++++++-- src/glyphy-outline.cc | 110 ++-------------------------------- src/glyphy-sdf.glsl | 2 + 3 files changed, 135 insertions(+), 111 deletions(-) diff --git a/src/glyphy-blob.cc b/src/glyphy-blob.cc index d532f601..c44ffbec 100644 --- a/src/glyphy-blob.cc +++ b/src/glyphy-blob.cc @@ -59,10 +59,10 @@ arc_endpoint_encode (unsigned int ix, unsigned int iy, double d) } static inline glyphy_rgba_t -arc_list_encode (unsigned int offset, unsigned int num_points, int side) +arc_list_encode (unsigned int first_contours_length, unsigned int offset, unsigned int num_points, int side) { glyphy_rgba_t v; - v.r = 0; // unused for arc-list encoding + v.r = 0;//LOWER_BITS (first_contours_length, 8, 8); //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); @@ -155,6 +155,124 @@ closest_arcs_to_cell (Point c0, Point c1, /* corners */ } + + + + +/* Returns true if the contour in endpoints[start...end-1] intersects any arc in endpoints[0...start-1]. */ +glyphy_bool_t +contour_intersects_contour_list (const glyphy_arc_endpoint_t *endpoints, + unsigned int start, + unsigned int end) +{ + /* Find the smallest box around this contour. */ + glyphy_extents_t extents; + glyphy_extents_clear (&extents); + + glyphy_arc_list_extents (endpoints + start, end - start, &extents); + + for (unsigned int j = 1; j < start; j++) { + // if (endpoints[j].d != GLYPHY_INFINITY) ????????????????????????????????????????????????????? + const glyphy_arc_endpoint_t ethis2 = endpoints[j - 1]; + const glyphy_arc_endpoint_t enext2 = endpoints[j]; + Arc current_arc (ethis2.p, enext2.p, enext2.d); + + Point c = current_arc.center (); + double r = current_arc.radius (); + if (c.x - r <= extents.max_x && c.x + r >= extents.min_x && c.y + r >= extents.min_y && c.y - r <= extents.max_y) { + + /* Compare every arc pair in the two contours. TODO: Be more efficient (sanity check first.) */ + for (unsigned int i = start + 1; i < end; i++) { + const glyphy_arc_endpoint_t ethis = endpoints[i - 1]; + const glyphy_arc_endpoint_t enext = endpoints[i]; + Arc a (ethis.p, enext.p, enext.d); + + if (current_arc.intersects_arc (a) != Point (GLYPHY_INFINITY, GLYPHY_INFINITY)) { + // printf("Contours intersect.\n"); + return true; + } + } + } + } +// printf("Contours do not intersect.\n"); + return false; +} + +unsigned int +rearrange_contours (const glyphy_arc_endpoint_t *endpoints, + unsigned int num_endpoints, + glyphy_arc_endpoint_t *rearranged_endpoints) +{ + + if (num_endpoints == 0) + return 0; + + /* Copy first contour unchanged. */ + + unsigned int i = 0; +// printf("Enter the REARRANGE function.. num_endpoints=%d.\n", num_endpoints); +// printf("Endpoint [0] is (%f,%f),%f.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d); + while (i + 1 < num_endpoints && endpoints[i + 1].d != GLYPHY_INFINITY) { + rearranged_endpoints [i] = glyphy_arc_endpoint_t (endpoints[i]); +// printf("Added endpoint (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); + printf(" REARRANGED[%d] = (%f,%f),%f.\n", i, endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d); + i++; + } + rearranged_endpoints [i] = endpoints [i]; + + // printf("Added final endpoint (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); + printf(" REARRANGED[%d] = (%f,%f),%f.\n", i, endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d); + i++; + + + /* Add new contours one-by-one. + * If the new contour intersects a contour at the top of the rearranged list, add it to the bottom. + * Otherwise, add it to the top. + */ + unsigned int top = i; + unsigned int bottom = num_endpoints; + unsigned int start = i; + + while (top < bottom ) { + // printf("Now, i = %d, top = %d, start = %d; bottom = %d, num_endpoints = %d.\n", i, top, start, bottom, num_endpoints); + // printf("Currently at (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); + + while (endpoints[i + 1].d != GLYPHY_INFINITY && i + 1 < num_endpoints ) { + // printf("New contour includes (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); + i++; + } + // printf("Added final endpoint (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); + i++; + + + if (contour_intersects_contour_list (endpoints, start, i)) { // TODO check for +-1 offsets + for (unsigned int j = start; j < i; j++) { + rearranged_endpoints[bottom - i + j] = endpoints[j]; + printf(" REARRANGED[%d] = (%f,%f),%f.\n", bottom - i + j, endpoints[j].p.x, endpoints[j].p.y, endpoints[j].d); + } + bottom = bottom - (i - start); + } + else { + for (unsigned int j = start; j < i; j++) { + rearranged_endpoints[top + j - start] = endpoints[j]; + printf(" REARRANGED[%d] = (%f,%f),%f.\n", top + j - start, endpoints[j].p.x, endpoints[j].p.y, endpoints[j].d); + } + top = top + (i - start); + } + start = i; + } + + + + return top; +} + + + + + + + glyphy_bool_t glyphy_arc_list_encode_blob (const glyphy_arc_endpoint_t *endpoints, unsigned int num_endpoints, @@ -177,7 +295,7 @@ glyphy_arc_list_encode_blob (const glyphy_arc_endpoint_t *endpoints, *pextents = extents; if (!blob_size) return false; - *blob = arc_list_encode (0, 0, +1); + *blob = arc_list_encode (0, 0, 0, +1); *avg_fetch_achieved = 1; *output_len = 1; *nominal_width = *nominal_height = 1; @@ -219,7 +337,11 @@ glyphy_arc_list_encode_blob (const glyphy_arc_endpoint_t *endpoints, tex_data.resize (header_length); Point origin = Point (extents.min_x, extents.min_y); unsigned int total_arcs = 0; - + + glyphy_arc_endpoint_t rearranged_endpoints [num_endpoints]; + unsigned int cutoff = rearrange_contours (endpoints, num_endpoints, rearranged_endpoints); + endpoints = rearranged_endpoints; + for (int row = 0; row < grid_h; row++) for (int col = 0; col < grid_w; col++) { @@ -298,8 +420,10 @@ glyphy_arc_list_encode_blob (const glyphy_arc_endpoint_t *endpoints, tex_data.resize (offset); offset = haystack - &tex_data[0]; } + + - tex_data[row * grid_w + col] = arc_list_encode (offset, current_endpoints, side); + tex_data[row * grid_w + col] = arc_list_encode (cutoff, offset, current_endpoints, side); offset = tex_data.size (); total_arcs += current_endpoints; diff --git a/src/glyphy-outline.cc b/src/glyphy-outline.cc index c1c52b83..e87eb412 100644 --- a/src/glyphy-outline.cc +++ b/src/glyphy-outline.cc @@ -338,7 +338,7 @@ process_contour (glyphy_arc_endpoint_t *endpoints, return false; } -/* Returns true if given arc intersects a previously seen contour. */ +/* Returns true if given arc intersects a previously seen contour. // *************************************** NOT USED. Point arc_intersects_contour (Arc &a, glyphy_arc_endpoint_t *endpoints, @@ -355,105 +355,10 @@ arc_intersects_contour (Arc &a, } } return Point (GLYPHY_INFINITY, GLYPHY_INFINITY);//false; -} +} */ -/* Returns true if the contour in endpoints[start...end-1] intersects any arc in endpoints[0...start-1]. */ -glyphy_bool_t -contour_intersects_contour_list (glyphy_arc_endpoint_t *endpoints, - unsigned int start, - unsigned int end) -{ - /* Compare every arc pair in the two contours. TODO: Be more efficient (sanity check first.) */ - for (unsigned int i = start + 1; i < end; i++) { - const glyphy_arc_endpoint_t ethis = endpoints[i - 1]; - const glyphy_arc_endpoint_t enext = endpoints[i]; - Arc a (ethis.p, enext.p, enext.d); - - for (unsigned int j = 1; j < start; j++) { - // if (endpoints[j].d != GLYPHY_INFINITY) ????????????????????????????????????????????????????? - const glyphy_arc_endpoint_t ethis2 = endpoints[j - 1]; - const glyphy_arc_endpoint_t enext2 = endpoints[j]; - Arc current_arc (ethis2.p, enext2.p, enext2.d); - - if (current_arc.intersects_arc (a) != Point (GLYPHY_INFINITY, GLYPHY_INFINITY)) { - // printf("Contours intersect.\n"); - return true; - } - } - } -// printf("Contours do not intersect.\n"); - return false; -} -glyphy_bool_t -rearrange_contours (glyphy_arc_endpoint_t *endpoints, - unsigned int num_endpoints, - glyphy_arc_endpoint_t *rearranged_endpoints) -{ - - if (num_endpoints == 0) - return true; - - /* Copy first contour unchanged. */ - - unsigned int i = 0; -// printf("Enter the REARRANGE function.. num_endpoints=%d.\n", num_endpoints); -// printf("Endpoint [0] is (%f,%f),%f.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d); - while (i + 1 < num_endpoints && endpoints[i + 1].d != GLYPHY_INFINITY) { - rearranged_endpoints [i] = glyphy_arc_endpoint_t (endpoints[i]); -// printf("Added endpoint (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); -// printf(" REARRANGED[%d] = (%f,%f),%f.\n", i, endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d); - i++; - } - rearranged_endpoints [i] = endpoints [i]; - - // printf("Added final endpoint (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); - // printf(" REARRANGED[%d] = (%f,%f),%f.\n", i, endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d); - i++; - - - /* Add new contours one-by-one. - * If the new contour intersects a contour at the top of the rearranged list, add it to the bottom. - * Otherwise, add it to the top. - */ - unsigned int top = i; - unsigned int bottom = num_endpoints; - unsigned int start = i; - - while (top < bottom ) { - // printf("Now, i = %d, top = %d, start = %d; bottom = %d, num_endpoints = %d.\n", i, top, start, bottom, num_endpoints); - // printf("Currently at (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); - - while (endpoints[i + 1].d != GLYPHY_INFINITY && i + 1 < num_endpoints ) { - // printf("New contour includes (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); - i++; - } - // printf("Added final endpoint (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); - i++; - - - if (contour_intersects_contour_list (endpoints, start, i)) { // TODO check for +-1 offsets - for (unsigned int j = start; j < i; j++) { - rearranged_endpoints[bottom - i + j] = endpoints[j]; - // printf(" REARRANGED[%d] = (%f,%f),%f.\n", bottom - i + j, endpoints[j].p.x, endpoints[j].p.y, endpoints[j].d); - } - bottom = bottom - (i - start); - } - else { - for (unsigned int j = start; j < i; j++) { - rearranged_endpoints[top + j - start] = endpoints[j]; - // printf(" REARRANGED[%d] = (%f,%f),%f.\n", top + j - start, endpoints[j].p.x, endpoints[j].p.y, endpoints[j].d); - } - top = top + (i - start); - } - start = i; - } - - - - return true; -} @@ -472,13 +377,6 @@ glyphy_outline_winding_from_even_odd (glyphy_arc_endpoint_t *endpoints, unsigned int start = 0; bool ret = false; for (unsigned int i = 1; i < num_endpoints; i++) { - // const glyphy_arc_endpoint_t ethis = endpoints[i - 1]; - // const glyphy_arc_endpoint_t enext = endpoints[i]; - // Arc current_arc (ethis.p, enext.p, enext.d); - // Point intersection = arc_intersects_contour (current_arc, endpoints, 1, start); - // if (intersection != Point (GLYPHY_INFINITY, GLYPHY_INFINITY)) - // printf("intersects the arc [(%f,%f), (%f,%f), %f], center (%f,%f), radius=%f at the point (%f,%f).\n", current_arc.p0.x, current_arc.p0.y, current_arc.p1.x, current_arc.p1.y, current_arc.d, current_arc.center ().x, current_arc.center ().y, current_arc.radius (), intersection.x, intersection.y); - 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)); @@ -487,8 +385,8 @@ glyphy_outline_winding_from_even_odd (glyphy_arc_endpoint_t *endpoints, } ret = ret | process_contour (endpoints + start, num_endpoints - start, endpoints, num_endpoints, bool (inverse)); - glyphy_arc_endpoint_t rearranged_endpoints [num_endpoints]; - rearrange_contours (endpoints, num_endpoints, rearranged_endpoints); + //glyphy_arc_endpoint_t rearranged_endpoints [num_endpoints]; + //rearrange_contours (endpoints, num_endpoints, rearranged_endpoints); return ret; } diff --git a/src/glyphy-sdf.glsl b/src/glyphy-sdf.glsl index c1d3bcc1..39e40889 100644 --- a/src/glyphy-sdf.glsl +++ b/src/glyphy-sdf.glsl @@ -74,6 +74,8 @@ glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) 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++) { From 6290a3ec62fc3a7f5491eec5000763f87bb41f15 Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Tue, 29 May 2012 12:31:44 -0400 Subject: [PATCH 11/35] Started work on processing intersecting contours in stages. Not complete yet! --- demo/demo-font.cc | 2 +- src/glyphy-blob.cc | 42 ++++++++++++++++------- src/glyphy-common.glsl | 9 ++++- src/glyphy-sdf.glsl | 78 +++++++++++++++++++++++++++++++++++++++--- 4 files changed, 111 insertions(+), 20 deletions(-) diff --git a/demo/demo-font.cc b/demo/demo-font.cc index 443a0348..2bebc8e8 100644 --- a/demo/demo-font.cc +++ b/demo/demo-font.cc @@ -154,7 +154,7 @@ encode_ft_glyph (demo_font_t *font, assert (glyphy_arc_accumulator_get_error (font->acc) <= tolerance); -#if 0 +#if 1 /* Technically speaking, we want the following code, * however, crappy fonts have crappy flags. So we just * fixup unconditionally... */ diff --git a/src/glyphy-blob.cc b/src/glyphy-blob.cc index c44ffbec..91cb6bc9 100644 --- a/src/glyphy-blob.cc +++ b/src/glyphy-blob.cc @@ -62,7 +62,7 @@ static inline glyphy_rgba_t arc_list_encode (unsigned int first_contours_length, unsigned int offset, unsigned int num_points, int side) { glyphy_rgba_t v; - v.r = 0;//LOWER_BITS (first_contours_length, 8, 8); //0; // unused for arc-list encoding + v.r = LOWER_BITS (first_contours_length, 7, 8); //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); @@ -106,6 +106,8 @@ closest_arcs_to_cell (Point c0, Point c1, /* corners */ double faraway, const glyphy_arc_endpoint_t *endpoints, unsigned int num_endpoints, + unsigned int cutoff, + unsigned int *num_group_1_arcs, std::vector &near_endpoints, int *side) { @@ -120,9 +122,13 @@ closest_arcs_to_cell (Point c0, Point c1, /* corners */ // 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.); + double radius_squared = (min_dist + half_diagonal) * (min_dist + half_diagonal); + unsigned int main_contour_arcs = 0; + 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) { @@ -132,11 +138,16 @@ closest_arcs_to_cell (Point c0, Point c1, /* corners */ Arc arc (p0, endpoint.p, endpoint.d); p0 = endpoint.p; - if (arc.squared_distance_to_point (c) <= radius_squared) + if (arc.squared_distance_to_point (c) <= radius_squared) { near_arcs.push_back (arc); + if (i < cutoff) { + main_contour_arcs++; + } + } } } + *num_group_1_arcs = main_contour_arcs; Point p1 = Point (0, 0); for (unsigned i = 0; i < near_arcs.size (); i++) { @@ -146,12 +157,15 @@ closest_arcs_to_cell (Point c0, Point c1, /* corners */ glyphy_arc_endpoint_t endpoint = {arc.p0, GLYPHY_INFINITY}; near_endpoints.push_back (endpoint); p1 = arc.p0; + if (i < main_contour_arcs) + (*num_group_1_arcs)++; } glyphy_arc_endpoint_t endpoint = {arc.p1, arc.d}; near_endpoints.push_back (endpoint); p1 = arc.p1; } + } @@ -215,13 +229,13 @@ rearrange_contours (const glyphy_arc_endpoint_t *endpoints, while (i + 1 < num_endpoints && endpoints[i + 1].d != GLYPHY_INFINITY) { rearranged_endpoints [i] = glyphy_arc_endpoint_t (endpoints[i]); // printf("Added endpoint (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); - printf(" REARRANGED[%d] = (%f,%f),%f.\n", i, endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d); +// printf(" REARRANGED[%d] = (%f,%f),%f.\n", i, endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d); i++; } rearranged_endpoints [i] = endpoints [i]; // printf("Added final endpoint (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); - printf(" REARRANGED[%d] = (%f,%f),%f.\n", i, endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d); + // printf(" REARRANGED[%d] = (%f,%f),%f.\n", i, endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d); i++; @@ -248,14 +262,14 @@ rearrange_contours (const glyphy_arc_endpoint_t *endpoints, if (contour_intersects_contour_list (endpoints, start, i)) { // TODO check for +-1 offsets for (unsigned int j = start; j < i; j++) { rearranged_endpoints[bottom - i + j] = endpoints[j]; - printf(" REARRANGED[%d] = (%f,%f),%f.\n", bottom - i + j, endpoints[j].p.x, endpoints[j].p.y, endpoints[j].d); + // printf(" REARRANGED[%d] = (%f,%f),%f.\n", bottom - i + j, endpoints[j].p.x, endpoints[j].p.y, endpoints[j].d); } bottom = bottom - (i - start); } else { for (unsigned int j = start; j < i; j++) { rearranged_endpoints[top + j - start] = endpoints[j]; - printf(" REARRANGED[%d] = (%f,%f),%f.\n", top + j - start, endpoints[j].p.x, endpoints[j].p.y, endpoints[j].d); + // printf(" REARRANGED[%d] = (%f,%f),%f.\n", top + j - start, endpoints[j].p.x, endpoints[j].p.y, endpoints[j].d); } top = top + (i - start); } @@ -350,12 +364,14 @@ glyphy_arc_list_encode_blob (const glyphy_arc_endpoint_t *endpoints, near_endpoints.clear (); int side; + unsigned int num_group_1_arcs = 0; closest_arcs_to_cell (cp0, cp1, faraway, - endpoints, num_endpoints, - near_endpoints, + endpoints, num_endpoints, cutoff, + &num_group_1_arcs, 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) @@ -402,7 +418,8 @@ glyphy_arc_list_encode_blob (const glyphy_arc_endpoint_t *endpoints, unsigned int haystack_len = offset - header_length; bool found = false; - if (needle_len) + + if (needle_len) 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 @@ -420,10 +437,9 @@ glyphy_arc_list_encode_blob (const glyphy_arc_endpoint_t *endpoints, tex_data.resize (offset); offset = haystack - &tex_data[0]; } - - + - tex_data[row * grid_w + col] = arc_list_encode (cutoff, offset, current_endpoints, side); + tex_data[row * grid_w + col] = arc_list_encode (num_group_1_arcs, offset, current_endpoints, side); offset = tex_data.size (); total_arcs += current_endpoints; diff --git a/src/glyphy-common.glsl b/src/glyphy-common.glsl index 2277bacd..d6d924a1 100644 --- a/src/glyphy-common.glsl +++ b/src/glyphy-common.glsl @@ -65,6 +65,11 @@ struct glyphy_arc_list_t { * 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; + + /* Number of endpoints corresponding to the arcs in the first set of contours 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 first_contours_length; /* If num_endpoints is zero, this specifies whether we are inside (-1) * or outside (+1). Otherwise we're unsure (0). */ @@ -204,9 +209,11 @@ glyphy_arc_list_decode (const vec4 v, 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.first_contours_length = 0; + if (iv.r < 128) { /* arc-list encoded */ l.offset = (iv.g * 256) + iv.b; l.num_endpoints = iv.a; + l.first_contours_length = iv.r; if (l.num_endpoints == 255) { l.num_endpoints = 0; l.side = -1; diff --git a/src/glyphy-sdf.glsl b/src/glyphy-sdf.glsl index 39e40889..295e4139 100644 --- a/src/glyphy-sdf.glsl +++ b/src/glyphy-sdf.glsl @@ -72,11 +72,11 @@ glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) 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++) + + /* Check arcs on the first contour group. */ + for (int i = 1; i < GLYPHY_MAX_NUM_ENDPOINTS && i <= arc_list.first_contours_length ; i++) { if (i >= arc_list.num_endpoints) { @@ -101,7 +101,7 @@ glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) min_dist = udist; side = 0.; /* unsure */ closest_arc = a; - } else if (side == 0. && udist == min_dist) { + } 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. */ @@ -119,12 +119,80 @@ glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) } } } + + + + endpoint_prev = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset + arc_list.first_contours_length), nominal_size); + + +#if 0 + + float side2 = float(arc_list.side); + float min_dist2 = GLYPHY_INFINITY; + glyphy_arc_t closest_arc2; + + /* Check arcs on the second contour group. */ + for (int i = arc_list.first_contours_length + 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_dist2) { + min_dist2 = udist; + side2 = sdist <= 0. ? -1. : +1.; + } + } else { + float udist = min (distance (p, a.p0), distance (p, a.p1)); + if (udist < min_dist2) { + min_dist2 = udist; + side2 = 0.; /* unsure */ + closest_arc2 = a; + } else if (side2 == 0. && udist == min_dist2) { + /* 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_arc2, 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_dist2 = abs (ext_dist); +#endif + side2 = sign (ext_dist); + } + } + } + + #endif + /* + if (side2 == -1.) + { + side = side2; + min_dist = min_dist2; + closest_arc = closest_arc2; + } +*/ 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; } From 87ab802ee152d8633f426bf534483e6ce8921801 Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Wed, 30 May 2012 14:53:43 -0400 Subject: [PATCH 12/35] Intersecting contours work! Kind of. Outlines on overlap regions are still visible, and coinciding contours seems to fail. --- src/glyphy-sdf.glsl | 81 ++++++++++++++++++++++++++++----------------- 1 file changed, 51 insertions(+), 30 deletions(-) diff --git a/src/glyphy-sdf.glsl b/src/glyphy-sdf.glsl index 295e4139..f6bfb5d4 100644 --- a/src/glyphy-sdf.glsl +++ b/src/glyphy-sdf.glsl @@ -56,7 +56,7 @@ glyphy_sdf (vec2 p, 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 */ + /* Short-circuits: 0 to 1 arcs near cell*/ if (arc_list.num_endpoints == 0) { /* far-away cell */ return GLYPHY_INFINITY * float(arc_list.side); @@ -69,17 +69,27 @@ glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) float side = float(arc_list.side); float min_dist = GLYPHY_INFINITY; - glyphy_arc_t closest_arc; + glyphy_arc_t closest_arc; + + float side2 = float(arc_list.side); + float min_dist2 = GLYPHY_INFINITY; + glyphy_arc_t closest_arc2; glyphy_arc_endpoint_t endpoint_prev, endpoint; - endpoint_prev = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset), nominal_size); - /* Check arcs on the first contour group. */ - for (int i = 1; i < GLYPHY_MAX_NUM_ENDPOINTS && i <= arc_list.first_contours_length ; i++) + + + + /* Check arcs on the first contour group. + * First contour group is non-empty IFF arc_list.first_contours_length > 0 + * IFF min_dist == GLYPHY_INFINITY after this loop + */ + 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) { + if (i >= arc_list.num_endpoints || i > arc_list.first_contours_length ) { break; } endpoint = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset + i), nominal_size); @@ -101,7 +111,7 @@ glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) min_dist = udist; side = 0.; /* unsure */ closest_arc = a; - } else if (/*side == 0. && */udist == min_dist) { + } 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. */ @@ -118,20 +128,21 @@ glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) side = sign (ext_dist); } } + } + if (side == 0. && arc_list.first_contours_length > 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); } - - + + + /* Check arcs on the second contour group. + * Second contour group is non-empty IFF arc_list.num_endpoints > arc_list.first_contours_length + * IFF min_dist2 == GLYPHY_INFINITY after this loop + */ endpoint_prev = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset + arc_list.first_contours_length), nominal_size); - -#if 0 - - float side2 = float(arc_list.side); - float min_dist2 = GLYPHY_INFINITY; - glyphy_arc_t closest_arc2; - - /* Check arcs on the second contour group. */ for (int i = arc_list.first_contours_length + 1; i < GLYPHY_MAX_NUM_ENDPOINTS; i++) { @@ -174,24 +185,34 @@ glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) side2 = sign (ext_dist); } } - } + } + if (side2 == 0.) { + // Technically speaking this should not happen, but it does. So try to fix it. + float ext_dist = glyphy_arc_extended_dist (closest_arc2, p); + if (ext_dist < 0.) + side2 = -1.; + else if (ext_dist == 0.) + side2 = 1.; + else + side2 = 1.; + side2 = sign (ext_dist); + } + + - #endif - /* - if (side2 == -1.) + + + if (side2 == -1. || side == 0.) { - side = side2; + side = -1.;//side2; min_dist = min_dist2; closest_arc = closest_arc2; } -*/ - - 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); - } - + /* else if (side2 == 1.) { + min_dist = min_dist2; +// side = side2; + }*/ + else side = 0.; return min_dist * side; From a023ecd01a4bb5a1371cfb90f37c690777962f8b Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Thu, 31 May 2012 11:47:35 -0400 Subject: [PATCH 13/35] Outlines work properly in intersecting contours!!! Just need to fix a with cedilla case. --- src/glyphy-blob.cc | 20 ++++++++++++---- src/glyphy-sdf.glsl | 57 +++++++++++++++++++++++++++++---------------- 2 files changed, 52 insertions(+), 25 deletions(-) diff --git a/src/glyphy-blob.cc b/src/glyphy-blob.cc index 91cb6bc9..036c1e89 100644 --- a/src/glyphy-blob.cc +++ b/src/glyphy-blob.cc @@ -191,10 +191,20 @@ contour_intersects_contour_list (const glyphy_arc_endpoint_t *endpoints, const glyphy_arc_endpoint_t enext2 = endpoints[j]; Arc current_arc (ethis2.p, enext2.p, enext2.d); - Point c = current_arc.center (); - double r = current_arc.radius (); - if (c.x - r <= extents.max_x && c.x + r >= extents.min_x && c.y + r >= extents.min_y && c.y - r <= extents.max_y) { + glyphy_bool_t feasible = false; + if (current_arc.d != 0) { + Point c = current_arc.center (); + double r = current_arc.radius (); + feasible = (c.x - r <= extents.max_x && c.x + r >= extents.min_x && c.y + r >= extents.min_y && c.y - r <= extents.max_y); + } else { + double min_x = (current_arc.p0.x < current_arc.p1.x ? current_arc.p0.x : current_arc.p1.x); + double min_y = (current_arc.p0.y < current_arc.p1.y ? current_arc.p0.y : current_arc.p1.y); + double max_x = (current_arc.p0.x > current_arc.p1.x ? current_arc.p0.x : current_arc.p1.x); + double max_y = (current_arc.p0.y > current_arc.p1.y ? current_arc.p0.y : current_arc.p1.y); + feasible = (min_x <= extents.max_x && max_x >= extents.min_x && max_y >= extents.min_y && min_y <= extents.max_y); + } + if (feasible) { /* Compare every arc pair in the two contours. TODO: Be more efficient (sanity check first.) */ for (unsigned int i = start + 1; i < end; i++) { const glyphy_arc_endpoint_t ethis = endpoints[i - 1]; @@ -202,13 +212,13 @@ contour_intersects_contour_list (const glyphy_arc_endpoint_t *endpoints, Arc a (ethis.p, enext.p, enext.d); if (current_arc.intersects_arc (a) != Point (GLYPHY_INFINITY, GLYPHY_INFINITY)) { - // printf("Contours intersect.\n"); + printf("Contours intersect.\n"); return true; } } } } -// printf("Contours do not intersect.\n"); + printf("Contours do not intersect.\n"); return false; } diff --git a/src/glyphy-sdf.glsl b/src/glyphy-sdf.glsl index f6bfb5d4..0e4c4f84 100644 --- a/src/glyphy-sdf.glsl +++ b/src/glyphy-sdf.glsl @@ -82,8 +82,8 @@ glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) /* Check arcs on the first contour group. - * First contour group is non-empty IFF arc_list.first_contours_length > 0 - * IFF min_dist == GLYPHY_INFINITY after this loop + * First contour group is non-empty <=> arc_list.first_contours_length > 0 + * <=> min_dist == GLYPHY_INFINITY after this loop */ endpoint_prev = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset), nominal_size); for (int i = 1; i < GLYPHY_MAX_NUM_ENDPOINTS; i++) @@ -141,7 +141,8 @@ glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) * Second contour group is non-empty IFF arc_list.num_endpoints > arc_list.first_contours_length * IFF min_dist2 == GLYPHY_INFINITY after this loop */ - endpoint_prev = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset + arc_list.first_contours_length), nominal_size); + endpoint_prev = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D + (arc_list.offset + arc_list.first_contours_length), nominal_size); for (int i = arc_list.first_contours_length + 1; i < GLYPHY_MAX_NUM_ENDPOINTS; i++) { @@ -189,32 +190,48 @@ glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) if (side2 == 0.) { // Technically speaking this should not happen, but it does. So try to fix it. float ext_dist = glyphy_arc_extended_dist (closest_arc2, p); - if (ext_dist < 0.) - side2 = -1.; - else if (ext_dist == 0.) - side2 = 1.; - else - side2 = 1.; side2 = sign (ext_dist); } - + if (side == 0. || (side == 1. && side2 == -1.)) + min_dist = min_dist2; + else if (side == 1. && side2 == 1.) + min_dist = min (min_dist, min_dist2); + else if (side == -1. && side2 == -1.) + min_dist = max (min_dist, min_dist2); + + + if (side2 < 0. || side == 0.) { + side = side2; +// min_dist = min_dist2; + } - - if (side2 == -1. || side == 0.) - { - side = -1.;//side2; + +/* + if (min_dist2 < GLYPHY_EPSILON && side == -1. && side2 == -1.) { + side = side2; + } else if ((side2 == -1. || side == 0.) && !(min_dist2 < GLYPHY_EPSILON && side == -1. )) { + side = side2; min_dist = min_dist2; - closest_arc = closest_arc2; } - /* else if (side2 == 1.) { + + + /* If far from Group 1 contours or within Group 2 contours, use Group 2 shading. + if (side2 == -1. || side == 0.) { + side = side2; + min_dist = min_dist2; + }*/ +/* else if (side2 == 1.&& side == 1.) { min_dist = min_dist2; // side = side2; - }*/ - else side = 0.; - - + } + + if (side2 == 1. && side != 0.) + return -1. * min_dist; + return 0.; +*/ + return min_dist * side; } From e3e08b25750c8db6ce74ccabc5f3643e3bd2c5f4 Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Fri, 1 Jun 2012 16:36:35 -0400 Subject: [PATCH 14/35] Simple code cleanup. No major change --- src/glyphy-blob.cc | 26 +++++--------------------- src/glyphy-sdf.glsl | 32 +++++--------------------------- 2 files changed, 10 insertions(+), 48 deletions(-) diff --git a/src/glyphy-blob.cc b/src/glyphy-blob.cc index 036c1e89..6e2e2405 100644 --- a/src/glyphy-blob.cc +++ b/src/glyphy-blob.cc @@ -171,8 +171,6 @@ closest_arcs_to_cell (Point c0, Point c1, /* corners */ - - /* Returns true if the contour in endpoints[start...end-1] intersects any arc in endpoints[0...start-1]. */ glyphy_bool_t contour_intersects_contour_list (const glyphy_arc_endpoint_t *endpoints, @@ -205,7 +203,7 @@ contour_intersects_contour_list (const glyphy_arc_endpoint_t *endpoints, } if (feasible) { - /* Compare every arc pair in the two contours. TODO: Be more efficient (sanity check first.) */ + /* If it seems feasible that this arc-arc pair (one per contour) might intersect, then check carefully. */ for (unsigned int i = start + 1; i < end; i++) { const glyphy_arc_endpoint_t ethis = endpoints[i - 1]; const glyphy_arc_endpoint_t enext = endpoints[i]; @@ -234,18 +232,11 @@ rearrange_contours (const glyphy_arc_endpoint_t *endpoints, /* Copy first contour unchanged. */ unsigned int i = 0; -// printf("Enter the REARRANGE function.. num_endpoints=%d.\n", num_endpoints); -// printf("Endpoint [0] is (%f,%f),%f.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d); while (i + 1 < num_endpoints && endpoints[i + 1].d != GLYPHY_INFINITY) { rearranged_endpoints [i] = glyphy_arc_endpoint_t (endpoints[i]); -// printf("Added endpoint (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); -// printf(" REARRANGED[%d] = (%f,%f),%f.\n", i, endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d); i++; } rearranged_endpoints [i] = endpoints [i]; - - // printf("Added final endpoint (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); - // printf(" REARRANGED[%d] = (%f,%f),%f.\n", i, endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d); i++; @@ -258,36 +249,27 @@ rearrange_contours (const glyphy_arc_endpoint_t *endpoints, unsigned int start = i; while (top < bottom ) { - // printf("Now, i = %d, top = %d, start = %d; bottom = %d, num_endpoints = %d.\n", i, top, start, bottom, num_endpoints); - // printf("Currently at (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); while (endpoints[i + 1].d != GLYPHY_INFINITY && i + 1 < num_endpoints ) { - // printf("New contour includes (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); i++; } - // printf("Added final endpoint (%f,%f),%f. Now i = %d.\n", endpoints[i].p.x, endpoints[i].p.y, endpoints[i].d, i); i++; - if (contour_intersects_contour_list (endpoints, start, i)) { // TODO check for +-1 offsets + if (contour_intersects_contour_list (endpoints, start, i)) { for (unsigned int j = start; j < i; j++) { rearranged_endpoints[bottom - i + j] = endpoints[j]; - // printf(" REARRANGED[%d] = (%f,%f),%f.\n", bottom - i + j, endpoints[j].p.x, endpoints[j].p.y, endpoints[j].d); } bottom = bottom - (i - start); } else { for (unsigned int j = start; j < i; j++) { rearranged_endpoints[top + j - start] = endpoints[j]; - // printf(" REARRANGED[%d] = (%f,%f),%f.\n", top + j - start, endpoints[j].p.x, endpoints[j].p.y, endpoints[j].d); } top = top + (i - start); } start = i; } - - - return top; } @@ -361,7 +343,9 @@ glyphy_arc_list_encode_blob (const glyphy_arc_endpoint_t *endpoints, tex_data.resize (header_length); Point origin = Point (extents.min_x, extents.min_y); unsigned int total_arcs = 0; - + + + /* Here is where we divide the arc list into two, based on intersecting contours. */ glyphy_arc_endpoint_t rearranged_endpoints [num_endpoints]; unsigned int cutoff = rearrange_contours (endpoints, num_endpoints, rearranged_endpoints); endpoints = rearranged_endpoints; diff --git a/src/glyphy-sdf.glsl b/src/glyphy-sdf.glsl index 0e4c4f84..08fb0596 100644 --- a/src/glyphy-sdf.glsl +++ b/src/glyphy-sdf.glsl @@ -192,7 +192,8 @@ glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) float ext_dist = glyphy_arc_extended_dist (closest_arc2, p); side2 = sign (ext_dist); } - + + /* Update the distance to use as min_dist to outline, based on which contours we are in. */ if (side == 0. || (side == 1. && side2 == -1.)) min_dist = min_dist2; else if (side == 1. && side2 == 1.) @@ -201,37 +202,14 @@ glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) min_dist = max (min_dist, min_dist2); - + /* Update side to reflect which side of the overall outline we are at: inside or outside the glyph. */ if (side2 < 0. || side == 0.) { side = side2; -// min_dist = min_dist2; } -/* - if (min_dist2 < GLYPHY_EPSILON && side == -1. && side2 == -1.) { - side = side2; - } else if ((side2 == -1. || side == 0.) && !(min_dist2 < GLYPHY_EPSILON && side == -1. )) { - side = side2; - min_dist = min_dist2; - } - - - /* If far from Group 1 contours or within Group 2 contours, use Group 2 shading. - if (side2 == -1. || side == 0.) { - side = side2; - min_dist = min_dist2; - }*/ -/* else if (side2 == 1.&& side == 1.) { - min_dist = min_dist2; -// side = side2; - } - - if (side2 == 1. && side != 0.) - return -1. * min_dist; - return 0.; -*/ - + + return min_dist * side; } From fce3ed7be6ca12e178744221685da78cbb15f607 Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Mon, 4 Jun 2012 11:50:17 -0400 Subject: [PATCH 15/35] =?UTF-8?q?Fixed=20outline=20seam=20glitch,=20as=20i?= =?UTF-8?q?n=20DroidSans.ttf=20glyph=20(a+cedilla)=20=C4=85.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/glyphy-sdf.glsl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/glyphy-sdf.glsl b/src/glyphy-sdf.glsl index 08fb0596..e2fff8e4 100644 --- a/src/glyphy-sdf.glsl +++ b/src/glyphy-sdf.glsl @@ -192,6 +192,10 @@ glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) float ext_dist = glyphy_arc_extended_dist (closest_arc2, p); side2 = sign (ext_dist); } + + /* If the two minimum distances are the same, but the sides are different, don't anti-alias. */ + if (min_dist == min_dist2 && side * side2 == -1.) + return -1. * GLYPHY_INFINITY; /* Update the distance to use as min_dist to outline, based on which contours we are in. */ if (side == 0. || (side == 1. && side2 == -1.)) From d57d973863cf16421ef426e9326ff4c42b7a99aa Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Mon, 4 Jun 2012 16:21:13 -0400 Subject: [PATCH 16/35] Began work on graph method for grouping contours. Set up vertex structure, made a vertex for each contour. --- src/glyphy-blob.cc | 49 +++++++++++++++++++++++++++++++++++++++++++++- src/glyphy.h | 1 + 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/glyphy-blob.cc b/src/glyphy-blob.cc index 6e2e2405..7530851c 100644 --- a/src/glyphy-blob.cc +++ b/src/glyphy-blob.cc @@ -190,7 +190,7 @@ contour_intersects_contour_list (const glyphy_arc_endpoint_t *endpoints, Arc current_arc (ethis2.p, enext2.p, enext2.d); glyphy_bool_t feasible = false; - if (current_arc.d != 0) { + if (!iszero (current_arc.d)) { Point c = current_arc.center (); double r = current_arc.radius (); feasible = (c.x - r <= extents.max_x && c.x + r >= extents.min_x && c.y + r >= extents.min_y && c.y - r <= extents.max_y); @@ -274,6 +274,52 @@ rearrange_contours (const glyphy_arc_endpoint_t *endpoints, } +typedef struct vertex glyphy_contour_vertex_t; +struct vertex { + unsigned int start_posn; + unsigned int end_posn; + std::vector dotted_edges; + std::vector solid_edges; +}; + + +unsigned int +rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, + unsigned int num_endpoints, + glyphy_arc_endpoint_t *rearranged_endpoints) +{ + + if (num_endpoints == 0) + return 0; + + std::vector contours; + unsigned int previous_index = 0; + + /* Create a list of vertices, where each vertex is a contour. */ + + unsigned int i = 0; + while (i < num_endpoints) { + while (i + 1 < num_endpoints && endpoints[i + 1].d != GLYPHY_INFINITY) { + i++; + } + rearranged_endpoints [i] = endpoints [i]; + i++; + glyphy_contour_vertex_t current_contour; + + current_contour.start_posn = previous_index; + current_contour.end_posn = i; + current_contour.dotted_edges = std::vector (); + current_contour.solid_edges = std::vector (); + + contours.push_back (current_contour); + previous_index = i + 1; + } + + for (int j = 0; j < contours.size (); j++) + printf ("Contour %d spans from %d to %d.\n", j, contours[j].start_posn, contours[j].end_posn); + + return 0; +} @@ -347,6 +393,7 @@ glyphy_arc_list_encode_blob (const glyphy_arc_endpoint_t *endpoints, /* Here is where we divide the arc list into two, based on intersecting contours. */ glyphy_arc_endpoint_t rearranged_endpoints [num_endpoints]; + rearrange_contours2 (endpoints, num_endpoints, rearranged_endpoints); unsigned int cutoff = rearrange_contours (endpoints, num_endpoints, rearranged_endpoints); endpoints = rearranged_endpoints; diff --git a/src/glyphy.h b/src/glyphy.h index 7f94ed2c..c567a458 100644 --- a/src/glyphy.h +++ b/src/glyphy.h @@ -33,6 +33,7 @@ extern "C" { typedef int glyphy_bool_t; + typedef struct { double x; double y; From 8e7da16e83c68ddd21d895320584e7ce8cdb91c5 Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Tue, 5 Jun 2012 18:05:03 -0400 Subject: [PATCH 17/35] Added support for solid edges between vertices. The same framework can be used to add dotted edges soon. --- src/glyphy-blob.cc | 121 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 101 insertions(+), 20 deletions(-) diff --git a/src/glyphy-blob.cc b/src/glyphy-blob.cc index 7530851c..b2ec3846 100644 --- a/src/glyphy-blob.cc +++ b/src/glyphy-blob.cc @@ -27,6 +27,13 @@ using namespace GLyphy::Geometry; +typedef struct vertex glyphy_contour_vertex_t; +struct vertex { + unsigned int start_posn; + unsigned int end_posn; + std::vector dotted_edges; + std::vector solid_edges; +}; #define UPPER_BITS(v,bits,total_bits) ((v) >> ((total_bits) - (bits))) #define LOWER_BITS(v,bits,total_bits) ((v) & ((1 << (bits)) - 1)) @@ -220,6 +227,60 @@ contour_intersects_contour_list (const glyphy_arc_endpoint_t *endpoints, return false; } + +/* Returns true if the contour in endpoints[start...end-1] intersects any arc in endpoints[0...start-1]. */ +glyphy_bool_t +contours_intersect (const glyphy_arc_endpoint_t *endpoints, + const glyphy_contour_vertex_t *contour_1, + const glyphy_contour_vertex_t *contour_2) +{ + /* Find the smallest box around these contours. + * TODO: Okay, so extents don't *actually* work just yet. */ + glyphy_extents_t extents_1; + glyphy_extents_clear (&extents_1); + glyphy_arc_list_extents (endpoints + contour_1->start_posn, contour_1->end_posn - contour_1->start_posn, &extents_1); + +// printf("Extents1: (%f,%f) by (%f,%f)\n", extents_1.min_x, extents_1.max_x, extents_1.min_y, extents_1.max_y); + + glyphy_extents_t extents_2; + glyphy_extents_clear (&extents_2); + glyphy_arc_list_extents (endpoints + contour_2->start_posn, contour_2->end_posn - contour_2->start_posn, &extents_2); + +// printf("Extents2: (%f,%f) by (%f,%f)\n", extents_2.min_x, extents_2.max_x, extents_2.min_y, extents_2.max_y); + + glyphy_bool_t feasible = false; + feasible = (extents_1.min_x <= extents_2.max_x && + extents_1.max_x >= extents_2.min_x && + extents_1.max_y >= extents_2.min_y && + extents_1.min_y <= extents_2.max_y); + + if (!feasible) + return false; + + // If it seems feasible that this arc-arc pair (one per contour) might intersect, then check carefully. + for (unsigned int j = contour_1->start_posn + 1; j < contour_1->end_posn; j++) { + const glyphy_arc_endpoint_t ethis1 = endpoints[j - 1]; + const glyphy_arc_endpoint_t enext1 = endpoints[j]; + Arc a1 (ethis1.p, enext1.p, enext1.d); + printf("#%2d. (%f,%f) to (%f,%f) with d=%f.\n", j, a1.p0.x, a1.p0.y, a1.p1.x, a1.p1.y, a1.d); + + for (unsigned int i = contour_2->start_posn + 1; i < contour_2->end_posn; i++) { + const glyphy_arc_endpoint_t ethis2 = endpoints[i - 1]; + const glyphy_arc_endpoint_t enext2 = endpoints[i]; + Arc a2 (ethis2.p, enext2.p, enext2.d); + + if (a1.intersects_arc (a2) != Point (GLYPHY_INFINITY, GLYPHY_INFINITY)) { + printf("Contours intersect!!)\n"); + return true; + } + } + } + printf("Contours do not intersect!!(\n"); + return false; +} + +/* Rearrange contours into two groups which do not intersect each other, based on a heuristic. + * Soon to be deprecated. */ unsigned int rearrange_contours (const glyphy_arc_endpoint_t *endpoints, unsigned int num_endpoints, @@ -230,7 +291,6 @@ rearrange_contours (const glyphy_arc_endpoint_t *endpoints, return 0; /* Copy first contour unchanged. */ - unsigned int i = 0; while (i + 1 < num_endpoints && endpoints[i + 1].d != GLYPHY_INFINITY) { rearranged_endpoints [i] = glyphy_arc_endpoint_t (endpoints[i]); @@ -274,15 +334,10 @@ rearrange_contours (const glyphy_arc_endpoint_t *endpoints, } -typedef struct vertex glyphy_contour_vertex_t; -struct vertex { - unsigned int start_posn; - unsigned int end_posn; - std::vector dotted_edges; - std::vector solid_edges; -}; +/* Rearranges contours into two groups that don't intersect, based on a bipartite graph partition. + * Still in progress. */ unsigned int rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, unsigned int num_endpoints, @@ -291,33 +346,59 @@ rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, if (num_endpoints == 0) return 0; - + std::vector contours; unsigned int previous_index = 0; - /* Create a list of vertices, where each vertex is a contour. */ - + /* Create a list of vertices, where each vertex is a contour. Edges are still empty for now. */ unsigned int i = 0; - while (i < num_endpoints) { + unsigned int num_contours = 0; + while (i < num_endpoints) { + while (i + 1 < num_endpoints && endpoints[i + 1].d != GLYPHY_INFINITY) { i++; - } - rearranged_endpoints [i] = endpoints [i]; + } i++; glyphy_contour_vertex_t current_contour; current_contour.start_posn = previous_index; current_contour.end_posn = i; - current_contour.dotted_edges = std::vector (); - current_contour.solid_edges = std::vector (); - + current_contour.dotted_edges = std::vector (); + current_contour.solid_edges = std::vector (); + contours.push_back (current_contour); - previous_index = i + 1; + num_contours++; + previous_index = i; } - for (int j = 0; j < contours.size (); j++) - printf ("Contour %d spans from %d to %d.\n", j, contours[j].start_posn, contours[j].end_posn); + /* Set up edges for vertices, based on intersections and inclusions. */ + for (int k = 0; k < num_contours; k++) { + for (int j = 0; j < k; j++) { + /* If contours intersect, we place a solid edge between them. */ + if (contours_intersect (endpoints, &contours[k], &contours[j])) { + contours[k].solid_edges.push_back (&contours[j]); + contours[j].solid_edges.push_back (&contours[k]); + } + else { + /* If one contour contains the other, we place a dotted edge between them. */ + } + } + } + + /* Print out a list of contours and the contours they intersect. */ + for (int j = 0; j < contours.size (); j++) { + printf ("Contour %d spans from %d to %d. ", j, contours[j].start_posn, contours[j].end_posn); + for (int k = 0; k < contours[j].solid_edges.size (); k++) + printf("It intersects contour from %d to %d. ", contours[j].solid_edges[k]->start_posn, contours[j].solid_edges[k]->end_posn); + printf("\n"); + /* printf("Contour Endpoint List:\n"); + for (unsigned int k = contours[j].start_posn; k < contours[j].end_posn; k++) { + printf("#%2d. (%f,%f) with d=%f.\n", k, endpoints[k].p.x, endpoints[k].p.y, endpoints[k].d); + } + */ + } + return 0; } From d42b6fbe4e10384d4d3fa9a8f5f22eeddbe51b14 Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Wed, 6 Jun 2012 12:13:02 -0400 Subject: [PATCH 18/35] Dotted edges are now formed between contours that surround/contain each other. --- src/glyphy-blob.cc | 30 +++++++++++++++++++++++------- src/glyphy-outline.cc | 24 ++++++++++++++++++++---- src/glyphy.h | 8 ++++++++ 3 files changed, 51 insertions(+), 11 deletions(-) diff --git a/src/glyphy-blob.cc b/src/glyphy-blob.cc index b2ec3846..73911690 100644 --- a/src/glyphy-blob.cc +++ b/src/glyphy-blob.cc @@ -262,7 +262,6 @@ contours_intersect (const glyphy_arc_endpoint_t *endpoints, const glyphy_arc_endpoint_t ethis1 = endpoints[j - 1]; const glyphy_arc_endpoint_t enext1 = endpoints[j]; Arc a1 (ethis1.p, enext1.p, enext1.d); - printf("#%2d. (%f,%f) to (%f,%f) with d=%f.\n", j, a1.p0.x, a1.p0.y, a1.p1.x, a1.p1.y, a1.d); for (unsigned int i = contour_2->start_posn + 1; i < contour_2->end_posn; i++) { const glyphy_arc_endpoint_t ethis2 = endpoints[i - 1]; @@ -270,12 +269,10 @@ contours_intersect (const glyphy_arc_endpoint_t *endpoints, Arc a2 (ethis2.p, enext2.p, enext2.d); if (a1.intersects_arc (a2) != Point (GLYPHY_INFINITY, GLYPHY_INFINITY)) { - printf("Contours intersect!!)\n"); return true; } } } - printf("Contours do not intersect!!(\n"); return false; } @@ -375,28 +372,47 @@ rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, for (int k = 0; k < num_contours; k++) { for (int j = 0; j < k; j++) { + /* If contours intersect, we place a solid edge between them. */ if (contours_intersect (endpoints, &contours[k], &contours[j])) { contours[k].solid_edges.push_back (&contours[j]); contours[j].solid_edges.push_back (&contours[k]); } - else { - /* If one contour contains the other, we place a dotted edge between them. */ + else + /* If one contour contains the other, we place a dotted edge between them. */ + // To check if a contour contains another, it is sufficient to check + // if contour_1 contains a point from contour_2, or vice versa, since we already + // know that these contours don't intersect. (For the same reason, we can be sure that + // the point from the first contour will not lie on the second contour.) + // Here we can use some code from glyphy-outline::even_odd. + + if (!even_odd (endpoints + contours[k].start_posn, 1, + endpoints + contours[j].start_posn, contours[j].end_posn - contours[j].start_posn) || + !even_odd (endpoints + contours[j].start_posn, 1, + endpoints + contours[k].start_posn, contours[k].end_posn - contours[k].start_posn)) { + contours[k].dotted_edges.push_back (&contours[j]); + contours[j].dotted_edges.push_back (&contours[k]); + } } } /* Print out a list of contours and the contours they intersect. */ for (int j = 0; j < contours.size (); j++) { + printf ("----------------------------------\n"); printf ("Contour %d spans from %d to %d. ", j, contours[j].start_posn, contours[j].end_posn); for (int k = 0; k < contours[j].solid_edges.size (); k++) printf("It intersects contour from %d to %d. ", contours[j].solid_edges[k]->start_posn, contours[j].solid_edges[k]->end_posn); printf("\n"); - /* printf("Contour Endpoint List:\n"); + for (int k = 0; k < contours[j].dotted_edges.size (); k++) + printf("It contains/surrounds contour from %d to %d. ", contours[j].dotted_edges[k]->start_posn, contours[j].dotted_edges[k]->end_posn); + printf("\n"); + + printf("Contour Endpoint List:\n"); for (unsigned int k = contours[j].start_posn; k < contours[j].end_posn; k++) { printf("#%2d. (%f,%f) with d=%f.\n", k, endpoints[k].p.x, endpoints[k].p.y, endpoints[k].d); } - */ + } return 0; diff --git a/src/glyphy-outline.cc b/src/glyphy-outline.cc index e87eb412..f9e9628d 100644 --- a/src/glyphy-outline.cc +++ b/src/glyphy-outline.cc @@ -126,7 +126,8 @@ is_zero (double v) return fabs (v) < GLYPHY_EPSILON; } -static bool +/*static bool*/ +glyphy_bool_t even_odd (const glyphy_arc_endpoint_t *c_endpoints, unsigned int num_c_endpoints, const glyphy_arc_endpoint_t *endpoints, @@ -192,6 +193,7 @@ even_odd (const glyphy_arc_endpoint_t *c_endpoints, */ const Point p = c_endpoints[0].p; +// printf("EVEN_ODD! p is (%f,%f).\n", p.x, p.y); double count = 0; Point p0 (0, 0); @@ -207,7 +209,7 @@ even_odd (const glyphy_arc_endpoint_t *c_endpoints, /* * Skip our own contour */ - if (&endpoint >= c_endpoints && &endpoint < c_endpoints + num_c_endpoints) + if (&endpoint >= c_endpoints && &endpoint < c_endpoints + num_c_endpoints) continue; /* End-point y's compared to the ref point; lt, eq, or gt */ @@ -217,6 +219,7 @@ even_odd (const glyphy_arc_endpoint_t *c_endpoints, if (is_zero (arc.d)) { /* Line */ + // printf(" Checking a line segment...\n"); if (!s0 || !s1) { @@ -241,15 +244,18 @@ even_odd (const glyphy_arc_endpoint_t *c_endpoints, if (x >= p.x - GLYPHY_EPSILON) continue; // Does not intersect halfline +// printf(" Crossing the line segment.\n"); count++; // Add one for full crossing continue; } else { /* Arc */ +// printf(" Checking an arc... (%f,%f) to (%f,%f) with %f.\n", arc.p0.x,arc.p0.y,arc.p1.x,arc.p1.y,arc.d); if (!s0 || !s1) { +// printf (" We hit a vertex.\n"); /* * Add +.5 / -.5 for each endpoint on the halfline, depending on * crossing direction. @@ -269,7 +275,13 @@ even_odd (const glyphy_arc_endpoint_t *c_endpoints, count += .5 * categorize (t.first.dy, 0); if (!s1 && arc.p1.x < p.x + GLYPHY_EPSILON) count += .5 * categorize (t.second.dy, 0); + +// printf(" Arc-specific execution status: %d, %d, %d, %d.\n", +// is_zero (t.first.dy) ? 1 : 0, is_zero (t.second.dy) ? 1 : 0, !s0 && arc.p0.x < p.x + GLYPHY_EPSILON ? 1 : 0, !s1 && arc.p1.x < p.x + GLYPHY_EPSILON ? 1 : 0); } + + + Point c = arc.center (); double r = arc.radius (); @@ -285,19 +297,23 @@ even_odd (const glyphy_arc_endpoint_t *c_endpoints, * ref point. */ Point pp[2] = { Point (c.x - dx, p.y), Point (c.x + dx, p.y) }; - +// printf(" Nontrivial arc... \n"); #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])) + pp[i].x < p.x - GLYPHY_EPSILON && arc.wedge_contains_point (pp[i])) { +// printf(" A cross! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); count++; // Add one for full crossing + } } #undef POINTS_EQ } } + +// printf ("Count is %d.\n", int (floor (count))); return !(int (floor (count)) & 1); } diff --git a/src/glyphy.h b/src/glyphy.h index c567a458..217936ef 100644 --- a/src/glyphy.h +++ b/src/glyphy.h @@ -272,6 +272,14 @@ glyphy_outline_winding_from_even_odd (glyphy_arc_endpoint_t *endpoints, glyphy_bool_t inverse); +/* Returns true if a half line from the contour in c_endpoints + * crosses an even number of features of other contours. + */ +glyphy_bool_t +even_odd (const glyphy_arc_endpoint_t *c_endpoints, + unsigned int num_c_endpoints, + const glyphy_arc_endpoint_t *endpoints, + unsigned int num_endpoints); /* * Encode an arc outline into binary blob for fast SDF calculation From a6f26c77fa2a1a5d8ce5ee258a4e28b09f6b97bb Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Fri, 8 Jun 2012 10:24:31 -0400 Subject: [PATCH 19/35] No functional change, but started setting up for collapsed dotted edges. --- src/glyphy-blob.cc | 71 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 63 insertions(+), 8 deletions(-) diff --git a/src/glyphy-blob.cc b/src/glyphy-blob.cc index 73911690..4b08b079 100644 --- a/src/glyphy-blob.cc +++ b/src/glyphy-blob.cc @@ -31,6 +31,7 @@ typedef struct vertex glyphy_contour_vertex_t; struct vertex { unsigned int start_posn; unsigned int end_posn; + unsigned int index; /* index in the relevant list of contours */ std::vector dotted_edges; std::vector solid_edges; }; @@ -331,6 +332,19 @@ rearrange_contours (const glyphy_arc_endpoint_t *endpoints, } +void +populate_connected_component (const std::vector contours, + const glyphy_contour_vertex_t current_contour, + std::vector *connected_contours, + bool *contours_seen) +{ +// if (contours_seen [int (&contours - ¤t_contour)]) +// return; + connected_contours->push_back (current_contour); + printf (" Just pushed back contour (%d to %d)!\n", current_contour.start_posn, current_contour.end_posn); + for (unsigned int k = 0; k < current_contour.dotted_edges.size (); k++) + populate_connected_component (contours, *current_contour.dotted_edges[k], connected_contours, contours_seen); +} /* Rearranges contours into two groups that don't intersect, based on a bipartite graph partition. @@ -360,6 +374,7 @@ rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, current_contour.start_posn = previous_index; current_contour.end_posn = i; + current_contour.index = num_contours; current_contour.dotted_edges = std::vector (); current_contour.solid_edges = std::vector (); @@ -369,8 +384,8 @@ rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, } /* Set up edges for vertices, based on intersections and inclusions. */ - for (int k = 0; k < num_contours; k++) { - for (int j = 0; j < k; j++) { + for (unsigned int k = 0; k < num_contours; k++) { + for (unsigned int j = 0; j < k; j++) { /* If contours intersect, we place a solid edge between them. */ @@ -405,15 +420,55 @@ rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, printf("It intersects contour from %d to %d. ", contours[j].solid_edges[k]->start_posn, contours[j].solid_edges[k]->end_posn); printf("\n"); for (int k = 0; k < contours[j].dotted_edges.size (); k++) - printf("It contains/surrounds contour from %d to %d. ", contours[j].dotted_edges[k]->start_posn, contours[j].dotted_edges[k]->end_posn); + printf("It (surrounds/is contained in) contour from %d to %d. ", contours[j].dotted_edges[k]->start_posn, contours[j].dotted_edges[k]->end_posn); printf("\n"); - printf("Contour Endpoint List:\n"); - for (unsigned int k = contours[j].start_posn; k < contours[j].end_posn; k++) { - printf("#%2d. (%f,%f) with d=%f.\n", k, endpoints[k].p.x, endpoints[k].p.y, endpoints[k].d); - } - + printf("Contour Endpoint List:\n"); + for (unsigned int k = contours[j].start_posn; k < contours[j].end_posn; k++) { + printf("#%2d. (%f,%f) with d=%f.\n", k, endpoints[k].p.x, endpoints[k].p.y, endpoints[k].d); } + + } + + /* Collapse all dotted edges by "merging" vertices together. + * Note: We are assuming quite a bit about the graph structure here. + * Hopefully it all works in the cases that ever come up. */ + bool contours_seen [contours.size ()]; + // TODO: Is there a better way to initialize the array to all false? + for (int j = 0; j < contours.size(); j++) { + contours_seen[j] = false; + printf("%s", contours_seen[j] ? "O" : "."); + } + unsigned int current_end = 0; + + + /* For each entry in the vector of contours, make a list of contours that it has a dot-line connection with. */ + std::vector connected_contours; + for (unsigned int j = 0; j < contours.size (); j++) { + if (contours_seen [j]) + continue; + + connected_contours.clear (); + // populate_connected_component (contours, contours [j], &connected_contours, &contours_seen); + + } + + + + /* + for (unsigned int j = 0; j < contours.size (); j++) { + // Add this new, unseen contour to the rearranged list. + if (!contours_seen [j]) { + contours_seen [j] = true; + merge_subtree_contours (endpoints, contours, j, current_end, rearranged_endpoints, &contours_seen); + + for (unsigned int k = 0; k < contours [j].end_posn - contours [j].start_posn; k++) { + rearranged_endpoints [k + current_end] = endpoints [k + contours [j].start_posn]; + } + current_end += (contours [j].end_posn - contours [j].start_posn); + } + } + */ return 0; } From e0af0fbc2b7d4189b0a38bcdef237d1600c45856 Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Fri, 8 Jun 2012 16:37:43 -0400 Subject: [PATCH 20/35] Dotted edges are collapsed and the relevant vertices are merged in the contour relationship graph. --- src/glyphy-blob.cc | 155 ++++++++++++++++++++++++++++++--------------- 1 file changed, 104 insertions(+), 51 deletions(-) diff --git a/src/glyphy-blob.cc b/src/glyphy-blob.cc index 4b08b079..715684c7 100644 --- a/src/glyphy-blob.cc +++ b/src/glyphy-blob.cc @@ -32,8 +32,8 @@ struct vertex { unsigned int start_posn; unsigned int end_posn; unsigned int index; /* index in the relevant list of contours */ - std::vector dotted_edges; - std::vector solid_edges; + std::vector dotted_edges; + std::vector solid_edges; }; #define UPPER_BITS(v,bits,total_bits) ((v) >> ((total_bits) - (bits))) @@ -334,16 +334,20 @@ rearrange_contours (const glyphy_arc_endpoint_t *endpoints, void populate_connected_component (const std::vector contours, - const glyphy_contour_vertex_t current_contour, - std::vector *connected_contours, + const unsigned int current_contour, + std::vector *connected_contours, bool *contours_seen) { -// if (contours_seen [int (&contours - ¤t_contour)]) -// return; + if (contours_seen [current_contour]) + return; + contours_seen [current_contour] = true; + connected_contours->push_back (current_contour); - printf (" Just pushed back contour (%d to %d)!\n", current_contour.start_posn, current_contour.end_posn); - for (unsigned int k = 0; k < current_contour.dotted_edges.size (); k++) - populate_connected_component (contours, *current_contour.dotted_edges[k], connected_contours, contours_seen); + printf (" Just pushed back contour (%d to %d)!\n", contours[current_contour].start_posn, contours[current_contour].end_posn); + for (unsigned int k = 0; k < contours[current_contour].dotted_edges.size (); k++) + populate_connected_component (contours, + contours[contours[current_contour].dotted_edges[k]].index, /* o_O */ + connected_contours, contours_seen); } @@ -375,8 +379,8 @@ rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, current_contour.start_posn = previous_index; current_contour.end_posn = i; current_contour.index = num_contours; - current_contour.dotted_edges = std::vector (); - current_contour.solid_edges = std::vector (); + current_contour.dotted_edges = std::vector (); + current_contour.solid_edges = std::vector (); contours.push_back (current_contour); num_contours++; @@ -390,8 +394,8 @@ rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, /* If contours intersect, we place a solid edge between them. */ if (contours_intersect (endpoints, &contours[k], &contours[j])) { - contours[k].solid_edges.push_back (&contours[j]); - contours[j].solid_edges.push_back (&contours[k]); + contours[k].solid_edges.push_back (j); + contours[j].solid_edges.push_back (k); } else /* If one contour contains the other, we place a dotted edge between them. */ @@ -405,30 +409,14 @@ rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, endpoints + contours[j].start_posn, contours[j].end_posn - contours[j].start_posn) || !even_odd (endpoints + contours[j].start_posn, 1, endpoints + contours[k].start_posn, contours[k].end_posn - contours[k].start_posn)) { - contours[k].dotted_edges.push_back (&contours[j]); - contours[j].dotted_edges.push_back (&contours[k]); + contours[k].dotted_edges.push_back (j); + contours[j].dotted_edges.push_back (k); } } } - /* Print out a list of contours and the contours they intersect. */ - for (int j = 0; j < contours.size (); j++) { - printf ("----------------------------------\n"); - printf ("Contour %d spans from %d to %d. ", j, contours[j].start_posn, contours[j].end_posn); - for (int k = 0; k < contours[j].solid_edges.size (); k++) - printf("It intersects contour from %d to %d. ", contours[j].solid_edges[k]->start_posn, contours[j].solid_edges[k]->end_posn); - printf("\n"); - for (int k = 0; k < contours[j].dotted_edges.size (); k++) - printf("It (surrounds/is contained in) contour from %d to %d. ", contours[j].dotted_edges[k]->start_posn, contours[j].dotted_edges[k]->end_posn); - printf("\n"); - - printf("Contour Endpoint List:\n"); - for (unsigned int k = contours[j].start_posn; k < contours[j].end_posn; k++) { - printf("#%2d. (%f,%f) with d=%f.\n", k, endpoints[k].p.x, endpoints[k].p.y, endpoints[k].d); - } - - } + /* Collapse all dotted edges by "merging" vertices together. * Note: We are assuming quite a bit about the graph structure here. @@ -440,36 +428,101 @@ rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, printf("%s", contours_seen[j] ? "O" : "."); } unsigned int current_end = 0; + std::vector new_contours; + unsigned int num_new_contours = 0; + unsigned int new_endpoint_list_index = 0; + + /* For each entry in the vector of contour vertices, make a list of contours that it has a dot-line connection with. */ + std::vector connected_contours; - /* For each entry in the vector of contours, make a list of contours that it has a dot-line connection with. */ - std::vector connected_contours; for (unsigned int j = 0; j < contours.size (); j++) { if (contours_seen [j]) continue; connected_contours.clear (); - // populate_connected_component (contours, contours [j], &connected_contours, &contours_seen); - - } - - - - /* - for (unsigned int j = 0; j < contours.size (); j++) { - // Add this new, unseen contour to the rearranged list. - if (!contours_seen [j]) { - contours_seen [j] = true; - merge_subtree_contours (endpoints, contours, j, current_end, rearranged_endpoints, &contours_seen); + populate_connected_component (contours, j, &connected_contours, contours_seen); + + printf("These contours are connected: "); + + /* Create a new vertex representing the merged contours. */ + glyphy_contour_vertex_t merged_contour; + merged_contour.start_posn = new_endpoint_list_index; + merged_contour.index = num_new_contours; + merged_contour.dotted_edges = std::vector (); + merged_contour.solid_edges = std::vector (); + + for (unsigned int k = 0; k < connected_contours.size (); k++) { + printf("(%d to %d); ", contours [connected_contours [k]].start_posn, contours [connected_contours [k]].end_posn); + + merged_contour.dotted_edges.push_back (contours [connected_contours [k]].index); + + /* Update the old contour vertex to tell us which new vertex it is now part of. */ + contours [connected_contours [k]].index = merged_contour.index; - for (unsigned int k = 0; k < contours [j].end_posn - contours [j].start_posn; k++) { - rearranged_endpoints [k + current_end] = endpoints [k + contours [j].start_posn]; + + /* Add all the endpoints to the rearranged endpoint array. */ + for (unsigned int m = contours [connected_contours [k]].start_posn; m < contours [connected_contours [k]].end_posn; m++) { + rearranged_endpoints [new_endpoint_list_index] = endpoints [m]; + new_endpoint_list_index++; } - current_end += (contours [j].end_posn - contours [j].start_posn); - } + + /* Merge the lists of solid edges. TODO This should happen outside, and use new contour references.*/ + for (unsigned int m = 0; m < contours [connected_contours [k]].solid_edges.size (); m++) { + unsigned int solid_edge_to_add = contours [contours [connected_contours [k]].solid_edges [m]].index; + bool is_original_edge = true; + for (unsigned int existing_edge = 0; existing_edge < merged_contour.solid_edges.size (); existing_edge++) { + if (solid_edge_to_add == existing_edge) + is_original_edge = false; + } + if (is_original_edge) { + merged_contour.solid_edges.push_back (solid_edge_to_add); + } + } + + + } + printf("\n"); + + for (unsigned int k = 0; k < new_contours.size (); k++) { + for (unsigned int m = 0; m < new_contours [k].solid_edges.size (); m++) { + new_contours[k].solid_edges[m] = contours[new_contours[k].solid_edges[m]].index; + } + } + + merged_contour.end_posn = new_endpoint_list_index; + printf("Made new contour: index=%d, startposn=%d, endposn=%d.\n", merged_contour.index, merged_contour.start_posn, merged_contour.end_posn); + for (unsigned int m = 0; m < merged_contour.dotted_edges.size (); m++) + printf("Dotted edge to %d! ", merged_contour.dotted_edges[m]); + printf("\n"); + for (unsigned int m = 0; m < merged_contour.solid_edges.size (); m++) + printf("Solidd edge to %d! ", merged_contour.solid_edges[m]); + printf("\n"); + + new_contours.push_back (merged_contour); + num_new_contours++; + + } - */ + printf("new_contours_size:%d\n", int (new_contours.size())); +/* Print out a list of contours and the contours they intersect. */ + for (int j = 0; j < new_contours.size (); j++) { + printf ("----------------------------------\n"); + printf ("Contour %d spans from %d to %d. ", j, new_contours[j].start_posn, new_contours[j].end_posn); + for (int k = 0; k < new_contours[j].solid_edges.size (); k++) + printf("It intersects contour #%d. ", new_contours[j].solid_edges[k]); + printf("\n"); + for (int k = 0; k < new_contours[j].dotted_edges.size (); k++) + printf("It includes the old contour #%d. ", new_contours[j].dotted_edges[k]); + printf("\n"); + + printf("Contour Endpoint List:\n"); + for (unsigned int k = new_contours[j].start_posn; k < new_contours[j].end_posn; k++) { + printf("#%2d. (%f,%f) with d=%f.\n", k, rearranged_endpoints[k].p.x, rearranged_endpoints[k].p.y, rearranged_endpoints[k].d); + } + } + return 0; } From 68ece9cfcf84c384921d3c583e1219a761652502 Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Tue, 12 Jun 2012 11:18:37 -0400 Subject: [PATCH 21/35] Handled cases where a cell is completely within one contour group, but contains other contours passing through it. --- src/glyphy-blob.cc | 23 ++++++++++++++++++----- src/glyphy-sdf.glsl | 11 ++++------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/glyphy-blob.cc b/src/glyphy-blob.cc index 715684c7..0ebd34fa 100644 --- a/src/glyphy-blob.cc +++ b/src/glyphy-blob.cc @@ -122,9 +122,17 @@ closest_arcs_to_cell (Point c0, Point c1, /* corners */ // 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); + double min_dist1 = glyphy_sdf_from_arc_list (endpoints, cutoff, &c, NULL); + double min_dist2 = glyphy_sdf_from_arc_list (endpoints + cutoff, num_endpoints - cutoff, &c, NULL); + printf("have distances %f, %f, and min of %f.\n", min_dist1, min_dist2, min_dist); + // if (min_dist2 < 0) + // min_dist = -1 * fabs(min_dist); + + *side = min_dist1 >= 0 ? +1 : -1; + if (min_dist2 < 0) + *side = -1; + + min_dist = fabs (glyphy_sdf_from_arc_list (endpoints, num_endpoints, &c, NULL)); std::vector near_arcs; // If d is the distance from the center of the square to the nearest arc, then @@ -133,7 +141,8 @@ closest_arcs_to_cell (Point c0, Point c1, /* corners */ double radius_squared = (min_dist + half_diagonal) * (min_dist + half_diagonal); unsigned int main_contour_arcs = 0; - if (min_dist - half_diagonal <= faraway) { + if (min_dist - half_diagonal <= faraway && + (min_dist1 > -1 * half_diagonal && min_dist2 > -1 * half_diagonal) ) { Point p0 (0, 0); @@ -154,6 +163,7 @@ closest_arcs_to_cell (Point c0, Point c1, /* corners */ } } } + *num_group_1_arcs = main_contour_arcs; Point p1 = Point (0, 0); @@ -598,9 +608,11 @@ glyphy_arc_list_encode_blob (const glyphy_arc_endpoint_t *endpoints, /* Here is where we divide the arc list into two, based on intersecting contours. */ glyphy_arc_endpoint_t rearranged_endpoints [num_endpoints]; - rearrange_contours2 (endpoints, num_endpoints, rearranged_endpoints); +// rearrange_contours2 (endpoints, num_endpoints, rearranged_endpoints); unsigned int cutoff = rearrange_contours (endpoints, num_endpoints, rearranged_endpoints); endpoints = rearranged_endpoints; + + printf("The cutoff is %d out of a total of %d.\n", cutoff, num_endpoints); for (int row = 0; row < grid_h; row++) for (int col = 0; col < grid_w; col++) @@ -611,6 +623,7 @@ glyphy_arc_list_encode_blob (const glyphy_arc_endpoint_t *endpoints, int side; unsigned int num_group_1_arcs = 0; + printf("For cell (%d,%d), ", row, col); closest_arcs_to_cell (cp0, cp1, faraway, endpoints, num_endpoints, cutoff, diff --git a/src/glyphy-sdf.glsl b/src/glyphy-sdf.glsl index e2fff8e4..6d755b24 100644 --- a/src/glyphy-sdf.glsl +++ b/src/glyphy-sdf.glsl @@ -77,10 +77,6 @@ glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) glyphy_arc_endpoint_t endpoint_prev, endpoint; - - - - /* Check arcs on the first contour group. * First contour group is non-empty <=> arc_list.first_contours_length > 0 * <=> min_dist == GLYPHY_INFINITY after this loop @@ -103,8 +99,10 @@ glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) float udist = abs (sdist) * (1. - GLYPHY_EPSILON); if (udist <= min_dist) { min_dist = udist; - side = sdist <= 0. ? -1. : +1.; + side = (sdist <= 0. ? -1. : +1.); + side = (float(arc_list.side) == -1. ? -1. : side); } + } else { float udist = min (distance (p, a.p0), distance (p, a.p1)); if (udist < min_dist) { @@ -211,12 +209,11 @@ glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) side = side2; } - - return min_dist * side; } + float glyphy_point_dist (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) { From aed4e4a2b9b7cbce30e4d5fa6e9570279cf64bc8 Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Wed, 13 Jun 2012 17:42:40 -0400 Subject: [PATCH 22/35] Partition now chosen using the graph algorithm. Edges are repeated after merge, though. Requires bipartite graphs. --- src/glyphy-blob.cc | 200 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 153 insertions(+), 47 deletions(-) diff --git a/src/glyphy-blob.cc b/src/glyphy-blob.cc index 0ebd34fa..0d02348c 100644 --- a/src/glyphy-blob.cc +++ b/src/glyphy-blob.cc @@ -121,18 +121,15 @@ closest_arcs_to_cell (Point c0, Point c1, /* corners */ { // Find distance between cell center Point c = c0.midpoint (c1); - double min_dist = glyphy_sdf_from_arc_list (endpoints, num_endpoints, &c, NULL); + double min_dist1 = glyphy_sdf_from_arc_list (endpoints, cutoff, &c, NULL); double min_dist2 = glyphy_sdf_from_arc_list (endpoints + cutoff, num_endpoints - cutoff, &c, NULL); - printf("have distances %f, %f, and min of %f.\n", min_dist1, min_dist2, min_dist); - // if (min_dist2 < 0) - // min_dist = -1 * fabs(min_dist); - + double min_dist = fabs (glyphy_sdf_from_arc_list (endpoints, num_endpoints, &c, NULL)); + *side = min_dist1 >= 0 ? +1 : -1; if (min_dist2 < 0) *side = -1; - min_dist = fabs (glyphy_sdf_from_arc_list (endpoints, num_endpoints, &c, NULL)); std::vector near_arcs; // If d is the distance from the center of the square to the nearest arc, then @@ -142,7 +139,7 @@ closest_arcs_to_cell (Point c0, Point c1, /* corners */ unsigned int main_contour_arcs = 0; if (min_dist - half_diagonal <= faraway && - (min_dist1 > -1 * half_diagonal && min_dist2 > -1 * half_diagonal) ) { + (min_dist1 > -1 * half_diagonal && min_dist2 > -1 * half_diagonal) ) { Point p0 (0, 0); @@ -184,6 +181,13 @@ closest_arcs_to_cell (Point c0, Point c1, /* corners */ p1 = arc.p1; } + +/* printf (" Endpoints in Group 1: \n"); + for (int j = 0; j < *num_group_1_arcs; j++) + printf (" (%f,%f), d=%f\n", near_endpoints[j].p.x, near_endpoints[j].p.y, near_endpoints[j].d); + printf (" Endpoints in Group 2: \n"); + for (int j = *num_group_1_arcs; j < near_endpoints.size (); j++) + printf (" (%f,%f), d=%f\n", near_endpoints[j].p.x, near_endpoints[j].p.y, near_endpoints[j].d);*/ } @@ -338,6 +342,8 @@ rearrange_contours (const glyphy_arc_endpoint_t *endpoints, } start = i; } + + return top; } @@ -360,13 +366,27 @@ populate_connected_component (const std::vector contour connected_contours, contours_seen); } +void +assign_contour_levels (const std::vector new_contours, + const unsigned int current_contour, + const unsigned int projected_level, + int* contour_levels) +{ + if (contour_levels [current_contour] != -1) + return; + + contour_levels [current_contour] = projected_level; + for (unsigned int i = 0; i < new_contours [current_contour].solid_edges.size (); i++) + assign_contour_levels (new_contours, new_contours [current_contour].solid_edges [i], projected_level + 1, contour_levels); +} + /* Rearranges contours into two groups that don't intersect, based on a bipartite graph partition. * Still in progress. */ unsigned int rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, unsigned int num_endpoints, - glyphy_arc_endpoint_t *rearranged_endpoints) + glyphy_arc_endpoint_t *rerearranged_endpoints) { if (num_endpoints == 0) @@ -408,12 +428,13 @@ rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, contours[j].solid_edges.push_back (k); } else - /* If one contour contains the other, we place a dotted edge between them. */ - // To check if a contour contains another, it is sufficient to check - // if contour_1 contains a point from contour_2, or vice versa, since we already - // know that these contours don't intersect. (For the same reason, we can be sure that - // the point from the first contour will not lie on the second contour.) - // Here we can use some code from glyphy-outline::even_odd. + /** If one contour contains the other, we place a dotted edge between them. + * To check if a contour contains another, it is sufficient to check + * if contour_1 contains a point from contour_2, or vice versa, since we already + * know that these contours don't intersect. (For the same reason, we can be sure that + * the point from the first contour will not lie on the second contour.) + * Here we can use some code from glyphy-outline::even_odd. + */ if (!even_odd (endpoints + contours[k].start_posn, 1, endpoints + contours[j].start_posn, contours[j].end_posn - contours[j].start_posn) || @@ -426,6 +447,26 @@ rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, } } + + printf("contours_size:%d\n", int (contours.size())); + +/* Print out a list of contours and the contours they intersect. */ + for (int j = 0; j < contours.size (); j++) { + printf ("----------------------------------\n"); + printf ("Contour %d spans from %d to %d. ", j, contours[j].start_posn, contours[j].end_posn); + for (int k = 0; k < contours[j].solid_edges.size (); k++) + printf("It intersects contour #%d. ", contours[j].solid_edges[k]); + printf("\n"); + for (int k = 0; k < contours[j].dotted_edges.size (); k++) + printf("It includes the old contour #%d. ", contours[j].dotted_edges[k]); + printf("\n"); + + printf("Contour Endpoint List:\n"); + for (unsigned int k = contours[j].start_posn; k < contours[j].end_posn; k++) { + printf("#%2d. (%f,%f) with d=%f.\n", k, endpoints[k].p.x, endpoints[k].p.y, endpoints[k].d); + } + } + /* Collapse all dotted edges by "merging" vertices together. @@ -444,6 +485,7 @@ rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, /* For each entry in the vector of contour vertices, make a list of contours that it has a dot-line connection with. */ std::vector connected_contours; + glyphy_arc_endpoint_t rearranged_endpoints [num_endpoints]; for (unsigned int j = 0; j < contours.size (); j++) { @@ -462,6 +504,7 @@ rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, merged_contour.dotted_edges = std::vector (); merged_contour.solid_edges = std::vector (); + for (unsigned int k = 0; k < connected_contours.size (); k++) { printf("(%d to %d); ", contours [connected_contours [k]].start_posn, contours [connected_contours [k]].end_posn); @@ -476,49 +519,65 @@ rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, rearranged_endpoints [new_endpoint_list_index] = endpoints [m]; new_endpoint_list_index++; } - - /* Merge the lists of solid edges. TODO This should happen outside, and use new contour references.*/ - for (unsigned int m = 0; m < contours [connected_contours [k]].solid_edges.size (); m++) { - unsigned int solid_edge_to_add = contours [contours [connected_contours [k]].solid_edges [m]].index; + } + merged_contour.end_posn = new_endpoint_list_index; + new_contours.push_back (merged_contour); + num_new_contours++; + + printf("JUST MADE NEW CONTOUR #%d.\n", new_contours[num_new_contours-1].index); + + } + + for (unsigned int j = 0; j < new_contours.size (); j++) + printf ("------\nNew Contour %d has index %d.\n", j, new_contours[j].index); + + + + /* Merge the lists of solid edges. TODO This should happen outside, and use new contour references.*/ + for (unsigned int j = 0; j < new_contours.size (); j++) { + new_contours[j].solid_edges.clear (); + + for (unsigned int m = 0; m < new_contours[j].dotted_edges.size (); m++) { + + for (unsigned int k = 0; k < contours[new_contours[j].dotted_edges[m]].solid_edges.size (); k++) { + + + unsigned int solid_edge_to_add = contours[contours[new_contours[j].dotted_edges[m]].solid_edges[k]].index; + printf(" (%d) Trying to add edge %d.\n", contours[new_contours[j].dotted_edges[m]].solid_edges[k], solid_edge_to_add); bool is_original_edge = true; - for (unsigned int existing_edge = 0; existing_edge < merged_contour.solid_edges.size (); existing_edge++) { + for (unsigned int existing_edge = 0; existing_edge < new_contours[j].solid_edges.size (); existing_edge++) { if (solid_edge_to_add == existing_edge) is_original_edge = false; } if (is_original_edge) { - merged_contour.solid_edges.push_back (solid_edge_to_add); + new_contours[j].solid_edges.push_back (solid_edge_to_add); + printf(" Success!\n"); } } - - } - printf("\n"); - - for (unsigned int k = 0; k < new_contours.size (); k++) { + + /* for (unsigned int k = 0; k < new_contours.size (); k++) { for (unsigned int m = 0; m < new_contours [k].solid_edges.size (); m++) { new_contours[k].solid_edges[m] = contours[new_contours[k].solid_edges[m]].index; } } - - merged_contour.end_posn = new_endpoint_list_index; - printf("Made new contour: index=%d, startposn=%d, endposn=%d.\n", merged_contour.index, merged_contour.start_posn, merged_contour.end_posn); - for (unsigned int m = 0; m < merged_contour.dotted_edges.size (); m++) - printf("Dotted edge to %d! ", merged_contour.dotted_edges[m]); + */ + + printf("Made new contour: index=%d, startposn=%d, endposn=%d.\n", new_contours[j].index, new_contours[j].start_posn, new_contours[j].end_posn); + for (unsigned int m = 0; m < new_contours[j].dotted_edges.size (); m++) + printf("Dotted edge to %d! ", new_contours[j].dotted_edges[m]); printf("\n"); - for (unsigned int m = 0; m < merged_contour.solid_edges.size (); m++) - printf("Solidd edge to %d! ", merged_contour.solid_edges[m]); + for (unsigned int m = 0; m < new_contours[j].solid_edges.size (); m++) + printf("Solidd edge to %d! ", new_contours[j].solid_edges[m]); printf("\n"); - - new_contours.push_back (merged_contour); - num_new_contours++; - - } + + printf("new_contours_size:%d\n", int (new_contours.size())); /* Print out a list of contours and the contours they intersect. */ for (int j = 0; j < new_contours.size (); j++) { - printf ("----------------------------------\n"); + printf ("@@---------------------------------\n"); printf ("Contour %d spans from %d to %d. ", j, new_contours[j].start_posn, new_contours[j].end_posn); for (int k = 0; k < new_contours[j].solid_edges.size (); k++) printf("It intersects contour #%d. ", new_contours[j].solid_edges[k]); @@ -527,13 +586,60 @@ rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, printf("It includes the old contour #%d. ", new_contours[j].dotted_edges[k]); printf("\n"); - printf("Contour Endpoint List:\n"); - for (unsigned int k = new_contours[j].start_posn; k < new_contours[j].end_posn; k++) { - printf("#%2d. (%f,%f) with d=%f.\n", k, rearranged_endpoints[k].p.x, rearranged_endpoints[k].p.y, rearranged_endpoints[k].d); - } + // printf("Contour Endpoint List:\n"); + // for (unsigned int k = new_contours[j].start_posn; k < new_contours[j].end_posn; k++) { + // printf("#%2d. (%f,%f) with d=%f.\n", k, rearranged_endpoints[k].p.x, rearranged_endpoints[k].p.y, rearranged_endpoints[k].d); + // } } + + /* Time to bipartition the graph, which should contain only solid edges at this point. */ + + int contour_levels [new_contours.size ()]; + // TODO: Is there a better way to initialize the array to all -1? + for (int j = 0; j < new_contours.size(); j++) { + contour_levels [j] = -1; + printf("%s", contour_levels [j] != -1 ? "O" : "."); + } + + for (unsigned int j = 0; j < new_contours.size (); j++) { + if (contour_levels [j] != -1) + continue; + assign_contour_levels (new_contours, j, 0, contour_levels); + } + + printf("The contours levels are as follows: \n"); + for (unsigned int j = 0; j < new_contours.size (); j++) { + printf ("Contour %d: Level %d.\n", j, contour_levels [j]); + } + + + /* Add new contours one-by-one. + * If the new contour has an even level, add it to the top of the list. + * Otherwise, add it to the bottom. + */ + unsigned int top = 0; + unsigned int bottom = num_endpoints; + + for (i = 0; i < new_contours.size (); i++) { + if (contour_levels [i] % 2 == 0) { + for (unsigned int j = new_contours [i].start_posn; j < new_contours [i].end_posn; j++) { + rerearranged_endpoints[top + j - new_contours [i].start_posn] = rearranged_endpoints[j]; + } + top = top + (new_contours [i].end_posn - new_contours [i].start_posn); + } else { + for (unsigned int j = new_contours [i].start_posn; j < new_contours [i].end_posn; j++) { + rerearranged_endpoints[bottom + j - new_contours [i].end_posn] = rearranged_endpoints[j]; + } + bottom = bottom - (new_contours [i].end_posn - new_contours [i].start_posn); + } + + + } + + + + return top; - return 0; } @@ -608,11 +714,11 @@ glyphy_arc_list_encode_blob (const glyphy_arc_endpoint_t *endpoints, /* Here is where we divide the arc list into two, based on intersecting contours. */ glyphy_arc_endpoint_t rearranged_endpoints [num_endpoints]; -// rearrange_contours2 (endpoints, num_endpoints, rearranged_endpoints); - unsigned int cutoff = rearrange_contours (endpoints, num_endpoints, rearranged_endpoints); + // rearrange_contours2 (endpoints, num_endpoints, rearranged_endpoints); + unsigned int cutoff = rearrange_contours2 (endpoints, num_endpoints, rearranged_endpoints); endpoints = rearranged_endpoints; - printf("The cutoff is %d out of a total of %d.\n", cutoff, num_endpoints); + // printf("The cutoff is %d out of a total of %d.\n", cutoff, num_endpoints); for (int row = 0; row < grid_h; row++) for (int col = 0; col < grid_w; col++) @@ -623,12 +729,12 @@ glyphy_arc_list_encode_blob (const glyphy_arc_endpoint_t *endpoints, int side; unsigned int num_group_1_arcs = 0; - printf("For cell (%d,%d), ", row, col); closest_arcs_to_cell (cp0, cp1, faraway, endpoints, num_endpoints, cutoff, &num_group_1_arcs, near_endpoints, &side); + // printf("Cell (%d,%d) has corner (%f,%f) and is close to %d arcs.\n", row, col, cp0.x, cp0.y, near_endpoints.size ()); #define QUANTIZE_X(X) (lround (MAX_X * ((X - extents.min_x) / glyph_width ))) From 44eb644e4cfab7e7f72712d9b553a942f305cba1 Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Thu, 14 Jun 2012 14:45:58 -0400 Subject: [PATCH 23/35] Edges in the new graph are no longer repeated. --- src/glyphy-blob.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/glyphy-blob.cc b/src/glyphy-blob.cc index 0d02348c..03a9d5a5 100644 --- a/src/glyphy-blob.cc +++ b/src/glyphy-blob.cc @@ -546,7 +546,7 @@ rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, printf(" (%d) Trying to add edge %d.\n", contours[new_contours[j].dotted_edges[m]].solid_edges[k], solid_edge_to_add); bool is_original_edge = true; for (unsigned int existing_edge = 0; existing_edge < new_contours[j].solid_edges.size (); existing_edge++) { - if (solid_edge_to_add == existing_edge) + if (solid_edge_to_add == new_contours[j].solid_edges [existing_edge]) is_original_edge = false; } if (is_original_edge) { From 3b353f2aa7c11530ca1135fe0e7d8047ad33e87d Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Thu, 14 Jun 2012 17:33:53 -0400 Subject: [PATCH 24/35] Small floating point fix to help coincident outlines keep working. --- src/glyphy-blob.cc | 8 +------- src/glyphy-sdf.glsl | 2 +- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/glyphy-blob.cc b/src/glyphy-blob.cc index 03a9d5a5..10349097 100644 --- a/src/glyphy-blob.cc +++ b/src/glyphy-blob.cc @@ -555,13 +555,7 @@ rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, } } } - - /* for (unsigned int k = 0; k < new_contours.size (); k++) { - for (unsigned int m = 0; m < new_contours [k].solid_edges.size (); m++) { - new_contours[k].solid_edges[m] = contours[new_contours[k].solid_edges[m]].index; - } - } - */ + printf("Made new contour: index=%d, startposn=%d, endposn=%d.\n", new_contours[j].index, new_contours[j].start_posn, new_contours[j].end_posn); for (unsigned int m = 0; m < new_contours[j].dotted_edges.size (); m++) diff --git a/src/glyphy-sdf.glsl b/src/glyphy-sdf.glsl index 6d755b24..c58ecd38 100644 --- a/src/glyphy-sdf.glsl +++ b/src/glyphy-sdf.glsl @@ -192,7 +192,7 @@ glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) } /* If the two minimum distances are the same, but the sides are different, don't anti-alias. */ - if (min_dist == min_dist2 && side * side2 == -1.) + if (glyphy_iszero (min_dist - min_dist2) && side * side2 == -1.) return -1. * GLYPHY_INFINITY; /* Update the distance to use as min_dist to outline, based on which contours we are in. */ From 38385829a3566ebcf09d1f9efbbeb050c218574f Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Fri, 15 Jun 2012 15:19:47 -0400 Subject: [PATCH 25/35] Fixed missing edge bug (very rare - need coincident points), and general code cleanup. --- src/glyphy-blob.cc | 190 ++++----------------------------------------- 1 file changed, 14 insertions(+), 176 deletions(-) diff --git a/src/glyphy-blob.cc b/src/glyphy-blob.cc index 10349097..1d9e87b9 100644 --- a/src/glyphy-blob.cc +++ b/src/glyphy-blob.cc @@ -70,7 +70,7 @@ static inline glyphy_rgba_t arc_list_encode (unsigned int first_contours_length, unsigned int offset, unsigned int num_points, int side) { glyphy_rgba_t v; - v.r = LOWER_BITS (first_contours_length, 7, 8); //0; // unused for arc-list encoding + v.r = LOWER_BITS (first_contours_length, 7, 8); /* store the number of contours in the first part of the partition */ v.g = UPPER_BITS (offset, 8, 16); v.b = LOWER_BITS (offset, 8, 16); v.a = LOWER_BITS (num_points, 8, 8); @@ -167,101 +167,38 @@ closest_arcs_to_cell (Point c0, Point c1, /* corners */ for (unsigned i = 0; i < near_arcs.size (); i++) { Arc arc = near_arcs[i]; - - if (i == 0 || p1 != arc.p0) { + + if (i == 0 || p1 != arc.p0 || i == main_contour_arcs) { glyphy_arc_endpoint_t endpoint = {arc.p0, GLYPHY_INFINITY}; near_endpoints.push_back (endpoint); p1 = arc.p0; - if (i < main_contour_arcs) + if (i < main_contour_arcs) { (*num_group_1_arcs)++; + } } glyphy_arc_endpoint_t endpoint = {arc.p1, arc.d}; near_endpoints.push_back (endpoint); p1 = arc.p1; } - - -/* printf (" Endpoints in Group 1: \n"); - for (int j = 0; j < *num_group_1_arcs; j++) - printf (" (%f,%f), d=%f\n", near_endpoints[j].p.x, near_endpoints[j].p.y, near_endpoints[j].d); - printf (" Endpoints in Group 2: \n"); - for (int j = *num_group_1_arcs; j < near_endpoints.size (); j++) - printf (" (%f,%f), d=%f\n", near_endpoints[j].p.x, near_endpoints[j].p.y, near_endpoints[j].d);*/ } - -/* Returns true if the contour in endpoints[start...end-1] intersects any arc in endpoints[0...start-1]. */ -glyphy_bool_t -contour_intersects_contour_list (const glyphy_arc_endpoint_t *endpoints, - unsigned int start, - unsigned int end) -{ - /* Find the smallest box around this contour. */ - glyphy_extents_t extents; - glyphy_extents_clear (&extents); - - glyphy_arc_list_extents (endpoints + start, end - start, &extents); - - for (unsigned int j = 1; j < start; j++) { - // if (endpoints[j].d != GLYPHY_INFINITY) ????????????????????????????????????????????????????? - const glyphy_arc_endpoint_t ethis2 = endpoints[j - 1]; - const glyphy_arc_endpoint_t enext2 = endpoints[j]; - Arc current_arc (ethis2.p, enext2.p, enext2.d); - - glyphy_bool_t feasible = false; - if (!iszero (current_arc.d)) { - Point c = current_arc.center (); - double r = current_arc.radius (); - feasible = (c.x - r <= extents.max_x && c.x + r >= extents.min_x && c.y + r >= extents.min_y && c.y - r <= extents.max_y); - } else { - double min_x = (current_arc.p0.x < current_arc.p1.x ? current_arc.p0.x : current_arc.p1.x); - double min_y = (current_arc.p0.y < current_arc.p1.y ? current_arc.p0.y : current_arc.p1.y); - double max_x = (current_arc.p0.x > current_arc.p1.x ? current_arc.p0.x : current_arc.p1.x); - double max_y = (current_arc.p0.y > current_arc.p1.y ? current_arc.p0.y : current_arc.p1.y); - feasible = (min_x <= extents.max_x && max_x >= extents.min_x && max_y >= extents.min_y && min_y <= extents.max_y); - } - - if (feasible) { - /* If it seems feasible that this arc-arc pair (one per contour) might intersect, then check carefully. */ - for (unsigned int i = start + 1; i < end; i++) { - const glyphy_arc_endpoint_t ethis = endpoints[i - 1]; - const glyphy_arc_endpoint_t enext = endpoints[i]; - Arc a (ethis.p, enext.p, enext.d); - - if (current_arc.intersects_arc (a) != Point (GLYPHY_INFINITY, GLYPHY_INFINITY)) { - printf("Contours intersect.\n"); - return true; - } - } - } - } - printf("Contours do not intersect.\n"); - return false; -} - - /* Returns true if the contour in endpoints[start...end-1] intersects any arc in endpoints[0...start-1]. */ glyphy_bool_t contours_intersect (const glyphy_arc_endpoint_t *endpoints, const glyphy_contour_vertex_t *contour_1, const glyphy_contour_vertex_t *contour_2) { - /* Find the smallest box around these contours. - * TODO: Okay, so extents don't *actually* work just yet. */ + /* Find the smallest box around these contours. */ glyphy_extents_t extents_1; glyphy_extents_clear (&extents_1); glyphy_arc_list_extents (endpoints + contour_1->start_posn, contour_1->end_posn - contour_1->start_posn, &extents_1); -// printf("Extents1: (%f,%f) by (%f,%f)\n", extents_1.min_x, extents_1.max_x, extents_1.min_y, extents_1.max_y); - glyphy_extents_t extents_2; glyphy_extents_clear (&extents_2); glyphy_arc_list_extents (endpoints + contour_2->start_posn, contour_2->end_posn - contour_2->start_posn, &extents_2); - -// printf("Extents2: (%f,%f) by (%f,%f)\n", extents_2.min_x, extents_2.max_x, extents_2.min_y, extents_2.max_y); glyphy_bool_t feasible = false; feasible = (extents_1.min_x <= extents_2.max_x && @@ -291,61 +228,6 @@ contours_intersect (const glyphy_arc_endpoint_t *endpoints, return false; } -/* Rearrange contours into two groups which do not intersect each other, based on a heuristic. - * Soon to be deprecated. */ -unsigned int -rearrange_contours (const glyphy_arc_endpoint_t *endpoints, - unsigned int num_endpoints, - glyphy_arc_endpoint_t *rearranged_endpoints) -{ - - if (num_endpoints == 0) - return 0; - - /* Copy first contour unchanged. */ - unsigned int i = 0; - while (i + 1 < num_endpoints && endpoints[i + 1].d != GLYPHY_INFINITY) { - rearranged_endpoints [i] = glyphy_arc_endpoint_t (endpoints[i]); - i++; - } - rearranged_endpoints [i] = endpoints [i]; - i++; - - - /* Add new contours one-by-one. - * If the new contour intersects a contour at the top of the rearranged list, add it to the bottom. - * Otherwise, add it to the top. - */ - unsigned int top = i; - unsigned int bottom = num_endpoints; - unsigned int start = i; - - while (top < bottom ) { - - while (endpoints[i + 1].d != GLYPHY_INFINITY && i + 1 < num_endpoints ) { - i++; - } - i++; - - - if (contour_intersects_contour_list (endpoints, start, i)) { - for (unsigned int j = start; j < i; j++) { - rearranged_endpoints[bottom - i + j] = endpoints[j]; - } - bottom = bottom - (i - start); - } - else { - for (unsigned int j = start; j < i; j++) { - rearranged_endpoints[top + j - start] = endpoints[j]; - } - top = top + (i - start); - } - start = i; - } - - - return top; -} void @@ -359,7 +241,6 @@ populate_connected_component (const std::vector contour contours_seen [current_contour] = true; connected_contours->push_back (current_contour); - printf (" Just pushed back contour (%d to %d)!\n", contours[current_contour].start_posn, contours[current_contour].end_posn); for (unsigned int k = 0; k < contours[current_contour].dotted_edges.size (); k++) populate_connected_component (contours, contours[contours[current_contour].dotted_edges[k]].index, /* o_O */ @@ -391,6 +272,11 @@ rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, if (num_endpoints == 0) return 0; + + printf("Original Endpoint List:\n"); + for (unsigned int k = 0; k < num_endpoints; k++) { + printf("#%2d. (%f,%f) with d=%f.\n", k, endpoints[k].p.x, endpoints[k].p.y, endpoints[k].d); + } std::vector contours; unsigned int previous_index = 0; @@ -446,26 +332,7 @@ rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, } } } - - - printf("contours_size:%d\n", int (contours.size())); - -/* Print out a list of contours and the contours they intersect. */ - for (int j = 0; j < contours.size (); j++) { - printf ("----------------------------------\n"); - printf ("Contour %d spans from %d to %d. ", j, contours[j].start_posn, contours[j].end_posn); - for (int k = 0; k < contours[j].solid_edges.size (); k++) - printf("It intersects contour #%d. ", contours[j].solid_edges[k]); - printf("\n"); - for (int k = 0; k < contours[j].dotted_edges.size (); k++) - printf("It includes the old contour #%d. ", contours[j].dotted_edges[k]); - printf("\n"); - - printf("Contour Endpoint List:\n"); - for (unsigned int k = contours[j].start_posn; k < contours[j].end_posn; k++) { - printf("#%2d. (%f,%f) with d=%f.\n", k, endpoints[k].p.x, endpoints[k].p.y, endpoints[k].d); - } - } + @@ -494,9 +361,7 @@ rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, connected_contours.clear (); populate_connected_component (contours, j, &connected_contours, contours_seen); - - printf("These contours are connected: "); - + /* Create a new vertex representing the merged contours. */ glyphy_contour_vertex_t merged_contour; merged_contour.start_posn = new_endpoint_list_index; @@ -506,7 +371,6 @@ rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, for (unsigned int k = 0; k < connected_contours.size (); k++) { - printf("(%d to %d); ", contours [connected_contours [k]].start_posn, contours [connected_contours [k]].end_posn); merged_contour.dotted_edges.push_back (contours [connected_contours [k]].index); @@ -524,15 +388,10 @@ rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, new_contours.push_back (merged_contour); num_new_contours++; - printf("JUST MADE NEW CONTOUR #%d.\n", new_contours[num_new_contours-1].index); - } for (unsigned int j = 0; j < new_contours.size (); j++) - printf ("------\nNew Contour %d has index %d.\n", j, new_contours[j].index); - - - + /* Merge the lists of solid edges. TODO This should happen outside, and use new contour references.*/ for (unsigned int j = 0; j < new_contours.size (); j++) { new_contours[j].solid_edges.clear (); @@ -543,7 +402,6 @@ rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, unsigned int solid_edge_to_add = contours[contours[new_contours[j].dotted_edges[m]].solid_edges[k]].index; - printf(" (%d) Trying to add edge %d.\n", contours[new_contours[j].dotted_edges[m]].solid_edges[k], solid_edge_to_add); bool is_original_edge = true; for (unsigned int existing_edge = 0; existing_edge < new_contours[j].solid_edges.size (); existing_edge++) { if (solid_edge_to_add == new_contours[j].solid_edges [existing_edge]) @@ -551,19 +409,10 @@ rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, } if (is_original_edge) { new_contours[j].solid_edges.push_back (solid_edge_to_add); - printf(" Success!\n"); } } } - - printf("Made new contour: index=%d, startposn=%d, endposn=%d.\n", new_contours[j].index, new_contours[j].start_posn, new_contours[j].end_posn); - for (unsigned int m = 0; m < new_contours[j].dotted_edges.size (); m++) - printf("Dotted edge to %d! ", new_contours[j].dotted_edges[m]); - printf("\n"); - for (unsigned int m = 0; m < new_contours[j].solid_edges.size (); m++) - printf("Solidd edge to %d! ", new_contours[j].solid_edges[m]); - printf("\n"); } @@ -571,7 +420,6 @@ rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, /* Print out a list of contours and the contours they intersect. */ for (int j = 0; j < new_contours.size (); j++) { - printf ("@@---------------------------------\n"); printf ("Contour %d spans from %d to %d. ", j, new_contours[j].start_posn, new_contours[j].end_posn); for (int k = 0; k < new_contours[j].solid_edges.size (); k++) printf("It intersects contour #%d. ", new_contours[j].solid_edges[k]); @@ -601,12 +449,6 @@ rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, assign_contour_levels (new_contours, j, 0, contour_levels); } - printf("The contours levels are as follows: \n"); - for (unsigned int j = 0; j < new_contours.size (); j++) { - printf ("Contour %d: Level %d.\n", j, contour_levels [j]); - } - - /* Add new contours one-by-one. * If the new contour has an even level, add it to the top of the list. * Otherwise, add it to the bottom. @@ -708,12 +550,9 @@ glyphy_arc_list_encode_blob (const glyphy_arc_endpoint_t *endpoints, /* Here is where we divide the arc list into two, based on intersecting contours. */ glyphy_arc_endpoint_t rearranged_endpoints [num_endpoints]; - // rearrange_contours2 (endpoints, num_endpoints, rearranged_endpoints); unsigned int cutoff = rearrange_contours2 (endpoints, num_endpoints, rearranged_endpoints); endpoints = rearranged_endpoints; - // printf("The cutoff is %d out of a total of %d.\n", cutoff, num_endpoints); - for (int row = 0; row < grid_h; row++) for (int col = 0; col < grid_w; col++) { @@ -728,7 +567,6 @@ glyphy_arc_list_encode_blob (const glyphy_arc_endpoint_t *endpoints, endpoints, num_endpoints, cutoff, &num_group_1_arcs, near_endpoints, &side); - // printf("Cell (%d,%d) has corner (%f,%f) and is close to %d arcs.\n", row, col, cp0.x, cp0.y, near_endpoints.size ()); #define QUANTIZE_X(X) (lround (MAX_X * ((X - extents.min_x) / glyph_width ))) From a7a6d909641a3074ceebad8964a68a310503767f Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Tue, 19 Jun 2012 12:20:30 -0400 Subject: [PATCH 26/35] Minor. Some light code cleanup; added some comments. --- src/glyphy-blob.cc | 110 ++++++++++++++++++++--------------------- src/glyphy-common.glsl | 8 +++ src/glyphy-sdf.glsl | 5 +- 3 files changed, 66 insertions(+), 57 deletions(-) diff --git a/src/glyphy-blob.cc b/src/glyphy-blob.cc index 1d9e87b9..1b6d055d 100644 --- a/src/glyphy-blob.cc +++ b/src/glyphy-blob.cc @@ -31,9 +31,9 @@ typedef struct vertex glyphy_contour_vertex_t; struct vertex { unsigned int start_posn; unsigned int end_posn; - unsigned int index; /* index in the relevant list of contours */ - std::vector dotted_edges; - std::vector solid_edges; + unsigned int index; /* index in whichever list of contours is most currently relevant */ + std::vector dotted_edges; /* in the contour relationship graph */ + std::vector solid_edges; /* in the contour relationship graph */ }; #define UPPER_BITS(v,bits,total_bits) ((v) >> ((total_bits) - (bits))) @@ -114,12 +114,12 @@ closest_arcs_to_cell (Point c0, Point c1, /* corners */ double faraway, const glyphy_arc_endpoint_t *endpoints, unsigned int num_endpoints, - unsigned int cutoff, + unsigned int cutoff, /* how many endpoints are from the first contour group? */ unsigned int *num_group_1_arcs, std::vector &near_endpoints, int *side) { - // Find distance between cell center + /* Find distance between arcs and cell center */ Point c = c0.midpoint (c1); double min_dist1 = glyphy_sdf_from_arc_list (endpoints, cutoff, &c, NULL); @@ -132,8 +132,9 @@ closest_arcs_to_cell (Point c0, Point c1, /* corners */ std::vector 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. + /* 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 = (min_dist + half_diagonal) * (min_dist + half_diagonal); unsigned int main_contour_arcs = 0; @@ -185,7 +186,7 @@ closest_arcs_to_cell (Point c0, Point c1, /* corners */ -/* Returns true if the contour in endpoints[start...end-1] intersects any arc in endpoints[0...start-1]. */ +/* Returns true if an arc in contour1 intersects any arc in contour2. */ glyphy_bool_t contours_intersect (const glyphy_arc_endpoint_t *endpoints, const glyphy_contour_vertex_t *contour_1, @@ -209,7 +210,7 @@ contours_intersect (const glyphy_arc_endpoint_t *endpoints, if (!feasible) return false; - // If it seems feasible that this arc-arc pair (one per contour) might intersect, then check carefully. + /* If it seems feasible that these contours might intersect, then check carefully. */ for (unsigned int j = contour_1->start_posn + 1; j < contour_1->end_posn; j++) { const glyphy_arc_endpoint_t ethis1 = endpoints[j - 1]; const glyphy_arc_endpoint_t enext1 = endpoints[j]; @@ -229,7 +230,12 @@ contours_intersect (const glyphy_arc_endpoint_t *endpoints, } - +/** Used to generate a list of contours that have dotted line + * connections in the contour relationship graph; that is, + * these contours surround each other, but do not intersect. + * NOTE: the contours may not all be nested, as in the contours + * that outline the letter B (all three contours are returned). + */ void populate_connected_component (const std::vector contours, const unsigned int current_contour, @@ -240,6 +246,7 @@ populate_connected_component (const std::vector contour return; contours_seen [current_contour] = true; + /* Depth-first search, essentially. */ connected_contours->push_back (current_contour); for (unsigned int k = 0; k < contours[current_contour].dotted_edges.size (); k++) populate_connected_component (contours, @@ -247,6 +254,10 @@ populate_connected_component (const std::vector contour connected_contours, contours_seen); } +/** To form a bipartition of the contour relationship graph, + * assign each vertex a "level" based on DFS reachability, + * and derive the bipartition using parities of these levels. + */ void assign_contour_levels (const std::vector new_contours, const unsigned int current_contour, @@ -262,45 +273,40 @@ assign_contour_levels (const std::vector new_contours, } -/* Rearranges contours into two groups that don't intersect, based on a bipartite graph partition. - * Still in progress. */ +/* Rearranges contours into two groups that don't intersect, based on a bipartite graph partition. */ unsigned int -rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, - unsigned int num_endpoints, - glyphy_arc_endpoint_t *rerearranged_endpoints) +rearrange_contours (const glyphy_arc_endpoint_t *endpoints, + unsigned int num_endpoints, + glyphy_arc_endpoint_t *rerearranged_endpoints) { if (num_endpoints == 0) return 0; - - printf("Original Endpoint List:\n"); - for (unsigned int k = 0; k < num_endpoints; k++) { - printf("#%2d. (%f,%f) with d=%f.\n", k, endpoints[k].p.x, endpoints[k].p.y, endpoints[k].d); - } - + std::vector contours; unsigned int previous_index = 0; /* Create a list of vertices, where each vertex is a contour. Edges are still empty for now. */ unsigned int i = 0; unsigned int num_contours = 0; - while (i < num_endpoints) { - - while (i + 1 < num_endpoints && endpoints[i + 1].d != GLYPHY_INFINITY) { - i++; - } - i++; - glyphy_contour_vertex_t current_contour; - - current_contour.start_posn = previous_index; - current_contour.end_posn = i; - current_contour.index = num_contours; - current_contour.dotted_edges = std::vector (); - current_contour.solid_edges = std::vector (); - - contours.push_back (current_contour); - num_contours++; - previous_index = i; + while (i < num_endpoints) { + + /* Find the next contour and create its corresponding vertex. */ + while (i + 1 < num_endpoints && endpoints[i + 1].d != GLYPHY_INFINITY) { + i++; + } + i++; + glyphy_contour_vertex_t current_contour; + + current_contour.start_posn = previous_index; + current_contour.end_posn = i; + current_contour.index = num_contours; + current_contour.dotted_edges = std::vector (); + current_contour.solid_edges = std::vector (); + + contours.push_back (current_contour); + num_contours++; + previous_index = i; } /* Set up edges for vertices, based on intersections and inclusions. */ @@ -343,8 +349,8 @@ rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, // TODO: Is there a better way to initialize the array to all false? for (int j = 0; j < contours.size(); j++) { contours_seen[j] = false; - printf("%s", contours_seen[j] ? "O" : "."); } + unsigned int current_end = 0; std::vector new_contours; unsigned int num_new_contours = 0; @@ -416,23 +422,17 @@ rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, } - printf("new_contours_size:%d\n", int (new_contours.size())); - -/* Print out a list of contours and the contours they intersect. */ +/* Print out a list of contours and the contours they intersect. for (int j = 0; j < new_contours.size (); j++) { - printf ("Contour %d spans from %d to %d. ", j, new_contours[j].start_posn, new_contours[j].end_posn); + printf ("Contour %d: ", j); for (int k = 0; k < new_contours[j].solid_edges.size (); k++) printf("It intersects contour #%d. ", new_contours[j].solid_edges[k]); printf("\n"); for (int k = 0; k < new_contours[j].dotted_edges.size (); k++) - printf("It includes the old contour #%d. ", new_contours[j].dotted_edges[k]); + printf(" It includes the old contour #%d. ", new_contours[j].dotted_edges[k]); printf("\n"); - // printf("Contour Endpoint List:\n"); - // for (unsigned int k = new_contours[j].start_posn; k < new_contours[j].end_posn; k++) { - // printf("#%2d. (%f,%f) with d=%f.\n", k, rearranged_endpoints[k].p.x, rearranged_endpoints[k].p.y, rearranged_endpoints[k].d); - // } - } + }*/ /* Time to bipartition the graph, which should contain only solid edges at this point. */ @@ -440,7 +440,6 @@ rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, // TODO: Is there a better way to initialize the array to all -1? for (int j = 0; j < new_contours.size(); j++) { contour_levels [j] = -1; - printf("%s", contour_levels [j] != -1 ? "O" : "."); } for (unsigned int j = 0; j < new_contours.size (); j++) { @@ -468,12 +467,11 @@ rearrange_contours2 (const glyphy_arc_endpoint_t *endpoints, } bottom = bottom - (new_contours [i].end_posn - new_contours [i].start_posn); } - - - } - + } - + /* Now "top" represents the partition index in the endpoint list, + * separating endpoints of contour group 1 and contour group 2. + */ return top; } @@ -550,7 +548,7 @@ glyphy_arc_list_encode_blob (const glyphy_arc_endpoint_t *endpoints, /* Here is where we divide the arc list into two, based on intersecting contours. */ glyphy_arc_endpoint_t rearranged_endpoints [num_endpoints]; - unsigned int cutoff = rearrange_contours2 (endpoints, num_endpoints, rearranged_endpoints); + unsigned int cutoff = rearrange_contours (endpoints, num_endpoints, rearranged_endpoints); endpoints = rearranged_endpoints; for (int row = 0; row < grid_h; row++) diff --git a/src/glyphy-common.glsl b/src/glyphy-common.glsl index d6d924a1..046cc003 100644 --- a/src/glyphy-common.glsl +++ b/src/glyphy-common.glsl @@ -184,6 +184,14 @@ glyphy_arc_wedge_signed_dist (const glyphy_arc_t a, const vec2 p) return sign (a.d) * (distance (a.p0, c) - distance (p, c)); } +vec2 +glyphy_point_to_point_vector (const vec2 p, const vec2 q) +{ + vec2 v = p - q; + return v; + +} + float glyphy_arc_extended_dist (const glyphy_arc_t a, const vec2 p) { diff --git a/src/glyphy-sdf.glsl b/src/glyphy-sdf.glsl index c58ecd38..4ab10747 100644 --- a/src/glyphy-sdf.glsl +++ b/src/glyphy-sdf.glsl @@ -51,8 +51,9 @@ glyphy_arc_list (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) return glyphy_arc_list_decode (arc_list_data, nominal_size); } + float -glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) +glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS /*, vec2 min_dist_vector*/) { glyphy_arc_list_t arc_list = glyphy_arc_list (p, nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS); @@ -191,6 +192,8 @@ glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) side2 = sign (ext_dist); } + + /* If the two minimum distances are the same, but the sides are different, don't anti-alias. */ if (glyphy_iszero (min_dist - min_dist2) && side * side2 == -1.) return -1. * GLYPHY_INFINITY; From 5e946bbdf4eb2b946aafa31488d5262e8705b1fa Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Wed, 20 Jun 2012 17:21:52 -0400 Subject: [PATCH 27/35] Modified glyphy_sdf to keep track of vector to nearest contour. Still not correct for line segments, and does not use this stored value. --- src/glyphy-blob.cc | 2 +- src/glyphy-common.glsl | 23 ++++++++---- src/glyphy-geometry.hh | 19 ++++------ src/glyphy-sdf.glsl | 84 ++++++++++++++++++++++++++++++++++++------ 4 files changed, 97 insertions(+), 31 deletions(-) diff --git a/src/glyphy-blob.cc b/src/glyphy-blob.cc index 1b6d055d..5c6329fe 100644 --- a/src/glyphy-blob.cc +++ b/src/glyphy-blob.cc @@ -398,7 +398,7 @@ rearrange_contours (const glyphy_arc_endpoint_t *endpoints, for (unsigned int j = 0; j < new_contours.size (); j++) - /* Merge the lists of solid edges. TODO This should happen outside, and use new contour references.*/ + /* Merge the lists of solid edges. */ for (unsigned int j = 0; j < new_contours.size (); j++) { new_contours[j].solid_edges.clear (); diff --git a/src/glyphy-common.glsl b/src/glyphy-common.glsl index 046cc003..cd94ea7d 100644 --- a/src/glyphy-common.glsl +++ b/src/glyphy-common.glsl @@ -66,9 +66,7 @@ struct glyphy_arc_list_t { * Will be -1 if this arc-list encodes a single line, in which case line_* are set. */ int num_endpoints; - /* Number of endpoints corresponding to the arcs in the first set of contours 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. */ + /* Number of endpoints corresponding to the arcs in the first set of contours in the list. */ int first_contours_length; /* If num_endpoints is zero, this specifies whether we are inside (-1) @@ -126,6 +124,13 @@ glyphy_tan2atan (float d) return 2. * d / (1. - d * d); } +/* returns sin (2 * atan (d)) */ +float +glyphy_sin2atan (float d) +{ + return 2. * d / (1. + d * d); +} + glyphy_arc_endpoint_t glyphy_arc_endpoint_decode (const vec4 v, ivec2 nominal_size) { @@ -147,6 +152,12 @@ glyphy_arc_center (glyphy_arc_t a) glyphy_perpendicular (a.p1 - a.p0) / (2. * glyphy_tan2atan (a.d)); } +float +glyphy_arc_radius (glyphy_arc_t a) +{ + return distance (a.p0, a.p1) / (2. * glyphy_sin2atan (a.d)); +} + bool glyphy_arc_wedge_contains (const glyphy_arc_t a, const vec2 p) { @@ -185,11 +196,9 @@ glyphy_arc_wedge_signed_dist (const glyphy_arc_t a, const vec2 p) } vec2 -glyphy_point_to_point_vector (const vec2 p, const vec2 q) +glyphy_unit_vector (const vec2 v) { - vec2 v = p - q; - return v; - + return v / length (v); } float diff --git a/src/glyphy-geometry.hh b/src/glyphy-geometry.hh index 39a0f224..1ac4effb 100644 --- a/src/glyphy-geometry.hh +++ b/src/glyphy-geometry.hh @@ -640,8 +640,6 @@ inline Point Arc::intersects_segment (const Segment &s) const { Segment arc_segment (p0, p1); return s.intersects_segment (arc_segment); } -// if (fabs(d) > 1e5) -// printf("WEIRDNESS. Arc from (%f,%f) to (%f,%f) with d=%f.\n", p0.x, p0.y, p1.x, p1.y, d); if (s.contains_point (p0)) return p0; @@ -649,28 +647,25 @@ inline Point Arc::intersects_segment (const Segment &s) const { return p1; Point c1 = center (); -// printf("Centre at (%f,%f), radius is %f, depth is %f.\n", c1.x, c1.y, radius (), d); double a = (s.p0.x - s.p1.x) * (s.p0.x - s.p1.x) + (s.p0.y - s.p1.y) * (s.p0.y - s.p1.y); double b = 2 * ((s.p1.x - s.p0.x) * (s.p0.x - c1.x) + (s.p1.y - s.p0.y) * (s.p0.y - c1.y)); double c = (c1.x * c1.x) + (c1.y * c1.y) + (s.p0.x * s.p0.x) + (s.p0.y * s.p0.y) - 2 * (c1.x * s.p0.x + c1.y * s.p0.y) - radius () * radius (); double disc = b * b - 4 * a * c; if (disc < 0) - return Point (GLYPHY_INFINITY, GLYPHY_INFINITY); //false; - - /* Sometimes, u = nan. Can't explain that. */ + return Point (GLYPHY_INFINITY, GLYPHY_INFINITY); double u = /* W... get it?! */ (-1 * b + sqrt (disc)) / (2 * a); -// printf("a=%f, b=%f, c=%f, disc=%f\n u=%f\n", a, b, c, disc, u); + Point p (s.p0.x + u * (s.p1.x - s.p0.x), s.p0.y + u * (s.p1.y - s.p0.y)); if ((0 <= u && u <= 1) && wedge_contains_point(p)) - return p; //true; + return p; - u = -1 * b / a - u; //(-1 * b - sqrt (d)) / (2 * a); + u = -1 * b / a - u; p = Point (s.p0.x + u * (s.p1.x - s.p0.x), s.p0.y + u * (s.p1.y - s.p0.y)); if ((0 <= u && u <= 1) && wedge_contains_point(p)) - return p; //true; + return p; - return Point (GLYPHY_INFINITY, GLYPHY_INFINITY); //((0 <= u && u <= 1) && wedge_contains_point(p)); + return Point (GLYPHY_INFINITY, GLYPHY_INFINITY); } /* TODO: Handle possibility that there are two intersection points. */ @@ -699,7 +694,7 @@ inline Point Arc::intersects_arc (const Arc &a) const { return p1; if (wedge_contains_point (p2) && a.wedge_contains_point (p2)) return p2; - return Point (GLYPHY_INFINITY, GLYPHY_INFINITY); //(wedge_contains_point (p1) && a.wedge_contains_point (p1)) || (wedge_contains_point (p2) && a.wedge_contains_point (p2)); + return Point (GLYPHY_INFINITY, GLYPHY_INFINITY); } inline void Arc::extents (glyphy_extents_t &extents) const { diff --git a/src/glyphy-sdf.glsl b/src/glyphy-sdf.glsl index 4ab10747..51f09e15 100644 --- a/src/glyphy-sdf.glsl +++ b/src/glyphy-sdf.glsl @@ -56,15 +56,22 @@ float glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS /*, vec2 min_dist_vector*/) { glyphy_arc_list_t arc_list = glyphy_arc_list (p, nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS); + + /* TODO: Make these returned parameter/global variables/etc so that it is returned from the function.*/ + vec2 min_dist_vector; + vec2 min_dist_vector2; /* Short-circuits: 0 to 1 arcs near cell*/ if (arc_list.num_endpoints == 0) { /* far-away cell */ + min_dist_vector = vec2 (GLYPHY_INFINITY, GLYPHY_INFINITY); 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)); + + /* TODO: Update min_dist_vector in this case. What should it be? */ return dot (p - (vec2(nominal_size) * .5), n) - arc_list.line_distance; } @@ -102,14 +109,26 @@ glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS /*, vec2 min_dist = udist; side = (sdist <= 0. ? -1. : +1.); side = (float(arc_list.side) == -1. ? -1. : side); + + /* TODO: Handle case where d=0 (and a has no center) */ + min_dist_vector = udist * glyphy_unit_vector (glyphy_arc_center (a) - p); + } } else { - float udist = min (distance (p, a.p0), distance (p, a.p1)); + float dist0 = distance (p, a.p0); + float dist1 = distance (p, a.p1); + float udist = min (dist0, dist1); if (udist < min_dist) { min_dist = udist; side = 0.; /* unsure */ closest_arc = a; + if (dist0 < dist1) + min_dist_vector = glyphy_unit_vector (a.p0 - p) * udist ; + else + min_dist_vector = glyphy_unit_vector (a.p1 - p) * udist ; + + } 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 @@ -125,8 +144,20 @@ glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS /*, vec2 min_dist = abs (ext_dist); #endif side = sign (ext_dist); + + if (abs (old_ext_dist) < abs (new_ext_dist)) { + float dist0 = distance (p, a.p0); + float dist1 = distance (p, a.p1); + if (dist0 < dist1) + min_dist_vector = glyphy_unit_vector (a.p0 - p) * udist ; + else + min_dist_vector = glyphy_unit_vector (a.p1 - p) * udist ; + } + + } } + } if (side == 0. && arc_list.first_contours_length > 0) { // Technically speaking this should not happen, but it does. So try to fix it. @@ -134,7 +165,7 @@ glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS /*, vec2 side = sign (ext_dist); } - + /* Check arcs on the second contour group. * Second contour group is non-empty IFF arc_list.num_endpoints > arc_list.first_contours_length @@ -161,13 +192,21 @@ glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS /*, vec2 if (udist <= min_dist2) { min_dist2 = udist; side2 = sdist <= 0. ? -1. : +1.; + /* TODO: Handle case where d=0 (and a has no center) */ + min_dist_vector2 = udist * glyphy_unit_vector (glyphy_arc_center (a) - p); } } else { - float udist = min (distance (p, a.p0), distance (p, a.p1)); + float dist0 = distance (p, a.p0); + float dist1 = distance (p, a.p1); + float udist = min (dist0, dist1); if (udist < min_dist2) { min_dist2 = udist; side2 = 0.; /* unsure */ closest_arc2 = a; + if (dist0 < dist1) + min_dist_vector2 = glyphy_unit_vector (a.p0 - p) * udist ; + else + min_dist_vector2 = glyphy_unit_vector (a.p1 - p) * udist ; } else if (side2 == 0. && udist == min_dist2) { /* If this new distance is the same as the current minimum, * compare extended distances. Take the sign from the arc @@ -183,8 +222,20 @@ glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS /*, vec2 min_dist2 = abs (ext_dist); #endif side2 = sign (ext_dist); + + if (abs (old_ext_dist) < abs (new_ext_dist)) { + float dist0 = distance (p, a.p0); + float dist1 = distance (p, a.p1); + if (dist0 < dist1) + min_dist_vector2 = (a.p0 - p) * udist / length (a.p0 - p); + else + min_dist_vector2 = (a.p1 - p) * udist / length (a.p1 - p); + } + } } + + } if (side2 == 0.) { // Technically speaking this should not happen, but it does. So try to fix it. @@ -192,27 +243,38 @@ glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS /*, vec2 side2 = sign (ext_dist); } - - - /* If the two minimum distances are the same, but the sides are different, don't anti-alias. */ + /** If the two minimum distances are the same, but the sides are different, don't anti-alias. + * We are fully contained in one contour region. + */ if (glyphy_iszero (min_dist - min_dist2) && side * side2 == -1.) return -1. * GLYPHY_INFINITY; /* Update the distance to use as min_dist to outline, based on which contours we are in. */ - if (side == 0. || (side == 1. && side2 == -1.)) + if (side == 0. || (side == 1. && side2 == -1.)) { min_dist = min_dist2; + min_dist_vector = min_dist_vector2; + } else if (side == 1. && side2 == 1.) - min_dist = min (min_dist, min_dist2); + if (min_dist2 < min_dist) { + min_dist = min_dist2; + min_dist_vector = min_dist_vector2; + } else if (side == -1. && side2 == -1.) - min_dist = max (min_dist, min_dist2); - + if (min_dist < min_dist2) { + min_dist = min_dist2; + min_dist_vector = min_dist_vector2; + } /* Update side to reflect which side of the overall outline we are at: inside or outside the glyph. */ if (side2 < 0. || side == 0.) { side = side2; } - +// min_dist = length (min_dist_vector); + + +// if (!glyphy_iszero (abs (min_dist) - length (min_dist_vector))) +// return 0.; return min_dist * side; } From b051088f1eea20de375189799fa49f854d158566 Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Mon, 25 Jun 2012 17:21:13 -0400 Subject: [PATCH 28/35] Subpixel rendering - Some progress on min_dist_vector returned by glyphy_sdf, but still not perfect at corners. --- demo/demo-fshader.glsl | 8 +++++- src/glyphy-blob.cc | 4 +-- src/glyphy-common.glsl | 7 +++++ src/glyphy-geometry.hh | 4 +-- src/glyphy-sdf.glsl | 65 ++++++++++++++++++++++++++++++------------ 5 files changed, 64 insertions(+), 24 deletions(-) diff --git a/demo/demo-fshader.glsl b/demo/demo-fshader.glsl index 597799ac..bb712874 100644 --- a/demo/demo-fshader.glsl +++ b/demo/demo-fshader.glsl @@ -62,8 +62,9 @@ main() float w = abs (normalize (dpdx).x) + abs (normalize (dpdy).x); vec4 color = vec4 (0,0,0,1); + vec2 hi; - float gsdist = glyphy_sdf (p, gi.nominal_size GLYPHY_DEMO_EXTRA_ARGS); + float gsdist = glyphy_sdf (p, gi.nominal_size, hi GLYPHY_DEMO_EXTRA_ARGS); float sdist = gsdist / m * u_contrast; if (!u_debug) { @@ -97,6 +98,11 @@ main() glyphy_arc_list_t arc_list = glyphy_arc_list (p, gi.nominal_size GLYPHY_DEMO_EXTRA_ARGS); // Color the number of endpoints per cell blue color += vec4 (0,0,1,.1) * float(arc_list.num_endpoints) * 32./255.; + + // if (hi.x >= 0. && hi.y >= 0.) + color = vec4 (GLYPHY_INFINITY*abs(hi.x), GLYPHY_INFINITY*abs(hi.y), 0.3, 1); + // else + // color = vec4 (0,0,0,1); } gl_FragColor = color; diff --git a/src/glyphy-blob.cc b/src/glyphy-blob.cc index 5c6329fe..b459592b 100644 --- a/src/glyphy-blob.cc +++ b/src/glyphy-blob.cc @@ -139,8 +139,8 @@ closest_arcs_to_cell (Point c0, Point c1, /* corners */ double radius_squared = (min_dist + half_diagonal) * (min_dist + half_diagonal); unsigned int main_contour_arcs = 0; - if (min_dist - half_diagonal <= faraway && - (min_dist1 > -1 * half_diagonal && min_dist2 > -1 * half_diagonal) ) { + if (0 || (min_dist - half_diagonal <= faraway && /// RANDOM FUN. Change 0 to 1 to get cooler debug images. /// + (min_dist1 > -1 * half_diagonal && min_dist2 > -1 * half_diagonal)) ) { Point p0 (0, 0); diff --git a/src/glyphy-common.glsl b/src/glyphy-common.glsl index cd94ea7d..ee895ee2 100644 --- a/src/glyphy-common.glsl +++ b/src/glyphy-common.glsl @@ -158,6 +158,13 @@ glyphy_arc_radius (glyphy_arc_t a) return distance (a.p0, a.p1) / (2. * glyphy_sin2atan (a.d)); } +vec2 +glyphy_segment_normal (glyphy_arc_t a) +{ + float unit = sign (a.d); + return vec2 (unit * (a.p0.y - a.p1.y), unit * (a.p1.x - a.p0.x)); +} + bool glyphy_arc_wedge_contains (const glyphy_arc_t a, const vec2 p) { diff --git a/src/glyphy-geometry.hh b/src/glyphy-geometry.hh index 1ac4effb..31c56ba4 100644 --- a/src/glyphy-geometry.hh +++ b/src/glyphy-geometry.hh @@ -379,7 +379,7 @@ inline const Point Line::operator+ (const Line &l) const { 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. *************************************/ + return SignedVector (n.normalized () * mag, mag < 0); /******************************************************* FIX. *************************************/ } inline const SignedVector operator- (const Point &p, const Line &l) { @@ -397,7 +397,7 @@ inline const Vector Line::normal (void) const { /* 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?? ***********************/ + return p - Line (p1, p0); /*********************************************************************** Should the order (p1, p0) depend on d?? ***********************/ } /* Segment */ diff --git a/src/glyphy-sdf.glsl b/src/glyphy-sdf.glsl index 51f09e15..64e8cdcf 100644 --- a/src/glyphy-sdf.glsl +++ b/src/glyphy-sdf.glsl @@ -52,15 +52,17 @@ glyphy_arc_list (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) } + + + + + + float -glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS /*, vec2 min_dist_vector*/) +glyphy_sdf (vec2 p, ivec2 nominal_size, out vec2 min_dist_vector GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) { glyphy_arc_list_t arc_list = glyphy_arc_list (p, nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS); - /* TODO: Make these returned parameter/global variables/etc so that it is returned from the function.*/ - vec2 min_dist_vector; - vec2 min_dist_vector2; - /* Short-circuits: 0 to 1 arcs near cell*/ if (arc_list.num_endpoints == 0) { /* far-away cell */ @@ -70,14 +72,17 @@ glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS /*, vec2 /* single-line */ float angle = arc_list.line_angle; vec2 n = vec2 (cos (angle), sin (angle)); + float dist = dot (p - (vec2(nominal_size) * .5), n) - arc_list.line_distance; + min_dist_vector = n * dist; - /* TODO: Update min_dist_vector in this case. What should it be? */ - return dot (p - (vec2(nominal_size) * .5), n) - arc_list.line_distance; + return dist; } float side = float(arc_list.side); float min_dist = GLYPHY_INFINITY; - glyphy_arc_t closest_arc; + glyphy_arc_t closest_arc; + + // float answer = shortest_dist_to_contours (arc_list, p, true, glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset), nominal_size) ) float side2 = float(arc_list.side); float min_dist2 = GLYPHY_INFINITY; @@ -110,9 +115,17 @@ glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS /*, vec2 side = (sdist <= 0. ? -1. : +1.); side = (float(arc_list.side) == -1. ? -1. : side); - /* TODO: Handle case where d=0 (and a has no center) */ - min_dist_vector = udist * glyphy_unit_vector (glyphy_arc_center (a) - p); - + /* TODO: Handle case where d=0 (and a has no center). CHECK VECTOR DIRECTION (+/-) */ + if (a.d == 0.) { + min_dist_vector = udist * glyphy_unit_vector (glyphy_segment_normal (a)); + if (distance (p + min_dist_vector, a.p0) > distance (p, a.p0)) + return 0.; + } + else { + vec2 center = glyphy_arc_center (a); + min_dist_vector = udist * glyphy_unit_vector (center - p) + * (distance (center, p) < glyphy_arc_radius (a) ? -1. : 1.); + } } } else { @@ -145,13 +158,17 @@ glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS /*, vec2 #endif side = sign (ext_dist); + + float dist0 = distance (p, a.p0); + float dist1 = distance (p, a.p1); + if (dist0 < dist1) + min_dist_vector = udist * glyphy_unit_vector (a.p0 - p); + else + min_dist_vector = udist * glyphy_unit_vector (a.p1 - p); + + if (abs (old_ext_dist) < abs (new_ext_dist)) { - float dist0 = distance (p, a.p0); - float dist1 = distance (p, a.p1); - if (dist0 < dist1) - min_dist_vector = glyphy_unit_vector (a.p0 - p) * udist ; - else - min_dist_vector = glyphy_unit_vector (a.p1 - p) * udist ; + } @@ -171,6 +188,7 @@ glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS /*, vec2 * Second contour group is non-empty IFF arc_list.num_endpoints > arc_list.first_contours_length * IFF min_dist2 == GLYPHY_INFINITY after this loop */ + vec2 min_dist_vector2; endpoint_prev = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset + arc_list.first_contours_length), nominal_size); @@ -192,8 +210,17 @@ glyphy_sdf (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS /*, vec2 if (udist <= min_dist2) { min_dist2 = udist; side2 = sdist <= 0. ? -1. : +1.; - /* TODO: Handle case where d=0 (and a has no center) */ - min_dist_vector2 = udist * glyphy_unit_vector (glyphy_arc_center (a) - p); + /* TODO: Handle case where d=0 (and a has no center). CHECK VECTOR DIRECTION (+/-) */ + if (a.d == 0.) { + min_dist_vector2 = udist * glyphy_unit_vector (glyphy_segment_normal (a)); + if (distance (p + min_dist_vector2, a.p0) >= distance (p, a.p0)) + return 0.; + } + else { + vec2 center = glyphy_arc_center (a); + min_dist_vector2 = udist * glyphy_unit_vector (center - p) + * (distance (center, p) < glyphy_arc_radius (a) ? -1. : 1.); + } } } else { float dist0 = distance (p, a.p0); From d61590b4157d251d4923b815c58bb5054ca631ba Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Tue, 26 Jun 2012 17:17:46 -0400 Subject: [PATCH 29/35] SDF now has min_dist_vector with some nice shading, and functions now compartmentalized in glyphy_sdf somewhat, but a seaming bug is back, and vector sometimes points backwards. --- demo/demo-fshader.glsl | 8 +-- src/glyphy-blob.cc | 2 +- src/glyphy-common.glsl | 2 +- src/glyphy-sdf.glsl | 151 +++++++++++++++++++++++++++++++++++------ 4 files changed, 136 insertions(+), 27 deletions(-) diff --git a/demo/demo-fshader.glsl b/demo/demo-fshader.glsl index bb712874..48bc628a 100644 --- a/demo/demo-fshader.glsl +++ b/demo/demo-fshader.glsl @@ -62,9 +62,9 @@ main() float w = abs (normalize (dpdx).x) + abs (normalize (dpdy).x); vec4 color = vec4 (0,0,0,1); - vec2 hi; + vec2 sdf_vector; - float gsdist = glyphy_sdf (p, gi.nominal_size, hi GLYPHY_DEMO_EXTRA_ARGS); + float gsdist = glyphy_sdf (p, gi.nominal_size, sdf_vector GLYPHY_DEMO_EXTRA_ARGS); float sdist = gsdist / m * u_contrast; if (!u_debug) { @@ -99,8 +99,8 @@ main() // Color the number of endpoints per cell blue color += vec4 (0,0,1,.1) * float(arc_list.num_endpoints) * 32./255.; - // if (hi.x >= 0. && hi.y >= 0.) - color = vec4 (GLYPHY_INFINITY*abs(hi.x), GLYPHY_INFINITY*abs(hi.y), 0.3, 1); + // if (sdf_vector.x >= 0. && sdf_vector.y >= 0.) + color = vec4 (abs(sdf_vector.x), abs(sdf_vector.y), 0.3, 1); // else // color = vec4 (0,0,0,1); } diff --git a/src/glyphy-blob.cc b/src/glyphy-blob.cc index b459592b..9b351a03 100644 --- a/src/glyphy-blob.cc +++ b/src/glyphy-blob.cc @@ -139,7 +139,7 @@ closest_arcs_to_cell (Point c0, Point c1, /* corners */ double radius_squared = (min_dist + half_diagonal) * (min_dist + half_diagonal); unsigned int main_contour_arcs = 0; - if (0 || (min_dist - half_diagonal <= faraway && /// RANDOM FUN. Change 0 to 1 to get cooler debug images. /// + if (0 || (min_dist - half_diagonal <= faraway && /// RANDOM FUN. 0 for correct. Change 0 to 1 to get cooler debug images. /// (min_dist1 > -1 * half_diagonal && min_dist2 > -1 * half_diagonal)) ) { Point p0 (0, 0); diff --git a/src/glyphy-common.glsl b/src/glyphy-common.glsl index ee895ee2..6ba6140f 100644 --- a/src/glyphy-common.glsl +++ b/src/glyphy-common.glsl @@ -161,7 +161,7 @@ glyphy_arc_radius (glyphy_arc_t a) vec2 glyphy_segment_normal (glyphy_arc_t a) { - float unit = sign (a.d); + float unit = -1.;//sign (a.d); return vec2 (unit * (a.p0.y - a.p1.y), unit * (a.p1.x - a.p0.x)); } diff --git a/src/glyphy-sdf.glsl b/src/glyphy-sdf.glsl index 64e8cdcf..8298f1a5 100644 --- a/src/glyphy-sdf.glsl +++ b/src/glyphy-sdf.glsl @@ -52,8 +52,102 @@ glyphy_arc_list (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) } +float find_min_dist (glyphy_arc_list_t arc_list, vec2 p, bool isContourGroup1, + ivec2 nominal_size, out vec2 min_dist_vector GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) +{ + + 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); + + int start_index = (isContourGroup1 ? 1 : arc_list.num_endpoints + 1); + for (int i = start_index; i < GLYPHY_MAX_NUM_ENDPOINTS; i++) + { + + if ((isContourGroup1 && i > arc_list.first_contours_length) || 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.); + side = (float(arc_list.side) == -1. ? -1. : side); + + /* TODO: Handle case where d=0 (and a has no center). CHECK VECTOR DIRECTION (+/-) */ + if (a.d == 0.) { + min_dist_vector = udist * glyphy_unit_vector (glyphy_segment_normal (a)); + if (distance (p + min_dist_vector, a.p0) > distance (p, a.p0)) + min_dist_vector = -1. * 1.* min_dist_vector; /* TODO: please make glyphy_segment_normal point the correct way to begin with.. */ + } + else { + vec2 center = glyphy_arc_center (a); + min_dist_vector = udist * glyphy_unit_vector (center - p) + * (distance (center, p) < glyphy_arc_radius (a) ? -1. : 1.); + } + } + + } else { + float dist0 = distance (p, a.p0); + float dist1 = distance (p, a.p1); + float udist = min (dist0, dist1); + if (udist < min_dist) { + min_dist = udist; + side = 0.; /* unsure */ + closest_arc = a; + if (dist0 < dist1) + min_dist_vector = glyphy_unit_vector (a.p0 - p) * udist ; + else + min_dist_vector = glyphy_unit_vector (a.p1 - p) * udist ; + + + } 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); + + + float dist0 = distance (p, a.p0); + float dist1 = distance (p, a.p1); + if (dist0 < dist1) + min_dist_vector = udist * glyphy_unit_vector (a.p0 - p); + else + min_dist_vector = udist * glyphy_unit_vector (a.p1 - p); + + + if (abs (old_ext_dist) < abs (new_ext_dist)) { + } + } + } + + } + if (side == 0. && (!isContourGroup1 || arc_list.first_contours_length > 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; +} @@ -78,18 +172,24 @@ glyphy_sdf (vec2 p, ivec2 nominal_size, out vec2 min_dist_vector GLYPHY_SDF_TEXT return dist; } + /* +*/ + glyphy_arc_endpoint_t endpoint_prev, endpoint; + + + + + +#if 1 + float side = float(arc_list.side); float min_dist = GLYPHY_INFINITY; glyphy_arc_t closest_arc; - // float answer = shortest_dist_to_contours (arc_list, p, true, glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset), nominal_size) ) - float side2 = float(arc_list.side); float min_dist2 = GLYPHY_INFINITY; glyphy_arc_t closest_arc2; - glyphy_arc_endpoint_t endpoint_prev, endpoint; - /* Check arcs on the first contour group. * First contour group is non-empty <=> arc_list.first_contours_length > 0 * <=> min_dist == GLYPHY_INFINITY after this loop @@ -119,7 +219,7 @@ glyphy_sdf (vec2 p, ivec2 nominal_size, out vec2 min_dist_vector GLYPHY_SDF_TEXT if (a.d == 0.) { min_dist_vector = udist * glyphy_unit_vector (glyphy_segment_normal (a)); if (distance (p + min_dist_vector, a.p0) > distance (p, a.p0)) - return 0.; + min_dist_vector = -1. * 1.* min_dist_vector; /* TODO: please make glyphy_segment_normal point the correct way to begin with.. */ } else { vec2 center = glyphy_arc_center (a); @@ -195,7 +295,7 @@ glyphy_sdf (vec2 p, ivec2 nominal_size, out vec2 min_dist_vector GLYPHY_SDF_TEXT for (int i = arc_list.first_contours_length + 1; i < GLYPHY_MAX_NUM_ENDPOINTS; i++) { - if (i >= arc_list.num_endpoints) { + if (i >= arc_list.num_endpoints /* || i < arc_list.num_endpoints*/) { break; } endpoint = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset + i), nominal_size); @@ -209,12 +309,12 @@ glyphy_sdf (vec2 p, ivec2 nominal_size, out vec2 min_dist_vector GLYPHY_SDF_TEXT float udist = abs (sdist) * (1. - GLYPHY_EPSILON); if (udist <= min_dist2) { min_dist2 = udist; - side2 = sdist <= 0. ? -1. : +1.; + side2 = (sdist <= 0. ? -1. : +1.); /* TODO: Handle case where d=0 (and a has no center). CHECK VECTOR DIRECTION (+/-) */ if (a.d == 0.) { min_dist_vector2 = udist * glyphy_unit_vector (glyphy_segment_normal (a)); if (distance (p + min_dist_vector2, a.p0) >= distance (p, a.p0)) - return 0.; + min_dist_vector2 = -1. * min_dist_vector2; } else { vec2 center = glyphy_arc_center (a); @@ -260,48 +360,57 @@ glyphy_sdf (vec2 p, ivec2 nominal_size, out vec2 min_dist_vector GLYPHY_SDF_TEXT } } - } - - - } + } + } if (side2 == 0.) { // Technically speaking this should not happen, but it does. So try to fix it. float ext_dist = glyphy_arc_extended_dist (closest_arc2, p); side2 = sign (ext_dist); } - + #else + vec2 min_dist_vector2; + float min_dist1 = find_min_dist (arc_list, p, true, nominal_size, min_dist_vector GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS); + float min_dist2 = find_min_dist (arc_list, p, false, nominal_size, min_dist_vector2 GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS); + + float min_dist = abs (min_dist1); + min_dist2 = abs (min_dist2); + float side = sign (min_dist1); + float side2 = sign (min_dist2); + #endif + + /** If the two minimum distances are the same, but the sides are different, don't anti-alias. * We are fully contained in one contour region. */ - if (glyphy_iszero (min_dist - min_dist2) && side * side2 == -1.) + if (glyphy_iszero (min_dist - min_dist2) && side * side2 == -1.) { return -1. * GLYPHY_INFINITY; + } /* Update the distance to use as min_dist to outline, based on which contours we are in. */ if (side == 0. || (side == 1. && side2 == -1.)) { min_dist = min_dist2; min_dist_vector = min_dist_vector2; + // return -1.; } else if (side == 1. && side2 == 1.) if (min_dist2 < min_dist) { min_dist = min_dist2; min_dist_vector = min_dist_vector2; +// return 1.; } - else if (side == -1. && side2 == -1.) + else if (side == -1. && side2 == -1.) // /************************************************************************Is this not getting run??????? if (min_dist < min_dist2) { min_dist = min_dist2; min_dist_vector = min_dist_vector2; + } - + // return 1.; /* Update side to reflect which side of the overall outline we are at: inside or outside the glyph. */ if (side2 < 0. || side == 0.) { side = side2; } -// min_dist = length (min_dist_vector); - - -// if (!glyphy_iszero (abs (min_dist) - length (min_dist_vector))) -// return 0.; + return min_dist * side; } From 27b20fa93ac634db3761d54d2330bb454f659a2e Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Wed, 27 Jun 2012 17:38:21 -0400 Subject: [PATCH 30/35] Merged repeated code into a single "find_min_dist" function in glyphy-sdf. Still have seams. :-( --- src/glyphy-common.glsl | 5 - src/glyphy-sdf.glsl | 269 +++++------------------------------------ 2 files changed, 32 insertions(+), 242 deletions(-) diff --git a/src/glyphy-common.glsl b/src/glyphy-common.glsl index 6ba6140f..8d361cac 100644 --- a/src/glyphy-common.glsl +++ b/src/glyphy-common.glsl @@ -202,11 +202,6 @@ glyphy_arc_wedge_signed_dist (const glyphy_arc_t a, const vec2 p) return sign (a.d) * (distance (a.p0, c) - distance (p, c)); } -vec2 -glyphy_unit_vector (const vec2 v) -{ - return v / length (v); -} float glyphy_arc_extended_dist (const glyphy_arc_t a, const vec2 p) diff --git a/src/glyphy-sdf.glsl b/src/glyphy-sdf.glsl index 8298f1a5..c7e0be1d 100644 --- a/src/glyphy-sdf.glsl +++ b/src/glyphy-sdf.glsl @@ -55,20 +55,21 @@ glyphy_arc_list (vec2 p, ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) float find_min_dist (glyphy_arc_list_t arc_list, vec2 p, bool isContourGroup1, ivec2 nominal_size, out vec2 min_dist_vector GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS) { - 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); - int start_index = (isContourGroup1 ? 1 : arc_list.num_endpoints + 1); + endpoint_prev = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D + (arc_list.offset + (isContourGroup1 ? 0 : arc_list.first_contours_length)), nominal_size); + int start_index = (isContourGroup1 ? 1 : arc_list.first_contours_length + 1); + for (int i = start_index; i < GLYPHY_MAX_NUM_ENDPOINTS; i++) { - - if ((isContourGroup1 && i > arc_list.first_contours_length) || i >= arc_list.num_endpoints ) { + if (i >= arc_list.num_endpoints || (isContourGroup1 && i > arc_list.first_contours_length)) { 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; @@ -81,17 +82,17 @@ float find_min_dist (glyphy_arc_list_t arc_list, vec2 p, bool isContourGroup1, if (udist <= min_dist) { min_dist = udist; side = (sdist <= 0. ? -1. : +1.); - side = (float(arc_list.side) == -1. ? -1. : side); +// side = (float(arc_list.side) == -1. ? -1. : side); /* TODO: Handle case where d=0 (and a has no center). CHECK VECTOR DIRECTION (+/-) */ if (a.d == 0.) { - min_dist_vector = udist * glyphy_unit_vector (glyphy_segment_normal (a)); - if (distance (p + min_dist_vector, a.p0) > distance (p, a.p0)) - min_dist_vector = -1. * 1.* min_dist_vector; /* TODO: please make glyphy_segment_normal point the correct way to begin with.. */ + min_dist_vector = udist * normalize (glyphy_segment_normal (a)); + if (distance (p + min_dist_vector, a.p0) >= distance (p, a.p0)) + min_dist_vector = -1. * min_dist_vector; /* TODO: please make glyphy_segment_normal point the correct way to begin with.. */ } else { vec2 center = glyphy_arc_center (a); - min_dist_vector = udist * glyphy_unit_vector (center - p) + min_dist_vector = udist * normalize (center - p) * (distance (center, p) < glyphy_arc_radius (a) ? -1. : 1.); } } @@ -105,11 +106,9 @@ float find_min_dist (glyphy_arc_list_t arc_list, vec2 p, bool isContourGroup1, side = 0.; /* unsure */ closest_arc = a; if (dist0 < dist1) - min_dist_vector = glyphy_unit_vector (a.p0 - p) * udist ; + min_dist_vector = normalize (a.p0 - p) * udist ; else - min_dist_vector = glyphy_unit_vector (a.p1 - p) * udist ; - - + min_dist_vector = normalize (a.p1 - p) * udist ; } 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 @@ -126,26 +125,23 @@ float find_min_dist (glyphy_arc_list_t arc_list, vec2 p, bool isContourGroup1, #endif side = sign (ext_dist); - - float dist0 = distance (p, a.p0); - float dist1 = distance (p, a.p1); - if (dist0 < dist1) - min_dist_vector = udist * glyphy_unit_vector (a.p0 - p); - else - min_dist_vector = udist * glyphy_unit_vector (a.p1 - p); - - - if (abs (old_ext_dist) < abs (new_ext_dist)) { + if (abs (old_ext_dist) < abs (new_ext_dist)) { + float dist0 = distance (p, a.p0); + float dist1 = distance (p, a.p1); + if (dist0 < dist1) + min_dist_vector = udist * normalize (a.p0 - p); + else + min_dist_vector = udist * normalize (a.p1 - p); } } } } - if (side == 0. && (!isContourGroup1 || arc_list.first_contours_length > 0)) { + if (side == 0. && (isContourGroup1 && arc_list.first_contours_length > 0 || !isContourGroup1)) { // 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; } @@ -168,217 +164,17 @@ glyphy_sdf (vec2 p, ivec2 nominal_size, out vec2 min_dist_vector GLYPHY_SDF_TEXT vec2 n = vec2 (cos (angle), sin (angle)); float dist = dot (p - (vec2(nominal_size) * .5), n) - arc_list.line_distance; min_dist_vector = n * dist; - return dist; } - /* -*/ - glyphy_arc_endpoint_t endpoint_prev, endpoint; - - - - - -#if 1 - - float side = float(arc_list.side); - float min_dist = GLYPHY_INFINITY; - glyphy_arc_t closest_arc; + vec2 min_dist_vector2; + float min_dist_first = find_min_dist (arc_list, p, true, nominal_size, min_dist_vector GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS); + float min_dist_last = find_min_dist (arc_list, p, false, nominal_size, min_dist_vector2 GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS); + float min_dist = abs (min_dist_first); + float min_dist2 = abs (min_dist_last); + float side = sign (min_dist_first); + float side2 = sign (min_dist_last); - float side2 = float(arc_list.side); - float min_dist2 = GLYPHY_INFINITY; - glyphy_arc_t closest_arc2; - - /* Check arcs on the first contour group. - * First contour group is non-empty <=> arc_list.first_contours_length > 0 - * <=> min_dist == GLYPHY_INFINITY after this loop - */ - 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 || i > arc_list.first_contours_length ) { - 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.); - side = (float(arc_list.side) == -1. ? -1. : side); - - /* TODO: Handle case where d=0 (and a has no center). CHECK VECTOR DIRECTION (+/-) */ - if (a.d == 0.) { - min_dist_vector = udist * glyphy_unit_vector (glyphy_segment_normal (a)); - if (distance (p + min_dist_vector, a.p0) > distance (p, a.p0)) - min_dist_vector = -1. * 1.* min_dist_vector; /* TODO: please make glyphy_segment_normal point the correct way to begin with.. */ - } - else { - vec2 center = glyphy_arc_center (a); - min_dist_vector = udist * glyphy_unit_vector (center - p) - * (distance (center, p) < glyphy_arc_radius (a) ? -1. : 1.); - } - } - - } else { - float dist0 = distance (p, a.p0); - float dist1 = distance (p, a.p1); - float udist = min (dist0, dist1); - if (udist < min_dist) { - min_dist = udist; - side = 0.; /* unsure */ - closest_arc = a; - if (dist0 < dist1) - min_dist_vector = glyphy_unit_vector (a.p0 - p) * udist ; - else - min_dist_vector = glyphy_unit_vector (a.p1 - p) * udist ; - - - } 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); - - - float dist0 = distance (p, a.p0); - float dist1 = distance (p, a.p1); - if (dist0 < dist1) - min_dist_vector = udist * glyphy_unit_vector (a.p0 - p); - else - min_dist_vector = udist * glyphy_unit_vector (a.p1 - p); - - - if (abs (old_ext_dist) < abs (new_ext_dist)) { - - } - - - } - } - - } - if (side == 0. && arc_list.first_contours_length > 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); - } - - - - /* Check arcs on the second contour group. - * Second contour group is non-empty IFF arc_list.num_endpoints > arc_list.first_contours_length - * IFF min_dist2 == GLYPHY_INFINITY after this loop - */ - vec2 min_dist_vector2; - endpoint_prev = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D - (arc_list.offset + arc_list.first_contours_length), nominal_size); - - for (int i = arc_list.first_contours_length + 1; i < GLYPHY_MAX_NUM_ENDPOINTS; i++) - { - - if (i >= arc_list.num_endpoints /* || 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_dist2) { - min_dist2 = udist; - side2 = (sdist <= 0. ? -1. : +1.); - /* TODO: Handle case where d=0 (and a has no center). CHECK VECTOR DIRECTION (+/-) */ - if (a.d == 0.) { - min_dist_vector2 = udist * glyphy_unit_vector (glyphy_segment_normal (a)); - if (distance (p + min_dist_vector2, a.p0) >= distance (p, a.p0)) - min_dist_vector2 = -1. * min_dist_vector2; - } - else { - vec2 center = glyphy_arc_center (a); - min_dist_vector2 = udist * glyphy_unit_vector (center - p) - * (distance (center, p) < glyphy_arc_radius (a) ? -1. : 1.); - } - } - } else { - float dist0 = distance (p, a.p0); - float dist1 = distance (p, a.p1); - float udist = min (dist0, dist1); - if (udist < min_dist2) { - min_dist2 = udist; - side2 = 0.; /* unsure */ - closest_arc2 = a; - if (dist0 < dist1) - min_dist_vector2 = glyphy_unit_vector (a.p0 - p) * udist ; - else - min_dist_vector2 = glyphy_unit_vector (a.p1 - p) * udist ; - } else if (side2 == 0. && udist == min_dist2) { - /* 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_arc2, 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_dist2 = abs (ext_dist); -#endif - side2 = sign (ext_dist); - - if (abs (old_ext_dist) < abs (new_ext_dist)) { - float dist0 = distance (p, a.p0); - float dist1 = distance (p, a.p1); - if (dist0 < dist1) - min_dist_vector2 = (a.p0 - p) * udist / length (a.p0 - p); - else - min_dist_vector2 = (a.p1 - p) * udist / length (a.p1 - p); - } - - } - } - } - if (side2 == 0.) { - // Technically speaking this should not happen, but it does. So try to fix it. - float ext_dist = glyphy_arc_extended_dist (closest_arc2, p); - side2 = sign (ext_dist); - } - #else - vec2 min_dist_vector2; - float min_dist1 = find_min_dist (arc_list, p, true, nominal_size, min_dist_vector GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS); - float min_dist2 = find_min_dist (arc_list, p, false, nominal_size, min_dist_vector2 GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS); - - float min_dist = abs (min_dist1); - min_dist2 = abs (min_dist2); - float side = sign (min_dist1); - float side2 = sign (min_dist2); - #endif - - /** If the two minimum distances are the same, but the sides are different, don't anti-alias. * We are fully contained in one contour region. */ @@ -390,8 +186,8 @@ glyphy_sdf (vec2 p, ivec2 nominal_size, out vec2 min_dist_vector GLYPHY_SDF_TEXT if (side == 0. || (side == 1. && side2 == -1.)) { min_dist = min_dist2; min_dist_vector = min_dist_vector2; - // return -1.; - } + // return -1.; + } else if (side == 1. && side2 == 1.) if (min_dist2 < min_dist) { min_dist = min_dist2; @@ -410,8 +206,7 @@ glyphy_sdf (vec2 p, ivec2 nominal_size, out vec2 min_dist_vector GLYPHY_SDF_TEXT side = side2; } - - return min_dist * side; + return min_dist * side; } From 309f59c1d115e58d94c711c1ceb82dbf32228aab Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Thu, 28 Jun 2012 17:46:32 -0400 Subject: [PATCH 31/35] The sdf vector now points in the correct direction... but seams still there!! --- demo/demo-fshader.glsl | 8 ++++---- src/glyphy-sdf.glsl | 20 +++++++++++++------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/demo/demo-fshader.glsl b/demo/demo-fshader.glsl index 48bc628a..d7872e41 100644 --- a/demo/demo-fshader.glsl +++ b/demo/demo-fshader.glsl @@ -99,10 +99,10 @@ main() // Color the number of endpoints per cell blue color += vec4 (0,0,1,.1) * float(arc_list.num_endpoints) * 32./255.; - // if (sdf_vector.x >= 0. && sdf_vector.y >= 0.) - color = vec4 (abs(sdf_vector.x), abs(sdf_vector.y), 0.3, 1); - // else - // color = vec4 (0,0,0,1); + // if (sdf_vector.x >= 0. && sdf_vector.y >= 0.) + color = vec4 (0.5*(sdf_vector.x)+0.5, 0.5*(sdf_vector.y)+0.5, 0.0, 1); + // else + // color = vec4 (0,0,0,1); } gl_FragColor = color; diff --git a/src/glyphy-sdf.glsl b/src/glyphy-sdf.glsl index c7e0be1d..3fe53dc6 100644 --- a/src/glyphy-sdf.glsl +++ b/src/glyphy-sdf.glsl @@ -62,7 +62,7 @@ float find_min_dist (glyphy_arc_list_t arc_list, vec2 p, bool isContourGroup1, endpoint_prev = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset + (isContourGroup1 ? 0 : arc_list.first_contours_length)), nominal_size); - int start_index = (isContourGroup1 ? 1 : arc_list.first_contours_length + 1); + int start_index = (isContourGroup1 ? 1 : arc_list.first_contours_length + 1); /*TODO: Should we subtract 0? #uncertain */ for (int i = start_index; i < GLYPHY_MAX_NUM_ENDPOINTS; i++) { @@ -82,18 +82,24 @@ float find_min_dist (glyphy_arc_list_t arc_list, vec2 p, bool isContourGroup1, if (udist <= min_dist) { min_dist = udist; side = (sdist <= 0. ? -1. : +1.); -// side = (float(arc_list.side) == -1. ? -1. : side); + side = (float(arc_list.side) == -1. ? -1. : side); /* TODO: Handle case where d=0 (and a has no center). CHECK VECTOR DIRECTION (+/-) */ if (a.d == 0.) { min_dist_vector = udist * normalize (glyphy_segment_normal (a)); - if (distance (p + min_dist_vector, a.p0) >= distance (p, a.p0)) - min_dist_vector = -1. * min_dist_vector; /* TODO: please make glyphy_segment_normal point the correct way to begin with.. */ + if (distance (p + min_dist_vector, mix(a.p0, a.p1, 0.5)) >= distance (p - min_dist_vector, mix(a.p0, a.p1, 0.5))) + min_dist_vector = -1. * min_dist_vector; + /* TODO: please make glyphy_segment_normal point the correct way to begin with.. */ } else { vec2 center = glyphy_arc_center (a); - min_dist_vector = udist * normalize (center - p) - * (distance (center, p) < glyphy_arc_radius (a) ? -1. : 1.); + min_dist_vector = udist * normalize (center - p); + /** Is there no better way to do this? + * I would like to have // if (distance (center, p) < glyphy_arc_radius (a)) // + * but that doesn't work. + */ + if (abs(glyphy_arc_wedge_signed_dist(a, p + min_dist_vector)) >= abs(glyphy_arc_wedge_signed_dist(a, p - min_dist_vector))) + min_dist_vector = -1. * min_dist_vector; } } @@ -163,7 +169,7 @@ glyphy_sdf (vec2 p, ivec2 nominal_size, out vec2 min_dist_vector GLYPHY_SDF_TEXT float angle = arc_list.line_angle; vec2 n = vec2 (cos (angle), sin (angle)); float dist = dot (p - (vec2(nominal_size) * .5), n) - arc_list.line_distance; - min_dist_vector = n * dist; + min_dist_vector = -1. * n * dist; return dist; } From 4e78597a4483ee877199407b63c080c00d64442c Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Fri, 29 Jun 2012 12:06:14 -0400 Subject: [PATCH 32/35] Minor fix.. but SEAMS ARE GONE. Smooth outlines, yessir. --- src/glyphy-sdf.glsl | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/glyphy-sdf.glsl b/src/glyphy-sdf.glsl index 3fe53dc6..db56ceed 100644 --- a/src/glyphy-sdf.glsl +++ b/src/glyphy-sdf.glsl @@ -192,21 +192,19 @@ glyphy_sdf (vec2 p, ivec2 nominal_size, out vec2 min_dist_vector GLYPHY_SDF_TEXT if (side == 0. || (side == 1. && side2 == -1.)) { min_dist = min_dist2; min_dist_vector = min_dist_vector2; - // return -1.; - } - else if (side == 1. && side2 == 1.) + } + else if (side == 1. && side2 == 1.) { if (min_dist2 < min_dist) { min_dist = min_dist2; min_dist_vector = min_dist_vector2; -// return 1.; } - else if (side == -1. && side2 == -1.) // /************************************************************************Is this not getting run??????? + } + else if (side == -1. && side2 == -1.) { if (min_dist < min_dist2) { min_dist = min_dist2; min_dist_vector = min_dist_vector2; - } - // return 1.; + } /* Update side to reflect which side of the overall outline we are at: inside or outside the glyph. */ if (side2 < 0. || side == 0.) { side = side2; From 8cbc8dabf3bf98ad618a9255802f7f355d80559f Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Wed, 4 Jul 2012 15:07:01 -0400 Subject: [PATCH 33/35] Added TestFont with some bad examples; some colour revamp for sdf. --- TestFont.ttf | Bin 0 -> 606800 bytes demo/demo-fshader.glsl | 16 ++++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 TestFont.ttf diff --git a/TestFont.ttf b/TestFont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..6055b9acb98eff80b998ed450f321e2e9119fa98 GIT binary patch literal 606800 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 z z%E4Vo6?=oSzrhvi!BSs_^K+9V{^s_TU`e^^KfYjQ%!u91}% zhKRES4!|lwnj@i@SU+Rvt`;fNAnYm2M( ztdfy`6N(EBIP^K9ded!@R6TW}yh0JLN`wiXi*5Q-(GX%nLqw$G=5_I`N2(}ez|O4 zub$(^8+*AvRe1+Mv^i1tUY#4jI#JJx2$3AnKBnX*=LeB=z@P6! z0s>o}HBZfCt5a4duMV$H@(C05_;5-%IUMeo+CHUya{F-4)Sf9llY538cMufI84G9x zTV2~Z1ryOvM455}{ukSjOJLgiyKi}C`t8TYfA+%@$4j?NUb}Yu{-JVdO3KrZ z-d&sN$tu5L__*TYH!?C_-nsVSe0SPledNeoxGs~-CR+jgTyf5HBl%%`hdcGB*r#!j z$z644vK!7G0cMT24}%OYYJhJka!k@m6G*KQ97#3W)`(nVd7T6_wkTvYbn<4UA9)5M z#a+^%?#6cx61GH!oz86WjZ=^h>ChX-cdX#05yifv#%ilKZO#fwS}f1H()-r(ho5>) zKJ-7IRqAthY;T`XcwJ|74RhWNeKT#xrMlZ4u!23Cn0Lbo+*C}K;i3{UV(GpF#Tt?h z2uYMAA*j{3Uk?_bf4EM;?!<2<9BSZqlju#p8~AnUF4bZ;Mq-4$b!COKva>&avQ>J7 zLl6`2>j^YxNnns^F}wO$J?OGKEgS$5RHh?Eyd&&Vpe3Hcl^&`FKfa1^Nita;;d!Rv zUc>NHYxX>AwzT8Q5wo<%5=%7$uZN_b$lqGQZZYak{@pmo(l4E4LvDG2`g)@2j~tgt z5;|Z|;m>E4Le7M6P^NTkXD${*6?vOAZdF*Q)z*ipix-arVL(3smJ}0DB}}eq_?#VL zJb8!s4*D?Vx;ZcIdEm{X#s@cExMc<|_4m_b_st&DpP3zd`?zRXu#CB-OAXquAEG&L zfGy$@zjII3J^paODI+HhQjXemH6faE^ms`D4td={k&1x09JXh1X~V&PnlPb|6FG2Y z2Xdz(e<|**$a-Sl%T3WtH&>!`FlimY*ajh^GQc6kCd)6|+{BtKe_9gE@*4M^YP>{A zM~9Ao9M|oGNagEJ2sIuhAX#!ZZf8HO!EO5iS$e$B9ZX71um)3` zIrvlMR7d2$;ot|Tz$2mYl08h?|5TIqKh^C`7E(>xfBb4o`yVlB|079AyXQC(A2Ab- zlac1XqVm5##?s%Gq5sk!ZS>hib z2WDTKDjFaF=tZXO%=DY$szVG}QF;N(#1E`co`cqr;6M&qM|Z~{aiC+6W>Zv$Civsj zL{0M-_>0vNt<*nIyJouF%H~sM6Ser`E9)u9|ArYdENrw>Z(nKm2eD(L9b?*Q$)vJt>ET+Qju4cu9UOEdj1usM|G4 z_3ZF^G!J1m^aose_HG_g(HxGT*3*HDi!d<;=z_G7rZC7zSK`<-Y;uso_=~vz%_&nS zOnl-HTh-7Y3&ylrD<_X04$9vPi|@Q^^{ncLSS8XLV6m-!G))fYI_<55-DN5Hsia{u;)*ncy zja!u=?@{oEwqLxV-y2E@C3pk=K(3X?Ch^@ot@vE{dN06BW~OE zgI903fuIn)&#lG~xfE+RB0R1;1W;T0lKhfIOat*UnGek=N^~X(36{RX0aZoXp97MA zbzrkrpMV5%X&UZ3blRaJ{B`gX^JTSo0lqO+B%DpwE+XMHvYQ2zI3YvHg4bdfrA+9j z+$@Y#?h;(k{gY&ijJy;9mSxGr+;y`IU}ct(YyuMgxS-u5nY_0>tlZ zjuGr|G(_Uf#x&&Rn8ps7BfyPtQ>Sn%91RdV%g*lKY`FGaf5W{P12Vz+eczqqqr=Ao z_yo9#X*>inc0^nEcFDp6G77O3XkkTyNM9KYh}9!+95#GR`RH4W2z!Wy|7QFF0W5gF z@hF>X6n<%Z8w|F8G2(Kw(6_}|lUIn{H}5y5er;UrlyJ*Bj6Du?`Ffn?nV=%U#Ny4- zI$na52AX4&AQkR5_y}xOWoyN^8iueQRmPL-%Sl-|H;r69Y38gY%g&6wzyj&1*WY@v z@F2L?^@ST}4;nIf@eMbmrS&`Asp!J5CyW?exe?|RJaZz}?@w62A)#1zCrMW9EGrVF zhtx7aUuQ6p(5^}Ccg59$9nezia=>K(bY0MMw9~*gm=+>?S=Q>!Qu~8O7GodYYJ4#|FFAARcjwxy z!9*Zej<9U?*`3xzYZ*5qN4w(@YlOsv*OSy5x3k86B+2X$GJ9Vv1Q^UgY#~mv)1@#)bQa$29F$C{^FDp)?@UWeZ;T7KKWjTe;BxGDy{O0o;Z0@`S{0G{4R`r1PoluVRti7Cu~8>je@rxGkTi90QOoC6w=qJ1j$m z#(tsyOmFF8>>E~fl1(!9(4Uj$FE$AlpRM~Z9c*kbo;i4Ff9#IVws2n_c??L`w@gQGTgu_qdE6t8&B^ipcLyv4w0AFGuVbVF<=_^)<5{WfCvPzUAekEikB1eFY#r+BeIw zcCKoFIIpkao^UJY^}|YT<>Pu4r<1rAZocr~ZI@$mG5vxMa50a=bkwO4hIX1`0h+$R z!i8@#d}R@f>P5U$Q!3`yQD<#iFB+fI!gaSe%4tVFL(N~(*A*H`!q%r({2$F=z-_)Iki%ZKFz5mKpv@7&gWF^gz|kf*NEL8!Fpb!{*$fi zTP~x1f2tpNvT3vN7V2B!Cq78+f;D!B_$ljy5nB^$U!ALbN9F87Qv=Gemmnj^<{;zz z%7QnQmX?{G683fxag9$1IkaqCjp3Sno_sF^JwZ-o>4K7!QJa-iYxV8%9tv{ji)=Eg zKz%TMFU~&axMAej=hLC}V$%crqF{s;Hw>Bk;oz3QNGoSJo|Ey3qL3ZsRdy zAzQ~P9%Sm=HtrYw8XJw5C8zPp*ruCCv4;@?HHSSssI0a7Mb1lO@5RuOET*{mpK(WZ z2wjA+y4#aplx3z2PiQ}&*z{{EB40W|Pl|Zm8ClLeTf*v4xIQS=7Zn`tj6CDP*R%5q zuF5D*bc%3t>$Zui(gXfOhH?Lk@1*vqZcZ~kKIm<{SKJbuvodi6-U7o`0}s4z7eyI1Cp-? z;GD`V9`n3devHQ}@VMoszd)ba$=gA^GJN|NONrRC`E^Wla-OOvR{(2z6U{`q0@y}j zC0j|CW5F^Jed%jVv*dF=gGYcLUBXj~_%rW-W{X_QuzNistmNe*csZ|c?qxInk3HQ| zKNkPzv#@8PedqU+Xy4)WkAGRp>yL#VTmZR_cTK|H5=WZ#c^vmtlJ}5sStMzA9JixR zidcctH_Jow9N}`i_b<;8UOw>}=LpI3iEYjib1rziE0`iE<{5K>aiMiN-ZBMy7PA29 zzbL5@JtS=ED{BX|oJ{(hJM0ZfVN3TU@+RR16xdLRRvrsEu~sCyg|NLgxIT<9VeXrC zoQS~FOha-!`NPmhEJZRhpgiLQF)Q@x{qUB)eNIlTH2!3KGh-@P7I3ca6sKOfxT}09 z8+OB9aaZH`&sQ#4vgj|k71A{j`-sjx5wf9KrwNlz6BbR^kQSY$mUNm`|BFszW}fEI zg{jkU>mMlUH=jJ&ebbmP-??dI!zOW0?_R6Ed39&wt7>)qpfSZuz_QTIc%L0&&J6?0 zj3#so<49|_vr6%s3zZbUcBAJg*6vixRE#gqPsq@IETO4|SGo%2HGFSWSthVM(GJPn zvnrKCszQcVDHnOUDMR`Ep(f2=D;dh?53&>OFJjZ08qp5tK8?n@7`*;=-cQbN#p}O{ z`k3!9<{S0RbA2A3Yo6;Xn{OsHN|L|dH}^V z{hIWW=K38l4(n8EKbODP3i%1%K0k{rQ+WHYHjy+K#M?LPQ~PH9CE!<~_Racc`v-XY zynYi#ORVDUgJS{Xwn7?5?Ki=DQ(R@XFHPs|L$5$P3d$F&)V^7N3HS!le$)RY?!5z} zDzm@w``j|Um-Ieq5Fm{t^b9R@5_%H|MXJ)90!vvWL2*GPG-+Z~f{64@G=Lyhz;zW- zceAf$t-Gk`s;iK>c|Yg5Ghu@I-TnUFKYoFfxpU_}=V|Ah=akR+JFbu57!>Cvj0EV> z?$`2qiGJ`6dcM-Vnf}GW@!8AAC&)h_!&>v_Yxgfx;+pAStUX`e&Y!Q{{|eU6a85t+ zH0k;BJ^cC5Zl(Ug@k!(KBS#bT(|Q}upRe7&OkT~Ok6D!_1fP#F1pV6mn%+b7lMX`k zd-?M%Yb1-xjV}=Q8W!4Bb)GJQ!U_ zMZh?S0GU^zfFZ#L_67oxg~rv5MG|CyPcGZJgOCD-T-yEjFJF^Zz57lOBA{YDBZz<- z@1sMMKR!>_3;r=Z_CLls4PI)PFH-cFTOJFq)B6gG(hJCr1tXk;0104~bLI<<$cUt( zLI=69Q$>&UtBR}bf?MTl9V_Wf)bUNraX;_mMRBayR zk4qIi`4B^0dz<1id&Eb@C3ooTh%4$L$7T2K0<9H}l4D7o*?9a$P8|hbL4LYY^C{T9 zi?wrH{6k&zhBg}!oCPoKr7M^48%8g3lxSVT`jW`mtfky(4j>9r1Z;lLp1@uB(DL97 zBCA!hc(HcY?Af!}yxFs_e82YK#LkxvOe`OG_u5akK5%gRp^4?Y9t}MA=&tffPe0vr z#M(tDOZn2ELF#vd1`Qg#zG5dTajz)t-M4M`?v;D81{tQ#nDpH0V@WAfrfhnD5x(Bv zG-XOkV#%1%YllH`;A0`rSM0zRX^*VDh{E0`LsSo2`#ggqvsIQMy@zZ_Bt4f#frK<- zp}6|czLh6MsB8C3fxa$oV*&3vdQD1tSids>kI9Wy;r$GCGhcUWM8x@>{ZS+o+=AZjzKIq56tjT9Rj=4?Qz38%h5^4klVp+vPIcixzlYOY<=B*Y<=xU z#bdS$krAF4yCX6?vcS{PUL4uS)8AeiIl?o>KFu@JJ~wiyXPJFfTNjg+#65i%a3qYIKS)O!r^{81Wzs7i^@FlB?k?XcKXh>C&AFW4j)pyj>Lz=I zLw-2(yjHu%<#g$^zTR>x@V*A!3Rdn`xNySnDtC$FsbI3>$_c->ob1-xFw|feYMk|+ znwG=BM}Ut-*f8WN?g)3fyN|n{O)=Z;kx`yldzL*ZvJjomiR|s^XCH;GPmG-AnSpMv zj(j%K{hJ+^{u=6dpn$3>YZaDnbsY7TA3>dEl0TXrR0g@n^&sT-UO?IVkY3}$b?85o z^E(mlW?U!SIK*b)I@eQx0lc4I2R3jRZX9q4mTP>P>k<5{O?m;&+LN{Gq}MFwXYE>& z&p2x@M?>{s%?0(&sXczheo*@LNDUdnsfKOD8!1iff zzBLfK%VAxpyVbRe&HcTxzj+YY)G+$hf4v0cvZ2AQy>#$ku)9)Z^EhA*aprqYS%F#? zE<}Z4r?GrDi!@R>9Xs>sGkmCjY(!2Cs_TgTKV8ozO@j}51&Zlhy_{Fld8o)d+2UsP z>j*aYG#d{%G8noa8>414#|g9))sd{OQe9SM0JeOP=QZn2uU2}WREI&PB+g7F< zF{EAFF%y?WM+M&2>!utp8(cbg(9mJyuRl`6zV6fK_>?IV27mV8CFa__+i7y#Rk~?} z%^a9uFwFNxWF1U(xi&LJ9O<0D;PP~$hpL}*d^hMto&6Cg8dfD*bO>88Q2LC%lLgpk zR5I)m*)*XwBO($D3{DWjSzE1NZCE9*l5QnIaL0s}GXt=-i9Bs)DTNGBDumc{40Do; zIk96E2yo}}_?iqxS!YF949W7B?bVcvs&%?JHt@B)qr4)uVC|km2?>WYGh4SF?oUfiwzU~BaKo-~e)rzrrS9ySKJH%$ z4oP(R&J@JNw#9;kzYTQfgKtIw`vsoWh)C89J_E|K5D(9z4+4Yl$YlmJe%B+s^{!(l zkb)qWA87oWBUk+?`1Imk77125Jhu$<37l9wx6to&xh-bdF2J=E9l_#cJIZulfkP9T z505c{M&d;xM2O#D_9o|MtP1J0DbgKU=!} zY4v*)(f&7P>Pbm>sG@RH>o%uK8a{gWbBzXR6XqmJDDpc@2Ay5DprVb-9bphGK@x)1 zSmAE1W098i)=ER2y*3gwpx^@$!7H1DyutkJL`C(0y^uZi!JPv~tnW8+aJu8clcwxc8e}D-lqtzxENz} zQae$$3UTRa5i+u2Ih+XaS1~*q42R#F$*R(1l>ClIIGGhu3`&*l8D9vUgB<^~7mnEp zsh??Xx&Hvv0n0smgpE_5_#bgP&Yl%tdu{XU6%TB@Pn@Q9o4a8CyeD5cx?#U3>EiZR z|H9^N*7)1sl{e5g4=kV){dTVuhZNNgm}NIIX<-5lCDf6wPhI2vgO(c+ABl8*y+^8Y z8Y3cvm@4Z=SVt3J6{U!`o;nZc5ynD3O3BTPb-Zv*6dGJY2`ApyRp@z94Uc@MwD`iqD6s8g8j5UpRHkHqsD-NG1uB6KU{ zfLFQf9-P*WIM#Rsrxp2=9ho!E;*f6{IS>ns8NZf?Kw-p^!Gla?kcn$^)r)c+5vfy# zQ_m*vUaxLEwtI705f5C(Jc~omYWdQX`Y0|9e5>UYiS{SO+5pU%Sby9<5C@%%=4+Tg zHS&z-Xp~)N7R(jK(@~IQ9AJ3MqpPz&OT%n#jU0B#$_v z{n2I7<;Fe;j(dP9*L3~_O5l^11tp#?fp<30lF4%k3(xESDZ!CmQ`iSx^ z_)jX%`l*t|s;e>{NlU2$B6$@dl0U?rO*85YVj{M`7#-~<+z@R1ygUbDMak(NOc8Me zb5IfU5Q+zOQo32t7Z<@CE@VG(Bo}hrf{yn`quuT2C`aJ8+;_(kSLqtFHLB-GcXR6TGpAuCe zoK8ytxI~-=F5#+AW06trM4(H!fu?TO(A0m0dW>oqnmP(3G`rS#<%D3b!eJ&9KLCI_ z9bIv;Nocyb;%KMZfirV&eiMS4P)ELSwSMX(){7bNuh*oh2XAiNF-hur3v5EGhc_I2 zDH4%H&!b+mPVyRsq!^cCLbiyvILZ`fb6R8+;^j;!Jj*57XwXY0ol}w}1pvlU57b_c z2DEK7szgS?IANBN{CMpOba)64N_+{61_aASjYmJhCHZ^Y8_5*NJVn$=df6*@nMaI} zB4w26WNBi$l%Y%4ryJ6ZNh!dE5=&T#I73+s+}Wj(mAXp(cHMS;BGo@hV3BSgprErz zOQEQjnlTJtzLCTLz2Fs&3NIV#p8F2bY`TcF8W$XLfcBwz8KVDRSRKMRXE>-`$ zT|*pKmr&p{yT7{nW8w{h89uv{T(kIx%fx`oxU6sdLljrq9iwS|+Q~S7mHU-ITT| zeN#r%cz;&0FZ8M6%;Hw1zR+h&GfP`d^o5=_)oFEj?y6*LVep6M}rAvYgk3P85< zTvzRMl9DdQe{iU~f9{Su#@E&sPnb}7Xxg2tes@zOLrFm_`xc2qN@gFl+;g;3p)jka1= zk4=K;t3FP!6iV(3!qtSBA$Uo`>V$m>9IPgkcN+w&3Fjfw{@O64n!qa|?jfBzcyr&c zmSLbZL$&E12VG{3E~(C9H`YaYH`;4s>!Ssis}D-U8e&R#(jin8&4RC?y@k=G+4Cu7 ztS~%>k5IDmrB6eY1Rf+7hci59akYSU)6jAN>lTKNbr37~7Vepu%aX(}x}uY761H*D z5|R@&>a=u2Wae-JvARNlbYX1xe;_fGf9U0;J_T~00vuf!nAh z?OiKZVvB&ktU^5B4;arR0XSYs!10Q!lWUWy9I~g*yfHbYca+P}7uwvf;ds$XOd_;A z6x9hkA%&K!e$~JsLq;&&)@|z5!1!T92jK{c=s$e%)2LkFb2)eKR=Y>s@Z4ZwgsDJ|PG%(hI-^k#GmhEPGwM z)^(9`U0Q8yqAL8uGJyQ z7so(2Y2t zK{upLe&4QRR%W+ycI-7{h%f&!IQv|zldrLpyW;@bVbQX0g6zgmwAGHp+AxZn^Sj_=3rDvKr&!t#sD^_x2mS`vc$M1$ zZ?63f))C}sh!=xhDMeV|x5h@rU~vzKF*u@o15Paj$>fg|fYh|!QR#`PiT2c4qMuL1 zmauH}aZ&Jz18YuGM|1qGic{yM?n`|$^?EAM)Qh8wql#mSW0f|}Y)7`ejSaZX(Q~8b z#>|a15^l2_zAWdq#~KJ2tG3l#$on zp9-zUxZY5yuo`bvoy+^YQfH}kZHyDWv9SjG0I$oydLv0I)b(HwQDY1R6|tyt+y%)1 z^r6!|bOx@?BB8t}fsWlp^QFO-%YW34HCWgk)pr{|R)4M)pQyxPMifH0(dw&E1HMvE zGv5WOOh`O@1!4-;VIEBIu`TsG3fpBGGTMtS>j1@-=+&ag8UeY|*l^)gdW2b)MZh4! z%jmaf*R;z>iK$DeEil$OHx^Ld9{s=4aP36m`h-df!}gmMuh}Zf=@Et$p!*@yV&y?zNx5B9789(UA|U}w;;zXkw@Zr7Fc)jEW&j1C@yqo`q_5AYgf3HC990ut zY+i4wwAbl27Sqttd5^}g@!F}b?GQ#46^$t;R&t`KrZA^94QtNvE?wJYBXqh8^jw0q zyq(Vnopa4BpVkRCp0*e_MJJwLalfj5T{dF)*ghjhjNdk5_~5=9wmiD1XRngpOZyBd zn>6|0zzg#y+OIVaocf_(yd&!2yPi3Pu&t+&h0vkH*wG#Gx3_6q;&0c^YK?y?Dr#_# zS?fbX_au((!S(+V#wG?b162YdU5U9aiz{7rwc)mLBx=Kt)`qLoj6+i)LsSVuFsw;GE?8xq^vl$oWFX+-`9`8EP zF0O9dCN<1iaQV%-i&}JM-{8^*$NRfS@!moovB4_4NAsD8anLT@kPeBVL$fD%X!ck< zI5dkmGy`s<1n2tSIyBRXIe3(xhch-=X?}5H4nHm5c2=e_g`BDdpEnCR!U%t>XrTSM z*1IF>>{4C2uQtAIP3vvOI{WFE_||Q+(xbI-P*+m#+~#mllF$_Li9sez1r!3NWd{DA zw>ocM-t7UO4zW4Z^Y$RmTbj@QC#tqQ@x+#@Cu-H^IL{Ne0z4l-d8P)SK3!jJXn6IN zhK7HtAFE&T7|+vZTf}#2LPP5#^j)eQFBs9l4gp_ znba=}n)FUTA{4~o~Ri+OHn0*!mlt5EI3&tn%{nzfS$n ztTmQ9^f%JeOTkOy32he<#H>b&tuwgRJ1aqZtzlyV>Xkd&%TdtPDd4dI0mo$P35zNQ zoEvi3oMg|^LWhGE@gVh5&7-XQo$oFWz%&OvXU0q8C%!P{_{%RJFI};RIX4Ebr>1I4 zmUSvBI@qn--!EVOyPaqgg>u9?P37y?C*0#VrHN54eUi)SN)3XwT{tPkd8DW$jk}vX zb*9re>$&PvL7;}!X4S`;_)ckgVkDiHfahaVuWyZxN zvMKGggGG3F!K3J`NXrja zWSDeFI-e-_{>cmbgqy3V&?`7r6JL$#hpAH7Gqtrnk1jsR`d57^LG^ zc|4itVam`BUi3#0D@=oVLH!l2a2ZE-8T8A#Wg2SOC8}FSbYV=0u4JLVKaIvDo>?p6 z6Khl4anUsq+g$nz*`)*S+~A1l$T)|=RYFic8g1C1Kzhc@7UcOjdCd-Rrz04Vc8f|V zmmm`4eK~XBPgREiYz7FLLBId}+{?U14B&cEA%=B5Qyr)XLY!TC4YZ16V-kU-1paOp zy7{AQXDml`8k||ZP7$pDIx|~@5(kMG7?wCT?I#WR3nY?o0dPc_vm9j_ZV8u=rO9`` zwz|6Z#EFmvmaIxJzCy=AI)OMxE{9!z5a(ly@OmBAkXgv^neA47CD-rrI7OdqPu9I?k2fd37$t0T!-0uLU`69g6xmcE zO+8$Kof7ssIzs1Z{E9JSTI$e>e*NXZ zeUd0k!B;xW0Y*VWtt-Ka(_n$$9D^EG2A80Zutqx?PyrZz8Pete*H-5-DK#z;5ft0> zpi|5Gf?5M#7?ohdx|Y=7;I8?~&f`UPV@6ts3k77aq~sHaig7x;rX z+-^VpWAu%613D7VW&-710jC1J1z*JZgSXLsm4KfkeJ(XLCc>kv+)J$Il|i07sX$B)(6T5M`+L26NK@6?jm z;i-4Tu8QSpwR*G85@U(6%do-WD1gvCSxc0r^N*H=3ayYOV>M80jMQ`HnkgfOsBfxY zOqeot*6>&FK7(B9aZep)hXb=}Yo$9`Lx-%pX59a`?_6%AOXnezdfkBjPqKeCBJ@uk zct9Jc=bAp#$IFx9b(-LJ0vj&@IG$xL1EBE?1`V(k*mxXJg9GEm02nXPV2!LulzkgB zVqJ!M;I$&aB@7wQ@6O3A%bb_FIddQWoz46pvnkWa#;5V6tl{PHV<^vUz+XYMJZ+_? zONV<-E?@iXnYsmwHw_zBw_xdmPuA6S9Xp!P^4`0rYnLBC26LIbe^>d0YVltBo-X27OtaA*QTVnjxbEYA+a6Be%*R76SaV!WyfO_oT%Ly4JDDkrl1mO0}8w>9K&z zY{oC-&TPz7URmC}yvx;` z2#29^VGL9EWF3GGAH)RK5zyg?kjuqP4nY_0%kZoInNCGJ9Q?~xZB<`Oq3a~1NH#N*^=iHwm9-oZxT zXA)u)fff=2wUS~|YpFNK)Wn`P3xw1}w%3zJ$s^gIYCTL44)jxz`Q+XeNy>boG9H{K&v+}tPK)wqSnsUvO^ zW2ZxePc$lqM#(j1_(B96B0L*oOtQ;4#4I7e>=pnd9U>fG!$v^SA21V1;2g=G2zMTx zBDAxFIRB9EdJ!1@DQuQL}4tMh_m(g){Otvc7Z?~5&4zK|MWB)SG8(JLXi zLE?otcOvCA6=UbZjP~3i07>!;02B}7;v)SBqj&Qu04RVncjaUKtMxZ$l_lnd)r)Y|G5rHeBH}FrfQ{zYK z^G_W(@D%IaI_>&0d|gkI%Xg}OdsN-B>kpflhq?Z+Y3*IJ-+TYAyFu%grUs=O><(^7 zxIDi#y|>;K?M57n%fsES0L15k;#R>_5h>X#5_}sYYtt}C|r0yZbG!-B;fgw_JGq zWX`zVz{1ak7`ncDT+YeIFT4s5^Brony85nTh4UU?e9zvm$i_4ed-~6);jNP>5SPKu z^r^TRV~t88exqKLO*SOiYb8gt=x?hD_&_qkHpPvWdMky0!@Yrhn&4pX zE>M3?>%h8<-t|;n-Qm|vr+pXCh=XtLqd5(>qciB#WjMMB;Ldxt&A*;UIe#9+lH9!C`Bx*PnKobOymt0&rLW*=k1p(72u` z1NIJaNN$0>#o!|%rT*MaTNiZNN+(>-i)R|~B<`-&`j7JmZ!=ox(yF6 zLeHiS5dT3An!F8b$PHiP5r6w%i97I0vbV#H^E?sM8c-Q%un=q;{DgdAJ+0 zAuM`pV(yA;Ar^5iVcJN)AQ{>z8d z)UkDcxjHZK!^=xoEnXv9O^e1ODKv3)CpAMZ-}A)Gjcm92?8w1`%4uD-9FyLDuTihF zOP06@mm*S$BGf|=e%WciU1xx`5}erMtuYAo?reDO5I+ZCF(-TsIJdx^0B66Aag!?C z+OP&_gg#eSGh})H{VyKQTbMIz-qpXTE9zcevv}1~7%4M4t!9bp8{-$5VmHowVh_8f zK3hI$@JOtQxmf$i)q{Sv+TYV^5pCvSnHdHIhMI9dP72%X2+x~7|0kL$qD|2%Rco7_!XfsfJbPe z`ZnCo96GU69U*QAOym}H*r2kB*K-td#MyAR*&acr?Etk|i1jEvKp~|YCT}Ue@Wj90 zn>yO7EzL{k)^5BLVW-QpX90O|1I{(i}});l)rI^~ote9zsSHD<_wGK85{QIsjo z7i)SS=Q+aIbPMfKP0C}lmnvqHfoT?F9OktsE1;EB*iU;*OsA_*wvnL*eFZbfiEQ44 zxAe0!8tNif%LaJl^StE5%~slu3~w_DUR#$nDUL-XyFH}}LOi1rSP8}SKzv4_pY=Lo_=eNWdt)f$kFhp8!!#K6X=_Lek zxhtI8pq3(l2?+=Y-$_O%>DWThrneZP7g?E_?~pD1<5^e1(39$)nJw7&7mqKMq!n|L zosZ7-m%sOxe3*XLrGOM({o~d^&@`}P>V0fEP)tw1v%jJOm36yq63aIX-nsX!z`jlD zd2O7(n@J9lBd+ z@C$fElZFX8aOUeDo_surp4u48cZBpQGEmTG5&F&F6&KeB63D)9WpNb_K`+;sJdud> zQ&_z@(jpslgQLh&NmZE8XU)#A3DB?|0dy0=bMfX z;y+06JN=H*_|gOmA~?xkMVdJ_Q4vi3-Vo$3Btk|}vb^rvq*dxCAAO{LvTD*-?73-` zM>cOhQaO#W6HBC_uyHtdpbaq5&-lIZw+wM=QGxk0Q4`L`D>Go*xV(LA~oc{_xQM zDFG~bZF=VP{LM%D_nR|g^i%mMqW$Yl4+D-|d_7ROBR5aHu;+_ArzC7ODInFXO{28)Sl0?M`L#Bv$LF5z*4Df4A02ClQE9n$jWQru{HC)Y5X^{a(Ji`YZ z@eUtH7kC<^hP9X%7ERa!1~eZ|23`iC`Ub0h5m+nxk(snlI@CBEO(9cUR{(k}>>Ctn zFq+I3CQ8s3P$}IS!t-46(WH#fDMq7-IS~m5?ju?(fS;2URJGAL^?Jjv zA)AH}PW2k#DZxlKnUFjkEw(jvGLS~ENPpnk7 zD%-?IO~;kv;yLA2`2{gvQBcD|GK(gQ*(_6uBqdsokYdDGORU*r^cvFiX*!>hAty^| zIMSpDX_gFgswvs%Gjx;-r9w+bLyoOP=_{8=eyNA(2N;Uq(#zb-)XV6%`E4WhBXuK{ zGHHl7lnoWiEW^yhO(Tp`^iy?rDzju{Ns6=BEMbm$l5x6Wu5Gb?vF;varMyg9Dc;Lg zv3rG8!ZOP}=2hn9rX|Leh6<%p++^FP-=^E5JREq?My{a?elkGmoYVub9yWTC3ORpt zSS?QO+ETbZ{uHez86n@AoyFmFT6oD7R5CJL%O@0cu4+I{W7-0}R@S%wibw7m*t%VI zGJEMo^)dBv`K?#Fb={fjtC(=}7&iximTA~Sv$19k@GF``gJQyZfk~cZ;}r^+%snm( z^<;oXmXAdu%v{ll1%@(QglTwVN1Eq9bNN>(#LW)^1CmDq!!4uOH9Q1;DVpW=eZ zgVbE~R|J0ELp&cj2A-j#erE&>E3pYKOEmgtVJs2|`2(=oEqtFxhIJ3fcO2`KcaNMe zV5!z|tPz69;{yrE%v+mV`HFUNCq;}9)5ShwzbM5VZTDdS zqO+otd>DY}9G^A-J)_b2=!rh9^OK`j`BwX$^+jSmQwmakC|oXr?2$ZLE*VyE*u)Fk zBZ7&B;n|eo-OJZ?N@v}M{%)qULsGZWaImHh_m{v=hz#ZZeTqhP995p(HNQ*e_86MR zmkY;>5Yn_BfHQ>kkR;UjO|gkySBfqn(T4EDW)DH4<{^mCJOl~J@ihq{4?#kGGE{T& zGKK&*f8icTib?!mxCfHp9!P?FAgLe;?tvt@2a^8R?g0o|u?xphz0Ea1Fsp|ti5rdq z0#f~jW8e|)6A*>FF(!9mOj41FA~5)N6vQl2$PITt;Q1l{ggyeXiy1k3U6JPb$tz-? zt4BqVwf=FB<&Fu}!S>WUXRet#d`QOB9hshO#+5Jqp6xj^MICthrXqK4oqJz@a!LS+ zGZpTN=?}~wacA|=4$gaSv>uQRhZ>(FoVlOSxo|3O?>8nWu80_eV2y{L3Za(dq_VEJ zSzN|C*S1)cTaOj8uY5xK^MJC^4Y60o@T4tRxDs;Wxq}OrCInyrXh~Cn-;{vL;}U`m zcz80XBBBt|YB3|Gb(;vVepGq9oha}rki_vO$lHU|PZ~p=o&v1J1Fv%sOXemJOD&9* zgIG!ljUS5}!w@X9yg>xZmNXS%oIsBRo6D_na)e0Q7!Q)zws?4MZl?-|WA1sPh{3QB zTLRg{P%$Fw?)x=t&B239%YxXN;`b5;=GV#6_88`m{Gx47rNtOrE&&eFYYp5S<1khj ztQGRM)R>Cch>FD12z9|x9rJeub$tkoBYbeUS)7M3HUsgFp0hz4C4%}qGObgmX-6pa zlqORBYQr4a-va9M=7%jN6n1FB_o8~5R%C{xU=V{blQ3SO|KJL+Ez=Li|4L2*+ZRu! zB;~YAN$N2nDTNJI`>FvZv0BDdA4&~Tp`n*imZyTF+paVR&mmkJJv7uXY6Qm~Pd{ihrEQNN4}uty`dBNSWK)o;s1aG5a;k!5yQ zS}?fG0cDpK8;>qC)fjW!btx^P%Q8*mtZa@h3(Ds3K(jP0qB@x>&4#c+3dP<_dzbX; zx#-a?8~P3&K4RNjGp0-_SAS%awjs7!efeuuy?@2LE?pMPmm1o&^Ov-3vpv7V=&>C- zESme~#4 z;WtBz?Dk~t?omGtMHmI=XAPg9KVyC*e%5Y>{z&i`#0nk#PNQ3qBV2YlUe6Si_~QjB z$dQiKPR1Nmwu-WzMw0bWqZ{lj8z6*mE)(V(G8nlxz4_>^$AQ~JEB#z;ZSBd^uA%|; zbmTr~s9nrfP0WhddA_`ObKe8Y`jr3e@&i4(=Ooeoe-3KD|Ze0f)0 z;IID_hX$&yiyiCKfzmcLUbKkA1Ah~J=mvcbo%t4@Q-oN*RX7U=hN71UBSD7))g>GO zvk74qtN|{J=W4}Ojjut6%zp%*)nfI2LT9u*goIEYLalwH?{r#XMI7SEksy)MM{v2C z^TA-xB0pFt3BhkHzg6!jJOCSkiN2Ij+2OE>MYe4yWkN(z@#d^BZBFZ&^AG}u!;`{Z z<`eq!U$j1t4$72NVW8if4w;e|V@MKgX^<)usDZlXaWRO%zC^XpJzT(~#?~Y!B$Aj( zgqT5KfW|v{V9I|ZYrJH*;DIW?DRVym{Pj;i`E|K-rCPnlJk@-@ZqYu-Z%KEg#2b8E z`cRq&r~bn6q!hsyB%X79F`*_k*+=5YC)LFJew}zX06c$7CUqtwInn>`&wpJsbpyOI z2)y!ZQb66wsmG8L5757eJ!3}1K`Zno40bAwhcyt&J@gFP3E;rZ098x_y9feKiAlB6 zOj3Uvx5eyfflT$CxKl&A2*OSE6(=Cpq4BSe90vy1m@ zliM4nRUguKel;FL4(ozEwzdT|ooWF-u7TSBnlg5yQy7Srbh$A)#>fj zE5QtK`}J+$2s{d$gCl76H_nJO4>=VP2nEN4VJzrmvTFD4#eour3|+DOy|I(VPe1+6 zkRd_rn6&hT$Aef2`E8Dd;1#%`yCqV>IHxl?y{z;tv0THJ3GCaDkuiwFB@7vmnc6CZ zu|R7Hwq0aCd$6*zX)Pt^kaiamxu_(7;|p9s1T9593fdAyHZYwGtF7d(`uTPmUY8BQtXb?BC_(9DOQ8+>J)IpH*@Cu+MY=UDU!1KCqjmsbf*w{+4eQw*hV zAdT|Q0lSCy6L;v;fASHQI`ebZ`s5^qx-&^H$`3~{KD|OlegI;xQ+Pau`gYxsBcn!9LFiyuk1=BxpPMp;hc0R(8w#k_YZ!n zRgug($!I3&4geJjgyRYLWH9Yvtr6>$8pQc=EC~&2O`%e{RFnj^%&QBVK9;^z5@A&YQjeQVT=*}My-NyzQMl-#%^M!t zyr`~n`;N-G@E76;HIjWv-+>23F`z14TfWA46$;PrHuUfw=fjf^BfXIU&;TbXq$Khn zO}LN%?Pjyqpj@&JLo4PkNUEakUTu3eK%N^x8LHh!?nVD9}TF5n;{u{Co{!g3~ZkSppiU0;mn5?7IMI-)+sK{-ADi4nZ!A3n~^iePDRJq4i!BHgmb*Nh`()(Q~ z6&=z%EU?N+!D7iut%IiqF-^E^#(lq zlE9w~*l@{aG-Ok(1`VlprozAm1Jxo$7t;7A&s@AXb@6aZyi0!8WSl=+JtZ!j)UgO5 zXMBD26(3}u0OQgr#GWwd%uYO>6Mj-~N;bVQ8{>s%yAv=$!C+8Q{L?e~@<%UPq&-?} zq(`&feZ52>`UEWaK?;8y!{>l6}g0HMTfw6 zD!IwSQN6&mC}7)$uBq1jD7KVZ#POFJPQi_) zPtr@{0ZVa;Ay&+=%?`HMa11jtz9Uvtffm$J0Ie6(v)Dg+w0~h)X=$1C&GOOy;?c{? zN0Zl9S9j-j2G*EOKR<1Eda9M3eR~)W} z)~&XZLMB3P!bG1!CQMJpJw>U^S3DmMgUZ(TGX)o-yxl_Pm? zbjgf~{+>=12X~FfX>_#po8p8hyAY*E(g-$5!zGk@(g}T&&Z>{(_M`DJ!CIT#pr!cfuh$P?fl2jxgYe5&jPw{2!+U zebWmV89+tC_u(vpCp6#9ooT1G@Mr6$X^ruDyw%3Q6Oyu+h1!tdHljAVTsh{TRro)* z;I|YAopc3aCt1#?B);*CYcdi$rS(Q$5gG^dAN~3|*smhL1)Vv8-h}lJk{JHt|Jb7p zy^r1MQRNR9+S{Kk2`8u*Vf{jfQ2FhDel`$ViqMM?>0h&DKm4Fp;@MZF&)Ednh#?0x<>tiAMJrwf^aYAly z@qt&==XPK==-CJ5>*5COJ-{|HHkZZhP@lt__fr`kv<F0;=T+_TxWgoz;xR}PAP@2VbwHrInKHz@sSCm##M_pg& zOQTTp@VcxQj@$Gj4Q!-f11CT_Hl?h_PveodmChow(oJ>4yJ(MhXF?rCqZ|> zIz-q=xRY}RcRp7nit@Sc@X8YNq){WwtxHUM9(rhxuJ3>W{ReK^yqV}^JC$DIG@S!< z4)z^VA6su(2C4kkp(%}3OiyQF#L#Z04L!WZ(?}Z&P$hcj!U%8 zzLr0dTzVbG4hUC%r*zKyo$;Lg+bChAWtncI3$$sihfbd4x0`Jy{l9GAV|Yw* zh7-Cs#S_D1j8Ggn9+ELaP_>}g6(RgbYlzh@ZJSk8nA9yXy;s7$3k$lAPHflCZokiD z8Z|y=CLVN3iAU{*BItEf{HX%4W>HVlrMH`9*Nf45`9-h!t2opT7xdnd5lb<t3%KQ`|&P?%s5XZ!HW!(D+Y&&sjy)E`dX*l_lb z8`Sy@m20GipHHk?cNW#qKm1U=|M2!fgErt;$_#uWjo{Po%-ys&&87Ik`py(GR+$WQ+xkpTvA5RB0e2PZP6jxO{m7bKTtV{PR%C z|D>Mz@ke<5vOf5LJq7c(`KCNCi-nI zL>L)kM#e5Rjx;Sv3Fk6EZ;LQGZ3>Gpx@=0si-|_%#TXmxCBMOZewFWp^m#3(S6k9_ zWGvFse$$EjI32f=d^rPZc|kp1)E7>Hb0vOVE*T4 zlP(vjZXjiD6R|WzQ;Ln}@LWxI*CUJC9@KJc4P4PR5ZS~uLHB>D>MDVtuFLRL71}OZ z!9Hv}p~N@!)fHjx_uN!*iLSk`Om51C-iay#C`Qb$-Mpr(5Ii~*(Kda`(R=B>vr4O` zT+|BEi#u=rME7AlwqvZPayc&}>%=0S5suP$z|N{bByyS&9VRfpUY6U-y<}-Tg8+{V zY`=7AhR*Tn5wL;AchUD&{28bKiwrbKjyGiCvZ2<+fueacXRI3C#wY8SCgitm*R9Xksk*-TBYJl2o)lwrBv~>G(^670y{YXne%IuW znt*^r`>uKHzn8ymItIIfUfipVJ=VfY7>}M)P-SPQ{Z3DyD~Ov2W}e|t312cFZ8 zRfA!S;D-}h3@lJDUsHSO4nRk<9YblyZ1nr6#IiLDqS~uccR=mM>TxS*zb;>Ea_A1A zF4LK&_GAIUOhW;~m)JNSeTe0IqJ`X7aHf=)Uin|keb_^i@g1;VuJ}n5&TRM~B>34f zPK&kUVEfuYuvGnEKBGo8|NBTHQIUU4c1#1rgBQ z^VPNA&71d~@}k zc!$nKDi7x1K;Q$lqG<&7Y0sPLPv6kB!2H19n#%aKCE7L6ld5{uE=_Ona|wBdpjrej z?Ay0&nR;^BV+6a5doJLf2JIdtc;pCNScaSO9$WU9z|;}SdZAc95As<6OehTd{ZLH$ zAC+~aSvQx+o3!o;$LLC}{rMMxlfi@H(Th9s3>6P6_bDXuTA@yB8ixJyXru6RPrjz!Q8zSY&^2M!O_i>Jr(>klD;Q@wQziHf zw;iSYI`26NXDn^3wG8fGoT$`sg&5|7%#6Z&R*a^3zG*Y+4J1bmMvSowi^>@k=_LAOs`tm51S8t)Csq5#ff+BI>vb`9fEk7xC2+Sh`g zG3eOHC-OPL&&t(BY@@&$ud8KEkxe^k-t`nng;V*L8`OVpn5LdOf1YdrxMzymv1xnL zXhPs+Sf5h+f_!og=SQGCWxl9S38-Bb{l&T1HsenF63fhK_9ga)Md|}XS&S%c-CD)A zsvk2xzAvesrk+h3ov2LQDF2);=#RoB>FAO}`}r*1>&oA&#Msk&V%U2fn{t~*YrO4e z2dC+*T8L{S$R7Sb@G!NonTMf`6X-`@KIf44KgV&J-p8nBldVVGbW7f=@q$M^gfZ?B z8snSS=vvd)&;ecujq%Nm>{`<^k_Bf}LE9o5s8Ya2m$%Do|mx;O;E9EZ%DAG zEDKx*LUJ{K@5WbnuSt84_RWp26c;dV=uLKWM$`VLdW4tZb4mt_y!mRm^uxpngXK%5 z+Gkx&&ow=SIv2tBZ`?CoiJn$6TBnTR?*|THy|4WZz9O8n>d)!;T32{(r!Qz+4;%{d zl^(a)3TymU9oH1q^aSTA!Sve3Z#OXS282BJKYt$fDlw3Zb^7 z9q-2aztx)TIqIpm-fFo96=)!Cj~6vjQuMxb)V1@uit++#XRN^`*6Gt6OU%JFcw?yg zS#SyBM6dNPOa7PosqPuhpY$0h?LswIBK4|aW%+^too%DB2&QTXg&Oyh3-i>RJbK13E(`7@l80X9j{8^tXB~6p{ zZ^2^|*GRjFp7pXiQr+KFjcXCwHH`H;(2KKl{b)ucjU^<%vsJyiRUE0rlQEC@VxpR- ze$-T}%^O+Y=${IUA7+fc^OkLef+7aInBRYLK1A~i=?lmpU%-pU__uE5Oh|?Eh~ar2 zJnt&WSOpT+nH(U?pn8SY0PKQ|Fhn%(;lnZdGO^ z+st`wb$2dt#3ooR`K@$Qmpa;Q6??*b30`$dehF=EcBFU~34e4*_$i>OE%D;arrk~F zNiMRYCI5{rqUg%hu{CZb#&h{`6IOwHbkrs@)y!7=W*%qZ564N{?={UwDvC;Tvj%C zf$jm;x{bekRu)^%O3OY&*h-h)1R9u#lJ+N%{l#X8GE`=2(w0Y3XR&e_R$ z?^avzBC;GZ-@rkq&mqqi?WVvotsUN`?t$fOFd8XEV_8|<{cT#K4r)84SJMsDWrGY4 zKncK?)VNu7HO*~0i?!>e{VGJ{bz|u%x}w6o2ny#0tVR36JXc|RT=PT(j0L3yVo_T^!aCh;F<14%SR~}!XzEL=+5VvD)=BcsL=BE3w zPd{sXjhdxvy4liZ{X5zbT;LWBHXy z9s9_kE4uzgW|t{7rw?D@Df~s70sKXXei^jR0sWtAeFBY3)lBITtToc*3-}`Q6*Vr^ zEu_`;yLIY|eD%Plf-yk-O89-9u-B1226VqkG1AVR)E|0Z7l*nF&c;QI$v56nvI4*$<Ls(*ogs*}?B^&H_z@plM_*MWZYr|EOtw>WqocpBtRYvCX0 z0loJxtdqpxd#m|-ZG=yP?|lVfvNHJIz5Km)&7b=Yv7_(}^0rs;w%cdY^FG4!9tvKc z!#~rJ9SlD2uXs-hzBhw^rfVUMH{_4F8Zt6Nifd{opxUD}$WGU_{^g(_sk~pb=25>1 zuOShFYZk@d@cC%?Wvkd40q8Gr45rIq_&g>-i&=e5dMwaNdFSAbchHpfTzpO>Pc_P& z3RUtNR)vxq64HZ_h{=-*c^IBcKqj#yI(0flaLNoR#xih6kab3BmyT;=P^3)3Op5jD zG^yZbo!IG9v7=(Ux$^)D4P|kf+k$4Qx2Y2{`Rh9{7pTdK*HAjqM_T8d`D@&d-4V)* zq1=XKAPmLHRqlsUq$=T=6mwO~#uT4}*`p)!1wbq~2ukt-QucAYg^g7EpF>=aK#h5^ zqM|}4>K0~D5{*{Po?wvJOXB%JH#WIp%~~ckG^|;@dQAhR(A3vc3Qhg#)AiE4gW~$? zYAti7x|%X)s_~Mi&b;;ZTW_(+Z1UT0h3IFGaQdO51p9+ILH{t5m?J)i7;7CYN#-89 zDsc?}4`sORwSlHoS1K**LY)^RXj7dRol^v2025mbbUt(#xPU)>hY#^vYB~+DLcB$5 zQ>Trowl9Lb12p9FF{O1g88nc-YZh7qP!AJsrZF{CnXNK20tG>q0e^__wJtQ8JgF3v z(O63OrUVR@C%zKsh%Cp(>HK^CLCJRT=Bk5epVuT+uA@D8OTy<=Iv#pWHQ4ZeJ|7dJ z2WtYfl=z)JOu8!l8bPj-0Kh3D(gtK);l=ehG=VlcW~ZXaCR&F03oB7+xeO6xo?Kvr zya1W(sQ8!0ZtMd!SvnHvz&<#5@E~%vod*vF{sr2aZlLWiIW4??xmF*QzwW}v3YIzK zWxWIWJkJit-vB!pP+isqSSkR;`yzU*RGws_4TcjSFgse@AsTOz59pP zzu#S7zx(^wRq{nE?$-ROu|zYo|~_QxtB_U?^b|Cow`RFAEX+)ZPT zT@~CzLA}u0tTNf#wXY6Wyt@6&=IrqPQ|D3h&D7E!h8C!qktxIeM z+o4WZKdatolfG@V+cwhvp)1=jz18j5wD)_k2O~%JcOVwZWF90b90TACk=BQ98h39Xv!ka0T^0dI+D`LNT*Z&6gY5n z%9M5M-g{5|_mru}0tZ;}o_>8_ILmTb_PH1O^m**qv15~-eDd|{4?U#*?VH!1d~(vU zV-HkS)v|6cz4X!r_2T(0TOPy^VoY^lnxplDQKNT(lub3+CEDAD6Gq^->a(!Nu&!`G zmp|9;k>~S!I`VrgqCRvF~&#nr{%HMWPfyQT;0V(aEK z4i7k6+FH0;I-AEfceb^**0f=U;Q@0!Yduz1Q^!`viQlvO>`}HDYYanGFQ*O}uiAQX z_2Q92qUxx$|IkcHDj9`zd>Tz=1e-MT-#yz}m{yU%ABlj|f5 znlhqa9cRN4_1AtsW7guwPqAi_@#`O^Ja+i%#L1W0*DN)(^B+y>G~U{;?x3jy>ulbJ z#&l_qZK3si6IlM0xqc-*DIQ%|x4 z-k44Pj^FCYojRGF;fwi=aYN91DvfpB2hkPnEo6az@H04D2^bsI1VQFVK<|+C21;GL zgtC0ZtWcEf4c##XZg_P6ZLAF-&S=o1QidYitOz+eL8=h!2z8073Yf4cYe4Nc;Rt0D ze`h0(^H#D{ z+oiao5`o5RNJIx|eQ>df4TtbXIzkI9lunx}`885WbZUuhO+yHCjF~bMTLg68*uGjo z18ok(vrx7&IVr*eWVm3Tr20C^PQ>8{WVe##!UHB4Zkl|3{Es1KxG?L9RjYpb@v&8_ zvb$|%C7;aYQ5~8M=szI1@ui`o7a{pLch<1Rsnb^Q@A)5Fw{6?X+~v;)QhGkl9JxFr zw#)SLb2IY3dHwXL2h2LGaky^(W9`fIY9`poGb zgA#9O+%Zec7sm`cfN9|n(dV;H2iPVVg@;;sH9UZp#pEdPVo3N_qvgv{}_5osQA~Ys6DY(Yb~@a>hiwmx7mgc1x%Ls@nqgd z{u8;bv8ak|HrZV9iZ9BKlDrt`B~<39K*qbHH^K>C3MUXzqnEU%#I+_aI&wwSrZ`N7 zy0F3XpNd@}$9ZzoY_BTvk`rVHd1@k{fk|bL^z7HQ*K-}~CM3kS4DDi4D+JNUhw3k8 z-FnW=>ou@jcWwRT)a?3or7U)x4K69+Px5p=5rjn;Q`8wpt+NQkJG>}v>Oyf->6ke( z7g%$(`l%P|4EZ3`7lL>q*=z^;%-62HN(tm)qqefnc}W!l=hi``bM5BgMAL*F{8pKz zOA$IjB5HlbSOLaNVnJt;wuDsDjvAxO+Z&Zh;yQ}z<{)h^NIMfl!MZpu1@vv5@lLx_ z9!?uiWh-=EWsb4~QBi%p{H#nGlAhgWhaX|2?zFmy|oBus6`Gr5EIbbQS;g=usDJ>XsxB%6(~9WCGsML9jW5pWHvS_<-x&I5B2H8lu@C2 z>l>nf%a}`28STj%ka>^dd1l0njaHpvWNH;{R9aM@iPEonGs^#>c8b^FG(u@370!Sn zIjE!}IgLhudz9-A?R8`8)`0n3cNkDi#mP`lB^fQ?lHYipeeoIZ#Ngr^v+8x!RB6QC z<3mEZQoDTK7Vn3yqbvs9TA@d3?aZu2I7)r9j?f~KR#cJ+M9EI3(J4;iAx`Mo_=NI6 z_A z6+YGJ-sBZYaWQ~Ur-OV+Eu;#0|KW5y9jPhczvQt^aC)>6DQ=haajj#%p54d4xq3m4 z2(6YJp;Hnn5#4dx*{iJnpcJN@?1K~k$s5K(FE8akV{NGp0c!QaZs?<~?d>bdW~^-_ zYPXtwCgw88C_U?qLMtFlBUfljBQ)rrjB;i;a;WEm8hTI^s?q`B z^@n?>tJ380Ce7^i^~qgR=MLjzOV=u+ibK6Rx7D&ot(Ij)($5l%$o5v4H#$x=5uhP-uLi^=+zy74MyC~`!fNxXZ zxD?8=i3J-;Gj?{kWEJmTehFH0z!_5#>n_o(Nj0J)lC?xvoJxBt28A8fl3}bt%}lj7 zxY`NjP8Kfh<-e*uQTp%d-eX%Y^h9}iS+6QaPS7GW@d04(cKSCsCxnK|)L(m}sa zJ`lVo4(n%5u$x@&-ij-xBh{e8g1NC^U>exKlE^jj&J`%gTpCa8Q(ZqH4r%{{SjTQw z^|B%rPs-ceXTXaP<^y_ek;cCBP?#@Hm*1I^_xjndzd3Vc-jof+TR-7HsKT8^Jd=;J zF%D<-A&iO8O$N7Bwi_%a)S^NOI+E1^gB`_WOQjMmnZub7Zeiszn^NPbIG^;dFl*$) z6eAy4uChi~adGI2^~4{AK91)T=E4-$(TIkA2ER}cp&mjg#I-fHb<4x?DxK9|sx67c zi(obiST3bw)jIZMjb+QMPiC{pPfcuPH^kxO=QgOjWGjE={xO0#uLyL!F#EOfOXe&a zGCyxi=(R7|+}S6IQ`7p3I>^cd1V8IQYjM;=-DbO6GQ@c^l3mdq>ynPrx||L>X{`=T ze2F=(xUQVO!tGrXajY&CrY9j!h9OIeaE9?k)FDa;Do`{jVr1GzggyAM8|8cM9XYc9 zfZUuli&w46KX>Hx@|7#cztFDbfC2YSlh3UW^_ejI(+ksvZhPc$eue+Mb2Fd9);|s1 zi^Xkt$p2hqkG$8*@*a?0W(~2Ht$2UP|Is-6`{CB)GQV z*m7Jygz{rH*?tIljr5Ph;*{+6L(GnRdix<*m%ycJp`9MW0#tr$HUYM&UUj+gaPjS6 zEwVJ3EF_8&NgB1A=qNo!x*Fu?udsuMn`~*4%cOgsWLZ~u5Ag||p4j5h1v!d+2r;AI z!}F!a72ohW^nvI~-OEvk0p|cW={9(LR#f2D8MJ_*Ra^1_o7#;ENkEY=(5>YkN8qY&-qna6~**`<`)j4Qy*K~=xCJ^^mzZ0gREB7h}zX3<|wha4Yo5`=bQ0IU>41X#j zmy^i5itFNBB8CG$b1d20u$IMjA#YSWd?8)$8@{gIFYNQAn)i!23p;$cYKJp=5@HF! zpmxZi&J|z4h|1TYG8y6pEkAvPxRZSuMa5GQ2#nqY=1b6MLQO z@GvW%H#~>k_;;&C+_rkEG^w*Ttx-H zpB-lJL!0^)T^rkB-v+`j)m!_iCV}+XBu$J*@!Rz%$yQ#`;_8V*Z8d=yp#LyPr(W@B zZ9#jyCTI?(5~K^-KnT^TjQFYjS^LhDS$x{ax_zC#ZjWl6o%yeiKOdScJ@)+L z%-T8GSZJ~~<}=v*_Qr(3&^nFUfu2RoVP`n5fa8ex#(35%OuJ%EVZYQ#HVafeUeH*$ zEc~^FUtNnOP516w93-m~{rCfoSVq@Ewxj4$Pxtz^ee{ ztLSVA9pzY;F3RBZxR{Mp3@C`;JZcXt?4Ui$;gnaf(so7C>0pAvc!g;W!|N0dlf6wt?3W zOR~6wru7NYL5<9gB{(3I#380UFiaY1LZYbtrPoOb6sd{yqSzlIHS#0H6*~}rVXaup z($dmr=kw0ghK>~@Mia%Sv31d}yf2+V0OleUF?;_NZ5K62gW!xBq#>dQzk#k!JwB`$ zH$3=>9ZfF3#;3QroQf+#Fr2Fg8#@_B-J-=+FnvWS&|ih9Lhm~o2X@wt&X6}fY4W}CYY3; zN_<^dV=TOKgoeG-=c1}&by$R)%YPj;f9OMJ<_)e=*jw^9p9q#b#^$p7we{v~=I8mV zi#PYHt+Su|fZfk}{BVFGm%`3adgF{Gpbnzh7wbxL>n$)dsBF0yk9c;QavczYH zv5{zmp^;cMQf(4h85m7vr^q`8EIm-J8W?OJANtCvlT)kBi-bz^B7W=Xcm8HtK$Zi4 zq$F!UfQ?v(#(Fz|I_J5tchfaFM~vvw;!4nD5C?BvPMq80UEwyZFuHB1{+^MrB0gnB z%rOzsp+yDzMzv;?Orc{JPC*fVI0}DJOo99{IDe|Q=EllV1%Mi7rPQfYe{Rce>|XxH z>M{FTWMwsMl9}0fV4#n(bjK6pj7HaPzs=sJ_f&p%ZK&;r=krWv@9ubqv)f2@|6jRX zpB*i@0AruYFiYl zKdSD7$;Wd09A+Q$_2|BNvGudLePKk zz8R>MGYb475g%|?&|Mhk-0gxPkPHeSpFAWXSZG@&B_>I|3(rruz?QNrKYZ}-e=?;{ zpOJy{(&5)G@ZF8IEkkRhF5M=cdY8Y$uZP~|gZKv4ot3fo7B;%C>4ng#M9K5V+Q*rq zuHhWMPI*e13;!h6Fd4m#p>dNtH5*I@uTKVJnet-^8)wVpxg}Ekn1-bnS%Y6bduit0 zQLHI1XKyCo7rG!7Elzx7_eW=VFa9ZC#YX&FeRdx224(*;d`$xb{?=CJFlZ34XzR#^ zHs-A7ub<@i#kpdAjy9G0Z3_S;NN2eUBcsUJdN3UfyV205UW?fLHrBKz!H6|&Kx~weJ{|fQC6rYKFPgduk^}ug)y+`9N#uA?B971}kPPe6Ywzjsk3;@}kwd-(kB2Re*PPak*xhKmo+AJ=O5U;S3J@7!hKjLw}-=jP5_es8DtEBf6W*?gSz z8UOLzzg}25u5RR`QH^^qiM)5jzI`J`95}=_pJldZ7w7Ufo;||PPkw0Pgi}BNd}_kP zhvu;KBhRvXbC+)A-;2Fo!TSq+KNU6HeU3z**A;%UhvxudSF@9(4E4pka!an(Th3MWgtAYD-y!MKNw0;=OBZ`EdqpB%D9O!vlwk zi1t=m?i42_`bR$lV#V&9RO$MmQIAd;bNs}Zu~)8im@uL6wr1a z7dLNynwh2Rf96Z;9tpI){0ZyCa+u*Vj-!xgYaq}3G$tFC*RL3&)S9oAV_M-~V=ax< z@9?a#sZl0J<(No!fOHkbc`7@@iJ*hDdP}bvBl@!L{rVMC^|*B(Ke}rB;*cD&jeY#W zvHY2NGtWs)(1ElM6;Ipy=k+tY=!~D`-L#+MJfx!TqzyH?BmC(dmDogof`ZK!cFENf zp!@??i$iR)*%#ClBiHa)LVjGMFDuHi&5c=QjFz@iP(4{Ds`ew4m7y;>Pt9^tg%qV)WcYcykO1@p z3`-Ckj-~jbrK2xMh@57TI=TMh$K#vDrp7vK7JF25azdQ1Q>!j1%>3Zusr-+}$9BuU zw|Bo4BbWARJ9JymZcSq1b7zh3RHt)hpmCkJ*!YHRdfh+b{dLXju52cE*z7eYMkmB1 zCPetr3`^_tG>OW5^HR~)l?{{c-PpZh@`%BU*G%_CHm#S2-t79M=*~^swQ6-wqqa%) zo*giu*9PoOPtdMe`)}gES|u?71@5X=RiyHf(gjrk9_g%vX3EXm8mQSX^AhRkD-S+6 zcK4wX$x%PmAMhNDV(y*0cJV)W)Yi+a&NtUzXV0;p|MAGy$L}A$A*b!m@o%qN|MN$O zaqJ#_^%Zeu#zEhj1o}+C>Vo9|_TH>ag)|gu0@F+x_VIW82EQh?+cRufztvCoiu07G zc3FMn8|HcJW!`9gLFgp^@oDxj8~pan^iwEzt7fh-rl|SB>(K_I=l~hDdu-r z`y;*skR&zHNNE+xNp?nQ0YY*cRevkVaIu{_y^&fY!|#$P5FPAeX$tfn4_m^ox}%fY z`n(+z6XN|dy47#QBxY=y-fc!~TtZ@p$f(w7?r8o#o2k>scICrJ0O z*J7iS6w_;Ft+steF3)F+yCt{RYR#{ilq6>w?-)96G$a-lCPG1>G3P)QpTio3$1EG+ z6S`y6F@GDiTzk}8SoxQb_$_{naK`3DxLf*TqNA1tQZr7T%t#F^i;9l%w{%D3#5yDX z%^HA!T6VcLxl2o*b~|g%Z?N6$9>2{e>mNs|PgYzuTui#`xGY66Jg%30Hb3eFKVZ=M zwr}^rYeH*`nz^aK1jcHRm&HP}dy;lA7?+&`-Q{>ocqu zyY~KTCR6%>6oanfUbggKc{ATUHa8DDjxmvcW+=vl8mM%RE5{V+tr06rtQ?iQlAoxy zQ;zh^7hURm>fAqcZu#OROBVm*_NtXLA7DL44(r=#c*h}o`}W%q95855zfDi}>8ouf z&Fxx{o6}_1uFy}rcGVcxo^-9Q;?MIl^1vKVV_3*0#JQ^v`ac4mXor4m1+v$!_)*Ks zY@rTa0KCERC_G+P3GuF=9bM(}wZ|M(Obw2&ayV2)F=3>iBSt~3R+J;>`1kZb`-~b1 z{4(z54(+IMaI(+htHt}8!58Y$zAGxlSrPxVD`;_n-oz8})UvxvynYIRBq0^Udn{E5ZWvPt4hfb{j3Z1(=`J!>5}YZ>9fXx7%+sSoa<(Hz zL!?tacj(}jT9&|m<9_av>-Fu&ulDOJDymAU7oHn4B3Y%ICXL7OL50%CP1#d3K`Nqf zYNel%;x@2ZMBdJA^c`gnQ;$NDPq1miIglEwOL{&u)HQPaktO$a?KxpG|4qa`EcZ{zNSF6pP0?eA6|5^5 zHa6O~$K~C+Rm#}9)oXyq5_^6E=d7OkKDXehkQ-PUYJZ5Zs1TQG!WBu<6X_XK?q?Qy zIR9<(gq~gRTS6}n4V9j!mroj-D(`>JV!$gxAK?|QJ-(_pn=n_(1ypkbcZj)*Jr!&5 zrua<#jM7DJVVW2l?x$Qw_*S0`IM8YhNs}g>UulC{Qi>IOUUA(?#tpJsO=vx8kTowG z%!mV{`yZ~0WI}|4k>>(KM>2@y7s+UXch+Pws)Z(Nw7WSt%|?Cd5UK{3Gv!EK^j%DY z^@B}@06Mu_(cQ{tOk;IWJFKPL(a_as5{)B}5{ttH3j_{d)_^TUytBbczW5wpd_sGf zC$dkGw;9iU?CYEVq_tiQ-th`-YYXxUjJ90l>!4Y>73P1~F(Ia5L?GR0Ii_m_4_4JY zT$0mZGKMFk&HyQ+KRD1w^#_CFhr#YdclA&fvlxy;9aF-uKh3`{0b7~R9!2AxgM1X* zadS787U!uy#zHYp@;YnK5iP9eR2>Vlg8{!z&eqgA7$SHn4#xaJgIlt%cudLt^12$Q zVx9Er*J}{TtUeZJ3a3pgWWUus7-6~>d(Ar6+WRyaiFokeKP-U@Ro_Q>>y)bvpC-a> zxZVJ?v|2wI{{8~G-!ltv>seLTd#Kl)de01H8=Iwh^uUHq?TR)QZEkm9iPG*szNX!R zB25uX?o#9~vL$yJU9@D(gd%tD=ps$-sG<$+i`b~-cIv-O?{=c5Bl#_^A~+9oNgGs(9JXMj!|M#X^Bol0RuhRDr#f^ZK?^!Qg33gFYJ8G< zA!=VL|FV0V|d;49C;)wDWvgY7(eZ36%0x5B61W=YR(54F(ND=g%>-`)^wNat~q zSVOogv4(ldeykM}JPCV)uI;EN6zxJcQIAiDp6yhbRJc|m-9gtrpJk_czb$B7@6+sL z`y+$$8XpvX;j$8c9dOyY9EfyxLGdYzQ9CoUi3U;J43BmWZnjkt`m zOYjV6UHFVS)ymPPJhbNeYiUK%EHfI&ex2mO%T*$DgLfyIUDsF6O0#vfy5 zev^(0(vdS$$a7mv(6Z0Nf~I`GE~rJhM@l~e3!=1XhosHUaXGUg&q?`Jk`q(mN=6jW zsQ}4yhOfU8l;?hTi#hmDw|I9X`vtZ=_nEd{ai}bGt9fA~_JTBshqiqD$+eGPV9wPm zLZ8sMFb{n>#zj^Cvk~6&*$o0?PtN6+Kf;Fguy{(ZfXx8sDYV)Il8bzf0A^M4= zUPyeTKnb}Y9vBm&LS$XBhL)F=N%P9W!(urY(q}uLrL=DtQ(L8R7|^v(K4wQ~JS&K9 zp@$RQy3r2}Ojvfn&uRnEO(k10md&Q1+v2hY?fF^@CF2muA`pcp-=ainHLWV1qu0*X zAX0hyw>S8B_E>HFLjl88gs7$Qr{CacHDElSKJy#=?O*BW$N>C@|8yTf9T`zB3hiYt+c7`!a z`?$YMx>m;hg-F8(g6L*F{szY9z&Ix8!gvjJzX-2^ys-#a?v_ZS#^-3LnEeq-I9ClB zE09#?U_`!00WE2Ro~q1yagq}=bKGz}CJGY52$aZe&+$^$;kj)Oh8(O1k|e>L#~Gf-4vbC{Wf>d=ZKX3R!=Yz**8eO5qmCnTn<|E zU0%B;k|u+Aib&Ze1OXK-&S~cIK`4=Tg!Z0Yl%C`<(<1qS?Qs-%*NQBo}q1>ILOUvpnq>Z>y;}PxHjgHpp7o0&Nr42GV*(p-Y zvY7l`nN;|D=u@e~MegRjjC1b3D0K*Z`nv?03dKpEhhC|eD>MEr6+~r`6}RP;(tRO; zyAu3u3wUvcrY&kW$NS{EUY`+CppK&gfng;65LtPngE1DzPWyg$(2}|{ZGTcwv);0% z4wbM0m!d!7D1tfZL^oO`IVmN*sxU-Ypok_>{v26WweA|tA{LA`J7c3~f zP;$Kd(kt7aJGFe+`RUiSKfQNw!HbFUC)WMz+jjm7gX^seJ`#Lk&a}MwQTLt9ND}9c z&MEdv^oU0jVWYu7fR}a#*{FM2!ukUwtjW>)b;|#?N4%lA+}Y4co@f{^FEQwmfoP0S zqK&yq7vn%>knw(HqVZwlqsn8(pt8mItmqL>dmt!~X|qm*Ch?z6NKX-#M)~J0sFkhm0qSZo+Yh~Na%U%zP583`dtlp;uV(1W?gwTGi`WbjI-_}Wpc%n@`D(( zOvpstB#c2PqLlXpoQV#T4<&gc{IOQA>~o3$Yh?hQ7^}^y2}XJ%^3m2U7;B4fMEuS1 z8~xoFt^w3KjLf2n0BPxR3WeKJ0WnhO8*N0gY`yZYe_c6u<;yRxoa4uN0UOBfImhl{ z{rQXh_&H^lr~Kr}a~{vRlPAkP6^=+WRxskLLFDSyk^C}rus`_a$b(o{4hg64fzT|TAKf=nS?P;mxA1qq%cTjX!}NTE%z zx#y&D-`-$b`0Qu5OQ(TI6f~zlDaKrvWWVH>O@1@6oEow}U@%E|x`8MGnMti1r>cTq zC;-Y!QqQu#lrsEXNRnS2x_ajM8-}T3+?fHp(;C#^(cvX=gf$CwQA|3MlyA3$mxb1) z#=_9MusHgY>PzT7RqI1kPirJ;fL7B*;awKUWFY#apq#I91-1L!L5;)eGrE8Sm7^Tx zSIH$0aZssOV6C8&stQH2$f==Ez(oGeJ4wq_mExycET?A=p=j*v)f3i1mEPB(edv=8 zaH)sSdM@zEY4V$-b7|@;uV4*?jw*B>6Lg-GfLj~1?la>|MMMI{B=bfVw@ zoq7@Ghv9~|;&VC9dxQUZTXXRO5P3b>ay}0x%kP(1?lIq1YYzl|`K|59e51Jb#`=g(gFsOcMLM5@+)i=ni?;$S5~Q!4c_qYJ5g( zB$#OUe8Tyn3p(8C_x2~cj3VO|%!6`{k&HK4hwV|DXFNqtBejRy1&j?C^us`( z8(1!(&#!`B4=DwJJHSs7#-JaSy`krnQ5!4Z#F2nY_(~g#-_wDP$fht@T?J8guWYcm z3%rqGn*t5e!R`ZQxxiBDjIe3E1@1d+3O!7U9ARdMH3asWEZzssu&)?wNYD($6c!7bfzJu^fk#&NBgR$Jo`75Qf3hb^ z|9`S42qNP|t^>8(liMC)-+q8RqjL0seC^0piF<=C{FQP1O3_7}bx+?*X{Oe>5sYQAeHh_JYSaztO8;NTv`y7E2oyT}FPf*Ig&_4ctFRvewVnl!QWfcp7uUQNkOEg30k^J>(REq*aj$^EzE+V zi2q<4(C@Fucx&1Q=!--e$lq;)(*Jwgpb|%Q^oXSYocCj2yuW4GNYvTeY|S+&K%}wC4S>cJrV;>T zU}2FuCXA1xB~t&AlF*CfJa5L%-r6B4A)vm)JftR0iT0P?quMnE`cg?J8;rR~z0&92 z-L6sc)d$nURb=5;RXS7s@rVoct$a^)+z9i54k+*|dX4`u;>iXe`p`dGFyB{YJ$hy% zFB#?mz)z$PB(_$X@OH2Ac7g}X=hb)IgLeQgjCTyf1(~n~x(6WNP4F&cA#co?-LZ}< z(W3Ji(i@^dh^u2$I!oaK2*ey*^$jI)5yieuO`FIiDfTtyV@*Z=WF|ytYcfsg*-(v~&b;91@xzLnW=~*sirI%F2NW|u|9w`gR_x!m zc3?^>z3T`sr}{Z_C4+1-pv#g@ofIK4Fe#Wir5Z!QT}>S=`?%z0QVF|Kf_`YXcBoSe zKbwE0uZL&bQKJR6P647;W>iCY~9hY?4aJ))DJ=cUwodS$zv$SG|ChizsQ@ z!0v2_cUfRl)DM^=0k)TIW`n`xb)3L)74v|TrNCUOw-s3I1?VG3(n$3*qq-?p4@M74 zys3(iJpF^Oq1rU(K`Djl`Cm-GXxTDp({p?G?v~GQwkRn^Jd@TQm}I%-^Ytr@4>Be=L&TBX2jL}NSXERB`3=B zmO<@;`n4<+C}B1+t`@BOkP#SyJcT!-F{$fKF<`>_MS+JJwFZ~Fv)%@GGHe_iaU8=) z^oCz)j#{o+DV2Ej1-jSFC5~b;ame3y!@=?A_ZtWPZsIhf^F}5P6_JFAla(M$oTT*W z+qZ3e-yJ$5Wm=v+y=CXN7f|KB0sjZTeQe|90WW^MapI=~UdqMsLhTX$Ht9~HFQKkG z#%M+^e#?M80f;x3?25AZVgY+2oS$mT5Z7>MO6I#uGP?} zSq^wbSp80?tOcY;bPa3Kq3Q0weyUWs|1w@EE|x#7RGazRuj4pWD%lPH4E+JFeJ{p{ zj146Tv_$qxYgC@r8k`zewe^Cbp-NAIqtqBtAd~H)64Kpm7xbnDS2L>h8F4BxKE~!P zne*qLbCzIN2h7~^;T3kcEEd=$Tz3MyqyZ;E_50djf@-0=oh0P7%ng~_UHio@|dfdpAd2l7F?QL-1?N!f<*tphK6a?@if& zpB5FBNU@Ms0f9U>k-}3K1=Y#94@v?^RUwHP! zc7Ch!?8+bM$cKAc_$X#;mP00se&FG=)FWUrnbCGm>g?_4b5wkpSs@x9MoP=&m0IU= z$4Xm?+gM-Y$oy-7){|=W+p$3%g{1n9EyO zbTvl=+8TVCzu~~a)B?pE5T9%1kbur{m+lSFxfeT>1MCJ;V=PWXoE~YpEFm1lR2io& zuD}>y;Bcuro$0uj$W76kI)GUzfNpd5SZ6;zo)jBCKCIcG;LBHd zE^?GaUVKx+d!_);=1B0@@%kgJeg&!DiX*!+^&3PcqUAkznJy8`JDh&{y z|2@Z@s7_!n;BJ>%{?DoH^XI>};eL?=AN#*cXaD+jKK|f=5h4K|>mJ6jLe3MWL83~B z+5^ysUGO5ohZOJjX{}D5UE?^T$0=gnMtTeI>3pL8&k ztIuDhxxI8|-uOv#WOR~3o8*B zVOee?)BX8R{vH3ejDO9)`==~@b%0;xSEZQHSM&!}Mt_x>h0fv`aFXeq;E~~H$TYlU zfLpTMW~OrSJ#hAPaI$W>#r=xC(|ETyd`WWCt#8A!$Y~DxVX307{a_#jK%1w zF%~v8^e56kMzYqm$5gq{(zvRzK^E!B=NEo<)!3?^ZD#rl;W0uDn_OJXzGZPW$I8Cu zKJZ}bh+IA9Je)PEy%z}-`O<&~;V`SmZ+D~PmfvEqMge&k1B0nW`PD;qLr(+RD1spa zcjyk-0w|-)NBEd`_F)7UhJqJ=%#r z(?B{=&RqDP!3P6=B>oZYg5v-`1S(~Tl#5MRBEX9h<<(^y$1S~lY;Ga%t#$EUyJwbO zUNY)W)+V$}8XVdq4fZeE4Hx5>_m?-3z6-fCm%fkg4RJf?l}Q=co5_$hsMmt;qBV;G z9)OmjjevB>m@VqwNmjojJkNtm&|X-~@?c}MX{<3rpW?JSG(jmEimLt28A^zmN$7D) zl{|=B$#l7I$^mZAO4Yw(9tRmII3W zHXrczs;&?6*W|7LEf(}g{%rL^KCP~9|0$tY%gW?OXj$dy$UmxH$b_1UJhG{pp)>`nOYa7K z>d0QK{q8#_sJzn857Spz@S)6YcK~?de_OuM}?`lEq{t+B6Q+B{XFv4 zFaZ|?r=j*_0NDeHK#CzrF#*0I&LY*b5qu(z%dByf}IvF!a?=U zl)Svnr#c)>9(DEJB{LJo^y@IQRYmKCU7yQtJBy*g>AkNF`pY#S^0_{<_{rz5?Z|&N zZ^xuKdt_vCyXfR}vpp$u$O~g;@E;%V)1STm?gJ|gOJ`Wjl0J1$dQAP%8|L*MF{sa^ zW6gXoNNG8b-{^X%ft4-e%dQ2Y(p@p8fm&&5S=7LBdw8g0+^|u^Q-|`I@)?~@0~T9j zt`w5WK_+$eWF1+;=mv2mp>ls@W)@nv2~0-yWW)E{8KFclPx;L3hjw+?>+3ZpF}?o5 z24e@c8q?(c%!zGRonZBcOzF{jhW4NtC>fSLqVurz#f!$%L>ooa>m8k(iCGS1jlY@N zsTb?BeZ&Am{^%HEO8V-g$kaZYm}S)9?#=5NHnSbQ>n1ka6K@tX92=Qw8mOOI*65cL znchGbnj7)&w?MmodUSIozvD>d zJLGGX??4ScdWUw>%_qa}fG$%jj~t&V)*<|qQZpeJX`YnR>B4}pXH`?BOa@nuwxDg> z4qjiEq)z>K{#T(>7ugloJa51DrwD?$wEv_6;^kJPd=JYE(tN%EY&x?#66=a!Nv!>*G+4-fbTjU3WeH^T*NhtM~zx6X%>yV>~GFDxAe!hU=vzU zM4Jbmij#)v?=U=a{FATP<0oaD&T-M-7Iun65Cc+>P}rWXMP?C>kAMNm)xWI_kNbYck|i^~k2Bl7G0|GxlBJHuB%9|Ak1-HEkN z)AYJy-Zu0rx?|RDa2zTpP3-z_vnDuO%~{Jc8tm*mU_jf#28aRGZ(84F(l>an(}4b+ zpHnY*W30xr4f*Z4t5(fq+J<_gHOAYNF6tXHX$~&(TQx539yRmGo@JxWCa1^aG?_=v zEH0fkl0Ko8hiT)gtv9~iwbEp=TTJxXv~uf@-|Sjd^%-YmHgXJZ>SsFAT;#D#SE6;B z@ULEp(luu3`1xkgz)q@v1T-bK{EJu1oYt2~J7q$?*4Y)3B zBkgC7G+c*`DgTa@C0<6DS>hwHz=WbcM2xku*Qa&F!QoeN=}@DXwkVrI)`!Km)4Jb< z64)%8XL}>@b!qX#k!&`og-X|!1Mkl{0kNf{H9LS@AUf$#GopE zzkv#k_IOA9lK6G;JK|BHky0u|ZDFE{+J!nH6{OAl*5koVPcdEp-o3l`=-H#!D`WBB zE5Dz8>e-vjwQZZzh018&i0L!Vm&}+RI!@)_QP1l3^KzNINAOF1Iw}RGhdaZhH;Y7f z7`bfRM-x99_tC=r3-LF7H*x<&$+>^wtLhc}P2asb?p5^P`B=GjyPa;HK*c43GOLfW zP&R}*ktom{l_ytVUFkMn!m~_fx5pRNJj&;Bo8b2#%0clUuQpprO-WApt8CxqPsX$KA7L_m2AJY&GoZ?| zcP;wq!y=cnne#P-tklYky=0f!&2*`vZ~fc-M!%!R=juko3-J8Z?ZcsNR=J?D(|?p zIeZ7Lzv0h8q2toqh6czF0b~T0T`a8dIz*|Ub2qgoOqU^_)0?G6YFVUSo1ThN!`g@j zECPjK(eymqon=PV13B3}`KgDe4lB4dNBpCWe`+2ZFpPh3vwQGiUNDsTb)#OQ>R*4p zjh1CBpo~QGvOX8-uOUz2hG8sL`|48({&R5Nl%e4#?UkY~?OxjF68$B8TJsU$ zcT~r#0{DTn2xLA23nOxXas4e^Z?5y;IwDh0E4FBMApS3rr6Y3R{@?kED!bX$@D;I* z)xM&=d&~B+tN#l}kp%kHC>^!i5!a0amqu(x<8pfAbQZrq${QVjho8vmjVp-qM{5f# z(Yk^Npw24YL^a0&&y|Xp1b-GDd~8#GoAyg6pqAgRP3TWxb{?KNGY?5b&pcDSjddSU zw;|uuu%7fOFYDij7xn2wF8nt9?X@JI5#><+37s3BHJmT7LnPLMxzal#Jg5;6Mya5A zmePOCqz#KcfLeX#){^|sEo{r+NF#_K3x`NUePl;VXc3}T3eB~>tU9lQ9-I}zQ(RIS&T^E zW$0Ej@Oie|kZu9F3&_uPxA0hS*)-&{n*`i!#wWfKmLdkiET)|D%vwXbt&z zg>X(jhli!m^4KB?=r+-U>NhL0Zl* zb`EMVf#=x9GMW@1a?>9Yz`5ql7A#ObV1UTYnQ;Sx0?4^;-2`+_><4UqGv*pgV{!XX z@*8788F*+vHOAsDa2;cs0zK0e$fYbi7D9@J$3mKP1eF*HXOm+vu*TSoV&u&2y2N+Q(FT@Wb9kwffX#+>hX$6fQ$#?LEG{7)Ha-vId*b7xi>>6v_% z0(=YVGtO&4=*}03Y;pZjK1)8METHS}(Die4UC_fD+CzeOgzGJ0=HWS`=AwW_upf4u z>{tsJfv%QS^TRWc{~>U=IHm-vfCVg`L3651pPKVTar0UURNsm5izF&_9I$~2^WhTD zXa+`t+K&PW?8IZvmhBtI-m1cAjN1nsLn!V5>vw~l3*$6W*(|g_70;^75eq*HiV%&7 zP{r9|NTcp&?J9G+?jI$Rx<-F8o8@wm*Tqj>8jaL0%nLF}j0tu*I>bSpqI#4nWQ5rE z*|NQR)fK7)j_d{h{A?Y6q9%Amxqlr!3sMj2#(eJzlZVMH>uU03)+1gomXzs+w0I~o74J8A1 zRW;?rOzH93^X2#436;?jPM|Kd4)#Ee38UG*0SCyyte>1+SWlXFqHLtmX9JyH{ zf3tG^taYsW_SVpVDX>A&7|p z_w~jHd!fD1@NjCIpmInWs!n>X?Ce<;Uqfh56?R9=kKXqd@}mM+54)yGAlfQ&=X3=| zv)!3%L0VgZNef_{Mx_2wfHs^%M=z|-qN{qC`Jq*i=D4%Ax;wFvg+KR zIJyLFGzdiLf{ICuSXLiW?nrbw7*iP zL-PUs{Y&g`J@gYOP|RXVMl0GRBScDb5pMu7hTniX9^rhzsyEO)h(T9Rq_CnZMVH0? zj5o~09AXh4wZ+^0?q~p;41{bVyBN_3)TARpXpaq=_DM3pPdazdqeHX;FM_OsX)J_; zn9JQnl?sIduJ!M-NM3ob#<KHg6EthrZ% z^pezua(2@;N>*kZT*5X9_(V!l676mqO6inDn35)CH+8jPxF|<>;w1Wc8~jp3WE|V@ zOL3A?uf>CXGTn7MjLz@dW8vuB1`*M1C-qL7(5lV-Sq-n$e_gQkFZQsTob7V^6Hfc>dXC=Dy8SVP*Z?dZJ#N>95Et@$oGqc~c z`HNfjJ#?_JYjlJ=dT*r5;7N{2YdZ5?7Q1%`bDUdf+v6R-<@|z$*Y=F@J=Ajf6YD!R z8b5Y$`;2;>hK?GUHs-}Arhv{>pVVAso~AANq})y0NHu38mH_jLlhjoGtW5Rilu>Py zlam@sS}|cHPug(H^loe4TR!};p$#%eJvJzPfIp>eqnM0dGw*9RtyhC#Ba=JC#Wbi> zH_DmXpm}PurS0Q#yL5_QacO;bc|cNwXtOsl!xddW(Jf^x`)KPR`59gAjLn0_?3mHU z>`Z-N?$W^UXY=lDF=4~tXMP^xHYp~zeVYm8t^M^~F)m}jr#~o88!>Kdy>1iR#iwuIP%!&x(13ru0yRAH4xsQzFe>p>myIW6kvV; zr40eC!9qEH6-Xw;ISd%lEX+u~>a>l@;XOi8_ApaH&DKQe!?S14g>EQ6hHey+Y^S;g zf}ga8Y^NHrW=%%GWJRj4g8XJY`07#v%bJkswuepb6+klrnFgP&pu6jNbgf8cHRjPSzOE>k)s9j!WH&O#QkQ8ANAxGqqCbR^;i2 zwkl@eMh9Q2=+Y9!gV8deoZ4mh^iCX0RAEF;F9N|jJ$2p_U|Gn%zZEJ;qHaP$XOT{# zLl5E*=+xul9ayQ-Lm&=Wmw3Of%jQCZ2q4z`hS;}Ib%XIwaasDH7hKB*q^ua-eM~@Z` z3J*m*L&e`i*HZUS1w|8%K{+?=q=ygVgFluccq0`)$rHqOO7laH%CS;$=(1EV1WSf$ z!ha?5{_pl2!*uAKNBPk!>=i!a3ai8FT;Y?&_OW8#S?UUu$aJx0gHZcDyK zJzN4=S$VoDbB_hSQh5c(3<%5V520WKAeQRpoQAYv&G;1nEyvM2pTgcix+7yZ7w?Qj zNmhdr0aU!V<~vRL0++{9dG16Cw6;i(oI_WUN2EaOT~#U2HO5j|2NTP#XfXAfnb2a3 zB_q(x*dU$wn?5`bQ8!zuLh$QWL((boUu-AbZFrGLO z9$RDatje*e*b9SSXVLiWs@^7&iUiixp0Bq7MkjOvWaWg@%1F;)^QfGQS~&xH?A97p zGr(72Gm#xJPSjKChWAP6C;x@s17Cd-G~6x$XL5?sp5ilP8GTVGW2%X&=eP=ujmiU@ z5Zox>r4j;`xF|zVld{he^kf8;^`15LD6Lpc^C!)qaU}rJod|d&iE6l($)PXnsum} z%MUTrp7-DX2Y-bB#@`t=^26Mel=E-1{_KItpLTDvC9;b9$!h4#`9WTWGN@DX+*RA^59et8=eXDH#{TgUe+iUmBp||jal`kQ*exQwOE#j z@DT;qs#c<^a2Ff2Zt$qBjazh$p1DDD`}1XwR2;O7f8fZZabw3!7(3;D{_EB! zzALv3A7+!3K0{v0ZL%pb?c~y(>o?pS^7^>3(a}x!*Y|k0KFRVo4H+_UAUV3RuY85r zS3On8VBxjayD%QO7HVz_8EYxEc1BuVwc0=5b#ES;bC8F2RBn#^kXZ3I{`bb^ql->IRCG!}G(z_Z_gF0m5)Gmf5pSMN~x z=~>bU57Tz8b`aHH%`1@gn)!0_>o9K@q#As3LP2E&Oev{1Qe^) zo~R4qfvsty8b@Bm)Et!sv`U0(_2C3U88q7*iWD^LGwSjc;Adb0!a_-f5T;cpkzD25 zQ>LS81lhOme1T$E&6`b-MyeS@VCx%IhaRm5{Q6?e(Ksq#MWJUyWUdK_7HzI5*F##U za9!F_5U#*r)Rih|`v7K%w<2w_>aEpYJoy5QA+mKVop&B7N=+1G=Wnf19e4Cz#2JJw z51oqkq3TJrj;fg_Y;&xCbuwP%x>GEI?DD()u4;`5V;gH9PJ0&SHdY?*g-0S+Lw?n0$jaPDlO6k9_l zpb|;!dzJ1;H_!;(pi{saVQ>Kr6`4zTD4`rwzSk5+OBHxr;x&9MA3cFr|3)9|< z0oB4t6&F9vrd8_&l*h~th0pN--8VP~&M@sF*+=!-!EKbNizmWo^};p$DogsIWEzN9 z8(#rc;3fhW6$bgwFb$!``lzaB;T%*yOWRo-f`bB~c#!D?U{ML5gD_4}#Vrci4If1~ z=f9`;j6K#)&~G3H;cce*MdVYvI zPvB0&p(OOp#+~@N`Yfu6hi8bIc%`Us<2htxbea|e&e)Ot9 z&CK4_zeDelV#H_hbF~kOHi3A%f>;IKuRdG!0_q2ARCx$brt29(7Kom|y54`21rFG+ zlNcl~>{rMF+)p*yVS+ixkz5yp5Q7WWO}-IYd! zN0j=B&zK?V4>iGirfYs@t?-*KiR+}#J*@p*T;Fi}Hm;Y~xL=HyDizhfAGsbFuV#Z7 zuX?|z#iOVFKdA1%HeKw$93O3@{SUGyrn<3Wjh`3+au2{P?&GZqpav#>ZUtPPZI&pZuim4FKA3@Kreg9ReD_3Yo;|C*jK1vT0HJ3gt|3#dcIC4u>c$8V zA9j5lRuD40%d@Cj!>(djaD`}21*ZqCH)v9qD`@78@V*@p`v#iSJ|k!Y<}_--OoIEA z-rWiEl;Vs&M4YWYTZ|fCj8GWi62cKi;eN4sP~4$95E+gLBDuSqiu+`%PF?sKprceu z*PQIyF-SJCQ=d2Zw-dWp2P3aPd1lmohQw$?G>SQZ-u#z!(8!vqa;#&@B-@X zm0kG)WgH*_lVjTVKJnHGU(alQtfr#`66jMNnbzX`=)A46>7mVlcT_n{#9AT_B=j@L zOE(3|Q124(20WW#ukyoAn;vW?pe*lP5zZVmU0B0VXHEES=Bx{KAZLzLx(<({@e)r{ zWhS0>#{=0BUJ&-*6rz{IXKc|G)vvRde=0o*ga+I=yy?17h4AYr>tGA5$MYy2NHvJk z0;Whs>p_P!pF>qIgi>SF1wANCqzzg`Uvr?;VXuL{kow5*Hx;A7M>Zb06|4gf;f=cA1)Hw*IL<s;dE~iE7k_n+1}$L;g-IPS26~ zhq?_&wAivHjhJ#Hf2CNZvu&GBo7k#t*^~(%UK!s+I@`Vj|E|}_hZa7|KZ*7KAI{zb zFsdqxAAa|h>61)LpOi_brjZ5#hLX@jhY(tT0HTN#QKSbDR6uHgwGk1)pn`^g6AUOt z1;LKGy0N>syRxnYT^BPi-|yTvlLXZN_y0bTlF7?`r{8nWJ*6TqtLpyOiE_VP-7*o4 zWgZsy`pZ9GwPXpdn}84Y0v+|FumYa~Z)kQ&s-Z)OHO3I9IKqpwG^_y?(QAo3rg)05M@kN4J{le%Q}n>^*dXJ*ahr1$kI zy7iW#UcSm(-h8hzUKG1_oHD6<;qBcXQGc16nKiBAz#-y=f7;#=!-tQ06zwW~R~Ic= zf-GOi_XY4qLd+!}9g{)}ySh8;%uz9&g{UNluE2&8JnGm8sKFa&yi%=8tIl>j?mQe? z9kH!T_ND^c*Rb-$9t`5;-Lir?0z8jCkW$CfWWX+j9a`}v3^o3NPlqN=e)90~>fysj zj@mQ&)WSuTGbdbGzka}gwcAFGY|p1mw};iO8$9GdkD~dDdiF|AtxvGoZkbcJeC#++ z{PgKtSKq*^f)Uez-_zh#3HI__npK$J)zR7P0D6ujohuLVOu`S)bM##6o%e+{MEHs8uby)P{CjQwbXG8{AZJhKE+yWsU9DE?B~vsiEB=fBB)T1!l>IUJBL@w+Rik$vbOs3$$X~!rg(TbsnZn#cxZC4S)Y?^EZYJPE z!mB-1iAuF?le;>`lxVv|eJi!Q)8E@F%*gT2Eb8< zNIsMpf!}P6tk$sFXm?~|1OaV~$RG{n7x@@Xd^5y7`E3%#TjcxNL#stT{s7cV!3c=P zXF4m~550;JkaZm^+mJx)a+_>a1m1*h_Zp9N(YESPN40gEZj+m0vD{u_^Mw5IFf$b< zXx+o@HYzu==P37AcDaA~ZuQ}FFTeB(X4$2Efl^2R-^7#;m%YwTe7>sC6Zh^V@$EO> zeelDV{CoX1JNL8iIgRKHQi2$=22Zih;c!_ULNUQZ^CJl!TSKH%-=H&M1bAe7c$@@A zu)dUUqLjbv;t(#_zKfaPK5^>Y$?4_g(@%csyYP3lx%xpdgM~c$_`E~QmoHS8FI>)g zoqFZ!HwPZ0J1L4~L;j->n?Y8dIVRGJUf*6>ueah@qYqi$qlxcuC1iw{=?%+ZZNyc#FZQjoICad zj%EC8kDvp-4)iR;iEI$(8A{Z7U)xB~%5066oo>Agjcua>jcqT1R90)XTt_j9JGcC0~$EylkRAB`^HzpdauvV=M8T&pZGXwbKa$zuap{Y8{k0G=FuEZt@b`l)d$}J?E;%AtWb}CJ-g|gAS~WowG_M?2tTldL zTQgtnX0`d(z)fpN5JQe50xoqNN1Q2I7e<%E00kqAO#dhj6^8=e`B6;K%Pd2vmp2Dv zERA)bbA|u3cKyoMa`R%v-|xr+x5*i>aE{!yb%4;H-blD$Osa0g6%H(kv4F= zWe%Hm1i7!Z=cW7)zgv98-$VSRxfia#?#f4B%mVfN_CW7Tq@*75e|3l&V9JNo>*$M# zSE0`APT2Xofnz+fzB52Ytr>}yK!Z!Uv?P$PD|!XP3r3xpfEpy~S(3u9MCo65<4Wp{ z7jAuR`i!?RHs;YiGCJ72s;wkkFdl-JT^|bz@oGJ>vx2emL8&j)rZPUK<_3!hmaHSCFg{|2Hy#@M`MyIh5 zLkCxMq9I zM`VI*h*dn4v6oC>HUW%)7}y=P_SjmTho|<%+fV9}aFIYAWHeC-WkAi2ut z(_R=z?9f^SGNBIsXASfrfpRRI4u{cgDge9spe1Y_g~l-q>GIX1kyfLL#*$~@!mK(% zL9bzxQ035iXE$9vZZ?PsvY^-<7={3fkb_4K6poJQuM>+39ICv4k)$Fxd)>vuXU`nI zXzaZ6Tpmt@VIII3%Pbu~){UWhO& z9h4t&mpKHp>YZ_s4wE~=SP+K}wtdhROoNr=i&}I7%!t@(M@Y4@&0!RTjC1GeZH@|u zI2j7uj10u%@d;ZJ_9jS^alc1ypI}Gg1yc7Db+~m8LX5sDbz8TwDEvykc=*iO!(v(W zOMuw_l(e5ES68basUH<45X6sa!1_;PZvdRSbAU4n7N)<~Zeo-fiDtnC15t%&Yg~2sHY+u|MeYtliJ5i7)2M?)I}#Ez5irT^CJ@XLRU1&B zGelIB4g)xF11_o^FYKMi(pdz4c{tp;C^(2B3 zJ}rt_Fs)5++H*2_1qPQe)H-0mvKCz8`7@fh)m;SJrjo$|pWz4P^=ZI^Bio zU_4U;!oy#m-YU=WEt7+n3C+c7d(iH$iZ6FCJvJ;Uh*2 zSHH)fN4|JF&EECC4c}g2;jbS0dfa67E%m=a*f6+w=;X=!9-lmA%H+rQP3Ckka5_Xm z%EBT;1((BFVAiCqyI@6+^k_0<*XmZI_LNitJ~dYi)R$C;C_;5eqooSzEMI?p^%AKB zwR6@K6;#AYtnDjIAG=qR`{#(1ng$%v_=90&8?}FF^3y^v{fJx!*j1<75$TBFN=iB! z8`M##s7(XKNcw4vK(~1+nuX|)V#aNW+Z*=>iW$}pCQ?fh@AQj@&z*fH08~IJKT+Q& zrTpOE{^S5;nod3lxVn%}z>+BbuSZf5CS=2V!C$;s9lE6*0a26Q##9e=-v~r3yD8o6 zv*+yDe)}4c4JsYN(!)EBKXVrH#KqRRdy*%Gvo=?K`^CQ$b}!ED-c@=&;j@K{Or|lj zPVN{wa#Z%Mx6b*#d9em+^~8Ogy|;GG+Aya}myzBb7@gf}KeU;dfGJ=#gYm|8uytU8 zB70teugo8?ZL9is_1}B8&f9x|eQX-xNx#Kyg()0MT3DW%_>-zcfqinl6 zFDPOw23CJQhu{M%TkS2?p>+3}jBY~#vxAGyAQzD-k>xd5t7V^1Wxz&o4hP4~I*bR0 zX#f{pTU>ix64eLrW{^Sailno;i#6|{xhhz9=JazHAwWGURq$*`_V@3-^P~T#pd88L zpyO7mhcb(T-l6L*xGg+i9}=z8Bs$Bh(~B4s1hWGn&h#pop(8>?YPr)+dhPAR7gH8K z4$5udJzpuvy~Q~ldu1?U&9^PM^J%G+!a`{v((;s?B~=|$E-om0_tnY;>ZOYp;jn+G z{=L`u@k2I<&-wG;Uon09d^U&eXdX@~L1&OY@Sp#pdjqzE(oD4$2ekXy@{=HXt=Wfd zl9rSLZU&l3P(OaIE0qwNPGYM6Co+_`{J4k93DxxX!gfS@na#p^V{6NM@&(x1G~{>nhPCA!$n6Gk|DD-|O6VzsLBU z(`$BH9AUCK6wzH5OmJ||q%AWJTP7N6w3*@?H%!4E+~?Kr$n*s^Oy&vL=)sG~`1Sf{5}giEEt+^~evoekQ{QT|y{E|&&7`$%Iv?VOgnx{9gQQj*^? zGCz}Vs3aWUY~Kolvgdo4joCjwjxF?v>* zt(~wTT+&W%lnyXs+#!VE(RR%o0r62%{bp{w;1Npu;Vja24RaVYl8qNN3;K`pc{ix5C z9p}_tKJ)7k_D-zpc4_=T_4%Lw@y##$N{2nn20gTQ&7BjbO&q)hNy9(X6YnR%hn~mn zh}UaDpIT#q;I>CN!ZCai&NGrj;g8DI)=h4EwGdwA7BF&$0?fxvdS;WuWpbPAkhx@g zIfEiz*q6VI&k*%TFm(AgxMS*D_f=OP`GBQXe*So$O{Y$sdgSrP#%k{i_~{NIAC(p$ z1#SMV+Xn3#7G_5WY=Lk7*!eNpgQlvsZ5lzJ9H<8zT<(X%F%0;#ft?=m-8_jT{yl7| z0bKiX|05o_l0!!Be5qo7xz^LP$`9T#PUzz(kk`U)laDZA|x(t9?{OsdoC{!jf-czq)wzK99&n{5@mNpbY=D031p#?51nrJT+v0dI zJ>bq^XK&|BCCO86-0lMI(@5I(wz3Y-@6k3r(R%&kR)d3h6Xk5R&I#3M#bwZeI*C7) ze_c@W10HX{R|<-K>rpg}i+#Y)#p&oq2Uin%Q3%?*Omr53pFvl*dL0}M&FX0)!h2OF zCP85GAuhZb5ydO;;0+!mgh`IuK5FE>>->Y)t>Xr9^ytx}e*SW1yfSOHlr(C4)xg0I z?|}E_+VSw9LF$P5X)^{5{`-|dgJ(>W#wX60apdPa(Y}Dp=fLN0!-5~^+BR;@K}$C zk=N|N7}Dwxp9xd7G=~$RxH|Moh09sDDx40Rt^JZS8Xw~87a+=F5#HnBdv#!T+nm$CjmCywjYkKn&?E}j&WOOVRRGv@69 za{*M+0>=i0U?hwvrjVA4FCr*ao_hq@VPeCA0aN<*QyU9&J4F|zG9~lN+vaZHrhaql zlDk(gyQ{eGsfja(OnmYiai{-RbGQC0=k@A|LX362L~qKr89DKNOr36@d;FvM^CKfO z-Y!mZnZ(YW$5%Z4;k1Rw00X>>rT?%E=zpRUt2Et}RQ4goZAF+I=+PAU2dP$f2A&~K zY)B8vd0)KiefbCW4!*Yp-&?Owq5N1bz)74tpmq+4bj!q1efQjQ>oM&w<&81@`>(lm zuJ$LE#=9SrzZX}a{~J0VU(??8cd1dIPqzh5tmU9`hcK5X(Vm0Gi`>SN1~osHumFIJ z%@0x4-}X$KWK4WRyi^z^|M1>umeAZM_jAl?n&eL1B-WJz#&W<|2N-o&6EQK#6IOoc z&YJZK5^-9HHUA>%w8OU4t`r0{^!2tgHim11u=nNOsWJ=fz-m1VW zmY!L@y!sjO2Y+ZoL*Ju|Pru5}H0^!t)P6PZ2<~J|hi6v)=O15k{l&e2Qjhx!Gd!On zZ%ATXbO_2d-2*`8Vj6cv@we=z%UNEB)DU7fHbh7G?3?0n!4}i#5o`#H5KOjLztd)q z@CzgiA4v*M9}(cBN1$U3Wvyi#+`j#(r?ziDD0T96e}4JJ7NOaEjK5BtO){UN=2E#EU{oX^+q`NgLzE7=LTTpfByH6!b3 z>h#B-^xyT&tQkv|kPRjtW`H&hM170A)&zLVQ3l5Vr^8fClOS+Y%sJ=`Z;nz)H`e56c(t#bMM>Z10XYkoh-QuWt;H}TE?R)C`rGw|)nC+|SavK$qtK4WiThoK!Sl3djrcGMC}p-ive${11~g;Ru6@oeYDL zxk{~igIOy$38Xgt|buxUDX?W$MjV6|bMRAl%z7u5+e!%rRyd_+@& zCScb|C-7X}2k`$|CnIDCmmbSNqgg z@0&jS;P!`xjrOTmhgAR4vTDWuSds62>G;xV&s_ZGwndlO2DP7h4=nSfLhf1tU@C=2LqT}2rAPB+*OZHmT?wga|* zk|qwneWE|*e+;%3??vs9_#yT%MM&`K^$fz#hxhT3hz7Y)hkE#vI@`6cZC@iXlq8Ma z!>0KE<%44BOd8y}^?*AHm82mSy}?w9LX;?%A-seKu<7`mjj)Nl!4m4M6%37`n<96I zoitJ8nr1`U&RspGXAa3CaN(}=qDd=oX}y8cEDv@*zKz(WoiK*aYNqGBy1StPfxKyZ z_nz7>F8i$pcIW$VSo8H7{V8>5fZxEth1f}^Fv)AqPOvzV!R^jGca)^O-r{L@ z1z9^vGZ+gU$F`~$4twt1@a2D3ty;CmfgCFKa~kR0>a zA@z9g`wwj1!r0^cnBm*QJf3$L8wBkGPQ-oPT#ig6N1NDgQ={dii=?QOb^($kVhw3+ zyX`ydt+2or(8dC8d13q8k)DkHZ_jFk|KBg-I8Yvb*$L!ax34p%JgRcQV#ZznOs~nI zGuW_yM-^i(#MNuf*b&klX=xo(QXC!Q962a^M;a`grHrdM6u7z9Wb0a+U~F*vu*W;Y zH>K^S8%x>}z&ku-q=z!S#)`bvc{O>T=gE*94Qg&&=rDzYJm0!7ZwxzrE^aZgi-9*e z+{5p|_>rK^0bu`}*MF<#12EzB@vPrnz2f6Mz7&H!dPjbT*j8tN-4;9IDfMsu_n&HY z35tvIVq@nI$Q_Xxq7Uut8IrH*2JUjn*7xvQA_U10a1D4VA<18xXMmxd;z9<{ z-ZNm(x|^&e482mQE^6l(Kpk)L3!0Hn0b3vR3u1A5GTmzt(+w`6G{F#JD(Q+MW^VJ2 z+pJxp5zrwGd?CtUi!)elRzBjIJ!j2;hn2EH(rsdKA+=GVjVx@vi?+dlUXb^2%wtNI zLM5)iFhc=f0U^qK#3%FelX;*QH^~vRy>jW&kLT}UG0$%P zq*vcL&#f8m-}6APKKE2V8$DyZnBf1MJc?ys5BlfphgMe{PCb&mE~Vh?U0YuL``~@U zhM(Hso%lz z*u)x>TP2I5K|WAG0RU$P!%dT>&s@*r`8hp+X+SX~$uz7hlY16zym~b~EYe=#l=a+0 zI?qms2Q(wac00opA{yssR(0)i#AuF)@Ay+jM7pba9a%2)65;cEsQ!!nkK>aKd`N$i zkW(F+f@x=#Qppe=;}IM&$u`P=Y$6qg6h)ZiFe%jHsZH2z4X>3fjaL1JP{$^^j3#Y? znMII}yiBJH9S_|8oz z{1MQ;20eDGA?qIU^pc8g4kccUaG?GHc_Y|YFBe_?8X*9re4k8=a5cpE63Mz=23InV zd+dVU8bb3Iu3lB3m^rYQ8bFLk$motd35iPD`JJr~$zb34&yMt_C9^mBC3)xeSkUm| zk;{wv7r*QbOW0T3X+UnC_-tkQgv<$3W;}8E>6zPiQ2ut%KJmK4k(|CIfVl_uz7(Mh z`7Vy6BqcgcF-ONa!bFD|=|r$HpfR-u$iM~>l4Mh2kiOfPN?4={fSr>SgG7&~1W=HH z!f~hFVNdWR=;@1_@yXAFFa=4S8s>s1;RMgpLvjeG@!f$_NjwuLRu2u&{$SC}io6GB zcRFtO0IiH(eKOdy=|#meo)|qdJ$va9*1cN<+DebegmNbMYa312RlXL;aw<|C_Xd&C;7Sa}9-=h;wzY1Ss>DY0wkCms-md+~_510ROp{teu&_ zR`5BHr-<0}V9w{$NV43^{pQ%;`OP}HQNlSk1A>Oc49#iAwQHj9$PxSm_9^J98#0n2 z-1dLskF!00VjJ0R7x~RNWc~le_lF$1Yr;(&k~8?J;U57OO*;77CtT#d zY2}e92=G5&g6u`&=6tNzmRf9fMmfv_;=^T!0ms&iCTs?X99=zUgYgMZY_Ny88x(^t zWK)VOveqGnpOhL?aN^R+ExEII?z=i6JdzAgcq9x@W*9XZ=ByKfV`D*Mq$tpEO-iSt zxY+wVOBalzlwI+k{)h&t6P+XJ_w`-!xxhhD{Z(z8R;gaw_1tq(hqkx?@f*Ht+dN-M zSPHy$={n+GvWt+1Q?tDw$Kg&0?`jZ|OdTCcNO3;xb0}%WEHD%;z-v<0%c%{H-T4{D z4RV68De+`Jd~F`;BRhNbXhagq0+Ewf7m`GOACJ!IYLXM+wNM-_A}KPmGj_=sj4(eCHO1YeknoxH~L!A4UCqUKrT^QPBSJ?I(WR@*aP;yIz(QW~9!^c=2(aD99p> zV{U31)IC$dYpM6D*nb!P>$0m7F=WWu(`r9yP0M?>G$lkpHw3$0aj9R!!Z`Z@iyBr&_!ShFSO>3Qvy^uva6+qy@t_J<6B1B zQWeJv^q5c_YXu>cl1C9kY5+CRGA|1-7R6=SKP* zu{$IG3gqHX8D%_$TR$e2V#EGgTo!~&0zZRr5%I**UAx3(gaYS%P)9W0x2F}ZFNnZh z)cO2bp;CHPTqWO%bp@JPUP&YIT z8_))qw^FNPqHMc#DYM?Ij8G`jf%m_2;)IfZ-NxUqL@9!Dr0pH;=}mYkQ5wYw9^n-T z+{8bA7QK;^UeO*Eg?I4qM(q4#pOTInMYLK#tM|+3xd%?xORQ1RqrQ%SGLA5EpfoE5 zz)qZyD_-|^(|S!&fq4_wu?n%rLlv|xu%Z?5)ytQ#%5jSFo2aB5!D*+B$DXhkQXqfU z8((eTxqcpN#E_yXEacjjU1!wrEu5avp%9e0k_Z$v zlv)f9el>KCVv|>4i_Cppc7q}djz$X_$X+YL&PHvUT`t9`!!NtR?r`WGdc7TA@rIU0 zYfD;UB0>jtm{YWoSv1wLw&D(#3m1zEmzd3 zKQ$z(-NiBXb(g&Q}56xx60mh6}|$>^S=!Lo&X4Vg>bk%%$X#C2x7>*^_#XgUE2QIMD^>B*hO*5r_}^Qk^fURT76bb zBsd7iTL6b%NIs@h&~X&Dg*OX1CP;vRdd_EOGOrRUhbrRaEOLf{U6}OP3ICn4O?sy} z1Jf7?CG4p@mWQ<@P^=p&hcPua6wwD}rvA=|8xenxizdulm+91i6lAa2X7}1h*emSw z?KCh48?BZB#7Svqi_nnlhXznmV%NWVLwvx0SCEhdJKo3c0iVMyL@q$N8A9*3_sclp!Zr zIg|rM0z=fy4!6sdCxGM0296{or5PQ4z$m^pd`g8vP?=ePNRsZ`x z1jGNO`d>c(?JMtYK}Fp6$Uy&?#j_0lZuUWdzOgsb_b3w^6&tLNMq#ilhk?TE1MvY) zWB9!yr*Y>OtR<+hDb-sLdqU`dY>vKBIBBJ;I?%!#uaDQ+tfBf)oie#S=Vg&7A`?Nd zSdykZd~L`pt!>BMgV9;6I6_K|0&bf?Taqr^hcz-9$b{u{DD}^-$OaE8(rT+xix5F?NjBgF%7j6E{iq zfrPP9w>yNtg>@6CmKisD7(fn5VJaKr*S#pJ>N78~kR8l6@fES3I#hjTsrrw(#M3rC z(ZMQrAc-*=lu|3iw^d?}TS*cFcmzZSZy@V}rm-YBCx|qDo0tbOo#N8s-?xSR>kRxR zuG5c!Mv=%dFh`e!8yps+ONT+_*De(XdS6(Ch7ey^t;J|+)HzUvRai(2d9E)R8w~t5 z8I5MU$z+tV`%|79w=u9ZWN+9}ky((ySXelLGBNa+u|sw?0>L(b2gL<^qWZ=7@nHi` zl(;Kj{b<@lpTF{k|4p{!0qLEC2Y0A8_Wk)9W>~!%BJSV!Aba~FoLDYzXpN@nbKH&c zR?kk7z4PWt1;A<69UI>L9Fv)1~cNywIydq0#sWoZ5(v+{&QgU!b z*Sz&Rw}Y4uu*RTu0WHC&GQ?8Tv95({pD79vN?n-2!Xl}eKVKbX!wp8kiQybZZOVH# zv=8?O9+c`p<#5r*AcA}bjV+udzApNhk%g+?s{UVpVc$J@;^lu{{SXEP>775Q^=b=q zvrM)BF=l9fQk|;4y&1TbwhWj42^hk0GB!n)=+Py@80LtuojZ5Au#h9zS8(aW8Xf3l zh^Qj*FVYfXMT3387HYRUTn+)#;2hW#5HrMvLDOnw+rRCF^cyTpp$st;3&LW6m-GvT zx!5&78#iEaqWeVW?ic1i`R0AwhJJcxZA`bZ53gVy|BEc+?~i;tzgJdI&-01VGOBXO z20~4#cTgC5FIpmC1H($;9^3eh^rdD36fLQ0ExKAe)IWmM|FUKbBM=AT(I50^LT}wL zp0m=}vjICviv=Ixw;k`FYqm+unYHt!4u2$kY#81a&p*_SJ`y^vRdYCJnuN z@q(YwiJqACz54lsFMNCDMGYF@-w$!&`G6w?wK*0WG}(wFUAwhQ1g&2&67GlU(ufoNE0~Jo5fQvev zkSpLx%FlD~ zxaA*b#@(fU+12lpy9MpHw)b?v-b0t*wD)i^sONhRw)dMi9*-t}FRych(w*O;WAJsb`2)5L!h=5OPGG?8rX0=QxmzY)7$J zex8(r>0ce#i3Vor9@8LZ&QsU0p^v;aZLQd_?h|#4dKQ%ZL3(~PGpMi6{f((_bjsg* znKk?W-K1^-uU+6Z^>~dCI(aQoKr+IqGuWM$NZUCWrhu#&b@o~(;Na0~a^eD5+5;^E zkOl@jMHt^l82|FbvC94nhc=2U;b*}G@xSuH%Uh-$5POivh_fPmEeW$$aW?G0;LYRA z*n!6)e*ZZ-Gt%?ygTV7$0?*@fzFb%&Xu!|t`{Ni)*Ddseh}!TUh2ct)4$_aG46ebJ^L2!l z59KC(BI2iX6s07{Bub>t!M}(jJav|5Z&E%X0y(gRDMqH~(*RFWuK0YY$+a*de)_Vw zC~It2MP6VGiA^;c7DRTLHYO~=6YKv4ld1$36SYD;-PeD3kuE$d`_`84mhF4PTbv~8 zliib7SdnrO8M)wTPf?;`*+Ci;!a`@miTww z2&KNm6jN+!k}DxboYXPd+cmKRvpOT^xop;wUXzCm>=@#R_9TrNnDpokz=Dsma4+;> zsp8`2Q!|VQb?;50-*n+98C_4WQO_4VS;8vm4<>-bM`;g72bJmBZ`MeTmx z*|tLaRdn}htNebY*0q>`{)eK#XjRlTVe+5E4!?&9etaq)eXCjaON#CX1azqCi|0au z_j+9fImggW@Lx-cWpCt{hUdny0o@{x%pW-``Ig=#eY|b4?07edjv*=9+`%Lb0t5`D6b^>J3!;Yf{0`{RbEtWe5bG9F5WvYt z+GAQ*mJ#TzfE2?p-d6$pQ9O&oIaX}EsMF~TX&GhZ13&Z4K0RgH(cyE~<`kBf7r=wx zv8-EBSX6GtxN-Ln-Fv2>u(4msya`!Tawm*iGxH(n+Y`cADNgznF=!#5T5bfh!Fg_T z7>EEe;CekET~B0;?%(afoZPUu*)yikE3Yic$*N%I3%d{OUjD{6W1rJSxjd0WhmYwq z~6WEWrs)e0Ju5g;NtOZ+K@Ofd4`jhf<;Q4F(`8&8> z!QBe=yaiop4p-7?pHJud-&K4IYpqfD>An>oMLY{-dgvRvLMl}E;q#3xuSzv2noU*E zy%nFY6s}9_==qkbx^Ja~*5_A>jp75r&-wG(I;#SoKdM@kbP4@C6`ZE|`iPEz_JPl- z7q>GRsp(-T5vCML3~>+R^;T4hlTSYMqs(=dC7)A2{_yj`tJsj!mv>!Pr_`>!Tyg)* zy(@2#(t77TbnvkH+lGq$cllJ@7#*{VQ5NmSPa& zj)J6-jSCt)%KxS`G~5g1WU~#=BpHhOKKs>zzM~RGsMou8nKgUS7|-sk`7s?!@2uKB zarvG(Glrb$pilL6#Jl*K{9WZ5uB@2e#rZg0Oy&KH=}kFwM=dI{Cl@=O_=G9fmu={Z zs?V?0Q!Ml1$B%U%xbnWc){W|=?t6H*Z#9mMkR6hR>C$oFflPd&qqsmy03K^pi!oaK zPOA|liA_pPOGZvqj*f0INS~2Fg^Y`w;FsK*=VbGGGyXgU=J9iSo!lHb=HAmImaM*A z{r4Q-T*h`x9XWmKJyX1x^X>H|+uS`Cjq04@b9(1J=$kZTR!YL4%m?gQQ?pCfbv}CA zp3Bl*I`k6(m7uuGM< zmVI|4Ub80d>*Ps$nuVCs7cE;^HGJfXX(xQIg9BGnyLAyCAG-3XZ7=@2>P05rpYr3w z!)`>a{{wSZ?RX$GKRtW<+Na+V?<3}# z)PKn=!0hWixj$Yva*4X#r%d`Sg!P``Nh|&q0CD*bybE$OU4ub-3sTR7#i~WFlRIKh z6_j>LhcvsO70e0luUv@2P!AX8Vx#Y7qqzo7JTQIyf?+usWtWyWpS^Q(W|yw%9UfEF z|6G0N`NyD#jdxsle&*UJIj&&M+pC7v_UU%Zkf=yUajY-8dTj&sCFbu}N&r`-1{b?q zeh#_)fUeR37G^Z{nY?lt#%b zAwOGNE-0^o#vTEkRoi?9o;DcJ?ts?wTqKr93c-(g;00QhQc7Dufuy$wr;Z4*^q*BW zs zmd)#!W-c>DN5`Sq*`3jKWNN48!-E);o^KwmHY__B?_^?J+1Vkv-8)a}niP`(-fUIR zE0KU5J8}xINT5L9g=F|V)Bf%HKmZa+L|LaOZt?H`-V*#HvG8TFnvi`9ZTyNUf4a- zRc5!u^zWa3+FcqwTy?Rl&(6y4n7(se@8r=3yA*8iGeQLacBsdcfm}xpYJ3%Ya~x=hfqz*^VdIRg65CGDhq; zzIfTF&YcUpjvdx#$6@8$4YViC2D)DxE?W2B$U&8c=a^i!MHGR6P-^c zvK=MZcfC7D=48A)E`@b{X6odZ)g5g1`lou`)n!-uofB@kf5N~uQFeB&(36~#(b?A{ z3bmt`YRWo}^9`N4)8t87B5&kV@H>0ojKAoq9Av0Y-rb*oWe!B2B&oF`D{;*OBB;m z6Z1Qc_Kuyabv1^pNlL`mo4Ex6$fOaZr10!bJ_2l3RXh!v*!RL0r^upfQh7VH(cLA?{OYPsk@U zB#9mkpobs64V(~~%|Z!k0egnbCff?rz}=T69!mkTVlG59uOa+ ztQ(qM+`HTDw@+VDFeWj|6?tgXgyg)lhZhwNy7S(=2__?o1UQ|q%3ny(Fz6jlH|;V_ zdNG$SF|}J>wz#Xz+h_dvKHjpWd#~)>dqug{yKFo@DLZL$K z@qq4bn_k&0yx+1}`%JZn2U^Z)pZ)qVU}nNk@^_L|*Ntk}7=pU_I7}TsyK&8$jc4WW zSjpM5Dh~Yk7W1();!d%VXig_S=4)ya8?S5M3x|+3;%tW#ktYdLC!`#QGhA$}Psw`Z z+&zO5SZx#Yuz7F>cRtMDi4%hKJ)V!mT0jwrEA%sjY&ckyL*cJPb|5AqfmV2}uQaND zSzf%M-q2yjPj^VuZe94W8Xj2lVP%h4J$A%Bx2xBI%TOFt9auNz=5;m3L+`W`KX?Qy z3)ZuzBSZO1&Sj*#G6ouS^&#OIJwmPZX#*a`%!jYD%(m^GGe2=!BIp}Tt;c1>)(@056XWfTQX2OQ~nLP&2 zC|fyh(DIoxtLInV)~9S>=X@r9IbTV5%HFM?H>ogF-apj4a8%J?7UAi1F2xg(xmQ1417JxS%$EV z+uYgp*<21#awFTYjstR&iX}*FA~09TnS%xO?2>)@-j(MbD$f+f%<_lMJ-K9T+%Fgi zhQ0`|tFJs|Hb2FBusroWb&&cx2_mB^-r#yHCtL%Jtdb}tMQE&S8%1%o$MyOIN%wF_*)W|ziGpa;CPdd5lp6nrF-ekp3iol zGj&<@LzAkkCPzy7xrv=S512H(u%IYr^Z;?JBPW06vMtkAjJ^B7hF$6#>VEbJn>T)L z(X{-$0fl*yE>IL2hFFR88t6i~04N1)A0LtA8zU@%_zH4BTH?i7;zr_0Sa6FCS~z{} z{M$03!*@ju9scB;lO@W6+qaAuUQtnc$Dx`73kE{-LAyGwHkV>5&~M!FFqvX1%KLlN z(+tNIdS<-vrmV~L%o2`C&2iV+nhxlJMR(<-i`t*D6v9b6W zezq1LrEZoyjajE)@@n8T$K8@_YSjQT>Y74_u2#>gUp2f`g`yQ-pNqHbZeT{CrC)xO z_-J{_hM7-$yQfZLmIo$Hxo<_k#KODz4YE8(+v^3N{7xU zoSo(=n)K6~>YMM~J8aYoVyZ=1SjP@IBT}RMx<&tD1Bdh*U)8Pi&f?_k z^1El%T-x;h$-RudH1BZzUmG4S>h^cgWT}$P-qHPw?4PssWD;x$Ohm~KQ4{8_%S?Ip$uZ{ z{7n z@SnSJJ$$aM$Kh&w{~A2cV=gznAD{E*d2B;D0(i^FA5)eJ5403ueeLr@!OvY)VsFJ2 z{JdQ(W+kqqqyFIYDoGC;{rh!Ru`_aX@bh--tQL0($TbVbbXwoL2A^Xc?qi=;G7zsC zBsB846k-^G&o9Ue@%i$bKUbV$Dt#{M{uhV%R@?LIc&q?lgU+kiHGWoDLuW%S(=bIh z%d`_(gg%RHM<)-zX2}1YnCo@AW9_B-=salHf7CD3kJhL!@YB`Bas)B@yz^mYlB-SF z%llSzjb!3Y;;nvMU(&NfB{Px+-Z?a}u*clg(l%)yI4ke|F9Wg&*mWVGnRc#Sr7Yp+ zT8>k@&(|nRlqK9o9MpHf*$|#(3U?o24zvo0d=^G=66i$0co2qKD2Vh#5`AYLO}6E! zuVE@_} z6!rMBWeaAG8#^dV z^C4zMb`Ie-?qRe68ua%OCQ}Ah&imiA5$kSOeHp&23zH`g9dLSR;w;}Stl-(YSNg}K z+{!Ay9l7%NP;@&GEZU{jz6Mkua6#iqeqB60DHo%Ek8?N!WVM!lR#@cAh=h9ArYFk z*zz4Y+0Jln1ctb}OSZ=uGroL$S^2n_(3I>h<>}jMy5>$jdT8&dskzyYY-8n*558^O zhkyP2^Y=e4x_9v7Z&yF&yN9KoV|S?!yr{mj5lz`S{%-^StxCL*fG*As>^p(|2PdYm z)OJA7iC_PApF8?jmUdk~eg38;W#bq1%IurpdG@A?FXpe$6$P^Cl41SKKx+#TFB+oi?l{d3Qs zm%c$=)h*3u(JTg@=#6U~m-KFacU5?)Z;OmD=vXuyP|PD&@NF<@3AVMzmicnJtaNj)eE*-1+QGz`_Yiszdj zY!8!Oh&hI=Yd6o^LtUS6+@h-y#2TGkWz0YuwR(Z!?j62BlU$UQnZi60FvP-aFH=?V!Ub_37Jm*S zzYS^)mM2_A;ZeZ4O!*G79w%gbLlTPh?&$D1cL;Mkd1HyDI&TP@++5hi6E%!dbx52M zy?HH27eLWlrr?TW*}Yh|u8emCp&Pqy)b%|MM|o&0E1dX<@6qz|M}3d5spm%wSa|Qf zU$5Wr^}2Nni-*ZC&acSNub4lzpy2uyDc&5Hb?}vg)2HK)tXK=@!)Xxn9?($|!n`Ko z2yRV~S0D#+8Bu`{xX=QfI&oa6&cq|_0Nqg#;WgQd6}OeSjm0)9k3?l|rnSZ@P1X?6 z*O+ZmP3R{29<(Y`Kzn-h#Y;fqDgVu^4NTY2pk7y>26NW4FdWR5ioMk94fMInf*&CT zoWlwSTS`+tLSlR;uUXJZB9q*D1Er^*%WgiGjkGXmtr6cq-nkz0Rj+3APH)I0fh58R z)Ezyee&bWWIV0z>C;TIuKae_#R11oA6`DuC#cO~scswE#ma!e;Zp>S<13iR8+tnaGkLTbk?VVWzVtv9Y= zG|GZokx>7D+!VgVap=zzGAZIUG7hB8o?Kc(3Tgh4AlV@f!7VOiY5`ywu6zmW=|N|X z(4=A(>$ZovbrEjaT#Oplb5|i%=v>;2zwBrS$;W_LqN{ab3DqIn1SM$FAYY{Kcu_#E z5&~k?Uh3diY-sMzHjElf!o@6C)~;PNWRyCxRq%G~*dZ=6CuBYKO6~ONwXZytm0)Ij z=T{UIRL~y;FQ=V+0KBsZDP9vUrxY|;HOp4pRpcFC;sq!oa$?Ojm>N&z2ARx8HzX9_ z0d%7M$93YpKZx@|ir1t^m}%BSk2U{Fq|j)AzN+8hyct9K6^rq=28Tf>L>a8w5EP_n zp!}Fjy56YN#IW$1kZqEtUDsQn)Kweh*< z*{mrWADLY6>g@}s$lWhMDn3=uv7!&y*uT%(qgGv5JGo%bt82+NL8qkt-2SH_@k}u~ zVV@*z79#p=lZ@(Xj11QM2&Fi~3WL=!bN~aU@u|69d*XA)5!Y-=bpl?$8L) z9VSzTFVcr-YhX3zaO^QIK41wgHIN7z2$^dUWgYL|EIy*X%{q_j*12=fs5z_3%F5>Y z-)s;+^&gu&eCdioQ+I5b`tGwE&=%DHNPs?aGTv)Lp8=BtZ86;zy;ZiOO=aCwJ)2yJ zz6!vHS#(yRCInmMwX20lBJ-l}hTyPREl4E7)MVU%o5qg#~|MQ+G8rvBGgAFd8kX{~KmHykL+-*)52A8W3YI;SxIb+`cD>i!Y6;GzV-_%8U}s7B+O)#~gb%I5*)DfuUh` z3CXs+C_;#M}s5m?ho>j14+8;*{e> zm$o<;Q=%@?{j4>T9$Hc5q#6UN%R&iaU}h%X6?`B5rM>la%rzWSw$H&gu zuUZkHd~Th$nDw8u>9T(ePWB5%7WXWwoZ^3kP#6Du@7CqpCN5{pp9o57Hf#l8Gs8Ew zSg}u`l1_H(P;&;;0I0||C=wiGa}|tO(mD(&mtTr=X z3#!fs&L)m?3@Z1mv2t{Lq!})R-Wh|e*-JEufY$b!VnS+!D6uA@D&PiXbK?`ZKvc+H z29Gg7G>kPNd-*aqKw?^h`t)rp$OwtqY^eBOaY(=l(Vz~^68RH%w9^N@5brg@Sr^@M zJbJz~p$i^F^_U{o=;2B7A{1?l$dxui`f;QB{*LRXl)gLuKwji_@}g9UHSj{Pm2-K4 zh=`2j1>-su2#%gm{$7RH;pOWV|RolbcWFp}INN%RM^_rH^UU5tZHG}g{8MS;v15BD6 zkoTzcRbOFma(e+ukXFc7;Atm$&1Pt;WTb`ofZrzK{xO39k6X;ROkx#W3TGrusH88O zw&Z{T)2wQ_{Y%J1y75;gITF~MLXJ?kvrEDy~NaZjrkq-M){<~R?fWn$GkH$9JJeH z#;wI3{zzQ%Ns_`mH#&U3f2Vp(DpilQbNb{FfAZ#^cI@zf-U=Vlj|m?s)1?fB?tN`_ zsHf${v~{co2enM9oBT)|=Rc(UvXejCSN>c&rJKcXF40#EURegyCpmKfd`>ocb)4E~ zFYZ}5GG<2o#-DfIsbpJIoJ(}G)W*bwl#C-kvn8LK+{s@GjO|zYi}Q6hyfd^8ry4Xx z5$c$MUdgWw_g}iCvt0sgFX7&?C*G$M^6O=BF-(5bRU9Rb%L+E12w?8}`Dc#HM6CTJU%U9I zg0ylVPD{i6m1+d)Sa-=@nE8SPaj#LRUo>qXUgKEZOxOB`P>TIvS z{Y!;2ltL2}qNJ~ZV}L`8Gk9n@uPtF@W?F*Z-^mfuZ@^VAxQ`ok91B$cHB+rR zs%|8uMh_Da5KU+V`|#2wb+dG|d6@LuC4c1({3K#%SmRT^hFM7S8m%U*BMSy9BP7d% zrLd9Jm}xl!UoNm9RnoJ-qQPawbr_5#eM-lRKwj8?ks&Mz4)7cbdJe5$pe|fP)9|C{ z&)NL*4mi+?@QQjxKA=nEaKyu|WMTohZIT_=PcWtUCp>c$QD`G?k=0;Nat8YWOWHqD z+1fYWctc&xHdel~aPg8mH;eBbs)v2%->O7o zj`mODs4)*MdC=i5n{e-uifN*HMR`KKTkf1$IU}o!|64rSy~omJcLE;?cTnHTe?wmn zic@qHhI&Jj4JkH5c!ZPCW$&(fPe-eT;AZ=l-$XN zy1vWj&|M(PupxaztPekf8oYCvDVP93SsPN|Z>K9MF}E9a{Kj7hs-hD#Z^(|&D!Zk3 z?>>F-+xNdKEUi=cl`Btm9(t1P@_l*#`0u^=Ptwz$&8OeE@HU%o`0EQJN2;fqUy}+C zJqVfE*z$?8LEZ!$G6b(TB+DJ@NY`~0O)f`LaVCJF@$XIAiP9OhAufD_XVd?~+s_n4-dt?|0_fMUec;^ZxTZ_ven~a+o=D`kXm)PNYjtuwtXDnNy{ZkKhAPens$A z8PvQpwx1DiO!3eKFOUGSfuA!1{bFP4@Y@~#00XE;{Qy|g^EB>=l+0GKCpham&AYUH z{rou@UB;c=#Twv&rsHKcEURszJQ72bSn-{CU$b4TxLw2MnL`#|>Yq35<FeY9E=Xo_`OF{cU-q#4|bVhidU%UWT zH{|S4Mx5#q*_vEZ($m@Anqjj)pm_3MFtV^ur~fc>TEm(RNO@J?SuB> z5_66S4N&$>%Z_V*amc#|mY@v-S}z=({ocE6Tf4FX`=DO+!xx<@;QD3+^OQRRPA{C` z;!q6N#)tyBIzM+G9gnO4r+83$gGY!ReLcNRIdWk@6{j5AWBhbig#REpk*=u!1unq5 zPxNVw$3|m~&VlYc!N)bkLm%%R8aHCoO&YxV+aKSnax7rN-WezkaOK>OO=T&$sZ8>= zcgLFlG%sN4EGH|_OnWreaDUQZa}9#x!OT&vl- z$!O6XB1&fA6=IRlPk8E@eq#Wr%W!S!KbcX`!kNMy4}`T=$k3^S|yjM=h!gxT8|KnfFgKgl6Uw%eY6~b0{WC9H0>}rsVl7D$_ z<~Lx}&$5TV?&p3cSb9$hIX#^iIAO)I+~aLn1~@vO+6#_u?d<)Z^YTdRwj$?EOhE^) zQJL)q4SCw^GAm`vI?_NI&;ELOWm-nlyeai!#~j1n#=L$C{?5nVY9g}X7-ADFn{2Cj z`awSng#!b@Ndk+3hW0sO3u{%&L4RnyOJT^-S}3){ch2`1iFcd)VMYii52_M|#Ji{> zua;j?#k=t5W_-!I6=ymCp`5f9O}gASjNXzsC=F%BC&JV$NU>*=_ZX#T={kVx>>XNdD275dW$ zuPW_rZG803lB11DbY13Zh3`UdpW|6*Q_UF;c9LG_sJJYwhFVWxf2)dAjWPayZbm;y zZ9uFMdIyi|jIA#8t>6x%!C{ti#v1E?8VNZd_66Nde3B z*T156!$#mW9M$?9on2h&c=_1|$bK%N%_F$bT`b}SUIbose)^z=5nefUs=4Jjh84P? zU^%Lo0j(GWu-N?f<7+0=$evU) zH82i{_PSK^$BK}80YSf8xkQehLTpEAfgE{#@4FetZebtS&P&Uw+t^*ueLCa>@3+_^ zUhmPdPLNHg-bM1Taja!mwYGC3;FPNtID|l~5jH0*r<#9ZZ5@)57KR+F4gLUP`EjN^ ze#vTrAif;Kc%8rxfZPOWh0UPLC0k&Yt->!KlZPbTdFo&ND$#{a@e{wGI_nDAz5RXu z!apWSfAe3>D{p>vTdHc1E}tYCJm}JhSJ&0x%?kt_x`DsXDtVwoZ64_fujb+x$!kX9Nz;PaiZoI+8*F7h6VI6%fT|kaw)k2Vglj$wBqe9d07a<{ekTtGX`h|oUMW9 zG0GI!{c6zbUz3oQ&=<{4tN>b=La2_oXjmPc zo4Y@(5x|4Shy@7jVgXVv?mi}B#YCwzw9tIZ{FnTMgJ;C$w zTBJMxe|qSe!zV2#?f&KdjErG@DDO@X=Mlx9#R}ewmQ9?3LGdxj%#4fWM%zPgz=Kt# zx`hMHddnZAlx0JP9^AHuN-qL`54LV8q|G0)`*h)Q)oKQp?bTKKdcS<$%9z&QORG`q z6xzI68gNT`bW&yGX3e4)c6NcP&Y*=hXP*$QM0! zHc4_0)!9__urWCYRq=C1!vln=Q2@Fq$tJ+b*S^qaMTnIx zG~NUs2%$sC2rhG|8!LXZY7#Y_?cm#E$ITbmZ`j+W4+~2ZfP3;|U$tpNjio6+KPqCq zwrrs!_MdGZDSw)aIAu8BrUU=(%KN~79cVabPa8L*jbm-w8ggx$Aiw6KelOPn7ZKlw zesIqZ0Fgw;B_x<%wxZ&=Hh{bWe>pl|Ir>+{NLDv@>_|g zMiOlg3)u6vdDsK#lE63a3V)*=lw?4e8Jsme5z-I_5_Av_!HG4w5^slIn>{91>0;?O?0CI;YnD&urU7^p zzK_7$|Ece@;{OHTN4{1XQs(gSb1}+6}LnJF%Ie(nDaIV2Q3m%5{7tPIv@pF&%qk)`#@t<^zWt%Tb zaWvrG*cW$ED`u(WZN{N0r^|(3+*1ydJEe(n80-8S)uW&rlaDN1&z7(cvzkvnd%m41 znA4&??8i<4Ke{v}IY-rY@%6?YT!LNX5O-co9<9Z>ABq?3*oM(DC)g8@Tzzs(5ew`3 z=hQ6Zp0;Mni*P$!PIIboN)6%^6N~M*3Y&*NAPFH9UI%wdO~D})19y~fhU{zaYUXfT zlD>aQVbrKwaI0RK~;U9%hZ_;|48(R=COTwBz;WV z$#Zm@fu@m-UP95%Ghckgtq|w6yUIA>OZlT}yushaMsg8%-WTD9>fIe|d;&SUBYu%& zi?F8Ro#V7HfFB;(g&;Ke5B3;dh8mMzs>v=e&9hR z^h-Z9ACbz_ws6k;P4A_wLVUD}u0D1a;HJmPJxKeFxSs~EliPAUuyhX&f*V?kS0ML5 zD8zD<=l^7Ib*Amv)FhGU7x5c=$$U1$mfw9M(b)M822`NYnW{RbR{!KQ4ID%g`@D3A+-)Xas)hQPe`E&$ z`xy9q8n5^vQiaolzl)|$qX9%gZ<#jQhE)3(Gf?OE)&>WjUoSQKQ zsuQt2E5F1GVFs`J2UOq~y{jOUzn@@?$L2pIHzaeh^X!M4j~h2hqS$x3up_LHT2XUq ziTxyJZH{(Ib-LKS6hY!?xpIn6!+nW8-Qf+IoCrIlq=w$802_V@eXxyw5=QH zBD>V#EeV7WUlb>07|^hVae7^Zb53xz98dooQ(+u-0SSjX`uc5kL@=J9QVhQx@w(jBYY{9bAI;iN>eWfMB|8Bnhi`;v_r+jq)O*Lt_`5&JvK_NdQru9J14 z_VO|r9ppDw*aQ4QhR0 z{w-Xw3m26w*V=WtJax@q>=UI*c8T8{^wachSU+?5yO4-n%KZ-7<($c%v3tqe`pfFJ z9qbg(O&ke*QlMlzhwANBC-Yc5O~LQ4PIDMb`l&vzKQi!FR8@J_5sDk37l)>DlT zemJj11wCWqZt#|jRa_+AUJCyZDI)?QWB`os9vu`K1BX(LF+gTK+`CKWldRw?aQ+_( z1^PFkp44^z_R^n{>rrAOeKq!a`>?BYr9+THUBX+;Uy_) zvKDO=H+!QK>TBWb0+kL>>|LwqJZud)x|{w1oxCs3=-}>SL%b0OeO3Y{PM-rBj1#*q0?av6MPy_Krf;FgM)1Z44GJ_ zz}4U&ImwQEor(*YkV3@Qg06kDR>DQ|4zLX&22pOg@olDB)|1NZ$xT-i+Q3C`l3X0b z#%|ygC@^j7Y;fD)YTX_W<^RhDd7;!d3zuz@etz=SKHJ?u|6IPVWuKn7AGgQ4o|1dn zUa_+9o$Xw)vd5bpzqNL`Jy%@5{Jtwdpl!V~K+s90%pA=MUZa>QvdeTzfGIjo<_}pc zo}qZKVtz8CNt0f=YK>+Gb`EaWv*_q_V&9MKX><-+_gTB13&tXyQY!t(yqKMOy;qzS zgOhBkdLiE7=w=szLjZV{$2km&gU%Ue$cUmMj@3xj8qa_aYW45o-dheTW?y#?x6#iN z+Ke4LV#c~z``z8$JXq4wF$s1(Cyq^=+&nprTCmT)0>iwKTk*X+VXlt}gTc72!3ZxP;wlxE%b5nb)v zw;%f$%n56bHGIq`byZ$}g8g~x0+Up|QSz)3QG|V9XLjy6HaaK8KF75xPH6bn2o8r3 zIOy2`DG;iROQC-hGJcT$U2-EbvX*rE+U~+$UnAS)r=R-u-ZtkytX*V8c-;(&_8a}5 zkEkg-cVhH2*oEncCH<*>3cC=6>lhI%)C!5C05Y6QJ}aL+l)IWZ?diB%qhJ*%`k=r7 zlaBtd=ymB6MrJdOxO#PQ9qLFe&1o;kl5L+U+3y{1&7OBokqQ#6?xu9W+>a%ZaT?V= z^~0E9%c;3E`hAMN@`L&7&aC9+$7~gsQ%N`J^=)Y-^b^lZteIr%rK@i5Y-8YEHA*d* zv3Ja|Ee!B6xhvc$10Qf-EEo<#V1PK9irWY`QTp8w6&J7NKT8=X{Zf6@)x@0{9FowCj&k=Mswd*z$MyXAS_4*shtITY|9wGptB1Hd!Udb zU64w07rc9VGvWv69#es*TV7=kmx>s`*RYH*x$>qgf&2d~ASk+YBlgFgMRl<*rfiVvb z!TpFKg!|>_LhWV@68sf!b#cF>40h%Dh6y)l7u{h?$m`dqPvL>c_X}^NeTEmcF&m~7 z_oEJM-UTky>T;j% zXpr>Ywpofo;SGO5J7v05vgRr2t;ms2&0YI--xs6ukL_N`=Gpyz4(Lf(HC9{m0~V~T zRNlkQS3|4`JH=<`Zb~)6LWaN)u(=kcJhSXf!bSRO|Cmw@P|QPU>Hx2YY# zVE~~DW=FJc*Q;^ljDqBDY&qN5x&1LWe7_4(w*#|A#=x%8fSOL#+HUkt*mQzgkn#cf?4_#)nSeM+xv^K9LeezsCf@;;0!fL;N zm))ElKFY9mF44@xy=p9a#o;YUP)_N>_0Qp5f~rs*Q8;dhD-;|`@hAQi(LWGt3GDNe z33n13@+UMrsE7`w;m;^IYHH1p)~#CISUW4Zy}C*oT7&)i&AGOo$xVA_1Sfbb9h?x} zFI|!nqLou*B99q_1Hk2}jgj}8KBHIA>|q1yHE0O8zD4dvsc#P&HY6&H)1OM)DZj9V z24C=;Kl)XuHam0@cOr1fEzE|5GN|@8+J{I~(u$4dSKKhQrR}aPzH();TF8IBf@{au zuS`?i&N* zEv{1O>Wk+to}1OSbB7M<@q-6Xoodyp6_*e3mId(^)Vb!EM`Qt#z|jWq_o9;$3tJ_K(e_e*Drijh&)&+_0G8Vz)F!_A#=m*Z5vsIzLIf^54# z&W~z!bm`E6L=my0uH2c^`rx9mWKYKF+t_!1OYYg(=7%|B>Fl&ot(rF-KDgIVN&5Ao zL|rc4SUqnHja_ld{QdSEzQ=*DCn~+vPq2Ov){lw_kfZR#PlVvab0vOka89J4SPy5? zDox3?va?5@3wDaW`OD+pLvFBdr*HfI0#z?$%dSot)rwkVvknEW@`)?#&a)vSu@ZIO zwDp$<#7?riJNmN{Km=s!++ROd=j*pX58yo>>;tbIW0CuE2N$Sngto073Sw706fYZp zEno#tH%9kv8^KN5upV`1HKC5j*bsK3h9#g?I1>-SGmm##apGQsOm4~2>!q|mHR=R= zj|E9moCt79c{ocx7C7jpd?#>#Fbl^41*uAIz>OG!%0X*?I{Ga-1&?`wGp$UgLOTZnJ zdpqFntP%8$djj{!y@CQ)4g0rh0e5q`c>7hh`<3Raj6K$x{qas)>h*JJf<=E*?X9cG z8gBpj?Pz-@HSfRr$`7SqamS@wz4HrD7R>vNB1i5B{41V2qC)#X+JfN$18w5h|G&8& z+1auoJG)|@2ftZEo`<4a&N`{1VC(F0f=cBT4a(au9h}Ahygb!z_Tq!fUswvG3tI^D zSKb!Jdl=lrVVNuGP`xYR%n5x?^DO9*?q+4NgX2cck*HRkeDV&6YW9|aoE2#?kc-<~ z33ka3k51eZJ7FA~73$=?VC?HJs*C zqdV`}gFCXs; zjO66e0$y_Y+xrRuFDcJ^$b>?6aduF>^;cE(>!4bl2Gn+q2bit?`$*WImP`J!P}m6b zg=OpHHl+pZ_`t!EeBuimy8VIC6yzMu!(Iq>{P%IPl85k*Eg1pODI6akSn$#M->{)w zZ3Y7y!Lh*1{~8q)<9$+|edmFN?7@JVN$kh#T5#`w+;p+7WVL5#5?u z7U}yRx6Ew`EWbWOPogT9$x#UiS7Kulq{95=D~=%@j`Is=9tII-bfmM#!=MvRVfU_dz50}#=U zr~++SAI1w^4#xYZv`Y<4FUV;ZlGw54xvY2Vw99NH(Q;3s%;2q>?pE7gbkZwyR z46HfkpXo_i9V2SB9hOKhUL7vv>%5kg^H|3Z>mk26CLD)9zD0KrLpZvfCrDAg654GT z6`3ul8qp*;G&!Pbtr}Y!CpXSmykWtR253fMR+fY|i}tM+-K>URr^t~_=QVFXcVNAG z1Lw9c4P~j&^T4P271nSQ7>x->HH|k|j5j%ANz3j8ihX6}pMa$9Bc?SUdSF)DwzCfm z$viZ(P0_F;uRq9T$492Ey)xZ=P<_{YaN3o%Y0}P?b0!RGU8DQ5uQD?V=A@>~K0GY< zWno4};mh1<*LRKe{N@{vv3stATLn&)dhqS4bDUP#DIRhqfTnz_az?F`p^XxTcc>HJ zU{qvkT(x#{4`&S7KdY^hkTfi%W@M*Pi3xKOH`UD;K0JEx{#mIl-rqB{rzWGGa^CSL>ZbBxLqcJq7hh@{|TPn)M3HUhB$a2cv<>D*-@iu zq<6LG7BvDpL`+M~YubM9;QDd>=5)BuS^%e1H|;t8mv zhD5Z_Y}7QfO=zvQ83~PtwKuoVIsDzh*{Q6#G{4p2R+)$Aq|(mpksZRr+Kpb2u(nn=5xi-kCf_t--67yqm$;y4p5iHQrZy`t z&r3?0cX_4ci%9v-jpX(H zc=NZ6J1&|$$_?}_;e&&2NE^i?3n|O|>uJef^`h_zuj*>}P-+1tS8+zKh!4q&a46*X zh!)`jLFRtIL*vBE)S9*1Wi(DmZ(D2Ds*D3O+njE`IF(adrj*IuBI9~ZXqqyib9hYJ zcykl#J0NA=@zJu5t&fXpx8V4w($^fmH?(lo;Sm7d-&#aS&_cGdH`swcQWn%8wI-Lr zCc{%}MRdq)lmsY>Qf3{>NH3V%?$J3ZyY;$O!w$`)dx;=J?GB@wCug;T5_j_>x* zNJ*Kof2cf=B}?PXnRTO5c>QV43k-XA7VBH7!8MeTlf()EXK~<-9g~LhIfo}D zWVEeC-@VqQ&OR_Sy>M>(cJmHrkgs`$+?KwOJ;FPVY{FGWM8~WoiZC0bm+S}5^{KP= z4^H1dqYX_iG=E#lk4m7^3>eLK00%sOi+sTpicB58GMb+{g7;x01^(yOPEBu=Ft|>K z(eEKaht5amn&`$3&Tg5c=z?{^Ax}8TSebhf?)+a-lr{F<$ zL_bh(3!MUg7dWq=QzYyino`r6JgHr1a3#u@muxpUlEG1i5+!w2&9<4-KWIPx`&He$ zt~@ts%B9t5t0N;qtLcx}H0VA$vDug|k$%nnvQF-X(vBarX!nULr}iuw9G}q0M$pKQ%j#sJPD7Di4&F# zWy*2>O9*KI-GfO_JlAv5nHq>M^za?ZX0tY7K7KAfrP>k+dQ*wsp%^ zy9c*j-KJm{nf$`sI*n?c6;?ZNt;T3{y?^@rpNZZO0qz(NVV z0zMB{ViFWckzi(DSzXor!}AlzpIhCXyBjkuuIO|+uK(=z0f`YlZb1>=4&g~DJu(wU z2=}Dk;Kh4R4jXxT&w_!mJ$r{Wi>xXulYU&+v*$X_zUz8+TXWewzRAe0vHAmQ)zApf zsuBLKu0GYhjbP&4C$F5;ycf>TGhdDKOl;X6yekWTX#i+$kGrP2_yS04A<-YT2q1cz zZ9wb>`@mQJcsg7Xst9;fS0#*C+PQi2&Pzv_*R<%eba+C-@TFZ^$isSVx{=+ys73Zq zTl@6c`cpP_%f7Lxm)w2l@^_n*7A0j#bCO0b@76UxE0I=Ay}G_9+f2QCZn#={ZGF$) z8?SQS049|?fXNAe0kd({%k2h#II8%tpTB3`XQ}G<^guJVvIp&bAw|RFw7}15ba&Hv zmFY2T0#m&45d^s#rKi+7-Fn8pbV1=diJF>BEV-c68MJ?PYU=F$gGw%NSRfO^Hi`L! zIufSH%BKKI?$`W-)cspA_`vKb$!%vJ%;>jsMkkvyYGm7i^*EchSln6@3mCu# z14Fx?rQe3`pOx~?qGQ8aOzII6`Ob)hopmGHOy4(@9y8aZ5go&8)#xyVUI~3=l?^E4 zin<=9>a7~SR!VxK_@OZ!PoK_PI{1^BZKWw(t=Fp6Zi;!Vo|sOkbMve+{WlDILM=jn z(Iit-+5DNaAzZi^mhEswwXgfmF2hf9e>;BA;@u~Qk2*i5XLzsf?*xrM_aT>piG6l< zI5IjaNprM^o!GTtU|gG4>%3}Lcj>YA(w~>s^=R0TCYaMS+o_kZt}}Aub@V^jPR>2B zoFlm99HCjxbBuAznQ?etJI!)_N8eO3o5hl;qS@rEW{%~uZ^fen?m;x!x9S+U#ju%z zbHTkr$+-B1xw9B5@(lBJIUCh=OcNF()%cvPJT2un8PhdN*;%u3hzmR69MrJ(J5#&V z`i$98edepDh%`Ka*7z_S{%K-mzTw&h#zEKz7;CKN5g2E6WVn&=fL9)#GV_xm1NO}B zY&fIVZ8x+57XY_fO=|Zz+++Oslv!Y~t&>_wU&u9D4Xl@t*{)94E`3h)j_Fj-SJSke z79AVjYEt)T?n`*bN7Z!lj`NPr?=twn?9|Rn{xhuAlpZk=owAa`n)&%ASMzSs31VZF z#d3BrR1_YIy}GTl|1Fb|LBmf390&3hx;dONFU_xhZ)j=Ot_87Vc-X|l$R51hHv^!SYdqI=eT z8!>lP`~`PgAdFC@U$sy`*AIp_ZZvFJw=VMsC)yk8cN`d<2%jdP>7XV)eoji= z8pdEhciCy+%98*cya2k%mo%Jc{!BRZ9jI3RKrGwV?p(XW{2>k2(s0|rW(|WA!@Y~7 z{@!klhR$!Fcw~LOj1G~$F)eCH-Jwd$>1IJg;TrU~_SP&Y-(bl64tuE^+Y!}mT+?Rb)1so%#y1MFyB$ z10#GUNjo~Uh{c(`MU5j>>kjXb(?5RW7n735bg5gn%a~dCZR6o1sq=<3YCLqlhI^ji zwOi=~e_Mw_`#h}{cX`hI#y>QK*TGff-Nd@Hezo>hyLTTs%D>k+y24)BPqKC$6`KFZn_#Nyh5w1bG*B}2c5=x z$}-;4Y+hV2bt5Glqg#*Z;a$nW{HIifE+oyL;8XQj_p0?j%^l9V(`-p*Q`j`(65fGz zlbeO~5N{Lf) z;ttA(Vt;Y*u}FbKGF3ExiXtM5A4lY;*x0^a2m6pHbe;db6G=40@pY{ojy{ zc?b8v6pOPWXX?>_Cy z_DVEqSaNjR@W)>t-nI~)$7|_KQk#@+Qz?zTd%c&bHjhV$_pab0UfWktnItvH=n@|r z5)UM!Ga#p~A;c946mm=`PppcQ_YmvB`bZl#ARbtonj+QC|343J6W#vp^9|XwG?!k& z3=qAb)@@7;9#BVi?87dm+AIxEM2Kx+`AX15>Bnnjbbei`niUgdgKH5;GwHN_a>!OaGLLfBof&6v=!$<@cdR)Enu&FC-U9 zI(n4Me^EBeW#Y~Rct*YCUEnDrml!oP4%x<-*uxOy%H?Mldsu4@-TQ53IKxAMEwoAU zXPxJb{g_-(e(pn7ynF0?Tt}RVfjchP z-PnNYTkP*Wew>qYjV(mE4Dw6DYF-Hw~9$tjp<7xWO%-4l99Bb&HR2m~`5El7?6 zen+sjv}H|G)AP@d&}7_bK6%%Xr<+zBDVei_K$GxgwBsPluju4Gn-A>n zo{;{*UgkV#X6kyKW=gJX($eMq$)Db1H%m(?kS%17MlWB|?jyiEC1> zt*tg7%IM5_CMup^x}sBnBE%coB#rfp`6%H2!-qpB?WL#ee8E$S`0PGCVJ@^TcVK+S z3_L0tKyf*z^8MrXwG0bmC1)F(aGNXE0)OsOqVP6Br$UhAXrvN*kqWiptj79hxO%Ry&tp`O zA82F?uAm8x&MI)_f~y-?GdH~JiH?i+Q=hX0Ql%?D+2`6zH?NZpk++j4r8!~dk!z-1 z?P%(JgL0*KRwrxuP}~rAU}v8^L9XsT_W7{oS#*Kwk_UNi+AyA7FvZfXTbv(+PYZtd zUD#6Kkw3VC%Z(PCNM_?&6P&;Xvd#t4i(9AHbnEp*lFepGmY3MKdm3`vkiNx+;St#c8P%y_U>p%wHU(X*7o&cFJ=^ zhH;!UuO^h+t`PIP<}m4|d9T!wN?MxlO5Sj_P@5by*bAKwdRuh_xA~w0kmd#k({u%w z<{(#juLLzQIDUKZt(TNP%Wk&q#;nW(bxo}nqyD)E8%4R>rzH27E9}Q=Qf{0*dt))J zUPTPGTZOIcuKt3xM3n$o5I2Gi}o zi2nZmee{8uyrPBapxAh3?+%eI#m4K?Ao=0$oi$-}#?vqf4x!*l)>X(aBKbm3$}XCh zpcpx`R}g0?N4LO`;1C1VZr+ovmL$r#+{M)KH1e*;T%aGXL9l=RRx;4IPY4ZAKR)@6 zm-_`gSAPEGm&8(JHgxOG;RvqPV2>fuR7r zkaLo7_xN?Ew%6mo{%wlh%lc7+KG$#meV{6Pk8-g^BITC>2;c>LJmZ}bw)c@_%V`U} zvCHy4O=u2yS{!Zg!q5U8X+s8R56vbBT`2i;O*J$1xC@KfK7Uwpw1nL{WaniuC?=v~;#(^%J4XhwHe3E7=c z<$9js%xxZ0rTB$0*f&mk^&QbShrgg3CHo0JUw;_SqkDZ5pL@%Hjb_)`=sPATNjy(s z-r7Agv~a5Z?U3@t~2D>2QyE((JQorbKohzF#2z{b+I98BhsdvJ8rPG56v4 zi10n{hu0Hw!*L59)%tgoxf~#quqt3yXi4xUZP*)S+JBTD{d)V6q?${}EP0KQ+LfAU z1{;TtoqR6DBIL7HI>DddG(or9Pz#j;++2n0Duk2!3NYF;$Z)p4DQVKEAyd~L7)(A5 zHq(06k9GU>>Fry;E5B3Vkt3V^z6$jJW&_(W+kBfD=p;KynS}bVIEO>OEC%esJd(vZ zP8Rx4^5BkINT`9kPaZgifmhrDO-{V;2AQHc)k5UOtQQ=(E=z*x-UFKZuG}3(_5xGa z_MyUKorq@TnrF}6MYL(L@KO4wXZSVc+-b96;K)g?6hrlG>6H0#!!Db;#JB2_kuJ49 zBp2@C=LL>~GiCS`M1*{6R$31$9VMS3)}N&n_@?I2h9lB%x9{KK=2@yD-!X5TB`mYV z84#A4%XSa!ag%bH-#M1)5I0PNDqJCmrgAX0(Nmm|xcI83t>SgOF zovow|g9o$XiyzbSNn=*d>f+~rZjiV4`GpatxOr0>nEGluth@XYywe!_2v3%51BuI z2>+cv%%g4V*AVT8pyEI2ll@cJCAtE&R^>J&;)?O^Ew+Ol*lul*^XA99OtHR`^Tk|akm|IR+&*+>1M`Ild`kWK9CE?wYsLI-g_ zyPG(B!8cPS9J1hM;~;{hRFxyaH57UG#$af5oW2MSQ~&A*-RSN;_HguQB$Kicd*teH zl1$)YiSkF9dg8^5!4F&AK!e-(7E$kNEb`NL+3y;!@wN77_sJG+zAU(T?iI zpA|;M?P-X#k!Tpalf74#ZQSqs-RTSR zz#p%CrO_-+Usw3MAz0A`**Ae$mS>!Z!;rAc+DQZc0{l9D4%OF{SdTd^O{~|wd-q?k z6xwpHtEv4x+WPr}o44*t9_9z**0br0pGwIz3a70#%Vhcs#WGKwLY06~Y|mxiz5%Z2QHTsq6_{hp@?Uy@qQvodNxEMybJ1CMdCtgd-$# z#=FDOLzZ)(n*>D?&BblT=k)mJpLabWHbh#UY?7Y+e1u>yy2{L4^dE{ef0Fns`-{a> z_uH%lHX82OLO#EQ*g!YMP6-12;N`eVIP7p210{5LOKm=LOni{5yBdT8q2FMFn0?2N zvuo?V+D|wj?0m`={)gb=y0XWJjtrwud7jRr9b?xWB3jtCEiT0B-S6Cu+Pn@4DX z`B~+VJQ_IUJ_ZtKfIU13jYUg7#9rXl2gnFDyL(7G-s?M~>5QiD{ff7p<`sE~toS#Q z(|hlql0xdl_u35c^nDjdM8L(ow=u1&&aQ7h6H=2`rFunCa)DBSKZ!mx6dQ;xXn}67 z_)ji4#V(#g&5&GBbrXI+dg_$G!64}`r1F}0hA%*jLbQOtFo5L?hUN3%6b1uP!*g`$ zhfg0d*5dJ$Q8adf8icMCh#B}&+e4kCj_bZW_!)l+2ArajoSLp)!JkkYG|3@Zhl-$- zuf8b~TE5n!qDPHKS&>oeQ3n=6ZMSl@L2adAg8dJqRcN~7Y(9C{d_oN`S)&ZvDT;&Q zO&TK6YPwAdx>2pseNN3?^!i!iEra;3UUJdPxYw|bGqiUOHBC}Jr}wmRfDj<7`%n{+ z!Sw<-KgQ#Gh<>)1N35dF zZ)h&&nM3*I;K4kW@7vUU;(Hl>4b8>;IhDtY`E#`S`A=!{tNZwP(elgM-367$i**-N7+((ma-vul{|;Sp8jZ#CMLkdGMz_Gz zMMdhRBJjsNX^nhe{aNrdI>h;_c(fta`x}pJyVKBI8mjg)@63{$mL9_#eWYvBUG*^Z zh0YauewG~H8v_Ik^W;cr4|=B>F_?GE6W0b% z)9`j;qoqA)nKw!F&QqF>*|1>@`LmzVIxndfj3?>l$^Q7+F5+j6fiXfIYWXs8QSQ>7 zNxbnMZ@Q->v!DO2m6X=43HzD+F^~A!Na+xM7QBN}kN(=@F8&91+-z;;nFvW~X-WL| zG3(dMk(1Ms64NHHzqf(Qj|OuW%b7uYIK>Nmz3KTEU9sn%()6vKf0C}1v{p_~wHkvu zTVO62|3OXp=CIo=l&ax3={woEZt1hS;#aY*v_{$rx^UfG{jjavTW9EvvaonGU5ux2 z1xWiNHP43E6o`sM{s6zSH%e}~<~z9{D99y9hP|Jbrc%C~B50=3T~7Iy<3!O*dz9(? zJI9H%$9zKyQuLGYSM0eiaNQMqhK~{$3+D^oakLvH6f!;9=-^n+8J0*MkaN_B9#jvV2m=!g~2v@x4rz4FTGB1wJyy zYcdGlws}|kuEHeayQW((4{QkZH-AYl)_YseYcg3jPL6ytPLolKp2s-sNyrdnMXzgc z2{a)_7*!wmeZYQ9KB+Wb)2;g}>q@{G!g2hsy7fTi@nZf1 z|Hb&jmB)+uftP=s|6j(7`43kZuknPSJ@CwJJLcmuCVePxfG*JM8XY86$4Oiig%|RN zk_qYksHJ;H<4FDcoXYQWD!(tQ@4roDP?%F$-cb5L_AvL89mmjsY#K0z{UFv@LtaAP zm<~w2c`;$|`$731%2Rl)16Qb*c^1_oXt^KtaKePlA+!S80<&tE#kYDUe5P z19}@TSM7Xk>KT1>Oo=}th$ZnMOk{3L?aN$`g@6RpP;`{=??Y@vH4F;<` z8&M@z@v0J~vvq+$|A|El4EeTjH=Tu(8IL8gFrETh|1h4817+3GPwgxUVy&nBw49~0 z4y^w+G*t^nVA5k7Tfwr~RJQyrIZ;lE^}iLkDMwd)=X5Riy@E{RJ7_TxxaDntU-^(+~1-=gXiyKNid zNHZv#GPa@U;ziWY_zn0H>uC5=0|dN32zXDwzOCOa_*wJ4PSZ?{#`wNfgI9G1=j!3v zSmk=R`UiZkvwS4Jmi=QvdbTMFHsWNW-h|JdKO$#a45@ybVTfxMDV zkUvZ~PcK0e6`L&FvcD!+-K^=~t~$P5w#zzu`SO{p4>o+tZ7$?fpRfK59G^m`!Z);n zjNm(`mGwJlgYn=|{ri^jgT#0ZmmCLsE#H@m@4x~4q87-jOMqP4BNh~ldcL+k9heu_o~ZVJqy7_=dJ%vN@5@zh;B{WK+LeJ)@}xbd`eyGhD$3sf zh&`pitHtDeM(wm^#r9=8KG?Ft9Nn6p6~DUmthnT%gEiifN@?G*A{{<%QzGx7cl)w<_n;}K}v-_Uf!#bZK=i;lls9eH(s)Sug7ZY#nNfqO1>VUgK$bb4&=Ji600FLYc(Mnc zI7|y2^Sn`z^2x>es1K#Nr~+Z!xdT8Ny4uYeS7le#ID*Ik)&}_{Gp_A|(bcO5#hh^}Brd}XzIUI6$Ib9ce{yV%fYJegr zA|OV*<(qP(#ijDitHtcunVD9~O5a*3i!g^Ki+p_zUO864`$YQ=KJ*lPd!MceKGb9s ze5f7}-?u4<%0LI)FB_jIzCWO;<;HW}V6=?aH%4xfqU3#%rA7H6Z-Ah`Je_pIRjB#(;U)qZ^i~% z1~1+Nt$Gf(*3jNiZ59nzG$eb!;-Tp^#be8g9U8w?)NKZwtgsgNR_Hb-)Z0fh8@-RM z;w*G67ITvG9juFKC)6@kCjYZPdq|N*gDD@S)@((8~6b$$)+Nw`9vPu(kg(~UazE@{CU(+Dwf)1%| z!7df%MT|+rmdexzd3Em9zQ52Ka(>6QsU4&?nzGB~>!;<7W*nq;zPj{gK8|0=;|^~BEc2CzPw}Dh@acGSP$**Y1WNHN z?JHg8&4JK974pV^&P$t5Js{=_6zlNsH!Sx50Js0Bms7SMajuJa^LOp%HG6Cbv3^%$ zg&h+1(omgnYp1QJ?iF@x8#=Z@=NfPWr0F&Fak=sSmNNzLq*~4tc!$Nu1Ao@>d|g98 zg)@Q}kMALd01Ka$ohbx7ykiU?DLaE;p8}o`zCXdofXXsIj|+zyf+~*}^9NNL&*2X> zpv^|P`K|DWaJ-25-@x-&%pY2LyqG_mbaEe8zJv-@u! zF*I4T!iG}_xH(n?AZ0u0Qt7cQ_!8rxE9T3*cCqk%WiJmmTQ4UscoS&NS07RUcLI*D zw}&p@!5hs?qn!V&cuWW_^CV;N4o_LMX2GexeNU}i@`_~kv=~Q)w&vB+g>6~emo3{q zGjHduo5jzb74OX43HrjG=)3Ff#9dFuYX$t>2uQ)Xg@3oe6o$TbUQR~YtBMDA$iIFA zlxd;2(|-vRuni~2;*v{Em#jL~ug|FkA1dzVRjD{66ypRVOBeEHa;UPl?F2j=tedw4 z-`Qh*U)4j%cgE{R9IkITT;NmSiuaxH(gmR5jDX9d${So2=<{85PWcX^v0;T1f(PQa zNQV=LDU+fsTC$R3X~CM3htiO?I35(k?>6uJFW?dDYVhcH3V0F(oZ5Fcz&ZNOcaA^6 z+1&zXAbO4pntD2w!yf>3(RuzWpk-%1lK~wxn|`?9RG)sQRxNqO%w#NnM8;HU=+4U2 z6!3_3EqLoJ;B2DF@$1_*t>pJ1mksE6Ik^Py8P4(V`fd7#{JWunHXbqLXn8fpH>qeJ zwSDpN3eLQsi)DU3p08_2t~_4#a0xLaTjUr&#rclUqYAt!WpDy-^W>jV>*o&Wi&tRf z{aX+C$}w?hEx>U?r!y1!wr)PKb>Fp{cT?N{h6nt+S?1nU#|>t7F3~ zi=7J>u>&2Izey3+j&5w(T* zY~U4g3FeF0pT1PL;=t`8!n_ujz!&mEjTa121pEqv?b$mB)+u`7M`azg$)=vhM^! zz9A47`)In+DWgMoX{kAD-R9jNspFdUXw@`p>dg0ZEb=7o?%{#+8=5*id|!p!RDMq* zXO=Ek?w6Y6;!;yV0Y%-pcXB}@e8ttc(zdFMl*sC)Gk&50~ z-CidPIXHQ;dAr1j`!Cvh$|CMV;SSwT_^#S|kcG0n;cSY%$z^-PY6k8P3*irpb=Cz# zBL?~*$?pvPN%}Jb*)g`ePMs`TOCx0|4NpuE@zrEOvD4O4H;c70%f1&`{N&BTPsVr9 zw8Eaz$rXE6-|QI}R?+cSKmiQ%hlq;K=oTn{#dfn}1J972{ybBMh7umPBXgI#sNxzwSzJucljYl(BI z;ils7kD6BnJ~wYK9uvYJ?i+pa1SL>PEBwAy?(O1S>BPx3RKPxUySuxq;1is4rDF6^ zuLY)Y;}2621ov>S&hvA%Kv`%kuPOnH5sHqS$n)e{0T~U2O~=P4rw7)l*K%6ZgdJNN zFKE+pUUHKWq2UoNrzJMrw50J=^{brfzOBNNT+!OtGpW&#iBqe3&k7A~Td#3o4cjUn z4deQb%;rJWH+yo#Um|g#9}^ePgK9h$<&|4}JGa&Mh0=+dU3cGgqn51A8u2smlhxsf zrB}tzXy@o?(RdBXUgAbB(3yj2loPu4>euPaXJ76-U-kz&ej&ZbEq4FQ!xSu~@jsK- zmxtN)O7j}EIRY&)D=|NwGVoKo^xpZMUw(F`Q@>ta%l?3FT4{t%HSGSa9_bg%+u3z= zt?|O2h5T}OIe(cZsn6*>@bwJqdiopkVezWag6NRISU(pxz2qMtMc@`ski_M7t2*|bqp(L<+R{vK+qeZcbn3fCM>M&UCP;-Z$ED+6vu%f`>- z-wo3(GKBaimubuRP{WK0_iTKB+IY}F$XvPcLI=#OJYL8smvk=EW#etG%7@{5BUc>% zV$}hd-=+)y4v*q<{+;7hgU9Bou=}$sj~8~?k^{zn$~s=mKd16|d=D`IFC3oodS|0wh-yG42yd8;Opxv{QvR_> z{_UI9gZt*<2Bp=`d4B5SLrw}TkRl9y`s0T0sZOG!WErR z_=1#gkjpKIG)TGJf(RI3IUWI%UYWl-BQ-W7Q&PHMj@)D3j;XC{YBDYVDr}*)X8AoD zd`Q;6*`oyCf4U+JFW=)^OCm&u{LomGHECG3MfDPDv)7T%?UB;>ntbjgiypZq*8EVw zg74^YtKFAf6Mg``zqNlAZMVzs-;gis;Ae3!;9n4q6lEOv&_ed~nKA?*`*ZsqbEI^k z(*DI=m|>muyZS=d_7xTGpE-=DEVeyb$i)ilc#ADv^|o!)yIIC(i}Ap(hIflCU0r#+ zkki!~pDXw&ZM+4Z5C0XO5Cd=}DY_iSq(jX^>Z7wWiI|>P$qAP-CYyY_H!G24b`hYqtf`-` zMexk`q&pY-4*rg>#1|mbPL{lV*~%^aa==0njrds~ z3e4h2;0SKH$=A=vhWcJG`$*neAdHUl?XcvXWU_3>!tXaMF^11yE3hX88cwnH4S6+i z>Yrq5?_+SqJ=hzZ7GR@%o7(Dlp{HdtaAaEGIITss&~D1-VxPg^(Q&>cE8a=R`370C zRn{y%g7UeDIh3s}&Qz{CMA@9Z)I>WUojqT?kvLTyu99zq-~-MWq7kvHC7L3NMrrYf zz|(XJ&llM15_X18En2;Lks7h>_Vt^;@)Oq5oH3ahDI$basBU)_4%r--WmRkg2Pd7+tN8XOZkcC*PGXG zV;Ru5h2<>g%A=n4KCU*2SPa}$jE&+hNG#(z-A>ykS%TC4I6+!6BK#FQR*$bkr?3tZ zVyJ{psS$i3es~sZgh!2_M7#q@W7QFE`Y=~k#HsADh)-r zTl3BM`r5kej0VXzfo6WT!ZJ0k;qcy z4Mt3!#;OiJUPkY#-kwGu52J&FkLHEI6|r%C%=`azw?s;WQ_RcbqY^MbG2t3C8ai=X zOru6owUZmL`(gX~Wq!1NDh1HB^LX^3wu^{N3Qw*b(3l<1oS3nO^2Q8VV^jL8>iDV_ z=lA8Wf35fi#PBr`fxYnWz=LHkvYV|_)rxyTP}^8#FH!}|?ZxEk<7PBEI#h8sIypHS z(X0r2sZwb#<@0%D4!T46fEL`9>YvAhil3&g|0uKHzMRGZ zwUfh>A|ohSalj)M$I@SI)(jbwM{6=BmhHvD)8d_qWiN=%scCA8*h^=`=+UOm$H&VB z`{Au_oIwdlRTTH%HFNm?7<&)Es*2@*{OmdB-kVA~0Rn`O1|*P>b`waW_YeZ4 zkw%9|4GBmMO(_8prAUz`D$&J@@7&gzx_s zO}KZ??Ck99?Ck8G+1b4%Q(rpVug5^83X#P_l&@?J>OQ)1_tG6NICfu2~f!4NSd9Ie}n)bEjb%b)aRH_E{=y&*7{xfvr1*u0&Ew#QDnRE*&Go`^QB0V{-Z! z^}T?Akd~n>e1co<(EdTuznX8$sG;2>BL?ugL`?55$d7<`lcFwe<8Wmwt;y-Q1~#)O zE|>37h+5fC9eQ>f*R5yI!|%U$_(ScM_MP^vcI(jU(pLuzT$HRX#!yU6g&wcevM5kj zsj4f`Zfc+575qn(ed+aC?HZHnMR0#Uuqb5ZWY1fcFs(aDPj4tTY6 z^&!;%EjYNv!-O3w_st$zT>k9KrIrj^<;vc=3S#Jyx_Ohipu=_Hf(67g>2=$@4E9sw zx*LQjvyt|O+v=8&G>%&SKk7EyoCsVnCK|2BKvCv&<-ViLQEw{*M+ezt?oc&5EP|u! z1Ewt*y3C=YT;}?Cag3jdVr$8deFaH7+z-oDLa65{Y0p6*dc?piX@-C2VO z>hQ2%lP4v2kB?_veXE|D_2NrYkJg7!i_q$IPa9ZCR8$EPUqyB;-K;2^XN=u#i>cP5 ztk*07ue@%ZR~}n!y2g2$3!awq^)7gl;CO`@!C0t@`x+>e+ZGrt#xqaZr``ca-IFJ2 zpK3on^(;k4v$OS4(?_Si^x~|is?^;jT^QIpv z5;oUZEc(J&#OIG2T(-0y)kUA%apMWSofDgWsNZB;oWOm@S=##WS~wIhY}NMH2iY#R zN7)*(EZZl@Zgu-?)uV1+hpq=a&err5ubb9N#ZA?%csT~j;s$ngY!jif+WxKV1$($G zDxPl>uaawdFhL&2+f8+dx>Zs4EnTOoR4?e1C;T%+Xei-W^1*uOGn>It5bH1W{A0H* zOp~SSft$)kc23h$*idb=h}LXj3*WTOWd`gu;oKE=w;==4VXR;A?)(k$9q-Ot(Vmg< z2PKdEUemdHINwjicg%Hn=_!>bd_Fb={6`xc`;40re;G#Qf&Y^u+yTF~9`4l20so#O z+yVb*8(gk3j^Xj0R)PpV#oC0A4R73t>#WFz*50nI-F)D6AOwdlsC4e>>aPedb%nJvt6h-E4MzjCs(OEy+icpUPRa5z}(Y~g@L_HYvEFUa93iLUOR78i_ z#|^LFskO%Bc3>i72Y!YLLnPka6P__FP?W5~%9#i+VM zk(zv*ofSh#gok2mN%#@_)HH6qaWdQ4)2mr)1|~%N(R#O@-X5r5T>}aDc-~1uFsP>x zL1PwdLriS#Bhx-Jsi|UMaTfScGx&?~Bmzb;zyuGr@#8I}(fZKM&{~mX2N}5aWU8Cf zMvpa+LqjeacZ4&>81^~1C!>do$`kqcV(ocHh-guRKOa{-PE_v+T{oRSB3;I1J6J10 zNB*$stn)_{ON|@yHj!lGs1soZ5Ji(;^!2^7j>;J@%7ex1PD~xsUQ@)5+LZ@n+7r7QxNahsTb1(x`r`r?0CY|P^^C1XT{3C!~^layaHje<*f=m#6QmF5XiKi`KCF(!X;zUF9Ne4oo( zN_-1Exp{gcL)q0N5kK=5_U>_f+uM`wX07E*wI+D-N9JQbx7i|5m}w4TPqthbBO*~S zA-hk^WwMW=;F1J zDGpr8IAh8bFBlJ-qzp9dL^O*2nj^@VXW2eUZdSKX1f_@&m0WG|RyLAC_;>^m@zs~= z7ksHARt_Tuq*uvr@>nWwd@+QF>Uw0Ot`=x-q_8fQs}xZoqAQexfAsu;qAI3Qe1(uV z{6-bF%@eT|bii4>`#|1vTzIF^aJLbsd7^VV@L90N1y8f^Js*APM5pj@3vz3h7`0_Hao!T!ZO3Vo6Pu9y zfG9&839ZIreY}FiC-vC}wj-7guGB9g3{kdImWHT@5w@e3Tz=#uWxywMhWyYUaOmS% z&}R8H%U`merMv8;84b6xElZ|l%d|lU+sbN{4C6ZNK{rQaC_j&n610;JEdc>~hva8g z;!SeMWMprQK}MXA$*i?@ht9`N{cNecy}CM^J;_Yd@UONW& zl?2JNu)l!p4=k9%rwP8xcYcHWc9xXH<>9uD0NGYPnp4Q~C$#f*8+26r~V zP7)o0JK($2!$H3u->sgG+hqrQcY;gITFd@WzLj@U{sRS_;H&&qXOegB6VI$nHQ<>^ zJi}&lkgwWO%e$iG0>$DY|ITG+t+g`41>iw;M1wY^Ij-Sfz{Tkk8@4EcI<3sK0{Dmn zbHEp6Oxt*wMx`3m<=h`-eI6+*$~zb6<(r`3P`|4)X!titL(p+;W2f^NN)9~X__@Kb zLC6W4LnKGG?+SbM@9*WE@^2Pb5~q;0;R5iuoahZfJ?uI8{ChBXd&PVF4uiLdX>c%Rx zLHnrgrt5zU50ByFalACikBuj3I5IxvDBQUA!+F)zx%;jp{_ZUWI(A&d1f;WZky< z^|9(jx}?xscp9!g^dg={?Ajl%Z{5lVZP}04w`{SEIjtG{1?JA;!c(pOE-7T|jV+;* zveXQog@patQ1TH$i+nI7T9RWv{YPC(R>XSWWxZLE_L6q`u69~`NooEGGEMxUwPN4x zvn!aqRzs(9TWZZQj)e_(C;p&QyFzyC%q_J6Ry>Spn&M|0Y@PjixYp`5{5 ztNA&t?)e-MDIeAJi7)f41Qdtip3a8pny{B-(e4h`}*GkvSpOPd>N7eKcp)K5XrhqK=5}N{jgO)_ybjYXdbL$!CwpTzgETm$Nr~P z(KpRw0sSy|9+C^q!_NIoX7qOya-W-VGkF^B+vtaz%7#)4$*r{i!rvs<*!ByLmi$lQ zgF>u+v7!2};W3|Sb`n2-V1E8X|4cK1@uxrj(9*=Ovb5>XnERXhQSLtim1K$vh~9WE8x`EWEFx{v+25B}Foshb+Cj)MOQ-!6#Z{gaug!P-KtR~Zs` zj4oqmP%Zz$c9dzog%03&;to+p31a@v*u)I-Wy{%_GHo>5S*G>U7Q(pT+ZZD7Hp<9S z3f3%@Y6-Y;k))tt=youvqoP*6KSA@H@IKr75J^-QpQH4IYKf(vOzu9)Va_&;LOBnz zOk98YsYNu#D@cJFd%3bNl~T*^>{rblnIWUJv*m2-4@^}{HfYy2Xe*y5g33phf5~B> zr%3a$&oLeM0LOu&fmnOd+r#j%6c*G4A8;9LJYD*StcKzr{)!2AeE8F@joA;o;Dk-V zvq+(yVCH+dbcMRfh$}Em18bK5XZdm^!|m!@lg8oa)6!QLEEqE2i*;{Lo?N-;Z%rFM zVspvy5#x)C^PeewqV5kiJZsgKg2HBO@~wkC(x>C&w)~>?&pph4=Tbnc_`{tdQC$C?xUWxiG+VJbKR+jDN6CcwW4a|xopP)r$x5NU4>c9Ca>0nl z_zG(|_2%-E$Xu#v4{zRNU)TQfOYOtoaA*);r*vd&*4i&W{P0Wd6x6FPi`G8Y&S;mFkLoU7{OtP0=W&zvZM-?7 zcVT#o!s)otYQx7?oYss%Sdt2|XiEb+n>Mj|?{fNU)e;*m_S@dQ+D;;`U4@>5Kcx!% zL7!+e*p%p$e7;_H>^cMdrD)#=$hFWFt>LlK)b+>$tam+yON&JMJaSs74lbYJ!6!!f zof*l=Wi!tY-alq^=CFQq`t z+IK%jqWjRF)PLL667=Uo04Te%q|{-Yz|LdW9+_~t#7yDlQzusqzAmq-J3DRQ33a|U zZglBp?TP*DOh)N4osMBB(NR9N(*@u7ewBZR-l!E^Z?gFJO33*)`Yty|y)x`kXM?la z6*`RXi1lu#Cv7qNN>GOQIQpwj{a%~){STKe-rcTU(rS^<^dd{5J1$tF9JS%#fsM}} zJox;5+^XSy|9^Cm1hr?TRBmuqex%cHp~0!hY%3_^!X$hqqR8=}zJD+x;u~$kHxUv0 zLqb?8?q~C6-Ga+AUd%jt;lk0(7c+*uTxh|<_L}x^A9 zyPIZS3EuOV!eL9=N%WEu$!B42s2K^E-jpMj>P{VgxHPn4YsZd1UF$!s%jO{;%%N7q z#_bz=bjXD#sbz7o`!bO2>HCfodpv*8x1iI+)XlH?_%2LH(0=}3;m%%F#m~hjprIwZ z)2c{2AYaq_=(jM;XRx^l%tA~*als8+bAPU*{>_m!8Crp?&cgoT0tI2w7<9&y7a*fI z6Si!^gttmBje#xO^~wou|w;Xlx?)R5TOw{?jZ%L=*C|*wAU-y)P+aupx z94`k+K^sIlsLLf>{o_lzwiz9G730MuY!-Ge@nS9%RuLxw;4QNZ#zu`DJ4)-%PMmr7 z-7}i?E#(94g`$H++xBb6_iHe>vJ``H;{h7YX=e@5{CHQIfSX(46w+*hr4j_rXBLuY zcgEfhGqV}i+vdyG84(O zVu}(H*yT>0MhuUDOWL?T%FB%<26|5q3FDy(j91QQE%v4v6&!wlPg?ixqhC9zE%*{0 zAiL`I$-})85{j^C^Y57X)POuBfXx~&me(}B-eRRrt zTlGbIu{I8A$IXkcv7N}I$-ZOqtdn1AxnG`K_{<*psHOXj+qZAXA6SO)vBIRo(qKb` z@;lAsq3{~TW-&ha1@l=+8DYtnckbMIcCY0rwdCN0vG)g`Sg>Hz!4oHX9w~qCk{EA? zr3~W@fq zCN-70^*Oin_2S}_WfkjQIhm9+XYKIeCr_qT&z+Y&lI*4K7s2l4aeJ7J{rPxqhx7UO zTaZMW; zA(LNlJhYhZRlxx9m!%UUld|7iIrWVbuTNclK09eRoWZWGhRnLmA`u5syM1BHd-qx{ z+>YUo?-whEv_f5jL3W`h?nO8HJ6-AnYujJjC*ULsHr0*;;P) z(}tN^iR@8#=CjX$X^^+8n^1=PnanSU{-Y@`p33>d&s0}yUD!KX5B9ZXk9KtY61F<$ zQ`X*ayZFyy?H|RTeWvuz)dsM)AReg_^|t~oy5|L6rw@5vLUj~B`$yOr5jbUY$+W8z zyT-(Hop|+3QRgmQIu~glus-XD4(-?>qiE8>9op+^g!XY**pQ*2p)9v9Ffcu>U0`8C z{J6ngI=gz8jhrzLO-DPZ?u~lgjy1y*6V>5bjIHmD%FiE#b4<*@yek(kUV=mme;bxr zW@ik2ZC^%4;rQ{Ne=%V^(PKnU{tEPTzsV++N;ymGjF=e^K}e zcfu9vQFL(S`3l=V1@KwR^tiF9Shvpp0$)T>nS`FEkVCCa}=*{rJ{%_{Tt z4WAny5HK=(|7+PJVe@%=l)-v?pzv7Xb0x-$gO3+4)?z9Rx3$+;PTd*05BeO=cMBl-gM_szZgl#G~Slch2lw4jxs z#pCNShEVk@dm+pRuWHFu{Z2Mon}>9d&*QcoA^%G#gYk(nP)ML(vAkutZ3!s0wdV$& za~`l;K;to30oAwf|MK>NUl#v5AE+1Qq`EWm*Ems=Vrg&hSEV1y(R+Yc3MURGRt~V; z3l3_GV!QA#Pgb`&YuK=?)m6jrqrJ}7%$YrVj#fTrj^X)H1v_^Xj2cz2V`ssrg4we# zd@y@<#cZ|)49QYI&`;&`(;ua;@NgyJ(vZmxkGGArdRLwl%naS)ipJiX)vI^!UbD)3 z_v+PiYgR&ha_HjHSbCd8LaNlqC%`ovr3Q&Of(>6DN)V2|1{B4Y5M$cTu@ zL4zaE?Q(E%WLU?RA)$lwT12Rc-4Z7Ei;3~}F(+ou?a^cD+{{F?k9T-X*8yERi7_gF z&1LTg>2vEq^9r{JT#LMdwOx79UAso-QTogsB$*w%Dhe#U`E&ccOG_Be; z-baC!ztj$LK=T4&>(DGc5?_pY`+7`H=@=FszGUUxE|HOgS6AY8$IPJ}J883a6%-W} zs3C40JM_Er*@)Hw+D@f+a`N1vadB*r_W9re17XCOwGOtW1?n=v$dP%($WfKn+L6WD z5tsl=fc&k{l^N)pbl_p0ht85mhHi(xpl#^!_!*0*&6{sdSUhT!wtW1N4$i(qzKsKe}aZhuW2KUHo+nmU-)3%g%6hgch`l>yP&2i^854)_4~|1 zvK=C?k#`%~q8!{Mp?AFg6lTUEk{cHhDaeDcXu+?0#O&0X1ans3l5X8+&FauSdF0f^ zyLP-(TAbW1DLy^9d(xJ{gOtx(x9MX}Pe~c)AE9k6P6`N^GHUV^mwp-U?yXAvTwVM2 zYfyh@)X(icH(za-2`_i`x@cPg*M|zp)Nd=q+c+pM=NzP`We%<9Avtl&;K9l@!9((R z{|GjLct}XdFHK0WapC3yF7)vspM@N7ZUubAV|5-n^gZ|K52YKU+ zVOy+&l4(B$%O8C|g`4eq@rs29j})esb6alqBkVBTFU7kkO^8dF`!-k|M?F3Knc*X3 zKT~>-Sv?k|rS<69vos?kx=ZigqvkBn9J+H)Tzqj#S$x`)NqJ9e%~@Prc1ibc&fly} zNa)z1@91vbashGngZc_J~fZJW_8+}zp+_3G6=Xi^auSa^6VbX)U;e~pNV?bq$hv*}+!T&FPlsRlz<|BQ?hSzOr z*h#i}(H7WB`8xWj73~T!WDgSZwkw`(t~KdXtx3La`N;`F@0FICn%c8R@7KnREh^mk z%<$pmBxFd|S@}7pG%?Ym85e6#&c>~y@`q(j9T6J?n`PHOs?!(tf5@O}x8b?zCON>v z*-vWiS#$M#&DEGe)qcYVRks+HKd9Pk#Hif2v1xfu^1yEZaxy0-=23u~;_N3I+*){3 znJ7fs;|xb0mb6`OK)0Xvm?Ss=hpLwO6P0Ai!;iR07 zd187SaNFYW#;tF@GUld`~533#HtC-Uj_rMlRA;*R7a zTTenM36-7hJJ`ljOl;>txtyi!E?wgjin|d@r7@ebhDAmwXWaY84ecC(dz1@NeH`bg zb-S)H?E+m~eM>w%V`BwJ&>wb)+Y)!;h{ghmgAZY|e?#WXxQa%1;B+(NkDC<+#>EvC z#^I;1C~jY7=F2ItK(R3~v1Lg~A&H3@ONVA=4qcj&m>5#7Oue0wnwmm?`tHgY>g?n> zzNMRMT>KNU=GFnZxvYI|Za`~uF?4z!+b7*Kc<^-~%`(A$SOv~2FE2NESk^vRx|I61 z0>0??7+($jt%?ekzX6vsKD}AnT47Wy8f%72q z*I>_@o5@jElcH{3?Rum#gcaf(R6C=azgKW;nI0x5Bq-dH;d=lNC+d!RCz0d7?nuA^Ke^qFt*58RpHbrMTJwQ6mC9rX!8pP52_cJ%$&Jo>5S>iat?3X`ugizw;kqV znCx2xcxZ<)>@dUf{Vm&ut**7Ee$lb92`?8F7Z&a677x20(=~PmtX$fRSbS9f@O5#{ z&E2v&FVDrrw-_@Lf6O#0MMxh_*%vA@d1jNlhc;e~LrqU8|@38xaw^A5hS zIVW4WKD{T*{>*KMb8@z!D3t||pC~-u%ZJY+3AlchZ^6Y!zh^I+ozt)=<{|WXE$T!r zcC^l}RJI8y#9?Oov7*9Z_F)t3vy%K!JF1K+w$DGi?URz=Em+>pZW!K$t(JWJ@VWpl z8@GAz)o9~AzV_#zqx;X9^K@+N$dQJ3k7Q~GheT#~j-1U#WFDcmO+(w>##qFTExcJ; z$J;zUo5wY+JUl$3D8XD_9$`)#ICqhf8)1Isd2^o+dA6Fg{GAJ)D9uAo~aqy5SieI0g z_VAnMX{$y>L?*<6dGRSBpPDhIdq8V?9fG>UV0*4ZCPv7F-r}<0u=!uzoUi@40|x3B zxtV1x;mOim^zRL$E8fx~MxOfDlNRc@ecKxww~%9eoFTqB-CXAP-*V=L8=Kg)YMf^M z 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 j`gGHx^%BJp(P!Y1 literal 0 HcmV?d00001 diff --git a/demo/demo-fshader.glsl b/demo/demo-fshader.glsl index d7872e41..a2c5cd18 100644 --- a/demo/demo-fshader.glsl +++ b/demo/demo-fshader.glsl @@ -85,22 +85,30 @@ main() float udist = abs (sdist); float gudist = abs (gsdist); - // Color the outline red + float pdist = glyphy_point_dist (p, gi.nominal_size GLYPHY_DEMO_EXTRA_ARGS); +/* // Color the outline red color += vec4 (1,0,0,1) * smoothstep (2., 1., udist); // Color the distance field in green if (!glyphy_isinf (udist)) color += vec4 (0,.3,0,(1. + sin (sdist)) * abs(1. - gsdist * 3.) / 3.); - float pdist = glyphy_point_dist (p, gi.nominal_size GLYPHY_DEMO_EXTRA_ARGS); + // Color points green color = mix (vec4 (0,1,0,.5), color, smoothstep (.05, .06, pdist)); glyphy_arc_list_t arc_list = glyphy_arc_list (p, gi.nominal_size GLYPHY_DEMO_EXTRA_ARGS); // Color the number of endpoints per cell blue color += vec4 (0,0,1,.1) * float(arc_list.num_endpoints) * 32./255.; +*/ + if (glyphy_isinf (sdf_vector.x) || glyphy_isinf (sdf_vector.y)) + color = vec4 (0, 0, 0, 1); - // if (sdf_vector.x >= 0. && sdf_vector.y >= 0.) - color = vec4 (0.5*(sdf_vector.x)+0.5, 0.5*(sdf_vector.y)+0.5, 0.0, 1); + else + color = vec4 (0.5*(sdf_vector.x)+0.5, 0.5*(sdf_vector.y)+0.5, 0.4, 1); + + + color += vec4 (1,1,1,1) * smoothstep (1.6, 1.4, udist); + color = mix (vec4 (0,0.2,0.2,.5), color, smoothstep (.04, .06, pdist)); // else // color = vec4 (0,0,0,1); } From d8f10c32a86c46b3825f4f72279978065d9d7064 Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Wed, 4 Jul 2012 18:17:45 -0400 Subject: [PATCH 34/35] Some work on anisotrpic antialias --- demo/demo-fshader.glsl | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/demo/demo-fshader.glsl b/demo/demo-fshader.glsl index a2c5cd18..81fce291 100644 --- a/demo/demo-fshader.glsl +++ b/demo/demo-fshader.glsl @@ -58,13 +58,35 @@ main() /* isotropic antialiasing */ vec2 dpdx = dFdx (p); vec2 dpdy = dFdy (p); + + float x1 = (dpdx.x - p.x) * (dpdx.x - p.x); + float y1 = (dpdx.y - p.y) * (dpdx.y - p.y); + float x2 = (dpdy.x - p.x) * (dpdy.x - p.x); + float y2 = (dpdy.y - p.y) * (dpdy.y - p.y); + + float a2 = y1 * ((x1 - x2) / (y2 - y1)) + x1; + float b2 = x1 * ((y2 - y1) / (x1 - x2)) + y1; + + + /*** We have (glyphy_iszero (abs (x1 / a2 + y1 / b2 - 1.) + abs (x2 / a2 + y2 / b2 - 1.))) ***/ + vec2 sdf_vector; + + float gsdist = glyphy_sdf (p, gi.nominal_size, sdf_vector GLYPHY_DEMO_EXTRA_ARGS); + + + float t = (sdf_vector.x * sdf_vector.x) / a2 + (sdf_vector.y * sdf_vector.y) / b2; + t = 1. / sqrt (t); + /** At this point, the intersection of the ellipse (centre p, through dpdx and dpdy) + * and the line (along sdf_vector, through p) + * is [p + t * sdf_vector]. + */ + float m = length (vec2 (length (dpdx), length (dpdy))) * SQRT2_2; + float w = abs (normalize (dpdx).x) + abs (normalize (dpdy).x); vec4 color = vec4 (0,0,0,1); - vec2 sdf_vector; - - float gsdist = glyphy_sdf (p, gi.nominal_size, sdf_vector GLYPHY_DEMO_EXTRA_ARGS); + float sdist = gsdist / m * u_contrast; if (!u_debug) { From 7c7575c26b8549a55f3bb724eb57208216ae3631 Mon Sep 17 00:00:00 2001 From: Maysum Panju Date: Mon, 9 Jul 2012 15:26:45 -0400 Subject: [PATCH 35/35] Enable anisotropic antialiasing: apply P_inverse to shortest vector when scaling. --- demo/demo-fshader.glsl | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/demo/demo-fshader.glsl b/demo/demo-fshader.glsl index 81fce291..ff2e587c 100644 --- a/demo/demo-fshader.glsl +++ b/demo/demo-fshader.glsl @@ -59,34 +59,26 @@ main() vec2 dpdx = dFdx (p); vec2 dpdy = dFdy (p); - float x1 = (dpdx.x - p.x) * (dpdx.x - p.x); - float y1 = (dpdx.y - p.y) * (dpdx.y - p.y); - float x2 = (dpdy.x - p.x) * (dpdy.x - p.x); - float y2 = (dpdy.y - p.y) * (dpdy.y - p.y); + float det = dpdx.x * dpdy.y - dpdx.y * dpdy.x; + mat2 P_inv = mat2(dpdy.y, -dpdx.y, -dpdy.x, dpdx.x) * (1. / det); + vec2 sdf_vector; - float a2 = y1 * ((x1 - x2) / (y2 - y1)) + x1; - float b2 = x1 * ((y2 - y1) / (x1 - x2)) + y1; + /* gdist is signed distance to nearest contour; sdf_vector is the shortest vector version. */ + float gsdist = glyphy_sdf (p, gi.nominal_size, sdf_vector GLYPHY_DEMO_EXTRA_ARGS); - /*** We have (glyphy_iszero (abs (x1 / a2 + y1 / b2 - 1.) + abs (x2 / a2 + y2 / b2 - 1.))) ***/ - vec2 sdf_vector; - - float gsdist = glyphy_sdf (p, gi.nominal_size, sdf_vector GLYPHY_DEMO_EXTRA_ARGS); - float t = (sdf_vector.x * sdf_vector.x) / a2 + (sdf_vector.y * sdf_vector.y) / b2; - t = 1. / sqrt (t); - /** At this point, the intersection of the ellipse (centre p, through dpdx and dpdy) - * and the line (along sdf_vector, through p) - * is [p + t * sdf_vector]. - */ - - float m = length (vec2 (length (dpdx), length (dpdy))) * SQRT2_2; + if (glyphy_iszero (det)) { + gl_FragColor = vec4(1,0,0,1); + return; + } - float w = abs (normalize (dpdx).x) + abs (normalize (dpdy).x); + float m = 1.;//SQRT2;//length (vec2 (length (dpdx), length (dpdy))); //1.0; + gsdist = sign (gsdist) * length (P_inv * sdf_vector); - vec4 color = vec4 (0,0,0,1); - + float w = abs (normalize (dpdx).x) + abs (normalize (dpdy).x); + vec4 color = vec4 (0,0,0,1); float sdist = gsdist / m * u_contrast; if (!u_debug) {