/* This file is a straight port of the following: * *https://github.com/fonttools/fonttools/blob/main/Lib/fontTools/varLib/iup.py * *Wherethatfilereturnsoptimzieddeltasvector,wereturnoptimized *referencedpointindices.
*/
constexpr staticunsigned MAX_LOOKBACK = 8;
staticvoid _iup_contour_bound_forced_set (const hb_array_t<const contour_point_t> contour_points, const hb_array_t<constint> x_deltas, const hb_array_t<constint> y_deltas,
hb_set_t& forced_set, /* OUT */ double tolerance = 0.0)
{ unsigned len = contour_points.length; unsigned next_i = 0; for (int i = len - 1; i >= 0; i--)
{ unsigned last_i = (len + i -1) % len; for (unsigned j = 0; j < 2; j++)
{ double cj, lcj, ncj; int dj, ldj, ndj; if (j == 0)
{
cj = static_cast<double> (contour_points.arrayZ[i].x);
dj = x_deltas.arrayZ[i];
lcj = static_cast<double> (contour_points.arrayZ[last_i].x);
ldj = x_deltas.arrayZ[last_i];
ncj = static_cast<double> (contour_points.arrayZ[next_i].x);
ndj = x_deltas.arrayZ[next_i];
} else
{
cj = static_cast<double> (contour_points.arrayZ[i].y);
dj = y_deltas.arrayZ[i];
lcj = static_cast<double> (contour_points.arrayZ[last_i].y);
ldj = y_deltas.arrayZ[last_i];
ncj = static_cast<double> (contour_points.arrayZ[next_i].y);
ndj = y_deltas.arrayZ[next_i];
}
staticbool rotate_set (const hb_set_t& org_set, int k, unsigned n,
hb_set_t& out)
{ if (!n) returnfalse;
k %= n; if (k < 0)
k = n + k;
if (k == 0)
{
out.set (org_set);
} else
{ for (auto v : org_set)
out.add ((v + k) % n);
} return !out.in_error ();
}
/* Given two reference coordinates (start and end of contour_points array),
* output interpolated deltas for points in between */ staticbool _iup_segment (const hb_array_t<const contour_point_t> contour_points, const hb_array_t<constint> x_deltas, const hb_array_t<constint> y_deltas, const contour_point_t& p1, const contour_point_t& p2, int p1_dx, int p2_dx, int p1_dy, int p2_dy,
hb_vector_t<double>& interp_x_deltas, /* OUT */
hb_vector_t<double>& interp_y_deltas /* OUT */)
{ unsigned n = contour_points.length; if (unlikely (!interp_x_deltas.resize (n, false) ||
!interp_y_deltas.resize (n, false))) returnfalse;
staticbool _iup_contour_optimize (const hb_array_t<const contour_point_t> contour_points, const hb_array_t<constint> x_deltas, const hb_array_t<constint> y_deltas,
hb_array_t<bool> opt_indices, /* OUT */ double tolerance = 0.0)
{ unsigned n = contour_points.length; if (opt_indices.length != n ||
x_deltas.length != n ||
y_deltas.length != n) returnfalse;
bool all_within_tolerance = true; for (unsigned i = 0; i < n; i++)
{ int dx = x_deltas.arrayZ[i]; int dy = y_deltas.arrayZ[i]; if (sqrt ((double) dx * dx + (double) dy * dy) > tolerance)
{
all_within_tolerance = false; break;
}
}
/* If all are within tolerance distance, do nothing, opt_indices is
* initilized to false */ if (all_within_tolerance) returntrue;
/* If there's exactly one point, return it */ if (n == 1)
{
opt_indices.arrayZ[0] = true; returntrue;
}
/* If all deltas are exactly the same, return just one (the first one) */ bool all_deltas_are_equal = true; for (unsigned i = 1; i < n; i++) if (x_deltas.arrayZ[i] != x_deltas.arrayZ[0] ||
y_deltas.arrayZ[i] != y_deltas.arrayZ[0])
{
all_deltas_are_equal = false; break;
}
if (all_deltas_are_equal)
{
opt_indices.arrayZ[0] = true; returntrue;
}
/* else, solve the general problem using Dynamic Programming */
hb_set_t forced_set;
_iup_contour_bound_forced_set (contour_points, x_deltas, y_deltas, forced_set, tolerance);
if (!forced_set.is_empty ())
{ int k = n - 1 - forced_set.get_max (); if (k < 0) returnfalse;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.