Merge pull request #17531 from calixteman/editor_free_highlight_print_save
[Editor] Add support for printing/saving free highlight annotations
This commit is contained in:
		
						commit
						f6c4b29aa2
					
				@ -355,13 +355,19 @@ class AnnotationFactory {
 | 
			
		||||
          );
 | 
			
		||||
          break;
 | 
			
		||||
        case AnnotationEditorType.HIGHLIGHT:
 | 
			
		||||
          promises.push(
 | 
			
		||||
            HighlightAnnotation.createNewAnnotation(
 | 
			
		||||
              xref,
 | 
			
		||||
              annotation,
 | 
			
		||||
              dependencies
 | 
			
		||||
            )
 | 
			
		||||
          );
 | 
			
		||||
          if (annotation.quadPoints) {
 | 
			
		||||
            promises.push(
 | 
			
		||||
              HighlightAnnotation.createNewAnnotation(
 | 
			
		||||
                xref,
 | 
			
		||||
                annotation,
 | 
			
		||||
                dependencies
 | 
			
		||||
              )
 | 
			
		||||
            );
 | 
			
		||||
          } else {
 | 
			
		||||
            promises.push(
 | 
			
		||||
              InkAnnotation.createNewAnnotation(xref, annotation, dependencies)
 | 
			
		||||
            );
 | 
			
		||||
          }
 | 
			
		||||
          break;
 | 
			
		||||
        case AnnotationEditorType.INK:
 | 
			
		||||
          promises.push(
 | 
			
		||||
@ -439,16 +445,29 @@ class AnnotationFactory {
 | 
			
		||||
          );
 | 
			
		||||
          break;
 | 
			
		||||
        case AnnotationEditorType.HIGHLIGHT:
 | 
			
		||||
          promises.push(
 | 
			
		||||
            HighlightAnnotation.createNewPrintAnnotation(
 | 
			
		||||
              annotationGlobals,
 | 
			
		||||
              xref,
 | 
			
		||||
              annotation,
 | 
			
		||||
              {
 | 
			
		||||
                evaluatorOptions: options,
 | 
			
		||||
              }
 | 
			
		||||
            )
 | 
			
		||||
          );
 | 
			
		||||
          if (annotation.quadPoints) {
 | 
			
		||||
            promises.push(
 | 
			
		||||
              HighlightAnnotation.createNewPrintAnnotation(
 | 
			
		||||
                annotationGlobals,
 | 
			
		||||
                xref,
 | 
			
		||||
                annotation,
 | 
			
		||||
                {
 | 
			
		||||
                  evaluatorOptions: options,
 | 
			
		||||
                }
 | 
			
		||||
              )
 | 
			
		||||
            );
 | 
			
		||||
          } else {
 | 
			
		||||
            promises.push(
 | 
			
		||||
              InkAnnotation.createNewPrintAnnotation(
 | 
			
		||||
                annotationGlobals,
 | 
			
		||||
                xref,
 | 
			
		||||
                annotation,
 | 
			
		||||
                {
 | 
			
		||||
                  evaluatorOptions: options,
 | 
			
		||||
                }
 | 
			
		||||
              )
 | 
			
		||||
            );
 | 
			
		||||
          }
 | 
			
		||||
          break;
 | 
			
		||||
        case AnnotationEditorType.INK:
 | 
			
		||||
          promises.push(
 | 
			
		||||
@ -4340,19 +4359,25 @@ class InkAnnotation extends MarkupAnnotation {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static createNewDict(annotation, xref, { apRef, ap }) {
 | 
			
		||||
    const { color, opacity, paths, rect, rotation, thickness } = annotation;
 | 
			
		||||
    const { color, opacity, paths, outlines, rect, rotation, thickness } =
 | 
			
		||||
      annotation;
 | 
			
		||||
    const ink = new Dict(xref);
 | 
			
		||||
    ink.set("Type", Name.get("Annot"));
 | 
			
		||||
    ink.set("Subtype", Name.get("Ink"));
 | 
			
		||||
    ink.set("CreationDate", `D:${getModificationDate()}`);
 | 
			
		||||
    ink.set("Rect", rect);
 | 
			
		||||
    ink.set(
 | 
			
		||||
      "InkList",
 | 
			
		||||
      paths.map(p => p.points)
 | 
			
		||||
    );
 | 
			
		||||
    ink.set("InkList", outlines?.points || paths.map(p => p.points));
 | 
			
		||||
    ink.set("F", 4);
 | 
			
		||||
    ink.set("Rotate", rotation);
 | 
			
		||||
 | 
			
		||||
    if (outlines) {
 | 
			
		||||
      // Free highlight.
 | 
			
		||||
      // There's nothing about this in the spec, but it's used when highlighting
 | 
			
		||||
      // in Edge's viewer. Acrobat takes into account this parameter to indicate
 | 
			
		||||
      // that the Ink is used for highlighting.
 | 
			
		||||
      ink.set("IT", Name.get("InkHighlight"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Line thickness.
 | 
			
		||||
    const bs = new Dict(xref);
 | 
			
		||||
    ink.set("BS", bs);
 | 
			
		||||
@ -4380,6 +4405,13 @@ class InkAnnotation extends MarkupAnnotation {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static async createNewAppearanceStream(annotation, xref, params) {
 | 
			
		||||
    if (annotation.outlines) {
 | 
			
		||||
      return this.createNewAppearanceStreamForHighlight(
 | 
			
		||||
        annotation,
 | 
			
		||||
        xref,
 | 
			
		||||
        params
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    const { color, rect, paths, thickness, opacity } = annotation;
 | 
			
		||||
 | 
			
		||||
    const appearanceBuffer = [
 | 
			
		||||
@ -4438,6 +4470,65 @@ class InkAnnotation extends MarkupAnnotation {
 | 
			
		||||
 | 
			
		||||
    return ap;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static async createNewAppearanceStreamForHighlight(annotation, xref, params) {
 | 
			
		||||
    const {
 | 
			
		||||
      color,
 | 
			
		||||
      rect,
 | 
			
		||||
      outlines: { outline },
 | 
			
		||||
      opacity,
 | 
			
		||||
    } = annotation;
 | 
			
		||||
    const appearanceBuffer = [
 | 
			
		||||
      `${getPdfColor(color, /* isFill */ true)}`,
 | 
			
		||||
      "/R0 gs",
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    appearanceBuffer.push(
 | 
			
		||||
      `${numberToString(outline[4])} ${numberToString(outline[5])} m`
 | 
			
		||||
    );
 | 
			
		||||
    for (let i = 6, ii = outline.length; i < ii; i += 6) {
 | 
			
		||||
      if (isNaN(outline[i]) || outline[i] === null) {
 | 
			
		||||
        appearanceBuffer.push(
 | 
			
		||||
          `${numberToString(outline[i + 4])} ${numberToString(
 | 
			
		||||
            outline[i + 5]
 | 
			
		||||
          )} l`
 | 
			
		||||
        );
 | 
			
		||||
      } else {
 | 
			
		||||
        const curve = outline
 | 
			
		||||
          .slice(i, i + 6)
 | 
			
		||||
          .map(numberToString)
 | 
			
		||||
          .join(" ");
 | 
			
		||||
        appearanceBuffer.push(`${curve} c`);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    appearanceBuffer.push("h f");
 | 
			
		||||
    const appearance = appearanceBuffer.join("\n");
 | 
			
		||||
 | 
			
		||||
    const appearanceStreamDict = new Dict(xref);
 | 
			
		||||
    appearanceStreamDict.set("FormType", 1);
 | 
			
		||||
    appearanceStreamDict.set("Subtype", Name.get("Form"));
 | 
			
		||||
    appearanceStreamDict.set("Type", Name.get("XObject"));
 | 
			
		||||
    appearanceStreamDict.set("BBox", rect);
 | 
			
		||||
    appearanceStreamDict.set("Length", appearance.length);
 | 
			
		||||
 | 
			
		||||
    const resources = new Dict(xref);
 | 
			
		||||
    const extGState = new Dict(xref);
 | 
			
		||||
    resources.set("ExtGState", extGState);
 | 
			
		||||
    appearanceStreamDict.set("Resources", resources);
 | 
			
		||||
    const r0 = new Dict(xref);
 | 
			
		||||
    extGState.set("R0", r0);
 | 
			
		||||
    r0.set("BM", Name.get("Multiply"));
 | 
			
		||||
 | 
			
		||||
    if (opacity !== 1) {
 | 
			
		||||
      r0.set("ca", opacity);
 | 
			
		||||
      r0.set("Type", Name.get("ExtGState"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const ap = new StringStream(appearance);
 | 
			
		||||
    ap.dict = appearanceStreamDict;
 | 
			
		||||
 | 
			
		||||
    return ap;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class HighlightAnnotation extends MarkupAnnotation {
 | 
			
		||||
 | 
			
		||||
@ -32,7 +32,7 @@ async function writeObject(ref, obj, buffer, { encrypt = null }) {
 | 
			
		||||
    await writeDict(obj, buffer, transform);
 | 
			
		||||
  } else if (obj instanceof BaseStream) {
 | 
			
		||||
    await writeStream(obj, buffer, transform);
 | 
			
		||||
  } else if (Array.isArray(obj)) {
 | 
			
		||||
  } else if (Array.isArray(obj) || ArrayBuffer.isView(obj)) {
 | 
			
		||||
    await writeArray(obj, buffer, transform);
 | 
			
		||||
  }
 | 
			
		||||
  buffer.push("\nendobj\n");
 | 
			
		||||
@ -132,7 +132,7 @@ async function writeValue(value, buffer, transform) {
 | 
			
		||||
    buffer.push(`/${escapePDFName(value.name)}`);
 | 
			
		||||
  } else if (value instanceof Ref) {
 | 
			
		||||
    buffer.push(`${value.num} ${value.gen} R`);
 | 
			
		||||
  } else if (Array.isArray(value)) {
 | 
			
		||||
  } else if (Array.isArray(value) || ArrayBuffer.isView(value)) {
 | 
			
		||||
    await writeArray(value, buffer, transform);
 | 
			
		||||
  } else if (typeof value === "string") {
 | 
			
		||||
    if (transform) {
 | 
			
		||||
 | 
			
		||||
@ -597,6 +597,7 @@ class HighlightEditor extends AnnotationEditor {
 | 
			
		||||
      annotationType: AnnotationEditorType.HIGHLIGHT,
 | 
			
		||||
      color,
 | 
			
		||||
      opacity: this.#opacity,
 | 
			
		||||
      thickness: 2 * HighlightEditor._defaultThickness,
 | 
			
		||||
      quadPoints: this.#serializeBoxes(rect),
 | 
			
		||||
      outlines: this.#serializeOutlines(rect),
 | 
			
		||||
      pageIndex: this.pageIndex,
 | 
			
		||||
 | 
			
		||||
@ -596,6 +596,12 @@ class FreeOutliner {
 | 
			
		||||
    const lastBottom = last.subarray(16, 18);
 | 
			
		||||
    const [layerX, layerY, layerWidth, layerHeight] = this.#box;
 | 
			
		||||
 | 
			
		||||
    const points = new Float64Array(this.#points?.length ?? 0);
 | 
			
		||||
    for (let i = 0, ii = points.length; i < ii; i += 2) {
 | 
			
		||||
      points[i] = (this.#points[i] - layerX) / layerWidth;
 | 
			
		||||
      points[i + 1] = (this.#points[i + 1] - layerY) / layerHeight;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (isNaN(last[6]) && !this.isEmpty()) {
 | 
			
		||||
      // We've only two points.
 | 
			
		||||
      const outline = new Float64Array(24);
 | 
			
		||||
@ -628,7 +634,12 @@ class FreeOutliner {
 | 
			
		||||
        ],
 | 
			
		||||
        0
 | 
			
		||||
      );
 | 
			
		||||
      return new FreeHighlightOutline(outline, this.#innerMargin, isLTR);
 | 
			
		||||
      return new FreeHighlightOutline(
 | 
			
		||||
        outline,
 | 
			
		||||
        points,
 | 
			
		||||
        this.#innerMargin,
 | 
			
		||||
        isLTR
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const outline = new Float64Array(
 | 
			
		||||
@ -675,7 +686,7 @@ class FreeOutliner {
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    outline.set([NaN, NaN, NaN, NaN, bottom[4], bottom[5]], N);
 | 
			
		||||
    return new FreeHighlightOutline(outline, this.#innerMargin, isLTR);
 | 
			
		||||
    return new FreeHighlightOutline(outline, points, this.#innerMargin, isLTR);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -684,11 +695,14 @@ class FreeHighlightOutline extends Outline {
 | 
			
		||||
 | 
			
		||||
  #innerMargin;
 | 
			
		||||
 | 
			
		||||
  #points;
 | 
			
		||||
 | 
			
		||||
  #outline;
 | 
			
		||||
 | 
			
		||||
  constructor(outline, innerMargin, isLTR) {
 | 
			
		||||
  constructor(outline, points, innerMargin, isLTR) {
 | 
			
		||||
    super();
 | 
			
		||||
    this.#outline = outline;
 | 
			
		||||
    this.#points = points;
 | 
			
		||||
    this.#innerMargin = innerMargin;
 | 
			
		||||
    this.#computeMinMax(isLTR);
 | 
			
		||||
 | 
			
		||||
@ -697,6 +711,10 @@ class FreeHighlightOutline extends Outline {
 | 
			
		||||
      outline[i] = (outline[i] - x) / width;
 | 
			
		||||
      outline[i + 1] = (outline[i + 1] - y) / height;
 | 
			
		||||
    }
 | 
			
		||||
    for (let i = 0, ii = points.length; i < ii; i += 2) {
 | 
			
		||||
      points[i] = (points[i] - x) / width;
 | 
			
		||||
      points[i + 1] = (points[i + 1] - y) / height;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  toSVGPath() {
 | 
			
		||||
@ -717,36 +735,53 @@ class FreeHighlightOutline extends Outline {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  serialize([blX, blY, trX, trY], rotation) {
 | 
			
		||||
    const src = this.#outline;
 | 
			
		||||
    const outline = new Float64Array(src.length);
 | 
			
		||||
    const width = trX - blX;
 | 
			
		||||
    const height = trY - blY;
 | 
			
		||||
    let outline;
 | 
			
		||||
    let points;
 | 
			
		||||
    switch (rotation) {
 | 
			
		||||
      case 0:
 | 
			
		||||
        for (let i = 0, ii = src.length; i < ii; i += 2) {
 | 
			
		||||
          outline[i] = blX + src[i] * width;
 | 
			
		||||
          outline[i + 1] = trY - src[i + 1] * height;
 | 
			
		||||
        }
 | 
			
		||||
        outline = this.#rescale(this.#outline, blX, trY, width, -height);
 | 
			
		||||
        points = this.#rescale(this.#points, blX, trY, width, -height);
 | 
			
		||||
        break;
 | 
			
		||||
      case 90:
 | 
			
		||||
        for (let i = 0, ii = src.length; i < ii; i += 2) {
 | 
			
		||||
          outline[i] = blX + src[i + 1] * width;
 | 
			
		||||
          outline[i + 1] = blY + src[i] * height;
 | 
			
		||||
        }
 | 
			
		||||
        outline = this.#rescaleAndSwap(this.#outline, blX, blY, width, height);
 | 
			
		||||
        points = this.#rescaleAndSwap(this.#points, blX, blY, width, height);
 | 
			
		||||
        break;
 | 
			
		||||
      case 180:
 | 
			
		||||
        for (let i = 0, ii = src.length; i < ii; i += 2) {
 | 
			
		||||
          outline[i] = trX - src[i] * width;
 | 
			
		||||
          outline[i + 1] = blY + src[i + 1] * height;
 | 
			
		||||
        }
 | 
			
		||||
        outline = this.#rescale(this.#outline, trX, blY, -width, height);
 | 
			
		||||
        points = this.#rescale(this.#points, trX, blY, -width, height);
 | 
			
		||||
        break;
 | 
			
		||||
      case 270:
 | 
			
		||||
        for (let i = 0, ii = src.length; i < ii; i += 2) {
 | 
			
		||||
          outline[i] = trX - src[i + 1] * width;
 | 
			
		||||
          outline[i + 1] = trY - src[i] * height;
 | 
			
		||||
        }
 | 
			
		||||
        outline = this.#rescaleAndSwap(
 | 
			
		||||
          this.#outline,
 | 
			
		||||
          trX,
 | 
			
		||||
          trY,
 | 
			
		||||
          -width,
 | 
			
		||||
          -height
 | 
			
		||||
        );
 | 
			
		||||
        points = this.#rescaleAndSwap(this.#points, trX, trY, -width, -height);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    return outline;
 | 
			
		||||
    return { outline: Array.from(outline), points: [Array.from(points)] };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  #rescale(src, tx, ty, sx, sy) {
 | 
			
		||||
    const dest = new Float64Array(src.length);
 | 
			
		||||
    for (let i = 0, ii = src.length; i < ii; i += 2) {
 | 
			
		||||
      dest[i] = tx + src[i] * sx;
 | 
			
		||||
      dest[i + 1] = ty + src[i + 1] * sy;
 | 
			
		||||
    }
 | 
			
		||||
    return dest;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  #rescaleAndSwap(src, tx, ty, sx, sy) {
 | 
			
		||||
    const dest = new Float64Array(src.length);
 | 
			
		||||
    for (let i = 0, ii = src.length; i < ii; i += 2) {
 | 
			
		||||
      dest[i] = tx + src[i + 1] * sx;
 | 
			
		||||
      dest[i + 1] = ty + src[i] * sy;
 | 
			
		||||
    }
 | 
			
		||||
    return dest;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  #computeMinMax(isLTR) {
 | 
			
		||||
 | 
			
		||||
@ -9324,5 +9324,324 @@
 | 
			
		||||
        "structTreeParentId": null
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "id": "tracemonkey-free-highlights",
 | 
			
		||||
    "file": "pdfs/tracemonkey.pdf",
 | 
			
		||||
    "md5": "9a192d8b1a7dc652a19835f6f08098bd",
 | 
			
		||||
    "rounds": 1,
 | 
			
		||||
    "lastPage": 1,
 | 
			
		||||
    "type": "eq",
 | 
			
		||||
    "print": true,
 | 
			
		||||
    "annotationStorage": {
 | 
			
		||||
      "pdfjs_internal_editor_0": {
 | 
			
		||||
        "annotationType": 9,
 | 
			
		||||
        "color": [83, 255, 188],
 | 
			
		||||
        "opacity": 1,
 | 
			
		||||
        "thickness": 20,
 | 
			
		||||
        "quadPoints": null,
 | 
			
		||||
        "outlines": {
 | 
			
		||||
          "outline": [
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            74.55,
 | 
			
		||||
            697.13,
 | 
			
		||||
            78.51721472766205,
 | 
			
		||||
            696.5192209591247,
 | 
			
		||||
            79.29044208205713,
 | 
			
		||||
            696.4224516456007,
 | 
			
		||||
            80.05486887178773,
 | 
			
		||||
            696.3379903011609,
 | 
			
		||||
            80.81929566151834,
 | 
			
		||||
            696.253528956721,
 | 
			
		||||
            81.57617646110613,
 | 
			
		||||
            696.1784636392651,
 | 
			
		||||
            82.32551127055109,
 | 
			
		||||
            696.1127943487935,
 | 
			
		||||
            83.07484607999606,
 | 
			
		||||
            696.047125058322,
 | 
			
		||||
            83.81784340794434,
 | 
			
		||||
            695.9886636959667,
 | 
			
		||||
            84.55450325439585,
 | 
			
		||||
            695.9374102617279,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            85.65949302407317,
 | 
			
		||||
            695.8605301103697,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            87.03393143844572,
 | 
			
		||||
            715.8149755833261,
 | 
			
		||||
            85.48426194954816,
 | 
			
		||||
            715.9204201846449,
 | 
			
		||||
            84.87281761152917,
 | 
			
		||||
            715.9671985492615,
 | 
			
		||||
            84.26979673105028,
 | 
			
		||||
            716.0185774379673,
 | 
			
		||||
            83.66677585057136,
 | 
			
		||||
            716.0699563266733,
 | 
			
		||||
            83.07457849467843,
 | 
			
		||||
            716.1266344280523,
 | 
			
		||||
            82.4932046633715,
 | 
			
		||||
            716.1886117421047,
 | 
			
		||||
            81.9118308320646,
 | 
			
		||||
            716.2505890561571,
 | 
			
		||||
            81.34439691081282,
 | 
			
		||||
            716.3184503202297,
 | 
			
		||||
            80.7909028996162,
 | 
			
		||||
            716.3921955343225,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            77.95775603227756,
 | 
			
		||||
            716.8481332058944
 | 
			
		||||
          ],
 | 
			
		||||
          "points": [
 | 
			
		||||
            [
 | 
			
		||||
              76.25849755587352, 706.9926836109859, 86.14596273693202,
 | 
			
		||||
              705.2879914026346, 88.1916451881855, 705.2879914026346,
 | 
			
		||||
              90.23732763943899, 705.2879914026346, 92.28301009069247,
 | 
			
		||||
              705.2879914026346, 94.32869254194594, 705.2879914026346
 | 
			
		||||
            ]
 | 
			
		||||
          ]
 | 
			
		||||
        },
 | 
			
		||||
        "pageIndex": 0,
 | 
			
		||||
        "rect": [
 | 
			
		||||
          73.94723907946947, 695.0685301103697, 87.64593143844571,
 | 
			
		||||
          717.6401332058945
 | 
			
		||||
        ],
 | 
			
		||||
        "rotation": 0,
 | 
			
		||||
        "structTreeParentId": null
 | 
			
		||||
      },
 | 
			
		||||
      "pdfjs_internal_editor_1": {
 | 
			
		||||
        "annotationType": 9,
 | 
			
		||||
        "color": [128, 235, 255],
 | 
			
		||||
        "opacity": 1,
 | 
			
		||||
        "thickness": 20,
 | 
			
		||||
        "quadPoints": null,
 | 
			
		||||
        "outlines": {
 | 
			
		||||
          "outline": [
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            260.9547742578311,
 | 
			
		||||
            674.9666484352592,
 | 
			
		||||
            265.0119754286617,
 | 
			
		||||
            674.7200369564051,
 | 
			
		||||
            265.85057115055446,
 | 
			
		||||
            674.6816601253416,
 | 
			
		||||
            266.8029560253001,
 | 
			
		||||
            674.6436779453497,
 | 
			
		||||
            267.7553409000457,
 | 
			
		||||
            674.6056957653577,
 | 
			
		||||
            268.641418670916,
 | 
			
		||||
            674.586241754074,
 | 
			
		||||
            269.46118933791087,
 | 
			
		||||
            674.5853159114982,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            270.6908453384032,
 | 
			
		||||
            674.5839271476348,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            270.6417128415015,
 | 
			
		||||
            694.586095213411,
 | 
			
		||||
            269.2921378713866,
 | 
			
		||||
            694.5754310173227,
 | 
			
		||||
            268.590908898233,
 | 
			
		||||
            694.5902107638636,
 | 
			
		||||
            267.72828093997174,
 | 
			
		||||
            694.624035935381,
 | 
			
		||||
            266.8656529817105,
 | 
			
		||||
            694.6578611068985,
 | 
			
		||||
            266.117024794879,
 | 
			
		||||
            694.6914601264726,
 | 
			
		||||
            265.48239637947734,
 | 
			
		||||
            694.7248329941037,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            262.2852690081439,
 | 
			
		||||
            694.9245750690663
 | 
			
		||||
          ],
 | 
			
		||||
          "points": [
 | 
			
		||||
            [
 | 
			
		||||
              261.6200216329875, 684.9456117521628, 271.8481748830951,
 | 
			
		||||
              684.263717601745, 273.8938055331166, 684.263717601745,
 | 
			
		||||
              276.6213130664787, 684.263717601745, 278.6669437165002,
 | 
			
		||||
              684.6046646769539
 | 
			
		||||
            ]
 | 
			
		||||
          ]
 | 
			
		||||
        },
 | 
			
		||||
        "pageIndex": 0,
 | 
			
		||||
        "rect": [
 | 
			
		||||
          260.342789755033, 673.7919070919245, 271.30282984120134,
 | 
			
		||||
          695.7165951247766
 | 
			
		||||
        ],
 | 
			
		||||
        "rotation": 90,
 | 
			
		||||
        "structTreeParentId": null
 | 
			
		||||
      },
 | 
			
		||||
      "pdfjs_internal_editor_2": {
 | 
			
		||||
        "annotationType": 9,
 | 
			
		||||
        "color": [255, 203, 230],
 | 
			
		||||
        "opacity": 1,
 | 
			
		||||
        "thickness": 20,
 | 
			
		||||
        "quadPoints": null,
 | 
			
		||||
        "outlines": {
 | 
			
		||||
          "outline": [
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            350.1249530717911,
 | 
			
		||||
            692.6633944602168,
 | 
			
		||||
            345.38916289103776,
 | 
			
		||||
            693.0766494920856,
 | 
			
		||||
            344.5712435088917,
 | 
			
		||||
            693.1558187178291,
 | 
			
		||||
            343.92282969955727,
 | 
			
		||||
            693.2395419718531,
 | 
			
		||||
            343.2744158902228,
 | 
			
		||||
            693.3232652258769,
 | 
			
		||||
            342.6222941207318,
 | 
			
		||||
            693.408487931081,
 | 
			
		||||
            341.96646439108423,
 | 
			
		||||
            693.4952100874651,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            340.9827197966128,
 | 
			
		||||
            693.6252933220413,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            338.36438011302045,
 | 
			
		||||
            673.7956810233082,
 | 
			
		||||
            340.14908906785814,
 | 
			
		||||
            673.5603604426211,
 | 
			
		||||
            340.9899862433436,
 | 
			
		||||
            673.4556612067797,
 | 
			
		||||
            341.95789701237936,
 | 
			
		||||
            673.3403909673718,
 | 
			
		||||
            342.92580778141513,
 | 
			
		||||
            673.2251207279638,
 | 
			
		||||
            343.81937416539495,
 | 
			
		||||
            673.1375137282872,
 | 
			
		||||
            344.63859616431887,
 | 
			
		||||
            673.0775699683421,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            348.1346569560641,
 | 
			
		||||
            672.7609372902139
 | 
			
		||||
          ],
 | 
			
		||||
          "points": [
 | 
			
		||||
            [
 | 
			
		||||
              349.12980501392764, 682.7121658752152, 338.9013927576602,
 | 
			
		||||
              683.734981200226, 336.1738161559889, 683.734981200226,
 | 
			
		||||
              333.7871866295265, 684.4168580835666, 331.74150417827303,
 | 
			
		||||
              684.7577965252368
 | 
			
		||||
            ]
 | 
			
		||||
          ]
 | 
			
		||||
        },
 | 
			
		||||
        "pageIndex": 0,
 | 
			
		||||
        "rect": [
 | 
			
		||||
          337.7523801130204, 671.9689372902138, 350.7369530717911,
 | 
			
		||||
          694.4172933220414
 | 
			
		||||
        ],
 | 
			
		||||
        "rotation": 180,
 | 
			
		||||
        "structTreeParentId": null
 | 
			
		||||
      },
 | 
			
		||||
      "pdfjs_internal_editor_3": {
 | 
			
		||||
        "annotationType": 9,
 | 
			
		||||
        "color": [255, 79, 95],
 | 
			
		||||
        "opacity": 1,
 | 
			
		||||
        "thickness": 20,
 | 
			
		||||
        "quadPoints": null,
 | 
			
		||||
        "outlines": {
 | 
			
		||||
          "outline": [
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            534.1504350586464,
 | 
			
		||||
            715.0615382740357,
 | 
			
		||||
            530.2182783647162,
 | 
			
		||||
            715.0615382740357,
 | 
			
		||||
            529.5364014813756,
 | 
			
		||||
            715.0615382740357,
 | 
			
		||||
            528.8545245980351,
 | 
			
		||||
            715.0615382740357,
 | 
			
		||||
            528.1726477146946,
 | 
			
		||||
            715.0615382740357,
 | 
			
		||||
            527.4339477577424,
 | 
			
		||||
            715.0615382740357,
 | 
			
		||||
            526.6384247271785,
 | 
			
		||||
            715.0615382740357,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            525.4451401813326,
 | 
			
		||||
            715.0615382740357,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            525.4451401813326,
 | 
			
		||||
            695.0593098617794,
 | 
			
		||||
            527.4339477577424,
 | 
			
		||||
            695.0593098617794,
 | 
			
		||||
            528.1726477146946,
 | 
			
		||||
            695.0593098617794,
 | 
			
		||||
            528.8545245980351,
 | 
			
		||||
            695.0593098617794,
 | 
			
		||||
            529.5364014813756,
 | 
			
		||||
            695.0593098617794,
 | 
			
		||||
            530.2182783647162,
 | 
			
		||||
            695.0593098617794,
 | 
			
		||||
            530.9001552480566,
 | 
			
		||||
            695.0593098617794,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            null,
 | 
			
		||||
            534.1504350586464,
 | 
			
		||||
            695.0593098617794
 | 
			
		||||
          ],
 | 
			
		||||
          "points": [
 | 
			
		||||
            [
 | 
			
		||||
              534.1504350586464, 705.0604240679075, 523.9222818085387,
 | 
			
		||||
              705.0604240679075, 521.8766511585172, 705.0604240679075,
 | 
			
		||||
              519.8310205084957, 705.0604240679075, 517.444451416804,
 | 
			
		||||
              705.0604240679075
 | 
			
		||||
            ]
 | 
			
		||||
          ]
 | 
			
		||||
        },
 | 
			
		||||
        "pageIndex": 0,
 | 
			
		||||
        "rect": [
 | 
			
		||||
          524.8331556785345, 694.2672898060691, 534.7624195614445,
 | 
			
		||||
          715.853558329746
 | 
			
		||||
        ],
 | 
			
		||||
        "rotation": 270,
 | 
			
		||||
        "structTreeParentId": null
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
@ -4708,6 +4708,125 @@ describe("annotation", function () {
 | 
			
		||||
        OPS.endAnnotation,
 | 
			
		||||
      ]);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("should create a new free Highlight annotation", async function () {
 | 
			
		||||
      partialEvaluator.xref = new XRefMock();
 | 
			
		||||
      const task = new WorkerTask("test free Highlight creation");
 | 
			
		||||
      const data = await AnnotationFactory.saveNewAnnotations(
 | 
			
		||||
        partialEvaluator,
 | 
			
		||||
        task,
 | 
			
		||||
        [
 | 
			
		||||
          {
 | 
			
		||||
            annotationType: AnnotationEditorType.HIGHLIGHT,
 | 
			
		||||
            rect: [12, 34, 56, 78],
 | 
			
		||||
            rotation: 0,
 | 
			
		||||
            opacity: 1,
 | 
			
		||||
            color: [0, 0, 0],
 | 
			
		||||
            thickness: 3.14,
 | 
			
		||||
            quadPoints: null,
 | 
			
		||||
            outlines: {
 | 
			
		||||
              outline: Float64Array.from([
 | 
			
		||||
                NaN,
 | 
			
		||||
                NaN,
 | 
			
		||||
                8,
 | 
			
		||||
                9,
 | 
			
		||||
                10,
 | 
			
		||||
                11,
 | 
			
		||||
                NaN,
 | 
			
		||||
                NaN,
 | 
			
		||||
                12,
 | 
			
		||||
                13,
 | 
			
		||||
                14,
 | 
			
		||||
                15,
 | 
			
		||||
              ]),
 | 
			
		||||
              points: [Float64Array.from([16, 17, 18, 19])],
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        ]
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      const base = data.annotations[0].data.replace(/\(D:\d+\)/, "(date)");
 | 
			
		||||
      expect(base).toEqual(
 | 
			
		||||
        "1 0 obj\n" +
 | 
			
		||||
          "<< /Type /Annot /Subtype /Ink /CreationDate (date) /Rect [12 34 56 78] " +
 | 
			
		||||
          "/InkList [[16 17 18 19]] /F 4 /Rotate 0 /IT /InkHighlight /BS << /W 3.14>> " +
 | 
			
		||||
          "/C [0 0 0] /CA 1 /AP << /N 2 0 R>>>>\n" +
 | 
			
		||||
          "endobj\n"
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      const appearance = data.dependencies[0].data;
 | 
			
		||||
      expect(appearance).toEqual(
 | 
			
		||||
        "2 0 obj\n" +
 | 
			
		||||
          "<< /FormType 1 /Subtype /Form /Type /XObject /BBox [12 34 56 78] " +
 | 
			
		||||
          "/Length 30 /Resources << /ExtGState << /R0 << /BM /Multiply>>>>>>>> " +
 | 
			
		||||
          "stream\n" +
 | 
			
		||||
          "0 g\n" +
 | 
			
		||||
          "/R0 gs\n" +
 | 
			
		||||
          "10 11 m\n" +
 | 
			
		||||
          "14 15 l\n" +
 | 
			
		||||
          "h f\n" +
 | 
			
		||||
          "endstream\n" +
 | 
			
		||||
          "endobj\n"
 | 
			
		||||
      );
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("should render a new free Highlight annotation for printing", async function () {
 | 
			
		||||
      partialEvaluator.xref = new XRefMock();
 | 
			
		||||
      const task = new WorkerTask("test free Highlight printing");
 | 
			
		||||
      const highlightAnnotation = (
 | 
			
		||||
        await AnnotationFactory.printNewAnnotations(
 | 
			
		||||
          annotationGlobalsMock,
 | 
			
		||||
          partialEvaluator,
 | 
			
		||||
          task,
 | 
			
		||||
          [
 | 
			
		||||
            {
 | 
			
		||||
              annotationType: AnnotationEditorType.HIGHLIGHT,
 | 
			
		||||
              rect: [12, 34, 56, 78],
 | 
			
		||||
              rotation: 0,
 | 
			
		||||
              opacity: 0.5,
 | 
			
		||||
              color: [0, 255, 0],
 | 
			
		||||
              thickness: 3.14,
 | 
			
		||||
              quadPoints: null,
 | 
			
		||||
              outlines: {
 | 
			
		||||
                outline: Float64Array.from([
 | 
			
		||||
                  NaN,
 | 
			
		||||
                  NaN,
 | 
			
		||||
                  8,
 | 
			
		||||
                  9,
 | 
			
		||||
                  10,
 | 
			
		||||
                  11,
 | 
			
		||||
                  NaN,
 | 
			
		||||
                  NaN,
 | 
			
		||||
                  12,
 | 
			
		||||
                  13,
 | 
			
		||||
                  14,
 | 
			
		||||
                  15,
 | 
			
		||||
                ]),
 | 
			
		||||
                points: [Float64Array.from([16, 17, 18, 19])],
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          ]
 | 
			
		||||
        )
 | 
			
		||||
      )[0];
 | 
			
		||||
 | 
			
		||||
      const { opList } = await highlightAnnotation.getOperatorList(
 | 
			
		||||
        partialEvaluator,
 | 
			
		||||
        task,
 | 
			
		||||
        RenderingIntentFlag.PRINT,
 | 
			
		||||
        false,
 | 
			
		||||
        null
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      expect(opList.argsArray.length).toEqual(6);
 | 
			
		||||
      expect(opList.fnArray).toEqual([
 | 
			
		||||
        OPS.beginAnnotation,
 | 
			
		||||
        OPS.setFillRGBColor,
 | 
			
		||||
        OPS.setGState,
 | 
			
		||||
        OPS.constructPath,
 | 
			
		||||
        OPS.fill,
 | 
			
		||||
        OPS.endAnnotation,
 | 
			
		||||
      ]);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe("UnderlineAnnotation", function () {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user