async save()

in src/core/annotation.js [2134:2268]


  async save(evaluator, task, annotationStorage, changes) {
    const storageEntry = annotationStorage?.get(this.data.id);
    const flags = this._buildFlags(storageEntry?.noView, storageEntry?.noPrint);
    let value = storageEntry?.value,
      rotation = storageEntry?.rotation;
    if (value === this.data.fieldValue || value === undefined) {
      if (
        !this._hasValueFromXFA &&
        rotation === undefined &&
        flags === undefined
      ) {
        return;
      }
      value ||= this.data.fieldValue;
    }

    // Value can be an array (with choice list and multiple selections)
    if (
      rotation === undefined &&
      !this._hasValueFromXFA &&
      Array.isArray(value) &&
      Array.isArray(this.data.fieldValue) &&
      isArrayEqual(value, this.data.fieldValue) &&
      flags === undefined
    ) {
      return;
    }

    if (rotation === undefined) {
      rotation = this.rotation;
    }

    let appearance = null;
    if (!this._needAppearances) {
      appearance = await this._getAppearance(
        evaluator,
        task,
        RenderingIntentFlag.SAVE,
        annotationStorage
      );
      if (appearance === null && flags === undefined) {
        // Appearance didn't change.
        return;
      }
    } else {
      // No need to create an appearance: the pdf has the flag /NeedAppearances
      // which means that it's up to the reader to produce an appearance.
    }

    let needAppearances = false;
    if (appearance?.needAppearances) {
      needAppearances = true;
      appearance = null;
    }

    const { xref } = evaluator;

    const originalDict = xref.fetchIfRef(this.ref);
    if (!(originalDict instanceof Dict)) {
      return;
    }

    const dict = new Dict(xref);
    for (const key of originalDict.getKeys()) {
      if (key !== "AP") {
        dict.set(key, originalDict.getRaw(key));
      }
    }
    if (flags !== undefined) {
      dict.set("F", flags);
      if (appearance === null && !needAppearances) {
        const ap = originalDict.getRaw("AP");
        if (ap) {
          dict.set("AP", ap);
        }
      }
    }

    const xfa = {
      path: this.data.fieldName,
      value,
    };

    const newParentDict = this.setValue(
      dict,
      Array.isArray(value)
        ? value.map(stringToAsciiOrUTF16BE)
        : stringToAsciiOrUTF16BE(value),
      xref,
      changes
    );
    this.amendSavedDict(annotationStorage, newParentDict || dict);

    const maybeMK = this._getMKDict(rotation);
    if (maybeMK) {
      dict.set("MK", maybeMK);
    }

    changes.put(this.ref, {
      data: dict,
      xfa,
      needAppearances,
    });
    if (appearance !== null) {
      const newRef = xref.getNewTemporaryRef();
      const AP = new Dict(xref);
      dict.set("AP", AP);
      AP.set("N", newRef);

      const resources = this._getSaveFieldResources(xref);
      const appearanceStream = new StringStream(appearance);
      const appearanceDict = (appearanceStream.dict = new Dict(xref));
      appearanceDict.set("Subtype", Name.get("Form"));
      appearanceDict.set("Resources", resources);
      const bbox =
        rotation % 180 === 0
          ? [0, 0, this.width, this.height]
          : [0, 0, this.height, this.width];
      appearanceDict.set("BBox", bbox);

      const rotationMatrix = this.getRotationMatrix(annotationStorage);
      if (rotationMatrix !== IDENTITY_MATRIX) {
        // The matrix isn't the identity one.
        appearanceDict.set("Matrix", rotationMatrix);
      }

      changes.put(newRef, {
        data: appearanceStream,
        xfa: null,
        needAppearances: false,
      });
    }

    dict.set("M", `D:${getModificationDate()}`);
  }