code: def _solve(tent, axisLimit, negative=False):
      (
          axisMin,
          axisDef,
          axisMax,
          _distanceNegative,
          _distancePositive,
      ) = axisLimit
      lower, peak, upper = tent
  
      # Mirror the problem such that axisDef <= peak
      if axisDef > peak:
          return [
              (scalar, _reverse_negate(t) if t is not None else None)
              for scalar, t in _solve(
                  _reverse_negate(tent),
                  axisLimit.reverse_negate(),
                  not negative,
              )
          ]
      # axisDef <= peak
  
      # case 1: The whole deltaset falls outside the new limit; we can drop it
      #
      #                                          peak
      #  1.........................................o..........
      #                                           / \
      #                                          /   \
      #                                         /     \
      #                                        /       \
      #  0---|-----------|----------|-------- o         o----1
      #    axisMin     axisDef    axisMax   lower     upper
      #
      if axisMax <= lower and axisMax < peak:
          return []  # 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
      # by the scalar value for the restricted axis at the new limit, and solve
      # recursively.
      #
      #                                  |peak
      #  1...............................|.o..........
      #                                  |/ \
      #                                  /   \
      #                                 /|    \
      #                                / |     \
      #  0--------------------------- o  |      o----1
      #                           lower  |      upper
      #                                  |
      #                                axisMax
      #
      # Convert to:
      #
      #  1............................................
      #                                  |
      #                                  o peak
      #                                 /|
      #                                /x|
      #  0--------------------------- o  o upper ----1
      #                           lower  |
      #                                  |
      #                                axisMax
      if axisMax < peak:
          mult = supportScalar({"tag": axisMax}, {"tag": tent})
          tent = (lower, axisMax, axisMax)
          return [
              (scalar * mult, t)
              for scalar, t in _solve(tent, axisLimit)
          ]
  
      # lower <= axisDef <= peak <= axisMax
  
      gain = supportScalar({"tag": axisDef}, {"tag": tent})
      out = [(gain, None)]
  
      # First, the positive side
  
      # outGain is the scalar of axisMax at the tent.
      outGain = supportScalar({"tag": axisMax}, {"tag": tent})
  
      # Case 3a: Gain is more than outGain. The tent down-slope crosses
      # the axis into negative. We have to split it into multiples.
      #
      #                      | peak  |
      #  1...................|.o.....|..............
      #                      |/x\_   |
      #  gain................+....+_.|..............
      #                     /|    |y\|
      #  ................../.|....|..+_......outGain
      #                   /  |    |  | \
      #  0---|-----------o   |    |  |  o----------1
      #    axisMin    lower  |    |  |   upper
      #                      |    |  |
      #                axisDef    |  axisMax
      #                           |
      #                      crossing
      if gain >= outGain:
          # Note that this is the branch taken if both gain and outGain are 0.
  
          # Crossing point on the axis.
          crossing = peak + (1 - gain) * (upper - peak)
  
          loc = (max(lower, axisDef), peak, crossing)
          scalar = 1
  
          # The part before the crossing point.
          out.append((scalar - gain, loc))
  
          # The part after the crossing point may use one or two tents,
          # depending on whether upper is before axisMax or not, in one
          # case we need to keep it down to eternity.
  
          # Case 3a1, similar to case 1neg; just one tent needed, as in
          # the drawing above.
          if upper >= axisMax:
              loc = (crossing, axisMax, axisMax)
              scalar = outGain
  
              out.append((scalar - gain, loc))
  
          # Case 3a2: Similar to case 2neg; two tents needed, to keep
          # down to eternity.
          #
          #                      | peak             |
          #  1...................|.o................|...
          #                      |/ \_              |
          #  gain................+....+_............|...
          #                     /|    | \xxxxxxxxxxy|
          #                    / |    |  \_xxxxxyyyy|
          #                   /  |    |    \xxyyyyyy|
          #  0---|-----------o   |    |     o-------|--1
          #    axisMin    lower  |    |      upper  |
          #                      |    |             |
          #                axisDef    |             axisMax
          #                           |
          #                      crossing
          else:
              # A tent's peak cannot fall on axis default. Nudge it.
              if upper == axisDef:
                  upper += EPSILON
  
              # Downslope.
              loc1 = (crossing, upper, axisMax)
              scalar1 = 0
  
              # Eternity justify.
              loc2 = (upper, axisMax, axisMax)
              scalar2 = 0
  
              out.append((scalar1 - gain, loc1))
              out.append((scalar2 - gain, loc2))
  
      else:
          # Special-case if peak is at axisMax.
          if axisMax == peak:
              upper = peak
  
          # Case 3:
          # We keep delta 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
          #
          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 and newUpper <= axisDef + (axisMax - axisDef) * 2:
              upper = newUpper
              if (
                  not negative
                  and 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
  
              loc = (max(axisDef, lower), peak, upper)
              scalar = 1
  
              out.append((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\|.............outGain
          #            |    |xxy|\_
          #            |   /xxxy|  \_
          #            |  |xxxxy|    \_
          #            |  /xxxxy|      \_
          #  0---|-----|-oxxxxxx|        o----------1
          #    axisMin | lower  |        upper
          #            |        |
          #          axisDef  axisMax
          #
          else:
              loc1 = (max(axisDef, lower), peak, axisMax)
              scalar1 = 1
  
              loc2 = (peak, axisMax, axisMax)
              scalar2 = outGain
  
              out.append((scalar1 - gain, loc1))
              # Don't add a dirac delta!
              if peak < axisMax:
                  out.append((scalar2 - gain, loc2))
  
      # Now, the negative side
  
      # Case 1neg: Lower extends beyond axisMin: we chop. Simple.
      #
      #                     |   |peak
      #  1..................|...|.o.................
      #                     |   |/ \
      #  gain...............|...+...\...............
      #                     |x_/|    \
      #                     |/  |     \
      #                   _/|   |      \
      #  0---------------o  |   |       o----------1
      #              lower  |   |       upper
      #                     |   |
      #               axisMin   axisDef
      #
      if lower <= axisMin:
          loc = (axisMin, axisMin, axisDef)
          scalar = supportScalar({"tag": axisMin}, {"tag": tent})
  
          out.append((scalar - gain, loc))
  
      # Case 2neg: Lower is betwen axisMin and axisDef: we add two
      # tents to keep it down all the way to eternity.
      #
      #      |               |peak
      #  1...|...............|.o.................
      #      |               |/ \
      #  gain|...............+...\...............
      #      |yxxxxxxxxxxxxx/|    \
      #      |yyyyyyxxxxxxx/ |     \
      #      |yyyyyyyyyyyx/  |      \
      #  0---|-----------o   |       o----------1
      #    axisMin    lower  |       upper
      #                      |
      #                    axisDef
      #
      else:
          # A tent's peak cannot fall on axis default. Nudge it.
          if lower == axisDef:
              lower -= EPSILON
  
          # Downslope.
          loc1 = (axisMin, lower, axisDef)
          scalar1 = 0
  
          # Eternity justify.
          loc2 = (axisMin, axisMin, lower)
          scalar2 = 0
  
          out.append((scalar1 - gain, loc1))
          out.append((scalar2 - gain, loc2))
  
      return out
  
imports: from fontTools.varLib.models import supportScalar
  from fontTools.misc.fixedTools import MAX_F2DOT14
  from functools import lru_cache
label_desc: Use image node_id 2 for calling a global function with example usage: _solve(tent, axisLimit, negative) and returns: out, unknown, list, unknown