function compareWithLastPosition()

in src/core/evaluator.js [2672:2881]


    function compareWithLastPosition(glyphWidth) {
      const currentTransform = getCurrentTextTransform();
      let posX = currentTransform[4];
      let posY = currentTransform[5];

      // Check if the glyph is in the viewbox.
      if (textState.font?.vertical) {
        if (
          posX < viewBox[0] ||
          posX > viewBox[2] ||
          posY + glyphWidth < viewBox[1] ||
          posY > viewBox[3]
        ) {
          return false;
        }
      } else if (
        posX + glyphWidth < viewBox[0] ||
        posX > viewBox[2] ||
        posY < viewBox[1] ||
        posY > viewBox[3]
      ) {
        return false;
      }

      if (!textState.font || !textContentItem.prevTransform) {
        return true;
      }

      let lastPosX = textContentItem.prevTransform[4];
      let lastPosY = textContentItem.prevTransform[5];

      if (lastPosX === posX && lastPosY === posY) {
        return true;
      }

      let rotate = -1;
      // Take into account the rotation is the current transform.
      if (
        currentTransform[0] &&
        currentTransform[1] === 0 &&
        currentTransform[2] === 0
      ) {
        rotate = currentTransform[0] > 0 ? 0 : 180;
      } else if (
        currentTransform[1] &&
        currentTransform[0] === 0 &&
        currentTransform[3] === 0
      ) {
        rotate = currentTransform[1] > 0 ? 90 : 270;
      }

      switch (rotate) {
        case 0:
          break;
        case 90:
          [posX, posY] = [posY, posX];
          [lastPosX, lastPosY] = [lastPosY, lastPosX];
          break;
        case 180:
          [posX, posY, lastPosX, lastPosY] = [
            -posX,
            -posY,
            -lastPosX,
            -lastPosY,
          ];
          break;
        case 270:
          [posX, posY] = [-posY, -posX];
          [lastPosX, lastPosY] = [-lastPosY, -lastPosX];
          break;
        default:
          // This is not a 0, 90, 180, 270 rotation so:
          //  - remove the scale factor from the matrix to get a rotation matrix
          //  - apply the inverse (which is the transposed) to the positions
          // and we can then compare positions of the glyphes to detect
          // a whitespace.
          [posX, posY] = applyInverseRotation(posX, posY, currentTransform);
          [lastPosX, lastPosY] = applyInverseRotation(
            lastPosX,
            lastPosY,
            textContentItem.prevTransform
          );
      }

      if (textState.font.vertical) {
        const advanceY = (lastPosY - posY) / textContentItem.textAdvanceScale;
        const advanceX = posX - lastPosX;

        // When the total height of the current chunk is negative
        // then we're writing from bottom to top.
        const textOrientation = Math.sign(textContentItem.height);
        if (advanceY < textOrientation * textContentItem.negativeSpaceMax) {
          if (
            Math.abs(advanceX) >
            0.5 * textContentItem.width /* not the same column */
          ) {
            appendEOL();
            return true;
          }

          resetLastChars();
          flushTextContentItem();
          return true;
        }

        if (Math.abs(advanceX) > textContentItem.width) {
          appendEOL();
          return true;
        }

        if (advanceY <= textOrientation * textContentItem.notASpace) {
          // The real spacing between 2 consecutive chars is thin enough to be
          // considered a non-space.
          resetLastChars();
        }

        if (advanceY <= textOrientation * textContentItem.trackingSpaceMin) {
          if (shouldAddWhitepsace()) {
            // The space is very thin, hence it deserves to have its own span in
            // order to avoid too much shift between the canvas and the text
            // layer.
            resetLastChars();
            flushTextContentItem();
            pushWhitespace({ height: Math.abs(advanceY) });
          } else {
            textContentItem.height += advanceY;
          }
        } else if (
          !addFakeSpaces(
            advanceY,
            textContentItem.prevTransform,
            textOrientation
          )
        ) {
          if (textContentItem.str.length === 0) {
            resetLastChars();
            pushWhitespace({ height: Math.abs(advanceY) });
          } else {
            textContentItem.height += advanceY;
          }
        }

        if (Math.abs(advanceX) > textContentItem.width * VERTICAL_SHIFT_RATIO) {
          flushTextContentItem();
        }

        return true;
      }

      const advanceX = (posX - lastPosX) / textContentItem.textAdvanceScale;
      const advanceY = posY - lastPosY;

      // When the total width of the current chunk is negative
      // then we're writing from right to left.
      const textOrientation = Math.sign(textContentItem.width);
      if (advanceX < textOrientation * textContentItem.negativeSpaceMax) {
        if (
          Math.abs(advanceY) >
          0.5 * textContentItem.height /* not the same line */
        ) {
          appendEOL();
          return true;
        }

        // We're moving back so in case the last char was a whitespace
        // we cancel it: it doesn't make sense to insert it.
        resetLastChars();
        flushTextContentItem();
        return true;
      }

      if (Math.abs(advanceY) > textContentItem.height) {
        appendEOL();
        return true;
      }

      if (advanceX <= textOrientation * textContentItem.notASpace) {
        // The real spacing between 2 consecutive chars is thin enough to be
        // considered a non-space.
        resetLastChars();
      }

      if (advanceX <= textOrientation * textContentItem.trackingSpaceMin) {
        if (shouldAddWhitepsace()) {
          // The space is very thin, hence it deserves to have its own span in
          // order to avoid too much shift between the canvas and the text
          // layer.
          resetLastChars();
          flushTextContentItem();
          pushWhitespace({ width: Math.abs(advanceX) });
        } else {
          textContentItem.width += advanceX;
        }
      } else if (
        !addFakeSpaces(advanceX, textContentItem.prevTransform, textOrientation)
      ) {
        if (textContentItem.str.length === 0) {
          resetLastChars();
          pushWhitespace({ width: Math.abs(advanceX) });
        } else {
          textContentItem.width += advanceX;
        }
      }

      if (Math.abs(advanceY) > textContentItem.height * VERTICAL_SHIFT_RATIO) {
        flushTextContentItem();
      }

      return true;
    }