summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/harfbuzz-ng/src/hb-subset-instancer-solver.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/harfbuzz-ng/src/hb-subset-instancer-solver.cc')
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-subset-instancer-solver.cc230
1 files changed, 100 insertions, 130 deletions
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-instancer-solver.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset-instancer-solver.cc
index 5c0f43ad4b..70783c0a0d 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-subset-instancer-solver.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-instancer-solver.cc
@@ -22,7 +22,7 @@
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
-#include "hb.hh"
+#include "hb-subset-instancer-solver.hh"
/* This file is a straight port of the following:
*
@@ -35,26 +35,6 @@
constexpr static float EPSILON = 1.f / (1 << 14);
constexpr static float MAX_F2DOT14 = float (0x7FFF) / (1 << 14);
-struct Triple {
-
- Triple () :
- minimum (0.f), middle (0.f), maximum (0.f) {}
-
- Triple (float minimum_, float middle_, float maximum_) :
- minimum (minimum_), middle (middle_), maximum (maximum_) {}
-
- bool operator == (const Triple &o) const
- {
- return minimum == o.minimum &&
- middle == o.middle &&
- maximum == o.maximum;
- }
-
- float minimum;
- float middle;
- float maximum;
-};
-
static inline Triple _reverse_negate(const Triple &v)
{ return {-v.maximum, -v.middle, -v.minimum}; }
@@ -82,10 +62,6 @@ static inline float supportScalar (float coord, const Triple &tent)
return (end - coord) / (end - peak);
}
-
-using result_item_t = hb_pair_t<float, Triple>;
-using result_t = hb_vector_t<result_item_t>;
-
static inline result_t
_solve (Triple tent, Triple axisLimit, bool negative = false)
{
@@ -125,7 +101,7 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
return result_t{}; // No overlap
/* case 2: Only the peak and outermost bound fall outside the new limit;
- * we keep the deltaset, update peak and outermost bound and and scale deltas
+ * we keep the deltaset, update peak and outermost bound and scale deltas
* by the scalar value for the restricted axis at the new limit, and solve
* recursively.
*
@@ -192,12 +168,14 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
* |
* crossing
*/
- if (gain > outGain)
+ if (gain >= outGain)
{
+ // Note that this is the branch taken if both gain and outGain are 0.
+
// Crossing point on the axis.
- float crossing = peak + ((1 - gain) * (upper - peak) / (1 - outGain));
+ float crossing = peak + (1 - gain) * (upper - peak);
- Triple loc{peak, peak, crossing};
+ Triple loc{hb_max (lower, axisDef), peak, crossing};
float scalar = 1.f;
// The part before the crossing point.
@@ -213,7 +191,7 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
if (upper >= axisMax)
{
Triple loc {crossing, axisMax, axisMax};
- float scalar = supportScalar (axisMax, tent);
+ float scalar = outGain;
out.push (hb_pair (scalar - gain, loc));
}
@@ -247,89 +225,85 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
// Eternity justify.
Triple loc2 {upper, axisMax, axisMax};
- float scalar2 = 1.f; // supportScalar({"tag": axisMax}, {"tag": tent})
+ float scalar2 = 0.f;
out.push (hb_pair (scalar1 - gain, loc1));
out.push (hb_pair (scalar2 - gain, loc2));
}
}
- /* Case 3: Outermost limit still fits within F2Dot14 bounds;
- * we keep deltas as is and only scale the axes bounds. Deltas beyond -1.0
- * or +1.0 will never be applied as implementations must clamp to that range.
- *
- * A second tent is needed for cases when gain is positive, though we add it
- * unconditionally and it will be dropped because scalar ends up 0.
- *
- * TODO: See if we can just move upper closer to adjust the slope, instead of
- * second tent.
- *
- * | peak |
- * 1.........|............o...|..................
- * | /x\ |
- * | /xxx\ |
- * | /xxxxx\|
- * | /xxxxxxx+
- * | /xxxxxxxx|\
- * 0---|-----|------oxxxxxxxxx|xo---------------1
- * axisMin | lower | upper
- * | |
- * axisDef axisMax
- */
- else if (axisDef + (axisMax - axisDef) * 2 >= upper)
+ else
{
- if (!negative && axisDef + (axisMax - axisDef) * MAX_F2DOT14 < upper)
- {
- // we clamp +2.0 to the max F2Dot14 (~1.99994) for convenience
- upper = axisDef + (axisMax - axisDef) * MAX_F2DOT14;
- assert (peak < upper);
- }
-
// Special-case if peak is at axisMax.
if (axisMax == peak)
upper = peak;
- Triple loc1 {hb_max (axisDef, lower), peak, upper};
- float scalar1 = 1.f;
+ /* Case 3:
+ * we keep deltas as is and only scale the axis upper to achieve
+ * the desired new tent if feasible.
+ *
+ * peak
+ * 1.....................o....................
+ * / \_|
+ * ..................../....+_.........outGain
+ * / | \
+ * gain..............+......|..+_.............
+ * /| | | \
+ * 0---|-----------o | | | o----------1
+ * axisMin lower| | | upper
+ * | | newUpper
+ * axisDef axisMax
+ */
+ float newUpper = peak + (1 - gain) * (upper - peak);
+ assert (axisMax <= newUpper); // Because outGain > gain
+ /* Disabled because ots doesn't like us:
+ * https://github.com/fonttools/fonttools/issues/3350 */
+
+ if (false && (newUpper <= axisDef + (axisMax - axisDef) * 2))
+ {
+ upper = newUpper;
+ if (!negative && axisDef + (axisMax - axisDef) * MAX_F2DOT14 < upper)
+ {
+ // we clamp +2.0 to the max F2Dot14 (~1.99994) for convenience
+ upper = axisDef + (axisMax - axisDef) * MAX_F2DOT14;
+ assert (peak < upper);
+ }
- Triple loc2 {peak, upper, upper};
- float scalar2 = 0.f;
+ Triple loc {hb_max (axisDef, lower), peak, upper};
+ float scalar = 1.f;
- // Don't add a dirac delta!
- if (axisDef < upper)
- out.push (hb_pair (scalar1 - gain, loc1));
- if (peak < upper)
- out.push (hb_pair (scalar2 - gain, loc2));
- }
+ out.push (hb_pair (scalar - gain, loc));
+ }
- /* Case 4: New limit doesn't fit; we need to chop into two tents,
- * because the shape of a triangle with part of one side cut off
- * cannot be represented as a triangle itself.
- *
- * | peak |
- * 1.........|......o.|...................
- * | /x\|
- * | |xxy|\_
- * | /xxxy| \_
- * | |xxxxy| \_
- * | /xxxxy| \_
- * 0---|-----|-oxxxxxx| o----------1
- * axisMin | lower | upper
- * | |
- * axisDef axisMax
- */
- else
- {
- Triple loc1 {hb_max (axisDef, lower), peak, axisMax};
- float scalar1 = 1.f;
+ /* Case 4: New limit doesn't fit; we need to chop into two tents,
+ * because the shape of a triangle with part of one side cut off
+ * cannot be represented as a triangle itself.
+ *
+ * | peak |
+ * 1.........|......o.|....................
+ * ..........|...../x\|.............outGain
+ * | |xxy|\_
+ * | /xxxy| \_
+ * | |xxxxy| \_
+ * | /xxxxy| \_
+ * 0---|-----|-oxxxxxx| o----------1
+ * axisMin | lower | upper
+ * | |
+ * axisDef axisMax
+ */
+ else
+ {
+ Triple loc1 {hb_max (axisDef, lower), peak, axisMax};
+ float scalar1 = 1.f;
- Triple loc2 {peak, axisMax, axisMax};
- float scalar2 = supportScalar (axisMax, tent);
+ Triple loc2 {peak, axisMax, axisMax};
+ float scalar2 = outGain;
- out.push (hb_pair (scalar1 - gain, loc1));
- // Don't add a dirac delta!
- if (peak < axisMax)
- out.push (hb_pair (scalar2 - gain, loc2));
+ out.push (hb_pair (scalar1 - gain, loc1));
+ // Don't add a dirac delta!
+ if (peak < axisMax)
+ out.push (hb_pair (scalar2 - gain, loc2));
+ }
}
/* Now, the negative side
@@ -392,51 +366,47 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
return out;
}
-/* Normalizes value based on a min/default/max triple. */
-static inline float normalizeValue (float v, const Triple &triple, bool extrapolate = false)
+static inline TripleDistances _reverse_triple_distances (const TripleDistances &v)
+{ return TripleDistances (v.positive, v.negative); }
+
+float renormalizeValue (float v, const Triple &triple,
+ const TripleDistances &triple_distances, bool extrapolate)
{
- /*
- >>> normalizeValue(400, (100, 400, 900))
- 0.0
- >>> normalizeValue(100, (100, 400, 900))
- -1.0
- >>> normalizeValue(650, (100, 400, 900))
- 0.5
- */
float lower = triple.minimum, def = triple.middle, upper = triple.maximum;
assert (lower <= def && def <= upper);
if (!extrapolate)
v = hb_max (hb_min (v, upper), lower);
- if ((v == def) || (lower == upper))
+ if (v == def)
return 0.f;
- if ((v < def && lower != def) || (v > def && upper == def))
+ if (def < 0.f)
+ return -renormalizeValue (-v, _reverse_negate (triple),
+ _reverse_triple_distances (triple_distances), extrapolate);
+
+ /* default >= 0 and v != default */
+ if (v > def)
+ return (v - def) / (upper - def);
+
+ /* v < def */
+ if (lower >= 0.f)
return (v - def) / (def - lower);
+
+ /* lower < 0 and v < default */
+ float total_distance = triple_distances.negative * (-lower) + triple_distances.positive * def;
+
+ float v_distance;
+ if (v >= 0.f)
+ v_distance = (def - v) * triple_distances.positive;
else
- {
- assert ((v > def && upper != def) ||
- (v < def && lower == def));
- return (v - def) / (upper - def);
- }
-}
+ v_distance = (-v) * triple_distances.negative + triple_distances.positive * def;
-/* Given a tuple (lower,peak,upper) "tent" and new axis limits
- * (axisMin,axisDefault,axisMax), solves how to represent the tent
- * under the new axis configuration. All values are in normalized
- * -1,0,+1 coordinate system. Tent values can be outside this range.
- *
- * Return value: a list of tuples. Each tuple is of the form
- * (scalar,tent), where scalar is a multipler to multiply any
- * delta-sets by, and tent is a new tent for that output delta-set.
- * If tent value is Triple{}, that is a special deltaset that should
- * be always-enabled (called "gain").
- */
-HB_INTERNAL result_t rebase_tent (Triple tent, Triple axisLimit);
+ return (-v_distance) /total_distance;
+}
result_t
-rebase_tent (Triple tent, Triple axisLimit)
+rebase_tent (Triple tent, Triple axisLimit, TripleDistances axis_triple_distances)
{
assert (-1.f <= axisLimit.minimum && axisLimit.minimum <= axisLimit.middle && axisLimit.middle <= axisLimit.maximum && axisLimit.maximum <= +1.f);
assert (-2.f <= tent.minimum && tent.minimum <= tent.middle && tent.middle <= tent.maximum && tent.maximum <= +2.f);
@@ -444,7 +414,7 @@ rebase_tent (Triple tent, Triple axisLimit)
result_t sols = _solve (tent, axisLimit);
- auto n = [&axisLimit] (float v) { return normalizeValue (v, axisLimit, true); };
+ auto n = [&axisLimit, &axis_triple_distances] (float v) { return renormalizeValue (v, axisLimit, axis_triple_distances); };
result_t out;
for (auto &p : sols)
@@ -460,5 +430,5 @@ rebase_tent (Triple tent, Triple axisLimit)
Triple{n (t.minimum), n (t.middle), n (t.maximum)}));
}
- return sols;
+ return out;
}