From 6bd8ac03be82830855c1ceced18f296b3d3e51b8 Mon Sep 17 00:00:00 2001 From: Kevin Rogovin Date: Tue, 17 Mar 2020 10:44:53 +0200 Subject: [PATCH 1/5] fastuidraw/glsl/shaders/fastuidraw_banded_rays, fastuidraw_restricted_rays: groaning fix for GLES3 --- .../glsl/shaders/fastuidraw_banded_rays.glsl.resource_string | 2 +- .../shaders/fastuidraw_restricted_rays.glsl.resource_string | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fastuidraw/glsl/shaders/fastuidraw_banded_rays.glsl.resource_string b/src/fastuidraw/glsl/shaders/fastuidraw_banded_rays.glsl.resource_string index 857d2422d..57b21de70 100644 --- a/src/fastuidraw/glsl/shaders/fastuidraw_banded_rays.glsl.resource_string +++ b/src/fastuidraw/glsl/shaders/fastuidraw_banded_rays.glsl.resource_string @@ -136,7 +136,7 @@ fastuidraw_banded_rays_compute_winding_contribution(in fastuidraw_banded_rays_cu || (curve.p3.y < 0.0 && curve.p2.y > 0.0) || (curve.p1.y >= 0.0 && curve.p2.y < 0.0); - use_t2 = (curve.p1.y < 0 && curve.p2.y > 0.0) + use_t2 = (curve.p1.y < 0.0 && curve.p2.y > 0.0) || (curve.p1.y < 0.0 && curve.p3.y > 0.0) || (curve.p3.y >= 0.0 && curve.p2.y < 0.0); diff --git a/src/fastuidraw/glsl/shaders/fastuidraw_restricted_rays.glsl.resource_string b/src/fastuidraw/glsl/shaders/fastuidraw_restricted_rays.glsl.resource_string index 9e0348213..4f2ca9432 100644 --- a/src/fastuidraw/glsl/shaders/fastuidraw_restricted_rays.glsl.resource_string +++ b/src/fastuidraw/glsl/shaders/fastuidraw_restricted_rays.glsl.resource_string @@ -455,7 +455,7 @@ fastuidraw_restricted_rays_compute_winding_contribution(in fastuidraw_restricted || (curve.p3.y < 0.0 && curve.p2.y > 0.0) || (curve.p1.y >= 0.0 && curve.p2.y < 0.0); - use_t2 = (curve.p1.y < 0 && curve.p2.y > 0.0) + use_t2 = (curve.p1.y < 0.0 && curve.p2.y > 0.0) || (curve.p1.y < 0.0 && curve.p3.y > 0.0) || (curve.p3.y >= 0.0 && curve.p2.y < 0.0); From 036d8ba571bba118490a9db5f20d8552a6a4c5ca Mon Sep 17 00:00:00 2001 From: Kevin Rogovin Date: Tue, 21 Apr 2020 15:21:54 +0300 Subject: [PATCH 2/5] fastuidraw/text/glyph_render_data_restricted_rays: different magic --- .../glyph_render_data_restricted_rays.cpp | 61 +++++++------------ 1 file changed, 21 insertions(+), 40 deletions(-) diff --git a/src/fastuidraw/text/glyph_render_data_restricted_rays.cpp b/src/fastuidraw/text/glyph_render_data_restricted_rays.cpp index f0ae8c3cc..46bb6f581 100644 --- a/src/fastuidraw/text/glyph_render_data_restricted_rays.cpp +++ b/src/fastuidraw/text/glyph_render_data_restricted_rays.cpp @@ -1077,85 +1077,66 @@ compute_winding_contribution_impl(int coord, { using namespace fastuidraw; - int iA, incr1, incr2; + int iA; float t1, t2, x1, x2; + bool use_t1, use_t2; iA = m_start[coord] - 2 * m_control[coord] + m_end[coord]; + use_t1 = (p3[coord] < 0.0f && p1[coord] > 0.0f) + || (p3[coord] < 0.0f && p2[coord] > 0.0f) + || (p1[coord] >= 0.0f && p2[coord] < 0.0f); + + use_t2 = (p1[coord] < 0.0f && p2[coord] > 0.0f) + || (p1[coord] < 0.0f && p3[coord] > 0.0f) + || (p3[coord] >= 0.0f && p2[coord] < 0.0f); + if (m_has_control && iA != 0) { - float D, rA, Ap, Bp, q1, q2, q3, sA; - int incr_base; - - sA = (iA > 0) ? 1.0 : -1.0; - incr_base = (iA > 0) ? 1 : -1; - Ap = sA * A[coord]; - Bp = sA * B[coord]; - q1 = sA * p1[coord]; - q2 = sA * p2[coord]; - q3 = sA * p3[coord]; + float D, rA; D = B[coord] * B[coord] - A[coord] * C[coord]; if (D > 0.0) { - rA = 1.0f / Ap; + rA = 1.0f / A[coord]; D = sqrt(D); - t1 = (Bp - D) * rA; - t2 = (Bp + D) * rA; - if ((q1 >= q2 && q1 >= 0.0) && (q3 > q2 || q3 < 0.0)) - { - incr1 = incr_base; - } - else - { - incr1 = 0; - } - - if ((q3 > q2 && q3 > 0.0) && (q1 >= q2 || q1 <= 0.0)) - { - incr2 = -incr_base; - } - else - { - incr2 = 0; - } + t1 = (B[coord] - D) * rA; + t2 = (B[coord] + D) * rA; } else { - incr1 = incr2 = 0; + use_t1 = use_t2 = false; t1 = t2 = 0.0f; } } else { t1 = t2 = 0.5f * C[coord] / B[coord]; - incr1 = (p1[coord] >= 0.0 && p3[coord] < 0.0) ? +1 : 0; - incr2 = (p1[coord] <= 0.0 && p3[coord] > 0.0) ? -1 : 0; } x1 = (A[1 - coord] * t1 - B[1 - coord] * 2.0f) * t1 + C[1 - coord]; x2 = (A[1 - coord] * t2 - B[1 - coord] * 2.0f) * t2 + C[1 - coord]; - if (t1 <= 1.0 && t1 >= 0.0f && incr1 != 0) + if (t1 <= 1.0 && t1 >= 0.0f && use_t1) { *dist = t_min(*dist, t_abs(x1)); } - if (t2 <= 1.0 && t2 >= 0.0f && incr2 != 0) + if (t2 <= 1.0 && t2 >= 0.0f && use_t2) { *dist = t_min(*dist, t_abs(x2)); } int r(0); - if (incr1 != 0 && x1 > 0.0f) + if (use_t1 && x1 > 0.0f) { - r += incr1; + ++r; } - if (incr2 != 0 && x2 > 0.0f) + if (use_t2 && x2 > 0.0f) { - r += incr2; + --r; } return r; From eca7688e8280b3e79df2a73d15eedd607b2b792e Mon Sep 17 00:00:00 2001 From: Kevin Rogovin Date: Tue, 21 Apr 2020 17:56:59 +0300 Subject: [PATCH 3/5] fastuidraw/text/glyph_render_data_restricted_rays: more robust way to compute the winding number at the sample point --- .../glyph_render_data_restricted_rays.cpp | 88 ++++++++++++------- 1 file changed, 57 insertions(+), 31 deletions(-) diff --git a/src/fastuidraw/text/glyph_render_data_restricted_rays.cpp b/src/fastuidraw/text/glyph_render_data_restricted_rays.cpp index 46bb6f581..9f27baf4e 100644 --- a/src/fastuidraw/text/glyph_render_data_restricted_rays.cpp +++ b/src/fastuidraw/text/glyph_render_data_restricted_rays.cpp @@ -270,9 +270,7 @@ namespace fastuidraw::vec2 A, fastuidraw::vec2 B, fastuidraw::vec2 C, - fastuidraw::vec2 p1, - fastuidraw::vec2 p2, - fastuidraw::vec2 p3, + float r, int v1, int v2, int v3, float *dist) const; float @@ -566,7 +564,8 @@ namespace m_child(nullptr, nullptr), m_offset(-1), m_splitting_coordinate(3), - m_generation(0) + m_generation(0), + m_mismatches(0) { m_curves.init(p, fastuidraw::vec2(min_pt), @@ -604,13 +603,20 @@ namespace float compute_average_node_cost(void) const; + int + mismatches(void) const + { + return m_mismatches; + } + private: explicit CurveListHierarchy(unsigned int parent_gen): m_child(nullptr, nullptr), m_offset(-1), m_splitting_coordinate(3), - m_generation(parent_gen + 1) + m_generation(parent_gen + 1), + m_mismatches(0) {} void @@ -638,7 +644,7 @@ namespace unsigned int m_offset, m_splitting_coordinate, m_generation; CurveList m_curves; - int m_winding; + int m_winding, m_mismatches; fastuidraw::ivec2 m_delta; }; @@ -700,7 +706,7 @@ namespace GlyphPath(void); int - compute_winding_number(fastuidraw::vec2 xy, float *dist) const; + compute_winding_number(fastuidraw::vec2 xy, float *dist, int *mismatch_found) const; void move_to(const fastuidraw::vec2 &pt) @@ -824,6 +830,7 @@ namespace node_average_cost, curve_average_cost, total_number_curves, + mismatches_found_const, num_costs }; @@ -1048,8 +1055,8 @@ compute_winding_contribution(fastuidraw::vec2 p, float *dist) const *dist = t_min(*dist, q.L1norm()); } - R.x() = -compute_winding_contribution_impl(0, A, B, C, p1, p2, p3, dist); - R.y() = compute_winding_contribution_impl(1, A, B, C, p1, p2, p3, dist); + R.x() = -compute_winding_contribution_impl(0, A, B, C, p.x(), m_start.x(), m_control.x(), m_end.x(), dist); + R.y() = compute_winding_contribution_impl(1, A, B, C, p.y(), m_start.y(), m_control.y(), m_end.y(), dist); if (m_has_control) { @@ -1070,9 +1077,7 @@ compute_winding_contribution_impl(int coord, fastuidraw::vec2 A, fastuidraw::vec2 B, fastuidraw::vec2 C, - fastuidraw::vec2 p1, - fastuidraw::vec2 p2, - fastuidraw::vec2 p3, + float rv, int v1, int v2, int v3, float *dist) const { using namespace fastuidraw; @@ -1081,33 +1086,34 @@ compute_winding_contribution_impl(int coord, float t1, t2, x1, x2; bool use_t1, use_t2; - iA = m_start[coord] - 2 * m_control[coord] + m_end[coord]; - - use_t1 = (p3[coord] < 0.0f && p1[coord] > 0.0f) - || (p3[coord] < 0.0f && p2[coord] > 0.0f) - || (p1[coord] >= 0.0f && p2[coord] < 0.0f); + /* TODO: if the reference value rv is an integer + * and if it is the same as one of v1 or + * or v3, this is not quite correct + */ + use_t1 = (v3 < rv && v1 >= rv) + || (v3 < rv && v2 >= rv) + || (v1 >= rv && v2 < rv); - use_t2 = (p1[coord] < 0.0f && p2[coord] > 0.0f) - || (p1[coord] < 0.0f && p3[coord] > 0.0f) - || (p3[coord] >= 0.0f && p2[coord] < 0.0f); + use_t2 = (v1 < rv && v2 >= rv) + || (v1 < rv && v3 >= rv) + || (v3 >= rv && v2 < rv); + iA = m_start[coord] - 2 * m_control[coord] + m_end[coord]; if (m_has_control && iA != 0) { - float D, rA; + float D, rA = 1.0f / A[coord]; D = B[coord] * B[coord] - A[coord] * C[coord]; - if (D > 0.0) + if (D >= 0.0f) { - rA = 1.0f / A[coord]; - - D = sqrt(D); + D = t_sqrt(D); t1 = (B[coord] - D) * rA; t2 = (B[coord] + D) * rA; } else { use_t1 = use_t2 = false; - t1 = t2 = 0.0f; + t1 = t2 = -1.0f; } } else @@ -1716,27 +1722,32 @@ subdivide(unsigned int max_recursion, unsigned int split_thresh, thresh = t_sqrt(box_size.x() * box_size.y()) * 0.01f; m_delta = ivec2(128, 128); m_winding = m_curves.glyph_path().compute_winding_number(pt + vec2(m_delta) * factor, - &best_dist); + &best_dist, &m_mismatches); for (int i = 0; i < MAX_TRIES && best_dist < thresh; ++i) { ivec2 idelta; vec2 delta; float dist; - int winding; + int winding, v; idelta.x() = std::rand() % GlyphRenderDataRestrictedRays::delta_div_factor; idelta.y() = std::rand() % GlyphRenderDataRestrictedRays::delta_div_factor; delta = vec2(idelta) * factor; - winding = m_curves.glyph_path().compute_winding_number(delta + pt, &dist); + winding = m_curves.glyph_path().compute_winding_number(delta + pt, &dist, &v); if (dist > best_dist) { m_delta = idelta; m_winding = winding; best_dist = dist; + m_mismatches = v; } } } + else + { + m_mismatches = m_child[0]->m_mismatches + m_child[1]->m_mismatches; + } } float @@ -2108,7 +2119,7 @@ pack_data(fastuidraw::c_array dst, int GlyphPath:: -compute_winding_number(fastuidraw::vec2 xy, float *dist) const +compute_winding_number(fastuidraw::vec2 xy, float *dist, int *mismatch_found) const { fastuidraw::ivec2 w(0, 0); @@ -2121,6 +2132,18 @@ compute_winding_number(fastuidraw::vec2 xy, float *dist) const } } + if (w.y() != w.x()) + { + *mismatch_found = 1; + // favor not covered over covered + w.y() = (fastuidraw::t_abs(w.y()) < fastuidraw::t_abs(w.x())) ? + w.y() : w.x(); + } + else + { + *mismatch_found = 0; + } + /* NOTE: if the point is on the curve, then the * winding value can be different in x and y. */ @@ -2130,7 +2153,8 @@ compute_winding_number(fastuidraw::vec2 xy, float *dist) const //////////////////////////////////////////////// // GlyphRenderDataRestrictedRaysPrivate methods GlyphRenderDataRestrictedRaysPrivate:: -GlyphRenderDataRestrictedRaysPrivate(void) +GlyphRenderDataRestrictedRaysPrivate(void): + m_costs(0.0f) { m_glyph = FASTUIDRAWnew GlyphPath(); } @@ -2324,6 +2348,7 @@ finalize(enum PainterEnums::fill_rule_t f, d->m_costs[node_average_cost] = hierarchy.compute_average_node_cost(); d->m_costs[curve_average_cost] = hierarchy.compute_average_curve_cost(); d->m_costs[total_number_curves] = d->m_glyph->number_curves(); + d->m_costs[mismatches_found_const] = hierarchy.mismatches(); FASTUIDRAWdelete(d->m_glyph); d->m_glyph = nullptr; @@ -2371,6 +2396,7 @@ render_info_labels(void) const [node_average_cost] = "AverageNodeCount", [curve_average_cost] = "AverageCurveCount", [total_number_curves] = "TotalNumberOfCurves", + [mismatches_found_const] = "MismatchesFound" }; return c_array(s, num_costs); } From 3fcfd6ed64c08205b216665bfcf4469d5a5c25d6 Mon Sep 17 00:00:00 2001 From: Kevin Rogovin Date: Tue, 21 Apr 2020 22:57:18 +0300 Subject: [PATCH 4/5] fastuidraw_restricted_rays.glsl.resource_string: fix algorithm on end point inclusion --- ...idraw_restricted_rays.glsl.resource_string | 72 +++++++++++-------- 1 file changed, 44 insertions(+), 28 deletions(-) diff --git a/src/fastuidraw/glsl/shaders/fastuidraw_restricted_rays.glsl.resource_string b/src/fastuidraw/glsl/shaders/fastuidraw_restricted_rays.glsl.resource_string index 4f2ca9432..c264c6644 100644 --- a/src/fastuidraw/glsl/shaders/fastuidraw_restricted_rays.glsl.resource_string +++ b/src/fastuidraw/glsl/shaders/fastuidraw_restricted_rays.glsl.resource_string @@ -412,52 +412,68 @@ fastuidraw_restricted_rays_compute_winding_contribution(in fastuidraw_restricted * = (p1 < 0 && p2 > 0) || (p1 < 0 && p3 > 0) || (p3 > 0 && p1 < 0) || (p3 > 0 && p2 < 0) * = (p1 < 0 && p2 > 0) || (p1 < 0 && p3 > 0) || (p3 > 0 && p2 < 0) * - * The last issue is to handle the end-points of the curve correctly. + * The last issue is to handle the end-points of the curve correctly + * * We use the rules: * - * (a) use 0 if and only if f(0) = 0 && f'(0) < 0 - * (b) use 1 if and only if f(1) = 1 && f'(1) > 0 + * (a) use 0 if and only if f(0) = 0 && f'(0) > 0 + * (b) use 1 if and only if f(1) = 1 && f'(1) < 0 + * + * For the case where p1.y = 0, one gets * - * Which become + * A = p3.y - 2 * p2.y + * B = -p2.y + * C = 0 + * + * thus, * - * (a) use 0 if and only if p1 == 0 && p2 < p1 - * (b) use 1 if and only if p3 == 0 && p2 < p3 + * B * B - A * C = p2.y * p2.y * - * If p1.y is zero, then + * which gives * - * t1 = (B - |B|) / A - * t2 = (B + |B|) / A + * t2 = (-p2.y + |p2.y|) / (p3.y - 2 * p2.y) * - * If p2 < 0 = p1, then B > 0 and thus t1 = 0, i.e. - * use t1 whenever (a) is true. + * for p2.y > 0, then t2 = 0 which corresponds to (a) + * and for p2.y < 0, t2 = -2 * p2.y / (p3.y - 2 * p2.y) + * which is 0 < t2 < 1 when p3.y > 0. So if p1.y is zero, + * use t2 if one of p3.y or p2.y is strictly positive. * - * If p3.y is zero, then algebra will give that + * For the case where p3.y = 0, one gets + * + * A = p1.y - 2 * p2.y + * B = p1.y - p2.y + * C = p1.y + * + * thus, * - * t1 = ((p1 - p2) - |p2|) / (p1 - 2p2) - * t2 = ((p1 - p2) + |p2|) / (p1 - 2p2) + * B * B - A * C = p2.y * p2.y * - * thus on condition (b) gives + * which gives * - * t1 = p1 / (p1 - 2p2) - * t2 = 1 + * t1 = (p1.y - p2.y - |p2.y|) / (p1.y - 2 * p2.y) * - * which means use t2 when (b) is true. + * for p2.y > 0, t1 = 1 and this correponds to (b) + * and for p2.y < 0, t1 = (p1.y) / (p1.y - 2 * p2.y) + * which is 0 < t1 < 1 if p1.y > 0. So if p3.y is zero, + * use t1 if one of p1.y or p2.y is strcitly positive. * * Thus, * - * use_t1 = T1 || (p1 == 0 && p2 < 0) - * = (p3 < 0 && p1 > 0) || (p3 < 0 && p2 > 0) || (p1 >= 0 && p2 < 0) + * use_t1 = T1 || (p3 == 0 && p2 > 0) || (p3 == 0 && p1 > 0) + * = (p3 <= 0 && p1 > 0) || (p3 <= 0 && p2 > 0) || (p1 > 0 && p2 < 0) + * = (p3 <= 0 && max(p1, p2) > 0) || (p1 > 0 && p2 < 0) * - * use_t2 = T2 || (p3 == 0 && p2 < 0) - * = (p1 < 0 && p2 > 0) || (p1 < 0 && p3 > 0) || (p3 >= 0 && p2 < 0) + * use_t2 = T2 || (p1 == 0 && p2 > 0) || (p1 == 0 && p3 > 0) + * = (p1 <= 0 && p2 > 0) || (p1 <= 0 && p3 > 0) || (p3 > 0 && p2 < 0) + * = (p1 <= 0 && max(p2, p3) > 0) || (p3 > 0 && p2 < 0) */ - use_t1 = (curve.p3.y < 0.0 && curve.p1.y > 0.0) - || (curve.p3.y < 0.0 && curve.p2.y > 0.0) - || (curve.p1.y >= 0.0 && curve.p2.y < 0.0); + use_t1 = (curve.p3.y <= 0.0 && curve.p1.y > 0.0) + || (curve.p3.y <= 0.0 && curve.p2.y > 0.0) + || (curve.p1.y > 0.0 && curve.p2.y < 0.0); - use_t2 = (curve.p1.y < 0.0 && curve.p2.y > 0.0) - || (curve.p1.y < 0.0 && curve.p3.y > 0.0) - || (curve.p3.y >= 0.0 && curve.p2.y < 0.0); + use_t2 = (curve.p1.y <= 0.0 && curve.p2.y > 0.0) + || (curve.p1.y <= 0.0 && curve.p3.y > 0.0) + || (curve.p3.y > 0.0 && curve.p2.y < 0.0); if (curve.is_quadratic && abs(A.y) > quad_tol) { From 79535700125f4e1ccfac7d8a6a97725f3f8805e4 Mon Sep 17 00:00:00 2001 From: Kevin Rogovin Date: Tue, 21 Apr 2020 22:58:07 +0300 Subject: [PATCH 5/5] fastuidraw/text/glyph_render_data_restricted_rays, fastuidraw/glsl/shaders/fastuidraw_banded_rays.glsl: update to new magic --- .../fastuidraw_banded_rays.glsl.resource_string | 12 ++++++------ .../text/glyph_render_data_restricted_rays.cpp | 17 ++++++++--------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/fastuidraw/glsl/shaders/fastuidraw_banded_rays.glsl.resource_string b/src/fastuidraw/glsl/shaders/fastuidraw_banded_rays.glsl.resource_string index 57b21de70..f8422a2fa 100644 --- a/src/fastuidraw/glsl/shaders/fastuidraw_banded_rays.glsl.resource_string +++ b/src/fastuidraw/glsl/shaders/fastuidraw_banded_rays.glsl.resource_string @@ -132,13 +132,13 @@ fastuidraw_banded_rays_compute_winding_contribution(in fastuidraw_banded_rays_cu B = curve.p1 - curve.p2; C = curve.p1; - use_t1 = (curve.p3.y < 0.0 && curve.p1.y > 0.0) - || (curve.p3.y < 0.0 && curve.p2.y > 0.0) - || (curve.p1.y >= 0.0 && curve.p2.y < 0.0); + use_t1 = (curve.p3.y <= 0.0 && curve.p1.y > 0.0) + || (curve.p3.y <= 0.0 && curve.p2.y > 0.0) + || (curve.p1.y > 0.0 && curve.p2.y < 0.0); - use_t2 = (curve.p1.y < 0.0 && curve.p2.y > 0.0) - || (curve.p1.y < 0.0 && curve.p3.y > 0.0) - || (curve.p3.y >= 0.0 && curve.p2.y < 0.0); + use_t2 = (curve.p1.y <= 0.0 && curve.p2.y > 0.0) + || (curve.p1.y <= 0.0 && curve.p3.y > 0.0) + || (curve.p3.y > 0.0 && curve.p2.y < 0.0); if (abs(A.y) > quad_tol) { diff --git a/src/fastuidraw/text/glyph_render_data_restricted_rays.cpp b/src/fastuidraw/text/glyph_render_data_restricted_rays.cpp index 9f27baf4e..0cdf46ad0 100644 --- a/src/fastuidraw/text/glyph_render_data_restricted_rays.cpp +++ b/src/fastuidraw/text/glyph_render_data_restricted_rays.cpp @@ -1086,17 +1086,16 @@ compute_winding_contribution_impl(int coord, float t1, t2, x1, x2; bool use_t1, use_t2; - /* TODO: if the reference value rv is an integer - * and if it is the same as one of v1 or - * or v3, this is not quite correct + /* For the derivation, see the shader file + * fastuidraw_restricted_rays.glsl.resource_string */ - use_t1 = (v3 < rv && v1 >= rv) - || (v3 < rv && v2 >= rv) - || (v1 >= rv && v2 < rv); + use_t1 = (v3 <= rv && v1 > rv) + || (v3 <= rv && v2 > rv) + || (v1 > rv && v2 < rv); - use_t2 = (v1 < rv && v2 >= rv) - || (v1 < rv && v3 >= rv) - || (v3 >= rv && v2 < rv); + use_t2 = (v1 <= rv && v2 > rv) + || (v1 <= rv && v3 > rv) + || (v3 > rv && v2 < rv); iA = m_start[coord] - 2 * m_control[coord] + m_end[coord]; if (m_has_control && iA != 0)