@syncfusion/ej2-pdf
Version:
Feature-rich JavaScript PDF library with built-in support for loading and manipulating PDF document.
20,022 lines • 901 kB
JavaScript
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
import { _PdfDestinationHelper } from './../pdf-page';
import { _PdfDictionary, _PdfName, _PdfReference } from './../pdf-primitives';
import { PdfFormFieldVisibility, _PdfCheckFieldState, PdfAnnotationFlag, PdfBorderStyle, PdfLineCaptionType, PdfLineEndingStyle, PdfLineIntent, PdfRotationAngle, PdfTextAlignment, PdfBorderEffectStyle, PdfMeasurementUnit, _PdfGraphicsUnit, PdfCircleMeasurementType, PdfRubberStampAnnotationIcon, PdfCheckBoxStyle, PdfTextMarkupAnnotationType, PdfPopupIcon, PdfAnnotationState, PdfAnnotationStateModel, PdfAttachmentIcon, PdfAnnotationIntent, _PdfAnnotationType, PdfBlendMode, PdfDashStyle, PdfLineCap, _PdfColorSpace, DataFormat } from './../enumerator';
import { _checkField, _removeDuplicateReference, _updateVisibility, _checkComment, _checkReview, _mapAnnotationStateModel, _mapAnnotationState, _decode, _setMatrix, _convertToColor, _findPage, _getItemValue, _areNotEqual, _calculateBounds, _parseColor, _mapHighlightMode, _reverseMapHighlightMode, _getUpdatedBounds, _mapBorderStyle, _mapLineEndingStyle, _reverseMapEndingStyle, _toRectangle, _mapBorderEffectStyle, _getStateTemplate, _mapMeasurementUnit, _mapGraphicsUnit, _stringToStyle, _styleToString, _mapMarkupAnnotationType, _reverseMarkupAnnotationType, _reverseMapAnnotationState, _reverseMapAnnotationStateModel, _mapPopupIcon, _mapRubberStampIcon, _mapAttachmentIcon, _mapAnnotationIntent, _reverseMapPdfFontStyle, _fromRectangle, _getNewGuidString, _getFontStyle, _mapFont, _checkInkPoints, _updateBounds, _isNullOrUndefined, _obtainFontDetails, _areArrayEqual, _arePointsNotEqual, _convertToPoints, _isPointArray, _convertPointsToNumberArrays, _convertNumberToPointArrays, _convertNumberArraysToPoints, _convertPointToNumberArray, _pad2, _getPageIndex, _stringToBytes } from './../utils';
import { PdfField, PdfTextBoxField, _PdfDefaultAppearance, PdfListBoxField, PdfComboBoxField } from './../form/field';
import { PdfTemplate } from './../graphics/pdf-template';
import { _TextRenderingMode, PdfBrush, PdfPen, _PdfTransformationMatrix, _PdfUnitConvertor } from './../graphics/pdf-graphics';
import { PdfPath } from './../graphics/pdf-path';
import { PdfFontFamily, PdfStandardFont, PdfFont, PdfFontStyle, PdfTrueTypeFont, PdfCjkStandardFont } from './../fonts/pdf-standard-font';
import { PdfStringFormat, PdfVerticalAlignment } from './../fonts/pdf-string-format';
import { _PdfBaseStream, _PdfStream } from './../base-stream';
import { PdfAppearance } from './pdf-appearance';
import { PdfPopupAnnotationCollection } from './annotation-collection';
import { _ContentParser } from '../content-parser';
import { _XfdfDocument } from './../import-export/xfdf-document';
import { _JsonDocument } from './../import-export/json-document';
import { _XmlWriter } from './../import-export/xml-writer';
import { initializeTelemetryFeature } from '@syncfusion/ej2-base';
/**
* Represents the base class for annotation objects.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Access first page
* let page: PdfPage = document.getPage(0);
* // Access the annotation at index 0
* let annotation: PdfAnnotation = page.annotations.at(0);
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
var PdfAnnotation = /** @class */ (function () {
function PdfAnnotation() {
/**
* Indicates whether this annotation was imported from an existing document.
*
* @private
*/
this._isImported = false;
/**
* Specifies whether the annotation was loaded from an existing document.
*
* @private
*/
this._isLoaded = false;
/**
* Indicates whether an appearance stream has been explicitly set.
*
* @private
*/
this._setAppearance = false;
/**
* Flags whether the annotation is currently being exported.
*
* @private
*/
this._isExport = false;
/**
* Controls the transparency level of the annotation appearance.
*
* @private
*/
this._opacity = 1;
/**
* When true, applies rotation to all relevant elements of the annotation.
*
* @private
*/
this._isAllRotation = true;
/**
* Determines whether the annotation should be flattened when saved.
*
* @private
*/
this._flatten = false;
/**
* Default font used for popup content rendering.
*
* @private
*/
this._popUpFont = new PdfStandardFont(PdfFontFamily.helvetica, 10.5);
/**
* Bold font used for author text in popups.
*
* @private
*/
this._authorBoldFont = new PdfStandardFont(PdfFontFamily.helvetica, 10.5, PdfFontStyle.bold);
/**
* Font used for line caption text.
*
* @private
*/
this._lineCaptionFont = new PdfStandardFont(PdfFontFamily.helvetica, 10, PdfFontStyle.regular);
/**
* Font used for circle caption text.
*
* @private
*/
this._circleCaptionFont = new PdfStandardFont(PdfFontFamily.helvetica, 8, PdfFontStyle.regular);
/**
* Indicates whether the color used should be treated as transparent.
*
* @private
*/
this._isTransparentColor = false;
/**
* Tracks whether the annotation has been rotated.
*
* @private
*/
this._isRotated = false;
/**
* Flags if any property of the annotation has changed.
*
* @private
*/
this._isChanged = false;
/**
* Stores the quad points for text markup annotations.
*
* @private
*/
this._quadPoints = new Array(8);
/**
* Holds multiple bounding rectangles for complex annotations.
*
* @private
*/
this._boundsCollection = [];
/**
* Caches custom appearance templates keyed by usage.
*
* @private
*/
this._customTemplate = new Map();
/**
* Indicates whether the annotation text was updated.
*
* @private
*/
this._isTextUpdated = false;
}
Object.defineProperty(PdfAnnotation.prototype, "author", {
/**
* Gets the author of the annotation.
*
* @returns {string} Author.
*
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* //Get the author of the annotation.
* let author: string = annotation.author;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._author === 'undefined' && this._dictionary.has('Author')) {
var author = this._dictionary.get('Author');
if (author) {
this._author = author;
}
}
if (typeof this._author === 'undefined' && this._dictionary.has('T')) {
var author = this._dictionary.get('T');
if (author) {
this._author = author;
}
}
return this._author;
},
/**
* Sets the author of the annotation.
*
* @param {string} value Author.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Sets the author of the annotation.
* annotation.author = 'Syncfusion';
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (this._isLoaded && typeof value === 'string' && value !== this.author) {
var hasKey = false;
if (this._dictionary && this._dictionary.has('T')) {
this._dictionary.update('T', value);
this._author = value;
hasKey = true;
}
if (this._dictionary && this._dictionary.has('Author')) {
this._dictionary.update('Author', value);
this._author = value;
hasKey = true;
}
if (!hasKey) {
this._dictionary.update('T', value);
this._author = value;
}
}
if (!this._isLoaded && typeof value === 'string') {
this._dictionary.update('T', value);
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfAnnotation.prototype, "border", {
/**
* Gets the border of the annotation.
*
* @returns {PdfAnnotationBorder} Annotation border.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Gets the border of the annotation.
* let border: PdfAnnotationBorder = annotation.border;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._border === 'undefined') {
var value = new PdfAnnotationBorder({ width: 1, style: PdfBorderStyle.solid });
value._dictionary = this._dictionary;
if (this._dictionary && this._dictionary.has('Border')) {
var border = this._dictionary.getArray('Border');
if (border && border.length >= 3) {
value._hRadius = border[0];
value._vRadius = border[1];
value._width = border[2];
}
}
var borderDictionary = void 0;
if (this._dictionary && this._dictionary.has('BS')) {
borderDictionary = this._dictionary;
}
else if (this instanceof PdfRadioButtonListItem && this._field && this._field._dictionary && this._field._dictionary.has('BS')) {
borderDictionary = this._field._dictionary;
}
if (borderDictionary) {
var border = borderDictionary.get('BS');
if (border) {
if (border.has('W')) {
var width = border.get('W');
if (typeof width !== 'undefined' && !Number.isNaN(width)) {
value._width = width;
}
}
if (border.has('S')) {
var style = border.get('S');
if (style) {
switch (style.name) {
case 'D':
value._style = PdfBorderStyle.dashed;
break;
case 'B':
value._style = PdfBorderStyle.beveled;
break;
case 'I':
value._style = PdfBorderStyle.inset;
break;
case 'U':
value._style = PdfBorderStyle.underline;
break;
default:
value._style = PdfBorderStyle.solid;
break;
}
}
}
if (border.has('D')) {
var dash = border.getArray('D');
if (dash) {
value._dash = dash;
}
}
}
}
this._border = value;
}
return this._border;
},
/**
* Sets the border of the annotation.
*
* @param {PdfAnnotationBorder} value Border.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Initializes a new instance of the `PdfAnnotationBorder` class.
* let border: PdfAnnotationBorder = new PdfAnnotationBorder();
* //Sets the width of the annotation border.
* border.width = 10;
* //Sets the style of the annotation border.
* border.style = PdfBorderStyle.dashed;
* //Sets the dash pattern of the annotation border.
* border.dash = [1, 2, 1];
* // Sets the border to the PDF annotation
* annotation.border = border;
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
var current = this.border;
var width;
if (!this._isLoaded || (typeof value.width !== 'undefined' && current.width !== value.width)) {
width = value.width;
}
var hRadius;
if (!this._isLoaded || (typeof value.hRadius !== 'undefined' && current.hRadius !== value.hRadius)) {
hRadius = value.hRadius;
}
var vRadius;
if (!this._isLoaded || (typeof value.vRadius !== 'undefined' && current.vRadius !== value.vRadius)) {
vRadius = value.vRadius;
}
var style;
if (!this._isLoaded || (typeof value.style !== 'undefined' && current.style !== value.style)) {
style = value.style;
}
var dash;
if (typeof value.dash !== 'undefined' && current.dash !== value.dash) {
dash = value.dash;
}
if (!this._isWidget && this._dictionary && this._dictionary.has('Border') || (width || vRadius || hRadius)) {
this._border._hRadius = typeof hRadius !== 'undefined' ? hRadius : current.hRadius;
this._border._vRadius = typeof vRadius !== 'undefined' ? vRadius : current.vRadius;
this._border._width = typeof width !== 'undefined' ? width : current.width;
this._dictionary.update('Border', [this._border.hRadius, this._border.vRadius, this._border.width]);
}
if (this._dictionary !== null && this._dictionary && this._dictionary.has('BS') || (width || style || dash)) {
this._border._width = typeof width !== 'undefined' ? width : current.width;
this._border._style = typeof style !== 'undefined' ? style : current.style;
this._border._dash = typeof dash !== 'undefined' ? dash : current.dash;
var bs = this._dictionary.has('BS') ? this._dictionary.get('BS') : new _PdfDictionary(this._crossReference);
bs.update('Type', _PdfName.get('Border'));
bs.update('W', this._border.width);
bs.update('S', _mapBorderStyle(this._border.style));
if (typeof this._border.dash !== 'undefined') {
bs.update('D', this._border.dash);
}
this._dictionary.update('BS', bs);
this._dictionary._updated = true;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfAnnotation.prototype, "flags", {
/**
* Gets the flags of the annotation.
*
* @returns {PdfAnnotationFlag} Annotation flag.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Gets the flags of the annotation.
* let flag: PdfAnnotationFlag = annotation.flags;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._annotFlags === 'undefined') {
this._annotFlags = PdfAnnotationFlag.default;
if (this._dictionary && this._dictionary.has('F')) {
this._annotFlags = this._dictionary.get('F');
}
}
return this._annotFlags;
},
/**
* Sets the flags of the annotation.
*
* @param {PdfAnnotationFlag} value flag value.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Sets the flags of the annotation.
* annotation.flags = PdfAnnotationFlag.print;
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (typeof value !== 'undefined' && value !== this._annotFlags) {
this._annotFlags = value;
this._dictionary.update('F', value);
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfAnnotation.prototype, "color", {
/**
* Gets the fore color of the annotation.
*
* @returns {PdfColor} R, G, B color values in between 0 to 255.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Gets the color of the annotation.
* let color: PdfColor = annotation.color;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._color === 'undefined' && this._dictionary.has('C')) {
this._color = _parseColor(this._dictionary.getArray('C'));
}
return this._color;
},
/**
* Sets the fore color of the annotation.
*
* @param {PdfColor} value R, G, B color values in between 0 to 255.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Sets the color of the annotation.
* annotation.color = {r: 255, g: 0, b: 0};
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value !== null && typeof value !== 'undefined') {
var extColor = this.color;
if (!this._isLoaded || typeof extColor === 'undefined' || (extColor.r !== value.r || extColor.g !== value.g || extColor.b !== value.b)) {
this._color = value;
this._dictionary.update('C', [Number.parseFloat((value.r / 255).toFixed(7)),
Number.parseFloat((value.g / 255).toFixed(7)),
Number.parseFloat((value.b / 255).toFixed(7))]);
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfAnnotation.prototype, "innerColor", {
/**
* Gets the inner color of the annotation.
*
* @returns {PdfColor} R, G, B color values in between 0 to 255.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Gets the inner color of the annotation.
* let innerColor: PdfColor = annotation.innerColor;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._innerColor === 'undefined' && this._dictionary.has('IC')) {
this._innerColor = _parseColor(this._dictionary.getArray('IC'));
}
return this._innerColor;
},
/**
* Sets the inner color of the annotation.
*
* @param {PdfColor} value R, G, B color values in between 0 to 255.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Sets the inner color of the annotation.
* annotation.innerColor = {r: 255, g: 0, b: 0};
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value) {
var extColor = this.innerColor;
if (!this._isLoaded ||
typeof extColor === 'undefined' ||
(extColor.r !== value.r || extColor.g !== value.g || extColor.b !== value.b)) {
this._innerColor = value;
this._dictionary.update('IC', [Number.parseFloat((value.r / 255).toFixed(7)),
Number.parseFloat((value.g / 255).toFixed(7)),
Number.parseFloat((value.b / 255).toFixed(7))]);
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfAnnotation.prototype, "creationDate", {
/**
* Gets the creation date of the annotation.
*
* @returns {Date} Creation date.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* //Get the creation date of the annotation.
* let creationDate: Date = annotation.creationDate;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if ((typeof this._creationDate === 'undefined' || this._creationDate === null) && this._dictionary.has('CreationDate')) {
var value = this._dictionary.get('CreationDate'); // eslint-disable-line
if (value !== null && typeof value === 'string') {
this._creationDate = this._stringToDate(value);
}
}
return this._creationDate;
},
/**
* Sets the creation date of the annotation.
*
* @param {Date} value Creation date.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* //Set the creation date of the annotation.
* annotation.creationDate = new Date();
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
this._creationDate = value;
this._dictionary.update('CreationDate', this._dateToString(value));
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfAnnotation.prototype, "modifiedDate", {
/**
* Gets the modification date of the annotation.
*
* @returns {Date} Modified date.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* //Get the modified date of the annotation.
* let modifiedDate: Date = annotation.modifiedDate;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if ((typeof this._modifiedDate === 'undefined' || this._modifiedDate === null)) {
var value = void 0; // eslint-disable-line
if (this._dictionary && this._dictionary.has('ModDate')) {
value = this._dictionary.get('ModDate');
}
else if (this._dictionary.has('M')) {
value = this._dictionary.get('M');
}
if (value !== null && typeof value === 'string') {
this._modifiedDate = this._stringToDate(value);
}
}
return this._modifiedDate;
},
/**
* Sets the modification date of the annotation.
*
* @param {Date} value Modified date.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* //Set the modified date of the annotation.
* annotation.modifiedDate = new Date();
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
this._modifiedDate = value;
this._dictionary.update('M', this._dateToString(value));
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfAnnotation.prototype, "bounds", {
/**
* Gets the bounds of the annotation.
*
* @returns {Rectangle} Bounds.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Gets the bounds of the annotation.
* let bounds: Rectangle = annotation.bounds;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (this._isLoaded) {
this._bounds = _calculateBounds(this._dictionary, this._page);
}
return this._bounds;
},
/**
* Sets the bounds of the annotation.
*
* @param {Rectangle} value bounds.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Sets the bounds of the annotation.
* annotation.bounds = {x: 10, y: 10, width: 150, height: 5};
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value) {
this._isBounds = true;
if (this._isLoaded) {
if ((value.x !== this.bounds.x) || (value.y !== this.bounds.y) ||
(value.width !== this.bounds.width) || (value.height !== this.bounds.height)) {
var size = this._page.size;
if (size) {
var y = size.height - (value.y + value.height);
var height = y + value.height;
this._dictionary.update('Rect', [value.x, y, value.x + value.width, height]);
this._bounds = value;
this._isChanged = true;
}
}
}
else {
this._bounds = value;
this._isChanged = true;
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfAnnotation.prototype, "caption", {
/**
* Gets the caption of the annotation.
*
* @returns {PdfAnnotationCaption} Annotation caption.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Gets the caption of the annotation.
* let caption: PdfAnnotationCaption = annotation.caption;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._caption === 'undefined') {
var value = new PdfAnnotationCaption();
value._dictionary = this._dictionary;
if (this._dictionary && this._dictionary.has('Cap')) {
value._cap = this._dictionary.get('Cap');
}
if (this._dictionary && this._dictionary.has('CP')) {
var capType = this._dictionary.get('CP');
if (capType) {
value._type = capType.name === 'Top' ? PdfLineCaptionType.top : PdfLineCaptionType.inline;
}
}
if (this._dictionary && this._dictionary.has('CO')) {
var offset = this._dictionary.getArray('CO');
value._offset = { x: offset[0], y: offset[1] };
}
this._caption = value;
}
return this._caption;
},
/**
* Sets the caption of the annotation.
*
* @param {PdfAnnotationCaption} value Annottion caption.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Create and set annotation caption values
* annotation.caption = new PdfAnnotationCaption(true, PdfLineCaptionType.inline, {x: 10, y: 10});
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
var current = this.caption;
if (value) {
if (!this._isLoaded || value.cap !== current.cap) {
this._caption.cap = value.cap;
}
if (!this._isLoaded || value.type !== current.type) {
this._caption.type = value.type;
}
if (!this._isLoaded || value.offset !== current.offset) {
this._caption.offset = value.offset;
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfAnnotation.prototype, "opacity", {
/**
* Gets the opacity of the annotation.
*
* @returns {number} Opacity in between 0 t0 1.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* //Get the opacity of the annotation.
* let opacity: number = annotation.opacity;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (this._dictionary && this._dictionary.has('CA')) {
var opacity = this._dictionary.get('CA');
if (typeof opacity !== 'undefined') {
this._opacity = opacity;
}
}
return this._opacity;
},
/**
* Sets the opacity of the annotation.
*
* @param {number} value opacity in between 0 t0 1.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Sets the opacity of the annotation.
* annotation.opacity = 0.5;
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (typeof value !== 'undefined' && !Number.isNaN(value)) {
if (value >= 0 && value <= 1) {
this._dictionary.update('CA', value);
this._opacity = value;
}
else if (value < 0) {
this._dictionary.update('CA', 0);
}
else {
this._dictionary.update('CA', 1);
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfAnnotation.prototype, "subject", {
/**
* Gets the subject of the annotation.
*
* @returns {string} Subject.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* //Get the subject of the annotation.
* let subject: string = annotation.subject;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._subject === 'undefined') {
this._subject = this._dictionary.get('Subject', 'Subj');
}
return this._subject;
},
/**
* Sets the subject of the annotation.
*
* @param {string} value Subject.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Sets the subject of the annotation.
* annotation.subject = 'Line Annotation';
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (typeof value === 'string' && this.subject !== value) {
this._dictionary.update('Subj', value);
this._subject = value;
if (this._dictionary.has('Subject')) {
this._dictionary.update('Subject', value);
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfAnnotation.prototype, "name", {
/**
* Gets the name of the annotation.
*
* @returns {string} Name.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* //Get the name of the annotation.
* let name: string = annotation.name;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._name === 'undefined' && this._dictionary.has('NM')) {
this._name = this._dictionary.get('NM');
}
return this._name;
},
/**
* Sets the name of the annotation.
*
* @param {string} value Name.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Sets the name of the annotation.
* annotation.name = 'LineAnnotation';
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (typeof value === 'string') {
this._dictionary.update('NM', value);
this._name = value;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfAnnotation.prototype, "text", {
/**
* Gets the text of the annotation.
*
* @returns {string} Text.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* //Get the text of the annotation.
* let text: string = annotation.text;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._text === 'undefined' && this._dictionary.has('Contents')) {
this._text = this._dictionary.get('Contents');
}
return this._text;
},
/**
* Sets the text of the annotation.
*
* @param {string} value Text.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Sets the text of the annotation.
* annotation.text = 'LineAnnotation';
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (typeof value === 'string') {
this._text = this._dictionary.get('Contents');
if (value !== this._text) {
if ((this instanceof PdfLineAnnotation || this instanceof PdfCircleAnnotation
|| this instanceof PdfSquareAnnotation) && this.measure) {
if (typeof this._unit === 'undefined' || this._isLoaded) {
if (this._dictionary.has('Contents')) {
this._isTextUpdated = true;
var text = this._dictionary.get('Contents');
this._unit = _mapMeasurementUnit(text.substring(text.length - 2));
}
}
}
this._dictionary.update('Contents', value);
this._text = value;
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfAnnotation.prototype, "rotationAngle", {
/**
* Gets the rotation of the annotation.
*
* @returns {PdfRotationAngle} Rotation angle.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* //Get the rotation angle of the annotation.
* let rotationAngle: PdfRotationAngle = annotation.rotationAngle;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._rotate === 'undefined' && this._dictionary && this._dictionary.has('Rotate')) {
this._rotate = (this._dictionary.get('Rotate') / 90);
}
if (this._rotate === null || typeof this._rotate === 'undefined') {
this._rotate = PdfRotationAngle.angle0;
}
return this._rotate;
},
/**
* Sets the rotation of the annotation.
*
* @param {PdfRotationAngle} value rotation angle.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Sets the rotation angle of the annotation.
* annotation.rotationAngle = PdfRotationAngle.angle180;
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
var prevRotate = this.rotationAngle;
if (typeof value !== 'undefined' && typeof prevRotate !== 'undefined') {
value = ((value + prevRotate) % 4);
}
this._dictionary.update('Rotate', value * 90);
this._isRotated = true;
this._rotate = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfAnnotation.prototype, "rotate", {
/**
* Gets the rotation angle of the annotation (Read only).
*
* @returns {number} Rotation angle.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* //Get the rotation angle of the annotation.
* let rotate: number = annotation.rotate;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
var angle = this._getRotationAngle();
if (angle < 0) {
angle = 360 + angle;
}
if (angle >= 360) {
angle = 360 - angle;
}
return angle;
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfAnnotation.prototype, "flattenPopups", {
/**
* Gets the boolean flag indicating whether annotations popup have been flattened or not.
*
* @returns {boolean} Flatten Popup.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Gets the boolean flag indicating whether annotations popup have been flattened or not.
* let flattenPopups: boolean = annotation.flattenPopups;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
return this._isFlattenPopups;
},
/**
* Sets the boolean flag indicating whether the annotations popup have been flattened or not.
*
* @param {boolean} value Flatten Popup.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Sets the boolean flag indicating whether the annotations popup have been flattened or not.
* annotation.flattenPopups = false;
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (typeof value !== 'undefined') {
this._isFlattenPopups = value;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfAnnotation.prototype, "flatten", {
/**
* Gets the boolean flag indicating whether the annotation have been flattened or not.
*
* @returns {boolean} Flatten.
*
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Gets the boolean flag indicating whether the annotation have been flattened or not.
* let flatten: boolean = annotation.flatten;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
return this._flatten;
},
/**
* Sets the boolean flag indicating whether the annotation have been flattened or not.
*
* @param {boolean} value Flatten.
*
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Sets the boolean flag indicating whether the annotation have been flattened or not.
* annotation.flatten = true;
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
this._flatten = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfAnnotation.prototype, "_hasFlags", {
/**
* Indicates whether the annotation dictionary defines flag entries,
* allowing consumers to detect the presence of annotation-level flags.
*
* @private
* @returns {boolean} hasFlags.
*/
get: function () {
return this._dictionary.has('F');
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfAnnotation.prototype, "_degreeToRadian", {
/**
* Converts degrees to radians on demand, initializing the cached conversion
* ratio if necessary and returning the precomputed value for reuse.
*
* @private
* @returns {number} degreeToRadian.
*/
get: function () {
if (typeof this._ratio === 'undefined') {
this._ratio = Math.PI / 180;
}
return this._ratio;
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfAnnotation.prototype, "layer", {
/**
* Gets the `PdfLayer` of the annotation.
*
* @returns {PdfLayer} PDF layer to the annotation.
*
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data);
* // Get the first page of the document
* let page: PdfPage = document.getPage(0);
* // Access the first annotation on the page
* let annotation: PdfAnnotation = page.annotations.at(0);
* // Get the layer of the annotation
* let layer: PdfLayer = annotation.layer;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (!this._layer) {
this._layer = this._getDocumentLayer();
}
return this._layer;
},
/**
* Set the `PdfLayer` to the annotation.
*
* @param {PdfLayer} value PDF layer to the annotation.
*
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data);
* // Get the first page of the document
* let page: PdfPage = document.getPage(0);
* // Access the collection of layers in the document
* let layers: PdfLayerCollection = document.layers;
* // Add a new layer to the document with the name 'Layer1'
* let layer: PdfLayer = layers.add('Layer1');
* // Access the first annotation on the page
* let annotation: PdfAnnotation = page.annotations.at(0);
* // Assign the layer to the annotation
* annotation.layer = layer;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (!this._layer) {
this._layer = value;
if (this._layer) {
this._dictionary.update('OC', this._layer._referenceHolder);
}
else {
delete this._dictionary._map['OC'];
}
}
},
enumerable: true,
configurable: true
});
/**
* Set the boolean flag to create a new appearance stream for annotations.
*
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Set the boolean flag to create a new appearance stream for annotations.
* document.getPage(0).annotations.at(0).setAppearance(true);
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*
* @param {boolean} value Set appearance.
* @returns {void} Nothing.
*/
PdfAnnotation.prototype.setAppearance = function (value) {
this._setAppearance = value;
if (value) {
this._dictionary._updated = true;
}
};
/**
* Gets the values associated with the specified key.
*
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Gets the values associated with the key 'Author'.
* let values: string[] = document.getPage(0).annotations.at(0).getValues('Author');
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*
* @param {string} name Key.
* @returns {string[]} Values associated with the key.
*/
PdfAnnotation.prototype.getValues = function (name) {
var values = [];
if (this._dictionary && this._dictionary.has(name)) {
var value = this._dictionary.get(name); // eslint-disable-line
if (Array.isArray(value)) {
value = this._dictionary.getArray(name);
value.forEach(function (element) {
if (element instanceof _PdfName) {
values.push(element.name);
}
else if (typeof element === 'string') {
values.push(element);
}
else if (typeof element === 'number') {
values.push(element.toString());
}
});
}
else if (value instanceof _PdfName) {
values.push(value.name);
}
else if (typeof value === 'string') {
values.push(value);
}
else {
throw new Error('PdfException: ' + name + ' is not found');
}
}
else {
throw new Error('PdfException: ' + name + ' is not found');
}
return values;
};
/**
* Sets the values associated with the specified key.
*
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Access the annotation at index 0
* let annotation: PdfAnnotation = document.getPage(0).annotations.at(0);
* // Set Unknown state and model
* annotation.setValues('State', 'StateModel');
* annotation.setValues('StateModel', 'CustomState');
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*
* @param {string} name Key.
* @param {string} value Value associated with the key..
* @returns {void} Nothing.
*/
PdfAnnotation.prototype.setValues = function (name, value) {
if (name && name !== '' && value && value !== '') {
this._dictionary.update(name, value);
}
};
/**
* Exports a single annotation to the specified format (XFDF or JSON).
*
* @private
* @param {DataFormat} format The format to export (DataFormat.xfdf or DataFormat.json).
* @returns {Uint8Array} Exported annotation data as byte array.
*/
PdfAnnotation.prototype._export = function (format) {
if (!this._page || !this._dictionary) {
throw new Error('Annotation must be added to a page before export.');
}
var document = this._crossReference._document;
var pageIndex;
if (this._dictionary && this._dictionary.has('P')) {
var pageDictionary = this._dictionary.get('P');
pageIndex = _getPageIndex(document, pageDictionary);
}
else {
pageIndex = this._page._pageIndex;
}
if (format === DataFormat.xfdf) {
return this._exportAsXfdf(document, pageIndex);
}
else if (format === DataFormat.json) {
return this._exportAsJson(document, pageIndex);
}
else {
throw new Error('Unsupported export format. Use DataFormat.xfdf or DataFormat.json.');
}
};
/**
* Exports the annotation as XFDF format.
*
* @private
* @param {PdfDocument} document The PDF document.
* @param {number} pageIndex The page index.
* @returns {Uint8Array} XFDF data as byte array.
*/
PdfAnnotation.prototype._exportAsXfdf = function (document, pageIndex) {
var helper = new _XfdfDocument();
helper.exportAppearance = true;
helper._document = document;
helper._crossReference = document._crossReference;
this._crossReference = document._crossReference;
helper._isAnnotationExport = true;
var writer = new _XmlWriter();
writer._writeStartDocument();
writer._writeStartElement('xfdf');
writer._writeAttributeString(null, 'http://ns.adobe.com/xfdf/', 'xmlns', null);
writer._writeAttributeString('space', 'preserve', 'xml', null);
writer._writeStartElement('annots');
this._doPostProcess(false);
helper._exportAnnotationData(this, writer, pageIndex);
var annotation = this; // eslint-disable-line
if (annotation && annotation.reviewHistory && annotation.reviewHistory.count > 0) {
for (var i = 0; i < annotation.reviewHistory.count; i++) {
var reply = annotation.reviewHistory.at(i);
reply._page = this._page;
reply._doPostProcess(false);
helper._exportAnnotationData(reply, writer, pageIndex);
}
}
if (annotation && annotation.comments && annotation.comments.count > 0) {
for (var i = 0; i < annotation.comments.count; i++) {
var comment = annotation.comments.at(i);
comment._page = this._page;
comment._doPostProcess(false);
helper._exportAnnotationData(comment, writer, pageIndex);
var commentAnnotation = comment; // eslint-disable-line
if (commentAnnotation && commentAnnotation.reviewHistory && commentAnnotation.reviewHistory.count > 0) {
for (var j = 0; j < commentAnnotation.reviewHistory.count; j++) {
var nestedReply = commentAnnotation.reviewHistory.at(j);
nestedReply._page = this._page;
nestedReply._doPostProcess(false);
helper._exportAnnotationData(nestedReply, writer, pageIndex);
}
}
}
}
writer._writeEndElement();
if (!helper._asPerSpecification) {
writer._writeStartElement('f');
writer._writeAttributeString('href', helper._fileName || '');
writer._writeEndElement();
}
writer._writeEndElement();
var result = writer._save();
writer._destroy();
return result;
};
/**
* Exports the annotation as JSON format.
*
* @private
* @param {PdfDocument} document The PDF document.
* @param {number} pageIndex The page index.
* @returns {Uint8Array} JSON data as byte array.
*/
PdfAnnotation.prototype._exportAsJson = function (document, pageIndex) {
var _a;
var helper = new _JsonDocument();
helper.exportAppearance = true;
helper._document = document;
helper._crossReference = document._crossReference;
this._crossReference = document._crossReference;
helper._isAnnotationExport = true;
var json = {
pdfAnnotation: (_a = {},
_a[pageIndex] = {
shapeAnnotation: []
},
_a)
};
this._doPostProcess(false);
helper._table.clear();
helper._exportAnnotation(this, pageIndex);
json.pdfAnnotation[pageIndex].shapeAnnotation.push(JSON.parse(helper._convertToJson(helper._table)));
var annotation = this; // eslint-disable-line
if (annotation && annotation.reviewHistory && annotation.reviewHistory.count > 0) {
for (var i = 0; i < annotation.reviewHistory.count; i++) {
var reply = annotation.reviewHistory.at(i);
reply._page = this._page;
reply._doPostProcess(false);
helper._table.clear();
helper._exportAnnotation(reply, pageIndex);
json.pdfAnnotation[pageIndex].shapeAnnotation.push(JSON.parse(helper._convertToJson(helper._table)));
}
}
if (annotation && annotation.comments && annotation.comments.count > 0) {
for (var i = 0; i < annotation.comments.count; i++) {
var comment = annotation.comments.at(i);
comment._page = this._page;
comment._doPostProcess(false);
helper._table.clear();
helper._exportAnnotation(comment, pageIndex);
json.pdfAnnotation[pageIndex].shapeAnnotation.push(JSON.parse(helper._convertToJson(helper._table)));
var commentAnnotation = comment; // eslint-disable-line
if (commentAnnotation && commentAnnotation.reviewHistory && commentAnnotation.reviewHistory.count > 0) {
for (var j = 0; j < commentAnnotation.reviewHistory.count; j++) {
var nestedReply = commentAnnotation.reviewHistory.at(j);
nestedReply._page = this._page;
nestedReply._doPostProcess(false);
helper._table.clear();
helper._exportAnnotation(nestedReply, pageIndex);
json.pdfAnnotation[pageIndex].shapeAnnotation.push(JSON.parse(helper._convertToJson(helper._table)));
}
}
}
}
var jsonString = JSON.stringify(json);
return _stringToBytes(jsonString);
};
/**
* Initializes the annotation with its owning page and dictionary,
* assigning cross reference information and setting the page reference
* when loading a new annotation instance.
*
* @private
* @param {PdfPage} page Owning page.
* @param {_PdfDictionary} [dictionary] Annotation dictionary to initialize from.
* @returns {void} nothing.
*/
PdfAnnotation.prototype._initialize = function (page, dictionary) {
this._page = page;
this._crossReference = page._crossReference;
if (dictionary) {
this._dictionary = dictionary;
}
if (!this._isLoaded) {
this._dictionary.set('P', this._page._ref);
this._dictionary.assignXref(this._crossReference);
}
};
/**
* Retrieves the rotation angle for the annotation from its dictionary,
* preferring `Rotate` over `Rotation`, and skipping polygon/rectangle types.
*
* @private
* @returns {number} angle Rotation angle in degrees.
*/
PdfAnnotation.prototype._getRotationAngle = function () {
var angle = 0;
if (this._dictionary && !(this instanceof PdfRectangleAnnotation) &&
!(this instanceof PdfPolygonAnnotation)) {
if (this._dictionary.has('Rotate')) {
angle = this._dictionary.get('Rotate');
}
else if (this._dictionary.has('Rotation')) {
angle = this._dictionary.get('Rotation');
}
}
return angle;
};
/**
* Retrieves the pages media box or crop box array, returning the media box
* when available, otherwise falling back to the crop box definition.
*
* @private
* @param {PdfPage} page Page whose box is requested.
* @returns {number[]} box Array in the form [x, y, width, height].
*/
PdfAnnotation.prototype._getMediaOrCropBox = function (page) {
var cropOrMediaBox;
if (page && page._pageDictionary && page._pageDictionary.has('MediaBox')) {
cropOrMediaBox = page._pageDictionary.get('MediaBox');
}
else if (page && page._pageDictionary && page._pageDictionary.has('CropBox')) {
cropOrMediaBox = page._pageDictionary.get('CropBox');
}
return cropOrMediaBox;
};
/**
* Computes the bounding rectangle from a flat array of line coordinates,
* optionally expanding the bounds by the annotations border width padding.
*
* @private
* @param {number[]} linePoints Flat array of points [x1, y1, x2, y2, ...].
* @param {number} [borderWidth] Optional border width to pad the bounds.
* @returns {{x: number, y: number, width: number, height: number}} bounds.
*/
PdfAnnotation.prototype._getBoundsValue = function (linePoints, borderWidth) {
var count = 0;
if (_isNullOrUndefined(linePoints)) {
count = linePoints.length;
}
var x = [];
var y = [];
if (count > 0) {
linePoints.forEach(function (value, i) {
if (i % 2 === 0) {
x.push(value);
}
else {
y.push(value);
}
});
}
x.sort(function (a, b) { return a > b ? 1 : -1; });
y.sort(function (a, b) { return a > b ? 1 : -1; });
if (borderWidth) {
var extraPadding = this.border.width * 2;
return { x: x[0] - extraPadding, y: y[0] - extraPadding, width: x[x.length - 1] - x[0] + (2 * extraPadding),
height: y[y.length - 1] - y[0] + (2 * extraPadding) };
}
else {
return { x: x[0], y: y[0], width: x[x.length - 1] - x[0], height: y[y.length - 1] - y[0] };
}
};
/**
* Validates the transformation matrix for the annotations appearance stream.
* When no template is provided, checks for identity rotation and flags location
* displacement when applicable. When a template is provided, draws the template
* with page graphics if offsets require it and removes the annotation; otherwise
* leaves the annotation as-is.
*
* @private
* @param {_PdfDictionary} dictionary Appearance dictionary.
* @param {PdfTemplate} [template] Appearance template (optional).
* @returns {boolean} valid True if matrix is valid and annotation/template kept.
*/
PdfAnnotation.prototype._validateTemplateMatrix = function (dictionary, template) {
var isRotatedMatrix = false;
var isValidMatrix = true;
if (template === null || typeof template === 'undefined') {
if (dictionary && dictionary.has('Matrix')) {
var matrix = dictionary.getArray('Matrix');
if (matrix && matrix.length > 3) {
if (typeof matrix[0] !== 'undefined' &&
typeof matrix[1] !== 'undefined' &&
typeof matrix[2] !== 'undefined' &&
typeof matrix[3] !== 'undefined') {
if (matrix[0] === 1 && matrix[1] === 0 && matrix[2] === 0 && matrix[3] === 1) {
isRotatedMatrix = true;
var locationX = 0;
var locationY = 0;
var templateX = 0;
var templateY = 0;
if (matrix.length > 4) {
templateX = -matrix[4];
if (matrix.length > 5) {
templateY = -matrix[5];
}
}
var annotationBounds = void 0;
if (this._dictionary && this._dictionary.has('Rect')) {
annotationBounds = this._dictionary.getArray('Rect');
if (annotationBounds && annotationBounds.length > 1) {
locationX = annotationBounds[0];
locationY = annotationBounds[1];
}
}
if (!(locationX === templateX && locationY === templateY) && templateX === 0 && templateY === 0) {
this._locationDisplaced = true;
}
}
}
}
}
else {
isRotatedMatrix = true;
}
return isRotatedMatrix;
}
else {
var point = this.bounds;
if (dictionary && dictionary.has('Matrix')) {
var box = dictionary.getArray('BBox');
var matrix = dictionary.getArray('Matrix');
if (matrix && box && matrix.length > 3 && box.length > 2) {
if (typeof matrix[0] !== 'undefined' &&
typeof matrix[1] !== 'undefined' &&
typeof matrix[2] !== 'undefined' &&
typeof matrix[3] !== 'undefined') {
if (matrix[0] === 1 && matrix[1] === 0 && matrix[2] === 0 && matrix[3] === 1) {
if (typeof box[0] !== 'undefined' &&
typeof box[1] !== 'undefined' &&
typeof box[2] !== 'undefined' &&
typeof box[3] !== 'undefined') {
if (this._page && box[0] !== -(matrix[4]) && box[1] !== -(matrix[5]) ||
(box[0] === 0 && -matrix[4] === 0)) {
var graphics = this._page.graphics;
var state = graphics.save();
if (typeof this.opacity !== 'undefined' && this._opacity < 1) {
graphics.setTransparency(this._opacity);
}
point.x -= box[0];
point.y += box[1];
graphics.drawTemplate(template, point);
graphics.restore(state);
this._page.annotations.remove(this);
isValidMatrix = false;
}
}
}
}
}
}
return isValidMatrix;
}
};
/**
* Flattens the annotations appearance template onto the page graphics,
* normalizing bounds with media/crop box adjustments, handling rotation and
* non identity matrices including rubber stamp scaling, applying opacity,
* drawing the template, and removing the annotation from the page.
*
* @private
* @param {PdfTemplate} template Appearance template to draw.
* @param {boolean} isNormalMatrix True if the template uses an identity matrix.
* @param {boolean} [isLineAnnotation=false] True if invoked for a line annotation.
* @returns {void} nothing.
*/
PdfAnnotation.prototype._flattenAnnotationTemplate = function (template, isNormalMatrix, isLineAnnotation) {
if (isLineAnnotation === void 0) { isLineAnnotation = false; }
this._page._isLineAnnotation = isLineAnnotation;
var graphics = this._page.graphics;
var currentBounds = this.bounds;
if (this instanceof PdfLineAnnotation && this._dictionary && !this._dictionary.has('AP')) {
if (this._isLoaded) {
currentBounds = this._bounds;
}
else {
if (this instanceof PdfLineAnnotation && !this.measure) {
currentBounds = _toRectangle([this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height]);
}
else {
if (this._setAppearance && this.flatten && !this.measure) {
currentBounds = this._bounds;
}
else {
currentBounds = _toRectangle([this.bounds.x, this.bounds.y,
this.bounds.width, this.bounds.height]);
}
}
}
if (this._page) {
var size = this._page.size;
var mBox = this._page.mediaBox;
var cropBox = this._page.cropBox;
if (cropBox && Array.isArray(cropBox) && cropBox.length === 4 && this._page._pageDictionary.has('CropBox') &&
!this._isLoaded && !this._flatten) {
if ((cropBox[0] !== 0 || cropBox[1] !== 0 || size.width === cropBox[2] ||
size.height === cropBox[3]) && (currentBounds.x !== cropBox[0])) {
currentBounds.x -= cropBox[0];
currentBounds.y = cropBox[3] - (currentBounds.y + currentBounds.height);
}
else {
currentBounds.y = size.height - (currentBounds.y + currentBounds.height);
}
}
else if (mBox && Array.isArray(mBox) && mBox.length === 4 && this._page._pageDictionary.has('MediaBox') &&
!this._isLoaded && !this._flatten) {
if (mBox[0] > 0 || mBox[1] > 0 || size.width === mBox[2] || size.height === mBox[3]) {
currentBounds.x -= mBox[0];
currentBounds.y = mBox[3] - (currentBounds.y + currentBounds.height);
}
else {
currentBounds.y = size.height - (currentBounds.y + currentBounds.height);
}
}
else {
if (this instanceof PdfLineAnnotation && !this.measure && !this._isLoaded) {
currentBounds.y = size.height - (currentBounds.y + currentBounds.height);
}
else {
if (this._setAppearance && this.flatten && !this.measure) {
currentBounds = this.bounds;
}
else if (!this._isLoaded) {
currentBounds.y = size.height - (currentBounds.y + currentBounds.height);
}
}
}
}
else {
currentBounds.y = currentBounds.y + currentBounds.height;
}
}
if (typeof currentBounds !== 'undefined' && currentBounds !== null) {
if (this._page && typeof this._page._getTemplateReservedSpace === 'function') {
var reserved = this._page._getTemplateReservedSpace();
if (reserved && Array.isArray(reserved) && reserved.length === 4) {
currentBounds.x += reserved[3];
currentBounds.y -= reserved[0];
}
}
var state = graphics.save();
this._page._needInitializeGraphics = true;
if (this._type === _PdfAnnotationType.rubberStampAnnotation) {
var needScale = true;
if (this._dictionary && this._dictionary.has('AP')) {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
var appearanceStream = dictionary.get('N');
if (this.rotate === 270 && this._page.rotation === PdfRotationAngle.angle270
&& appearanceStream && appearanceStream.dictionary
&& appearanceStream.dictionary.has('Matrix')) {
var matrix = appearanceStream.dictionary.getArray('Matrix');
if (matrix && matrix.length === 6 && matrix[4] === 0 && matrix[5] !== 0) {
needScale = false;
}
}
}
if (!isNormalMatrix && this.rotate !== PdfRotationAngle.angle180 && needScale) {
template._isAnnotationTemplate = true;
template._needScale = true;
}
}
}
if (!isNormalMatrix && this._type !== _PdfAnnotationType.rubberStampAnnotation) {
template._isAnnotationTemplate = true;
template._needScale = true;
}
if (typeof this.opacity !== 'undefined' && this._opacity < 1) {
graphics.setTransparency(this._opacity);
}
var bounds = this._calculateTemplateBounds(currentBounds, this._page, template, isNormalMatrix, graphics);
if (this._type === _PdfAnnotationType.rubberStampAnnotation) {
var size = void 0;
var location_1;
if (this.rotate === PdfRotationAngle.angle0) {
size = { width: bounds.width, height: bounds.height };
location_1 = [bounds.x, bounds.y];
}
else {
size = template._size;
location_1 = [bounds.x, bounds.y];
}
var isRotatedMatrix = false;
if (this.rotate !== PdfRotationAngle.angle0 && template._content) {
if (template._content.dictionary.has('Matrix')) {
var matrix = template._content.dictionary.getArray('Matrix');
if (matrix && matrix.length === 6 && matrix[4] === 0 && matrix[5] !== 0) {
isRotatedMatrix = true;
}
}
}
var scaleX = (template._size.width > 0) ? bounds.width / template._size.width : 1;
var scaleY = (template._size.height > 0) ? bounds.height / template._size.height : 1;
var needScale = !(Math.trunc(scaleX * 1000) / 1000 === 1 && Math.trunc(scaleY * 1000) / 1000 === 1);
if (this.rotate !== PdfRotationAngle.angle0 && isRotatedMatrix) {
if (this.rotate === PdfRotationAngle.angle90) {
if (this._page && this._page.rotation === PdfRotationAngle.angle270) {
if (needScale && !(bounds.x === 0 && bounds.y === 0)) {
location_1[0] += (size.width - size.height);
location_1[1] += size.width;
}
else {
location_1[0] += size.height;
location_1[1] += (size.width - size.height) + (size.width - size.height);
}
}
else if (!needScale) {
location_1[0] += size.height;
}
}
else if (this.rotate === PdfRotationAngle.angle270) {
if (this._page && this._page.rotation === PdfRotationAngle.angle270) {
if (needScale && template._isAnnotationTemplate) {
location_1[1] = bounds.y - bounds.width;
}
else if (needScale) {
location_1[1] += (size.width - size.height);
}
}
else {
if (!needScale && !(bounds.x === 0 && bounds.y === 0)) {
location_1[1] += -(size.width);
}
else {
location_1[1] += -(size.width - size.height);
}
}
}
else if (this.rotate === PdfRotationAngle.angle180) {
location_1[0] += size.width;
location_1[1] += -(size.height);
}
}
}
if (!template._content.dictionary.has('Matrix') && template._content.dictionary.has('BBox')) {
var box = template._content.dictionary.getArray('BBox');
bounds.x -= box[0];
bounds.y += box[1];
}
if (this instanceof PdfAngleMeasurementAnnotation && !this._isLoaded) {
bounds = _calculateBounds(this._dictionary, this._page);
}
graphics.drawTemplate(template, bounds);
graphics.restore(state);
}
this._page.annotations.remove(this);
};
/* eslint-disable */
/**
* Computes the templates final drawing bounds on the page by considering the page graphics rotation,
* annotation rotation, and non identity matrices, applying the necessary transforms and size swaps.
*
* @private
* @param {{x: number, y: number, width: number, height: number}} bounds Annotation bounds in page space. // eslint-disable-line
* @param {PdfPage} page Page to draw on.
* @param {PdfTemplate} template Appearance template.
* @param {boolean} isNormalMatrix True when the template uses identity matrix.
* @param {PdfGraphics} graphics Target graphics.
* @returns {{x: number, y: number, width: number, height: number}} computedBounds.
*/
PdfAnnotation.prototype._calculateTemplateBounds = function (bounds, page, template, isNormalMatrix, graphics) {
var annotationBounds = bounds;
var x = bounds.x;
var y = bounds.y;
var width = bounds.width;
var height = bounds.height;
if (!isNormalMatrix) {
var rect = this._dictionary.getArray('Rect');
if (rect) {
annotationBounds = _toRectangle(rect);
}
}
if (typeof page !== 'undefined') {
var graphicsRotation = this._obtainGraphicsRotation(graphics._matrix);
if (graphicsRotation === 90) {
graphics.translateTransform({ x: template._size.height, y: 0 });
graphics.rotateTransform(90);
if (isNormalMatrix || (typeof this._rotate !== 'undefined' && this._rotate === PdfRotationAngle.angle180)) {
x = bounds.x;
if (!this._locationDisplaced) {
y = -(page.size.height - bounds.y - bounds.height);
}
else if (page._origin && page._o[1] !== 0) {
y = bounds.y + bounds.height;
}
else {
y = -(page.size.height - (bounds.height + bounds.y) + (bounds.height - template._size.height));
}
}
else {
x = bounds.x;
y = -(page.size.height - (bounds.height + bounds.y) + (bounds.width - template._size.height));
width = bounds.height;
height = bounds.width;
}
}
else if (graphicsRotation === 180) {
graphics.translateTransform({ x: template._size.width, y: template._size.height });
graphics.rotateTransform(180);
if (isNormalMatrix) {
x = -(page.size.width - (bounds.x + bounds.width));
y = -(page.size.height - bounds.y - bounds.height);
}
else {
x = -(page.size.width - (bounds.x + template._size.width));
y = -(page.size.height - bounds.y - template._size.height);
if (typeof this.rotationAngle !== 'undefined' &&
(this._rotate === PdfRotationAngle.angle90 ||
this._rotate === PdfRotationAngle.angle270)) {
y = (-(page.size.height - bounds.y - template._size.height) - (bounds.width - bounds.height));
width = bounds.height;
height = bounds.width;
}
}
}
else if (graphicsRotation === 270) {
graphics.translateTransform({ x: 0, y: template._size.width });
graphics.rotateTransform(270);
if (isNormalMatrix || (typeof this.rotationAngle !== 'undefined' && this._rotate === PdfRotationAngle.angle180)) {
x = -(page.size.width - bounds.x - bounds.width);
y = bounds.y;
}
else {
x = -(page.size.width - annotationBounds.x - template._size.width);
var matrix = template._content.dictionary.getArray('Matrix');
var box = template._content.dictionary.getArray('BBox');
if (matrix && box && matrix[5] !== box[2]) {
y = bounds.y - (bounds.height - bounds.width);
}
else {
y = (bounds.y + bounds.height) - bounds.width;
}
width = bounds.height;
height = bounds.width;
}
}
else if (graphicsRotation === 0) {
if (!isNormalMatrix &&
(typeof this.rotationAngle !== 'undefined' &&
(this.rotationAngle === PdfRotationAngle.angle90 ||
this.rotationAngle === PdfRotationAngle.angle270))) {
x = bounds.x;
y = (bounds.y + bounds.height - bounds.width);
width = bounds.height;
height = bounds.width;
}
}
}
return { x: x, y: y, width: width, height: height };
};
/* eslint-enable */
/**
* Derives the graphics rotation angle in degrees from the transformation matrix and normalizes it to standard orientations.
*
* @private
* @param {_PdfTransformationMatrix} matrix Graphics transformation matrix.
* @returns {number} angle Rotation angle in degrees (0, 90, 180, 270).
*/
PdfAnnotation.prototype._obtainGraphicsRotation = function (matrix) {
var radians = Math.atan2(matrix._matrix._elements[2], matrix._matrix._elements[0]);
var angle = Math.round(radians * 180 / Math.PI);
switch (angle) {
case -90:
angle = 90;
break;
case -180:
angle = 180;
break;
case 90:
angle = 270;
break;
}
return angle;
};
/**
* Removes the specified annotation from the given page and marks the page dictionary as updated.
*
* @private
* @param {PdfPage} page Page from which to remove the annotation.
* @param {PdfAnnotation} annotation Annotation to remove.
* @returns {void} nothing.
*/
PdfAnnotation.prototype._removeAnnotation = function (page, annotation) {
if (page && annotation) {
page.annotations.remove(annotation);
page._pageDictionary._updated = true;
}
};
/**
* Draws a cloud-style path along the given polyline by laying out overlapping circular arcs (using radius/overlap),
* resolving arc angles, building the path in appearance or page space, and rendering it with the provided brush/pen.
*
* @private
* @param {PdfGraphics} graphics Target graphics.
* @param {PdfBrush} brush Fill brush (optional).
* @param {PdfPen} pen Stroke pen.
* @param {number} radius Arc radius.
* @param {number} overlap Overlap factor (0..1).
* @param {Array<Point>} points Polyline points.
* @param {boolean} isAppearance True if drawing in appearance space.
* @returns {void} nothing.
*/
PdfAnnotation.prototype._drawCloudStyle = function (graphics, brush, pen, radius, overlap, points, isAppearance) {
if (_isNullOrUndefined(points) && this._isClockWise(points)) {
points.reverse();
}
var circles = [];
var circleOverlap = 2 * radius * overlap;
var previousPoint;
if (_isNullOrUndefined(points)) {
previousPoint = points[points.length - 1];
}
else {
points = [];
}
for (var i = 0; i < points.length; i++) {
var currentPoint = points[i];
var dx = currentPoint.x - previousPoint.x;
var dy = currentPoint.y - previousPoint.y;
var length_1 = Math.sqrt(dx * dx + dy * dy);
dx = dx / length_1;
dy = dy / length_1;
for (var a = 0; a + 0.1 * circleOverlap < length_1; a += circleOverlap) {
var cur = new _CloudStyleArc();
cur.point = { x: previousPoint.x + a * dx, y: previousPoint.y + a * dy };
circles.push(cur);
}
previousPoint = currentPoint;
}
var previousCurvedStyleArc = circles[circles.length - 1];
for (var i = 0; i < circles.length; i++) {
var currentCurvedStyleArc = circles[i];
var angle = this._getIntersectionDegrees([previousCurvedStyleArc.point.x, previousCurvedStyleArc.point.y], [currentCurvedStyleArc.point.x, currentCurvedStyleArc.point.y], radius);
previousCurvedStyleArc.endAngle = angle[0];
currentCurvedStyleArc.startAngle = angle[1];
previousCurvedStyleArc = currentCurvedStyleArc;
}
var path = new PdfPath();
for (var i = 0; i < circles.length; i++) {
var current = circles[i];
var startAngle = current.startAngle % 360;
var endAngle = current.endAngle % 360;
var sweepAngel = 0;
if (startAngle > 0 && endAngle < 0) {
sweepAngel = (180 - startAngle) + (180 - (endAngle < 0 ? -endAngle : endAngle));
}
else if (startAngle < 0 && endAngle > 0) {
sweepAngel = -startAngle + endAngle;
}
else if (startAngle > 0 && endAngle > 0) {
var difference = 0;
if (startAngle > endAngle) {
difference = startAngle - endAngle;
sweepAngel = 360 - difference;
}
else {
sweepAngel = endAngle - startAngle;
}
}
else if (startAngle < 0 && endAngle < 0) {
var difference = 0;
if (startAngle > endAngle) {
difference = startAngle - endAngle;
sweepAngel = 360 - difference;
}
else {
sweepAngel = -(startAngle + (-endAngle));
}
}
if (sweepAngel < 0) {
sweepAngel = -sweepAngel;
}
current.endAngle = sweepAngel;
path.addArc({ x: current.point.x - radius, y: current.point.y - radius,
width: 2 * radius, height: 2 * radius }, startAngle, sweepAngel);
}
path.closeFigure();
var tempPoints = [];
if (isAppearance) {
tempPoints = path._points.map(function (point) { return ({ x: point.x, y: -point.y }); });
}
var pdfpath;
if (isAppearance) {
pdfpath = new PdfPath();
pdfpath._points = tempPoints;
pdfpath._pathTypes = path._pathTypes;
}
else {
pdfpath = new PdfPath();
pdfpath._points = path._points;
pdfpath._pathTypes = path._pathTypes;
}
if (_isNullOrUndefined(brush)) {
graphics.drawPath(pdfpath, brush);
}
var incise = 180 / (Math.PI * 3);
path = new PdfPath();
for (var i = 0; i < circles.length; i++) {
var current = circles[i];
path.addArc({ x: current.point.x - radius,
y: current.point.y - radius,
width: 2 * radius,
height: 2 * radius }, current.startAngle, current.endAngle + incise);
}
path.closeFigure();
tempPoints = [];
if (isAppearance) {
tempPoints = path._points.map(function (point) { return ({ x: point.x, y: -point.y }); });
}
if (isAppearance) {
pdfpath = new PdfPath();
pdfpath._points = tempPoints;
pdfpath._pathTypes = path._pathTypes;
}
else {
pdfpath = new PdfPath();
pdfpath._points = path._points;
pdfpath._pathTypes = path._pathTypes;
}
graphics.drawPath(pdfpath, pen);
};
/**
* Determines whether the given polygon/polyline points are ordered clockwise using a signed edge-sum test.
*
* @private
* @param {Array<Point>} points Points of polygon/polyline.
* @returns {boolean} isClockwise.
*/
PdfAnnotation.prototype._isClockWise = function (points) {
var sum = 0;
if (_isNullOrUndefined(points)) {
for (var i = 0; i < points.length; i++) {
var first = points[i];
var second = points[(i + 1) % points.length];
sum += (second.x - first.x) * (second.y + first.y);
}
}
return sum > 0;
};
/**
* Computes the pair of intersection angles in degrees between two points
* for a circle of the given radius, returning [startAngle, endAngle].
*
* @private
* @param {number[]} first First point as [x, y].
* @param {number[]} second Second point as [x, y].
* @param {number} radius Circle radius.
* @returns {number[]} degreesPair [startAngle, endAngle] in degrees.
*/
PdfAnnotation.prototype._getIntersectionDegrees = function (first, second, radius) {
var dx = second[0] - first[0];
var dy = second[1] - first[1];
var length = Math.sqrt(dx * dx + dy * dy);
var a = 0.5 * length / radius;
if (a < -1) {
a = -1;
}
else if (a > 1) {
a = 1;
}
var radian = Math.atan2(dy, dx);
var cosvalue = Math.acos(a);
return [(radian - cosvalue) * (180 / Math.PI), (Math.PI + radian + cosvalue) * (180 / Math.PI)];
};
/**
* Applies border style settings like dash/dash pattern and adjusts the given rectangle based on border width,
* dictionary RD insets, and the provided parameter (paint bounds or cloudy effect), then returns the updated bounds.
*
* @private
* @param {PdfPen} borderPen Border pen (modified when dashes are present).
* @param {number[]} rectangle Rectangle as [x, y, width, height] (updated in place).
* @param {number} borderWidth Half of border width.
* @param {PdfBorderEffect|_PaintParameter} [parameter] Optional border effect or paint parameter.
* @returns {number[]} rect Updated rectangle [x, y, width, height].
*/
PdfAnnotation.prototype._obtainStyle = function (borderPen, rectangle, borderWidth, parameter) {
var dash = this.border.dash;
if (dash && dash.length > 0) {
var isDash = false;
var dashPattern = dash.slice();
isDash = dash.some(function (value) { return value > 0; });
if (isDash && this.border.style === PdfBorderStyle.dashed) {
borderPen._dashStyle = PdfDashStyle.dash;
borderPen._dashPattern = dashPattern;
}
}
if (parameter) {
if (parameter instanceof _PaintParameter) {
if (!this._isBounds && this._dictionary.has('RD')) {
var array = this._dictionary.getArray('RD');
if (array) {
rectangle[0] = rectangle[0] + array[0];
rectangle[1] = rectangle[1] + borderWidth + array[1];
rectangle[2] = rectangle[2] - (array[0] + array[2]);
rectangle[3] = rectangle[3] - (array[1] + array[3]);
}
}
else {
rectangle[0] = rectangle[0] + borderWidth;
rectangle[1] = rectangle[1] + borderWidth;
rectangle[2] = rectangle[2] - this.border.width;
rectangle[3] = rectangle[3] - this.border.width;
}
parameter.bounds = { x: rectangle[0], y: rectangle[1], width: rectangle[2], height: rectangle[3] };
}
else {
if (parameter.intensity !== 0 && parameter.style === PdfBorderEffectStyle.cloudy) {
var radius = parameter.intensity * 5;
rectangle[0] = rectangle[0] + radius + borderWidth;
rectangle[1] = rectangle[1] + radius + borderWidth;
rectangle[2] = rectangle[2] - (2 * radius) - 2 * borderWidth;
rectangle[3] = rectangle[3] - (2 * radius) - 2 * borderWidth;
}
else {
rectangle[0] = rectangle[0] + borderWidth;
rectangle[1] = rectangle[1] + borderWidth;
rectangle[2] = rectangle[2] - this.border.width;
rectangle[3] = this.bounds.height - this.border.width;
}
}
}
else {
if (!this._isBounds && this._dictionary && this._dictionary.has('RD')) {
var array = this._dictionary.getArray('RD');
if (array) {
rectangle[0] = rectangle[0] + array[0];
rectangle[1] = rectangle[1] + borderWidth + array[1];
rectangle[2] = rectangle[2] - (2 * array[2]);
rectangle[3] = rectangle[3] - this.border.width;
rectangle[3] = rectangle[3] - (2 * array[3]);
}
}
else {
rectangle[1] = rectangle[1] + borderWidth;
rectangle[3] = this.bounds.height - this.border.width;
}
}
return rectangle;
};
/**
* Creates the normal appearance template for a rectangle annotation, updating RD/bounds for cloudy effects,
* configuring pens/brushes and opacity, and drawing either a clouded or standard rectangle.
*
* @private
* @param {PdfBorderEffect} borderEffect Border effect (cloudy) definition.
* @returns {PdfTemplate} template Appearance template.
*/
PdfAnnotation.prototype._createRectangleAppearance = function (borderEffect) {
var width = this.border.width;
var rdArray = this._dictionary.getArray('RD');
if (!rdArray && borderEffect !== null && typeof borderEffect !== 'undefined' && borderEffect.intensity !== 0 && borderEffect.style === PdfBorderEffectStyle.cloudy) {
var cloudRectangle = { x: this.bounds.x - borderEffect.intensity * 5 - width / 2,
y: this.bounds.y - borderEffect.intensity * 5 - width / 2,
width: this.bounds.width + borderEffect.intensity * 10 + width,
height: this.bounds.height + borderEffect.intensity * 10 + width };
var radius = borderEffect.intensity * 5;
rdArray = [radius + width / 2, radius + width / 2, radius + width / 2, radius + width / 2];
this._dictionary.set('RD', rdArray);
this.bounds = cloudRectangle;
}
if (!this._isBounds && rdArray) {
var cloudRectangle = { x: this.bounds.x + rdArray[0],
y: this.bounds.y + rdArray[1],
width: this.bounds.width - rdArray[2] * 2,
height: this.bounds.height - rdArray[3] * 2 };
if (borderEffect.intensity !== 0 && borderEffect.style === PdfBorderEffectStyle.cloudy) {
cloudRectangle.x = cloudRectangle.x - borderEffect.intensity * 5 - width / 2;
cloudRectangle.y = cloudRectangle.y - borderEffect.intensity * 5 - width / 2;
cloudRectangle.width = cloudRectangle.width + borderEffect.intensity * 10 + width;
cloudRectangle.height = cloudRectangle.height + borderEffect.intensity * 10 + width;
var radius = borderEffect.intensity * 5;
this._dictionary.set('RD', [radius + width / 2, radius + width / 2, radius + width / 2, radius + width / 2]);
}
else {
delete this._dictionary._map.RD;
}
this.bounds = cloudRectangle;
}
var borderWidth = width / 2;
var nativeRectangle = [0, 0, this.bounds.width, this.bounds.height];
var template;
if (this._customTemplate.has('N')) {
template = this._customTemplate.get('N');
}
else {
template = new PdfTemplate(nativeRectangle, this._crossReference);
_setMatrix(template, this._getRotationAngle());
if (borderEffect.intensity !== 0 && borderEffect.style === PdfBorderEffectStyle.cloudy) {
template._writeTransformation = false;
}
var graphics = template.graphics;
var parameter = new _PaintParameter();
if (this.innerColor) {
parameter.backBrush = new PdfBrush(this._innerColor);
}
if (width > 0 && this.color) {
parameter.borderPen = new PdfPen(this._color, width);
}
if (this.color) {
parameter.foreBrush = new PdfBrush(this._color);
}
var rectangle = this._obtainStyle(parameter.borderPen, nativeRectangle, borderWidth, borderEffect);
if (typeof this.opacity !== 'undefined' && this._opacity < 1) {
graphics.save();
graphics.setTransparency(this._opacity);
}
if (borderEffect.intensity !== 0 && borderEffect.style === PdfBorderEffectStyle.cloudy) {
this._drawRectangleAppearance(rectangle, graphics, parameter, borderEffect.intensity);
}
else {
graphics.drawRectangle({ x: rectangle[0], y: rectangle[1],
width: rectangle[2], height: rectangle[3] }, parameter.borderPen, parameter.backBrush);
}
if (typeof this.opacity !== 'undefined' && this._opacity < 1) {
graphics.restore();
}
}
return template;
};
/**
* Renders a rectangle annotation appearance, using a cloudy outline when intensity produces a positive radius,
* otherwise drawing a standard rectangle with the provided pen and brush.
*
* @private
* @param {number[]} rectangle Rectangle [x, y, width, height] in template space.
* @param {PdfGraphics} graphics Target graphics.
* @param {_PaintParameter} parameter Paint parameter containing pen/brush.
* @param {number} intensity Cloudy intensity (affects radius).
* @returns {void} nothing.
*/
PdfAnnotation.prototype._drawRectangleAppearance = function (rectangle, graphics, parameter, intensity) {
var graphicsPath = new PdfPath();
if (_isNullOrUndefined(rectangle) && rectangle.length === 4) {
graphicsPath.addRectangle({ x: rectangle[0], y: rectangle[1], width: rectangle[2], height: rectangle[3] });
}
var radius = 0;
if (_isNullOrUndefined(intensity)) {
radius = intensity * 4.25;
}
if (radius > 0) {
var points = graphicsPath._points.map(function (point) { return ({ x: point.x, y: -point.y }); });
graphicsPath = new PdfPath();
graphicsPath.addPolygon(points);
this._drawCloudStyle(graphics, parameter.backBrush, parameter.borderPen, radius, 0.833, graphicsPath._points, false);
}
else {
graphics.drawRectangle({ x: rectangle[0], y: rectangle[1],
width: rectangle[2], height: rectangle[3] }, parameter.borderPen, parameter.backBrush);
}
};
/**
* Creates the normal appearance template for a circle/ellipse annotation, configuring dash styles and brushes,
* adjusting bounds via border insets, handling opacity and BE effects, and drawing the ellipse.
*
* @private
* @returns {PdfTemplate} template Appearance template.
*/
PdfAnnotation.prototype._createCircleAppearance = function () {
var nativeBounds = [0, 0, this.bounds.width, this.bounds.height];
var template;
if (this._customTemplate.has('N')) {
template = this._customTemplate.get('N');
}
else {
template = new PdfTemplate(nativeBounds, this._crossReference);
_setMatrix(template, this._getRotationAngle(), this);
if (this._dictionary.has('BE')) {
template._writeTransformation = false;
}
if (typeof this.color === 'undefined') {
this._isTransparentColor = true;
}
var graphics = template.graphics;
var width = this.border.width;
var borderPen = new PdfPen(this.color, width);
if (this.border.style === PdfBorderStyle.dashed) {
borderPen._dashStyle = PdfDashStyle.dash;
borderPen._dashPattern = [3, 1];
}
else if (this.border.style === PdfBorderStyle.dot) {
borderPen._dashStyle = PdfDashStyle.dot;
borderPen._dashPattern = [1, 1];
}
var parameter = new _PaintParameter();
if (this.innerColor) {
parameter.backBrush = new PdfBrush(this._innerColor);
}
if (width > 0) {
parameter.borderPen = borderPen;
}
if (this.color) {
parameter.foreBrush = new PdfBrush(this._color);
}
parameter.borderWidth = width;
var borderWidth = width / 2;
var rectangle = this._obtainStyle(borderPen, nativeBounds, borderWidth);
if (typeof this.opacity !== 'undefined' && this._opacity < 1) {
graphics.save();
graphics.setTransparency(this._opacity);
}
if (this._dictionary.has('BE')) {
this._drawCircleAppearance(rectangle, borderWidth, graphics, parameter);
}
else {
graphics.drawEllipse({ x: rectangle[0] + borderWidth,
y: rectangle[1],
width: rectangle[2] - width,
height: rectangle[3] }, parameter.borderPen, parameter.backBrush);
}
if (typeof this._opacity !== 'undefined' && this._opacity < 1) {
graphics.restore();
}
}
return template;
};
/**
* Draws the circle/ellipse annotation appearance, using a cloudy outline when an RD-derived radius is present;
* otherwise renders a standard ellipse with the given border width, pen, and brush.
*
* @private
* @param {number[]} rectangle Rectangle [x, y, width, height] in template space.
* @param {number} borderWidth Half of border width.
* @param {PdfGraphics} graphics Target graphics.
* @param {_PaintParameter} parameter Paint parameter with pen/brush.
* @returns {void} nothing.
*/
PdfAnnotation.prototype._drawCircleAppearance = function (rectangle, borderWidth, graphics, parameter) {
var radius = 0;
if (this._dictionary.has('RD')) {
var array = this._dictionary.getArray('RD');
if (array && array.length > 0) {
radius = array[0];
}
}
if (radius > 0) {
var rect = [rectangle[0] + borderWidth,
-rectangle[1] - rectangle[3],
rectangle[2] - this.border.width,
rectangle[3]];
var left = rect[0];
var top_1 = rect[1];
var right = rect[0] + rect[2];
var bottom = rect[1] + rect[3];
var controlPointList = [];
controlPointList.push([right, bottom]);
controlPointList.push([left, bottom]);
controlPointList.push([left, top_1]);
controlPointList.push([right, top_1]);
var startPointList = [];
startPointList.push([right, top_1 + (rect[3] / 2)]);
startPointList.push([left + rect[2] / 2, bottom]);
startPointList.push([left, top_1 + (rect[3] / 2)]);
startPointList.push([left + (rect[2] / 2), top_1]);
var endPointList = [];
endPointList.push([left + rect[2] / 2, bottom]);
endPointList.push([left, top_1 + (rect[3] / 2)]);
endPointList.push([left + (rect[2] / 2), top_1]);
endPointList.push([right, top_1 + (rect[3] / 2)]);
var points = [];
for (var i = 0; i < controlPointList.length; i++) {
this._createBezier(startPointList[i], controlPointList[i], endPointList[i], points);
}
this._drawCloudStyle(graphics, parameter.backBrush, parameter.borderPen, radius, 0.833, points.map(function (_a) {
var x = _a[0], y = _a[1];
return ({ x: x, y: y });
}), false); // eslint-disable-line
}
else {
graphics.drawEllipse({ x: rectangle[0] + borderWidth,
y: -rectangle[1],
width: rectangle[2] - this.border.width,
height: -rectangle[3] }, parameter.borderPen, parameter.backBrush);
}
};
/**
* Generates Bezier points between the given start and end knots using the control point,
* seeding both endpoints and delegating subdivision to the internal routine, and appends them to the output list.
*
* @private
* @param {number[]} first Start point [x, y].
* @param {number[]} second Control point [x, y].
* @param {number[]} third End point [x, y].
* @param {Array<number[]>} bezierPoints Output array to receive points.
* @returns {void} nothing.
*/
PdfAnnotation.prototype._createBezier = function (first, second, third, bezierPoints) {
bezierPoints.push(first);
this._populateBezierPoints(first, second, third, 0, bezierPoints);
bezierPoints.push(third);
};
/**
* Recursively subdivides a quadratic Bézier segment using midpoints to refine the curve up to the iteration limit,
* appending the computed midpoints to the output list.
*
* @private
* @param {number[]} first Start point [x, y].
* @param {number[]} second Control point [x, y].
* @param {number[]} third End point [x, y].
* @param {number} currentIteration Current iteration count.
* @param {Array<number[]>} bezierPoints Output point array.
* @returns {void} nothing.
*/
PdfAnnotation.prototype._populateBezierPoints = function (first, second, third, currentIteration, bezierPoints) {
if (currentIteration < 2) {
var midPoint1 = this._midPoint(first, second);
var midPoint2 = this._midPoint(second, third);
var midPoint3 = this._midPoint(midPoint1, midPoint2);
currentIteration++;
this._populateBezierPoints(first, midPoint1, midPoint3, currentIteration, bezierPoints);
bezierPoints.push(midPoint3);
this._populateBezierPoints(midPoint3, midPoint2, third, currentIteration, bezierPoints);
}
};
/**
* Computes the midpoint between two 2D points represented as [x, y] coordinate arrays.
*
* @private
* @param {number[]} first First point [x, y].
* @param {number[]} second Second point [x, y].
* @returns {number[]} midpoint [x, y].
*/
PdfAnnotation.prototype._midPoint = function (first, second) {
return [(first[0] + second[0]) / 2, (first[1] + second[1]) / 2];
};
/**
* Calculates the absolute angle in degrees of a line defined by two points, normalizing to the range 0..360 and handling vertical lines.
*
* @private
* @param {Point[]} linePoints Two points defining a line.
* @returns {number} angle Angle in degrees.
*/
PdfAnnotation.prototype._getAngle = function (linePoints) {
var x1 = linePoints[0].x;
var y1 = linePoints[0].y;
var x2 = linePoints[1].x;
var y2 = linePoints[1].y;
var angle = 0;
if (x2 - x1 === 0) {
angle = (y2 > y1) ? 90 : 270;
}
else {
var angleRatio = (y2 - y1) / (x2 - x1);
var radians = Math.atan(angleRatio);
angle = radians * (180 / Math.PI);
if ((x2 - x1) < 0 || (y2 - y1) < 0) {
angle += 180;
}
if ((x2 - x1) > 0 && (y2 - y1) < 0) {
angle -= 180;
}
if (angle < 0) {
angle += 360;
}
}
return angle;
};
/**
* Computes a new point by offsetting the given coordinate by the specified angle and optional length using degree-to-radian conversion.
*
* @private
* @param {Point} value Base coordinate.
* @param {number} angle Angle in degrees.
* @param {number} [length] Offset length (defaults to 0).
* @returns {Point} point New coordinate.
*/
PdfAnnotation.prototype._getAxisValue = function (value, angle, length) {
if (length === null || typeof length === 'undefined') {
length = 0;
}
return { x: value.x + Math.cos(angle * this._degreeToRadian) * length,
y: value.y + Math.sin(angle * this._degreeToRadian) * length };
};
/**
* Computes the geometry for an open arrowhead at the lines begin or end.
*
* @private
* @param {boolean} isBegin True for begin, false for end.
* @param {Point} axisPoint Axis point.
* @param {number} angle Angle in degrees.
* @param {number} length Marker length unit.
* @returns {{startPoint: Point, first: Point, second: Point}} points.
*/
PdfAnnotation.prototype._prepareOpenArrow = function (isBegin, axisPoint, angle, length) {
var arraowAngle = isBegin ? 30 : 150;
var count = 9 * length;
var startPoint = this._getAxisValue(axisPoint, angle, (isBegin ? length : (-length)));
var first = this._getAxisValue(startPoint, (angle + arraowAngle), count);
var second = this._getAxisValue(startPoint, (angle - arraowAngle), count);
return { startPoint: startPoint, first: first, second: second };
};
/**
* Computes the geometry for a reverse open arrowhead at the lines begin or end.
*
* @private
* @param {boolean} isBegin True for begin, false for end.
* @param {Point} axisPoint Axis point.
* @param {number} angle Angle in degrees.
* @param {number} length Marker length unit.
* @returns {{startPoint: Point, first: Point, second: Point}} points.
*/
PdfAnnotation.prototype._prepareReverseOpenArrow = function (isBegin, axisPoint, angle, length) {
var arraowAngle = isBegin ? 150 : 30;
var count = 9 * length;
var startPoint = this._getAxisValue(axisPoint, angle, (isBegin ? (-length) : length));
var first = this._getAxisValue(startPoint, (angle + arraowAngle), count);
var second = this._getAxisValue(startPoint, (angle - arraowAngle), count);
return { startPoint: startPoint, first: first, second: second };
};
/**
* Computes the geometry for a closed arrowhead at the lines begin or end.
*
* @private
* @param {boolean} isBegin True for begin, false for end.
* @param {Point} axisPoint Axis point.
* @param {number} angle Angle in degrees.
* @param {number} length Marker length unit.
* @returns {{startPoint: Point, first: Point, second: Point}} points.
*/
PdfAnnotation.prototype._prepareClosedArrow = function (isBegin, axisPoint, angle, length) {
var arraowAngle = isBegin ? 30 : 150;
var count = 9 * length;
var startPoint = this._getAxisValue(axisPoint, angle, (isBegin ? length : (-length)));
var first = this._getAxisValue(startPoint, (angle + arraowAngle), count);
var second = this._getAxisValue(startPoint, (angle - arraowAngle), count);
return { startPoint: startPoint, first: first, second: second };
};
/**
* Computes the geometry for a reverse closed arrowhead at the lines begin or end.
*
* @private
* @param {boolean} isBegin True for begin, false for end.
* @param {Point} axisPoint Axis point.
* @param {number} angle Angle in degrees.
* @param {number} length Marker length unit.
* @returns {{startPoint: Point, first: Point, second: Point}} points.
*/
PdfAnnotation.prototype._prepareReverseCloseArrow = function (isBegin, axisPoint, angle, length) {
var arraowAngle = isBegin ? 150 : 30;
var count = 9 * length;
var startPoint = this._getAxisValue(axisPoint, angle, (isBegin ? (-length) : length));
var first = this._getAxisValue(startPoint, (angle + arraowAngle), count);
var second = this._getAxisValue(startPoint, (angle - arraowAngle), count);
return { startPoint: startPoint, first: first, second: second };
};
/**
* Computes the two points of a slash marker relative to the axis point by offsetting at angle ± fixed offsets scaled by the given length.
*
* @private
* @param {Point} axisPoint Axis point.
* @param {number} angle Angle in degrees.
* @param {number} length Marker length unit.
* @returns {{first: Point, second: Point}} points.
*/
PdfAnnotation.prototype._prepareSlash = function (axisPoint, angle, length) {
var count = 9 * length;
var first = this._getAxisValue(axisPoint, (angle + 60), count);
var second = this._getAxisValue(axisPoint, (angle - 120), count);
return { first: first, second: second };
};
/**
* Computes the four vertices of a diamond centered at the axis point by offsetting at 0°, 90°, 180°, scaled by the given length.
*
* @private
* @param {Point} axisPoint Axis point.
* @param {number} length Marker length unit.
* @returns {{first: Point, second: Point, third: Point, fourth: Point}} points.
*/
PdfAnnotation.prototype._prepareDiamond = function (axisPoint, length) {
var count = 3 * length;
var first = this._getAxisValue(axisPoint, 180, count);
var second = this._getAxisValue(axisPoint, 90, count);
var third = this._getAxisValue(axisPoint, 0, count);
var fourth = this._getAxisValue(axisPoint, -90, count);
return { first: first, second: second, third: third, fourth: fourth };
};
/**
* Computes the two points of a butt marker relative to the axis point by offsetting at angle ±90°, scaled by the given length.
*
* @private
* @param {Point} axisPoint Axis point.
* @param {number} angle Angle in degrees.
* @param {number} length Marker length unit.
* @returns {{first: Point, second: Point}} points.
*/
PdfAnnotation.prototype._prepareButt = function (axisPoint, angle, length) {
var count = 3 * length;
var first = this._getAxisValue(axisPoint, (angle + 90), count);
var second = this._getAxisValue(axisPoint, (angle - 90), count);
return { first: first, second: second };
};
/**
* Computes the bounding rectangle for the specified line ending style at the given axis point and angle,
* using the provided pen, length, and begin/end flag.
*
* @private
* @param {Point} axisPoint Axis point.
* @param {number} angle Angle in degrees.
* @param {PdfPen} pen Pen used to draw (for path metrics).
* @param {PdfLineEndingStyle} style Line ending style.
* @param {number} length Marker length unit.
* @param {boolean} isBegin True if begin marker.
* @returns {{x: number, y: number, width: number, height: number}} bounds.
*/
PdfAnnotation.prototype._getBoundsFromLineEndStyle = function (axisPoint, angle, pen, style, length, isBegin) {
var result;
var path;
var bounds;
var values; // eslint-disable-line
switch (style) {
case PdfLineEndingStyle.square:
case PdfLineEndingStyle.circle:
result = { x: axisPoint.x - (3 * length),
y: axisPoint.y + (3 * length),
width: (6 * length),
height: (6 * length) };
break;
case PdfLineEndingStyle.openArrow:
values = this._prepareOpenArrow(isBegin, axisPoint, angle, length);
path = new PdfPath();
path._pen = pen;
path.addLine({ x: values.startPoint.x, y: values.startPoint.y }, { x: values.first.x, y: values.first.y });
path.addLine({ x: values.startPoint.x, y: values.startPoint.y }, { x: values.second.x, y: values.second.y });
bounds = path._getBounds();
result = { x: bounds[0], y: bounds[1], width: bounds[2], height: bounds[3] };
break;
case PdfLineEndingStyle.closedArrow:
values = this._prepareClosedArrow(isBegin, axisPoint, angle, length);
result = this._getBoundsValue([values.startPoint.x, values.startPoint.y,
values.first.x, values.first.y,
values.second.x, values.second.y]);
break;
case PdfLineEndingStyle.rOpenArrow:
values = this._prepareReverseOpenArrow(isBegin, axisPoint, angle, length);
path = new PdfPath();
path._pen = pen;
path.addLine({ x: values.startPoint.x, y: values.startPoint.y }, { x: values.first.x, y: values.first.y });
path.addLine({ x: values.startPoint.x, y: values.startPoint.y }, { x: values.second.x, y: values.second.y });
bounds = path._getBounds();
result = { x: bounds[0], y: bounds[1], width: bounds[2], height: bounds[3] };
break;
case PdfLineEndingStyle.rClosedArrow:
values = this._prepareReverseCloseArrow(isBegin, axisPoint, angle, length);
result = this._getBoundsValue([values.startPoint.x, values.startPoint.y,
values.first.x, values.first.y,
values.second.x, values.second.y]);
break;
case PdfLineEndingStyle.slash:
values = this._prepareSlash(axisPoint, angle, length);
result = this._getBoundsValue([axisPoint.x, axisPoint.y, values.first.x,
values.first.y, values.second.x, values.second.y]);
break;
case PdfLineEndingStyle.diamond:
values = this._prepareDiamond(axisPoint, length);
result = this._getBoundsValue([values.first.x, values.first.y, values.second.x,
values.second.y, values.third.x, values.third.y,
values.fourth.x, values.fourth.y]);
break;
case PdfLineEndingStyle.butt:
values = this._prepareButt(axisPoint, angle, length);
result = this._getBoundsValue([values.first.x, values.first.y, values.second.x, values.second.y]);
break;
}
return result;
};
/**
* Draws the specified line ending style at the given axis point and angle using the provided pen and brush,
* honoring the marker length and whether it applies to the begin or end of the line.
*
* @private
* @param {Point} axisPoint Axis point.
* @param {PdfGraphics} graphics Target graphics.
* @param {number} angle Angle in degrees.
* @param {PdfPen} pen Stroke pen.
* @param {PdfBrush} brush Fill brush.
* @param {PdfLineEndingStyle} style Line ending style.
* @param {number} length Marker length unit.
* @param {boolean} isBegin True if begin marker.
* @returns {void} nothing.
*/
PdfAnnotation.prototype._drawLineEndStyle = function (axisPoint, graphics, angle, pen, brush, style, length, isBegin) {
var path;
var values; // eslint-disable-line
switch (style) {
case PdfLineEndingStyle.square:
graphics.drawRectangle({ x: axisPoint.x - (3 * length),
y: -(axisPoint.y + (3 * length)),
width: (6 * length),
height: (6 * length) }, pen, brush);
break;
case PdfLineEndingStyle.circle:
graphics.drawEllipse({ x: axisPoint.x - (3 * length),
y: -(axisPoint.y + (3 * length)),
width: (6 * length),
height: (6 * length) }, pen, brush);
break;
case PdfLineEndingStyle.openArrow:
values = this._prepareOpenArrow(isBegin, axisPoint, angle, length);
path = new PdfPath();
path._pen = pen;
path.addLine({ x: values.startPoint.x, y: -values.startPoint.y }, { x: values.first.x, y: -values.first.y });
path.addLine({ x: values.startPoint.x, y: -values.startPoint.y }, { x: values.second.x, y: -values.second.y });
graphics._stateControl(pen, null, null);
graphics._buildUpPath(path._points, path._pathTypes);
graphics._drawGraphicsPath(pen, null, path._fillMode, false);
break;
case PdfLineEndingStyle.closedArrow:
values = this._prepareClosedArrow(isBegin, axisPoint, angle, length);
graphics.drawPolygon([{ x: values.startPoint.x, y: -values.startPoint.y },
{ x: values.first.x, y: -values.first.y }, { x: values.second.x,
y: -values.second.y }], pen, brush);
break;
case PdfLineEndingStyle.rOpenArrow:
values = this._prepareReverseOpenArrow(isBegin, axisPoint, angle, length);
path = new PdfPath();
path._pen = pen;
path.addLine({ x: values.startPoint.x, y: -values.startPoint.y }, { x: values.first.x, y: -values.first.y });
path.addLine({ x: values.startPoint.x, y: -values.startPoint.y }, { x: values.second.x, y: -values.second.y });
graphics._stateControl(pen, null, null);
graphics._buildUpPath(path._points, path._pathTypes);
graphics._drawGraphicsPath(pen, null, path._fillMode, false);
break;
case PdfLineEndingStyle.rClosedArrow:
values = this._prepareReverseCloseArrow(isBegin, axisPoint, angle, length);
graphics.drawPolygon([{ x: values.startPoint.x, y: -values.startPoint.y },
{ x: values.first.x, y: -values.first.y }, { x: values.second.x,
y: -values.second.y }], pen, brush);
break;
case PdfLineEndingStyle.slash:
values = this._prepareSlash(axisPoint, angle, length);
graphics.drawLine(pen, { x: axisPoint.x, y: -axisPoint.y }, { x: values.first.x, y: -values.first.y });
graphics.drawLine(pen, { x: axisPoint.x, y: -axisPoint.y }, { x: values.second.x, y: -values.second.y });
break;
case PdfLineEndingStyle.diamond:
values = this._prepareDiamond(axisPoint, length);
graphics.drawPolygon([{ x: values.first.x, y: -values.first.y },
{ x: values.second.x, y: -values.second.y }, { x: values.third.x, y: -values.third.y },
{ x: values.fourth.x, y: -values.fourth.y }], pen, brush);
break;
case PdfLineEndingStyle.butt:
values = this._prepareButt(axisPoint, angle, length);
graphics.drawLine(pen, { x: values.first.x, y: -values.first.y }, { x: values.second.x, y: -values.second.y });
break;
}
};
/* eslint-disable */
/**
* Computes the minimal bounding rectangle that encloses both input rectangles and returns the combined bounds.
*
* @private
* @param {{x: number, y: number, width: number, height: number}} rect1 First rectangle.
* @param {{x: number, y: number, width: number, height: number}} rect2 Second rectangle.
* @returns {{x: number, y: number, width: number, height: number}} combinedBounds.
*/
PdfAnnotation.prototype._getCombinedRectangleBounds = function (rect1, rect2) {
var left = Math.min(rect1.x, rect2.x);
var top = Math.min(rect1.y, rect2.y);
var right = Math.max(rect1.x + rect1.width, rect2.x + rect2.width);
var bottom = Math.max(rect1.y + rect1.height, rect2.y + rect2.height);
return {
x: left,
y: top,
width: right - left,
height: bottom - top
};
};
/* eslint-enable */
/**
* Draws the lines begin and end markers using the given angle, pen, brush, and marker length, defaulting the length when zero.
*
* @private
* @param {Point} start Start point of the line.
* @param {Point} end End point of the line.
* @param {PdfGraphics} graphics Target graphics.
* @param {number} angle Line angle in degrees.
* @param {PdfPen} pen Border pen (or null).
* @param {PdfBrush} brush Fill brush.
* @param {PdfAnnotationLineEndingStyle} lineStyle Begin/end line-ending styles.
* @param {number} length Marker length unit.
* @returns {void} nothing.
*/
PdfAnnotation.prototype._drawLineStyle = function (start, end, graphics, angle, pen, brush, lineStyle, length) {
if (length === 0) {
length = 1;
pen = null;
}
this._drawLineEndStyle(start, graphics, angle, pen, brush, lineStyle.begin, length, true);
this._drawLineEndStyle(end, graphics, angle, pen, brush, lineStyle.end, length, false);
};
/**
* Extracts and returns the annotations font settingsfamily, size, and style—by parsing DS/DA entries or appearance streams,
* normalizing font names and flags, and honoring FreeText font overrides.
*
* @private
* @returns {{ name: string, size: number, style: PdfFontStyle }} fontData.
*/
PdfAnnotation.prototype._obtainFontDetails = function () {
var fontFamily = '';
var fontSize;
var style = PdfFontStyle.regular;
if (this._dictionary.has('DS') || this._dictionary.has('DA')) {
var fontStyle_1;
var skipProcess = false;
if (this._dictionary.has('DS')) {
var collection = this._dictionary.get('DS').split(';');
collection.forEach(function (item) {
var entry = item.split(':');
if (item.indexOf('font-family') !== -1) {
fontFamily = entry[1];
}
else if (item.indexOf('font-size') !== -1) {
if (entry[1].endsWith('pt')) {
fontSize = Number.parseFloat(entry[1].replace('pt', ''));
}
}
else if (item.indexOf('font-style') !== -1 || item.indexOf('style') !== -1) {
fontStyle_1 = entry[1];
}
else if (item.indexOf('font') !== -1) {
var name_1 = entry[1];
var split = name_1.split(' ');
split.forEach(function (part) {
if (part !== '' && !part.endsWith('pt')) {
fontFamily += part + ' ';
}
if (part.endsWith('pt')) {
fontSize = Number.parseFloat(part.replace('pt', ''));
}
});
while (fontFamily !== ' ' && fontFamily.endsWith(' ')) {
fontFamily = fontFamily.substring(0, fontFamily.length - 1);
}
if (fontFamily.indexOf(',') !== -1) {
fontFamily = fontFamily.split(',')[0];
}
}
});
}
else {
var value = this._dictionary.get('DA');
if (value && value !== '' && value.indexOf('Tf') !== -1) {
var textCollection_1 = value.split(' ');
textCollection_1.forEach(function (text, i) {
if (text.indexOf('Tf') !== -1) {
fontFamily = textCollection_1[i - 2];
while (fontFamily !== '' && fontFamily.length > 1 && fontFamily[0] === '/') {
fontFamily = fontFamily.substring(1);
}
fontSize = Number.parseFloat(textCollection_1[i - 1]);
}
});
}
else if (this._dictionary.has('AP')) {
var appearanceDict = this._dictionary.get('AP');
var fontData = this._parseFontFromAppearance(appearanceDict, (this instanceof PdfRedactionAnnotation) ?
['R', 'N', 'D'] : ['N', 'R', 'D']);
switch (fontData.name) {
case 'Helvetica':
case 'Courier':
case 'Symbol':
case 'TimesRoman':
case 'ZapfDingbats':
case 'MonotypeSungLight':
case 'SinoTypeSongLight':
case 'MonotypeHeiMedium':
case 'HanyangSystemsGothicMedium':
case 'HanyangSystemsShinMyeongJoMedium':
case 'HeiseiKakuGothicW5':
case 'HeiseiMinchoW3':
fontFamily = fontData.name;
break;
case 'Times-Roman':
fontFamily = 'TimesRoman';
break;
default:
fontFamily = 'Helvetica';
break;
}
fontSize = fontData.fontSize;
if (typeof fontData.style === 'undefined' || fontData.style === null) {
style = PdfFontStyle.regular;
}
else {
style = fontData.style;
}
skipProcess = true;
}
}
if (!skipProcess) {
if (fontStyle_1 && fontStyle_1 !== '') {
var styleArray = [fontStyle_1];
if (fontStyle_1.includes(':')) {
styleArray = fontStyle_1.split(':');
}
else if (fontStyle_1.includes(',')) {
styleArray = fontStyle_1.split(',');
}
if (styleArray) {
styleArray.forEach(function (entry) {
entry = entry.trim();
switch (entry.toLowerCase()) {
case 'bold':
style |= PdfFontStyle.bold;
break;
case 'italic':
style |= PdfFontStyle.italic;
break;
case 'strikeout':
style |= PdfFontStyle.strikeout;
break;
case 'underline':
style |= PdfFontStyle.underline;
break;
}
});
}
}
}
if (fontFamily) {
fontFamily = fontFamily.trim();
}
}
else if (this._dictionary.has('AP')) {
var appearanceDict = this._dictionary.get('AP');
var fontData = this._parseFontFromAppearance(appearanceDict, (this instanceof PdfRedactionAnnotation) ?
['R', 'N', 'D'] : ['N', 'R', 'D']);
fontFamily = fontData.name;
fontSize = fontData.fontSize;
style = fontData.style;
}
if (this instanceof PdfFreeTextAnnotation && this._font && this._font.style !== style) {
style = this._font.style;
}
return { name: fontFamily, size: fontSize, style: style };
};
/* eslint-disable */
/**
* Parses the appearance dictionary using the provided key order to extract font family, size, and style
* from the selected appearance stream.
*
* @private
* @param {_PdfDictionary} source Appearance dictionary (AP).
* @param {string[]} keys Order of keys to check (e.g., N, R, D).
* @returns {{ name: string; fontSize: number; style: PdfFontStyle }} fontData.
*/
PdfAnnotation.prototype._parseFontFromAppearance = function (source, keys) {
var fontData;
var fontFamily;
var fontSize;
var style;
if (source) {
for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
var key = keys_1[_i];
if (source.has(key)) {
var appearance = source.get(key);
if (appearance) {
fontData = this._obtainAppearanceFont(appearance, fontFamily, fontSize, style);
}
break;
}
}
}
return fontData;
};
/**
* Parses font information from an appearance streams resources by reading `Tf` operators,
* resolving the BaseFont name, inferring bold/italic style flags, and extracting the font size.
*
* @private
* @param {any} resourceDict Appearance stream (or reference) containing resources. // eslint-disable-line
* @param {string} fontFamily Placeholder for resolved font family (unused input).
* @param {number} fontSize Placeholder for resolved size (unused input).
* @param {PdfFontStyle} style Placeholder for resolved style (unused input).
* @returns {{ name: string; fontSize: number; style: PdfFontStyle }} fontData.
*/
PdfAnnotation.prototype._obtainAppearanceFont = function (resourceDict, fontFamily, fontSize, style) {
if (resourceDict && resourceDict instanceof _PdfBaseStream && resourceDict.dictionary &&
resourceDict.dictionary.has('Resources')) {
var resourcesDict = resourceDict.dictionary.get('Resources');
var pdfStream = resourceDict;
var contentParser = new _ContentParser(pdfStream.getBytes());
var pdfRecords = contentParser._readContent();
for (var _i = 0, pdfRecords_1 = pdfRecords; _i < pdfRecords_1.length; _i++) {
var record = pdfRecords_1[_i];
var operandTokens = record._operands;
var operatorToken = record._operator;
if (operatorToken === 'Tf') {
var fontFamilyToken = operandTokens[0];
if (resourcesDict.has('Font')) {
var fontDict = resourcesDict.get('Font');
if (fontDict && fontFamilyToken.includes('/')) {
fontFamilyToken = fontFamilyToken.replace(/\//g, '');
var fontRefDict = fontDict.get(fontFamilyToken);
if (fontRefDict && fontRefDict.has('BaseFont')) {
var baseFontName = fontRefDict.get('BaseFont');
fontFamily = baseFontName.name;
if (fontFamily) {
var containsBold = fontFamily.includes('Bold');
var containsItalic = fontFamily.includes('Italic') || fontFamily.includes('Oblique');
if (fontFamily.includes('Times') || fontFamily.includes('Helvetica') || fontFamily.includes('Courier')) {
if (containsBold && containsItalic) {
style = PdfFontStyle.bold | PdfFontStyle.italic;
}
else if (containsBold) {
style = PdfFontStyle.bold;
}
else if (containsItalic) {
style = PdfFontStyle.italic;
}
}
if (operandTokens[1]) {
fontSize = Number.parseFloat(operandTokens[1]);
}
}
}
}
}
}
}
}
return { name: fontFamily, fontSize: fontSize, style: style };
};
/* eslint-enable */
/**
* Obtains and returns the resolved PdfFont instance by mapping the parsed font name, size, and style
* from the annotations appearance or DS/DA settings.
*
* @private
* @returns {PdfFont} font.
*/
PdfAnnotation.prototype._obtainFont = function () {
var fontData = this._obtainFontDetails();
return _mapFont(fontData.name, fontData.size, fontData.style, this);
};
/**
* Maps the given measurement unit to its corresponding graphics unit and canonical unit string e.g., in, cm, mm, p, pt,
* defaulting to inches.
*
* @private
* @param {PdfMeasurementUnit} measurementUnit Input measurement unit.
* @param {string} unitString Output unit string (updated in return object).
* @returns {{graphicsUnit: _PdfGraphicsUnit, unitString: string}} mapping.
*/
PdfAnnotation.prototype._getEqualPdfGraphicsUnit = function (measurementUnit, unitString) {
var graphicsUnit;
switch (measurementUnit) {
case PdfMeasurementUnit.inch:
graphicsUnit = _PdfGraphicsUnit.inch;
unitString = 'in';
break;
case PdfMeasurementUnit.centimeter:
graphicsUnit = _PdfGraphicsUnit.centimeter;
unitString = 'cm';
break;
case PdfMeasurementUnit.millimeter:
graphicsUnit = _PdfGraphicsUnit.millimeter;
unitString = 'mm';
break;
case PdfMeasurementUnit.pica:
graphicsUnit = _PdfGraphicsUnit.pica;
unitString = 'p';
break;
case PdfMeasurementUnit.point:
graphicsUnit = _PdfGraphicsUnit.point;
unitString = 'pt';
break;
default:
graphicsUnit = _PdfGraphicsUnit.inch;
unitString = 'in';
break;
}
return { graphicsUnit: graphicsUnit, unitString: unitString };
};
/**
* Creates and returns a Measure dictionary configured for the given unit string, initializing distance/area entries,
* formatting fields, and unit conversion factors.
*
* @private
* @param {string} unitString Canonical unit string (in, cm, mm, pt, p).
* @returns {_PdfDictionary} measureDictionary.
*/
PdfAnnotation.prototype._createMeasureDictionary = function (unitString) {
var d = new _PdfDictionary();
d.set('C', 1);
d.set('D', 100);
d.set('F', _PdfName.get('D'));
d.set('RD', '.');
d.set('RT', '');
d.set('SS', '');
d.set('U', unitString);
var a = new _PdfDictionary();
a.set('C', 1);
a.set('D', 100);
a.set('F', _PdfName.get('D'));
a.set('RD', '.');
a.set('RT', '');
a.set('SS', '');
a.set('U', 'sq ' + unitString);
var x = new _PdfDictionary();
if (unitString === 'in') {
x.set('C', 0.0138889);
}
else if (unitString === 'cm') {
x.set('C', 0.0352778);
}
else if (unitString === 'mm') {
x.set('C', 0.352778);
}
else if (unitString === 'pt') {
x.set('C', 1);
}
else if (unitString === 'p') {
x.set('C', 0.0833333);
}
x.set('D', 100);
x.set('F', _PdfName.get('D'));
x.set('RD', '.');
x.set('RT', '');
x.set('SS', '');
x.set('U', unitString);
var measureDictionary = new _PdfDictionary();
measureDictionary.set('A', [a]);
measureDictionary.set('D', [d]);
measureDictionary.set('R', '1 ' + unitString + ' = 1 ' + unitString);
measureDictionary.set('Type', _PdfName.get('Measure'));
measureDictionary.set('X', [x]);
return measureDictionary;
};
/**
* Converts an RGB triplet to a hex color string, defaulting to black when undefined.
*
* @private
* @param {number[]} col RGB array [r, g, b].
* @returns {string} hex Hex color string (#RRGGBB).
*/
PdfAnnotation.prototype._colorToHex = function (col) {
if (col) {
return '#' + this._componentToHex(col[0]) + this._componentToHex(col[1]) + this._componentToHex(col[2]);
}
else {
return '#' + this._componentToHex(0) + this._componentToHex(0) + this._componentToHex(0);
}
};
/**
* Converts a single byte component to a two-digit hexadecimal string.
*
* @private
* @param {number} c Component value (0..255).
* @returns {string} hex Two-digit hex.
*/
PdfAnnotation.prototype._componentToHex = function (c) {
var hex = c.toString(16);
return hex.length === 1 ? '0' + hex : hex;
};
/* eslint-disable */
/**
* Computes the axis-aligned bounding box of a rectangle after rotation by the given angle and returns the rotated bounds.
*
* @private
* @param {{ x: number, y: number, width: number, height: number }} bounds Rectangle bounds. // eslint-disable-line
* @param {number} rotateAngle Rotation angle in degrees.
* @returns {{ x: number, y: number, width: number, height: number }} rotatedBounds.
*/
PdfAnnotation.prototype._getRotatedBounds = function (bounds, rotateAngle) {
if (bounds.width > 0 && bounds.height > 0) {
var matrix_1 = new _PdfTransformationMatrix();
matrix_1._rotate(rotateAngle);
var corners = [];
corners.push({ x: bounds.x, y: bounds.y });
corners.push({ x: bounds.x + bounds.width, y: bounds.y });
corners.push({ x: bounds.x + bounds.width, y: bounds.y + bounds.height });
corners.push({ x: bounds.x, y: bounds.y + bounds.height });
corners = corners.map(function (point) { return matrix_1._matrix._transform(point); });
var path = new PdfPath();
path.addRectangle({ x: bounds.x, y: bounds.y, width: bounds.width, height: bounds.height });
path._points = corners.slice(0, 4);
var minX = corners[0].x;
var maxX = corners[3].x;
var minY = corners[0].y;
var maxY = corners[3].y;
for (var i = 0; i < 4; i++) {
if (corners[i].x < minX) {
minX = corners[i].x;
}
if (corners[i].x > maxX) {
maxX = corners[i].x;
}
if (corners[i].y < minY) {
minY = corners[i].y;
}
if (corners[i].y > maxY) {
maxY = corners[i].y;
}
}
return { x: bounds.x, y: bounds.y, width: Math.round(maxX - minX), height: Math.round(maxY - minY) };
}
return bounds;
};
/* eslint-enable */
/**
* Flattens the current annotations pop-up by drawing a static popup appearance onto the page.
*
* @private
* @returns {void} nothing.
*/
PdfAnnotation.prototype._flattenPopUp = function () {
this._flattenPop(this._page, this.color, this.bounds, this.border, this.author, this.subject, this.text);
};
/* eslint-disable */
/**
* Renders and flattens a pop-up annotation onto the specified page using the provided visual settings and content.
*
* @private
* @param {PdfPage} _page Target page.
* @param {PdfColor} color Background color.
* @param {{ x: number, y: number, width: number, height: number }} boundsValue Popup bounds. // eslint-disable-line
* @param {PdfAnnotationBorder} border Popup border.
* @param {string} author Author name.
* @param {string} subject Subject text.
* @param {string} text Content text.
* @returns {void} nothing.
*/
PdfAnnotation.prototype._flattenPop = function (_page, color, boundsValue, border, author, subject, text) {
var clientSize = { width: 0, height: 0 };
if (_page && _page.size) {
clientSize = _page.size;
}
var x = clientSize.width - 180;
var annotBounds = boundsValue;
var y = (annotBounds.y + 142) < clientSize.height ? annotBounds.y : clientSize.height - 142;
var bounds = [x, y, 180, 142];
if (this._dictionary.has('Popup')) {
var dictionary = this._dictionary.get('Popup');
if (dictionary) {
var rectValue = this._dictionary.getArray('Rect');
if (rectValue && rectValue.length === 4) {
var left = rectValue[0];
var top_2 = rectValue[1];
var width = rectValue[2];
var height = rectValue[3];
bounds = [left, top_2, width - left, height - top_2];
}
}
}
if (typeof color === 'undefined') {
color = { r: 0, g: 0, b: 0 };
}
var backBrush = new PdfBrush(color);
var borderWidth = border.width / 2;
var pen = new PdfPen({ r: 0, g: 0, b: 0 }, 1);
var track = 0;
var aBrush = new PdfBrush(this._getForeColor(color));
if (typeof author !== 'undefined' && author !== null && author !== '') {
track = this._drawAuthor(author, subject, bounds, backBrush, aBrush, _page, track, border);
}
else if (typeof subject !== 'undefined' && subject !== null && subject !== '') {
var titleRect = [bounds[0] + borderWidth, bounds[1] + borderWidth, bounds[2] - border.width, 40];
this._saveGraphics(_page, PdfBlendMode.hardLight);
if (this._isTransparentColor) {
_page.graphics.drawRectangle({ x: titleRect[0], y: titleRect[1], width: titleRect[2], height: titleRect[3] }, pen);
}
else {
_page.graphics.drawRectangle({ x: titleRect[0], y: titleRect[1], width: titleRect[2], height: titleRect[3] }, pen, backBrush);
}
_page.graphics.restore();
var contentRect = [titleRect[0] + 11, titleRect[1], titleRect[2], titleRect[3] / 2];
contentRect = [contentRect[0], (contentRect[1] + contentRect[3] - 2), contentRect[2], titleRect[3] / 2];
this._saveGraphics(_page, PdfBlendMode.normal);
this._drawSubject(subject, { x: contentRect[0], y: contentRect[1], width: contentRect[2], height: contentRect[3] }, _page);
_page.graphics.restore();
track = 40;
}
else {
this._saveGraphics(_page, PdfBlendMode.hardLight);
var titleRect = [bounds[0] + borderWidth, bounds[1] + borderWidth, bounds[2] - border.width, 20];
if (this._isTransparentColor) {
_page.graphics.drawRectangle({ x: titleRect[0], y: titleRect[1], width: titleRect[2], height: titleRect[3] }, pen);
}
else {
_page.graphics.drawRectangle({ x: titleRect[0], y: titleRect[1], width: titleRect[2], height: titleRect[3] }, pen, backBrush);
}
track = 20;
_page.graphics.restore();
}
var rect = [bounds[0] + borderWidth, bounds[1] + borderWidth + track,
bounds[2] - border.width, bounds[3] - (track + border.width)];
this._saveGraphics(_page, PdfBlendMode.hardLight);
_page.graphics.drawRectangle({ x: rect[0], y: rect[1],
width: rect[2], height: rect[3] }, new PdfPen({ r: 0, g: 0, b: 0 }, 1), new PdfBrush({ r: 255, g: 255, b: 255 }));
rect[0] += 11;
rect[1] += 5;
rect[2] -= 22;
_page.graphics.restore();
this._saveGraphics(_page, PdfBlendMode.normal);
if (typeof text !== 'undefined' && text !== null && text !== '') {
_page.graphics.drawString(text, this._popUpFont, { x: rect[0], y: rect[1],
width: rect[2], height: rect[3] }, null, new PdfBrush({ r: 0, g: 0, b: 0 }), null);
}
_page.graphics.restore();
};
/* eslint-enable */
/**
* Flattens a previously loaded pop-up annotation by rendering its stored content and removing the interactive object.
*
* @private
* @returns {void} nothing.
*/
PdfAnnotation.prototype._flattenLoadedPopUp = function () {
var content = '';
if (this._dictionary.has('Contents')) {
content = this._dictionary.get('Contents');
}
var author = this.author;
var subject = this.subject;
var pen = new PdfPen({ r: 0, g: 0, b: 0 }, 1);
if (!this._dictionary.has('Popup')) {
this._flattenPop(this._page, this.color, this.bounds, this.border, author, subject, content);
this._page.annotations.remove(this);
}
else {
var bounds = this._getRectangleBoundsValue();
if (typeof this.color === 'undefined') {
this.color = { r: 0, g: 0, b: 0 };
}
var backBrush = new PdfBrush(this.color);
var borderWidth = this.border.width / 2;
var track = 0;
var aBrush = new PdfBrush(this._getForeColor(this.color));
if (typeof this.author !== 'undefined' && this.author !== null && this.author !== '') {
track = this._drawAuthor(this.author, this.subject, bounds, backBrush, aBrush, this._page, track, this.border);
}
else if (typeof this.subject !== 'undefined' && this.subject !== null && this.subject !== '') {
var titleRect = [bounds[0] + borderWidth, bounds[1] + borderWidth, bounds[2] - this.border.width, 40];
this._saveGraphics(this._page, PdfBlendMode.hardLight);
this._page.graphics.drawRectangle({ x: titleRect[0], y: titleRect[1],
width: titleRect[2], height: titleRect[3] }, pen, backBrush);
this._page.graphics.restore();
var contentRect = [titleRect[0] + 11, titleRect[1], titleRect[2], titleRect[3] / 2];
contentRect = [contentRect[0], (contentRect[1] + contentRect[3] - 2), contentRect[2], titleRect[3] / 2];
this._saveGraphics(this._page, PdfBlendMode.normal);
this._drawSubject(this.subject, { x: contentRect[0], y: contentRect[1],
width: contentRect[2], height: contentRect[3] }, this._page);
track = 40;
this._page.graphics.restore();
}
else {
this._saveGraphics(this._page, PdfBlendMode.hardLight);
var titleRect = [bounds[0] + borderWidth, bounds[1] + borderWidth, bounds[2] - this.border.width, 20];
this._page.graphics.drawRectangle({ x: titleRect[0], y: titleRect[1],
width: titleRect[2], height: titleRect[3] }, pen, backBrush);
track = 20;
this._page.graphics.restore();
}
this._saveGraphics(this._page, PdfBlendMode.hardLight);
var rect = [bounds[0] + borderWidth, bounds[1] + borderWidth + track,
bounds[2] - this.border.width, bounds[3] - (track + this.border.width)];
this._page.graphics.drawRectangle({ x: rect[0], y: rect[1], width: rect[2],
height: rect[3] }, pen, new PdfBrush({ r: 255, g: 255, b: 255 }));
rect[0] += 11;
rect[1] += 5;
rect[2] -= 22;
this._page.graphics.restore();
this._saveGraphics(this._page, PdfBlendMode.normal);
this._page.graphics.restore();
//let xmlData: Array<any> = Array<any>();
// if (this._dictionary.has('RC')) {
// //xmlData = this.parseXMLData();
// }
// if (xmlData !== null) {
// // Need to add xml data code
// } else {
if (typeof content !== 'undefined' && content !== null && content !== '') {
this._page.graphics.drawString(content, this._popUpFont, { x: rect[0], y: rect[1],
width: rect[2], height: rect[3] }, null, new PdfBrush({ r: 0, g: 0, b: 0 }), null);
}
// }
this._page.graphics.restore();
this._page.annotations.remove(this);
}
};
/**
* Retrieves and normalizes the rectangle bounds of the pop up from the dictionary, converting coordinates to page space.
*
* @private
* @returns {number[]} rect Normalized array [x, y, width, height].
*/
PdfAnnotation.prototype._getRectangleBoundsValue = function () {
if (this._dictionary.has('Popup')) {
var dic = this._dictionary.get('Popup');
var rect = dic.getArray('Rect');
if (rect !== null) {
if (this._page !== null) {
if (rect[1] === 0 && rect[3] === 0) {
rect[1] = rect[1] + rect[3];
}
else {
rect[1] = this._page._size.height - (rect[1] + rect[3]);
}
}
else {
rect[1] = (rect[1] - rect[3]);
}
return rect;
}
else {
return [0, 0, 0, 0];
}
}
else {
return [0, 0, 0, 0];
}
};
/**
* Determines a contrasting foreground color (black or white) based on the luminance of the given background color.
*
* @private
* @param {PdfColor} color Background color.
* @returns {PdfColor} foreColor.
*/
PdfAnnotation.prototype._getForeColor = function (color) {
var fore = (((color.r + color.g + color.b) / 3) > 128) ? { r: 0, g: 0, b: 0 } : { r: 255, g: 255, b: 255 };
return fore;
};
/**
* Draws the author/subject title area of a pop-up and returns the consumed vertical space (tracking height).
*
* @private
* @param {string} author Author text.
* @param {string} subject Subject text.
* @param {number[]} bounds Bounds array [x, y, width, height].
* @param {PdfBrush} backBrush Background brush.
* @param {PdfBrush} aBrush Foreground brush.
* @param {PdfPage} _page Target page.
* @param {number} trackingHeight Current tracking height.
* @param {PdfAnnotationBorder} border Annotation border.
* @returns {number} consumedHeight.
*/
PdfAnnotation.prototype._drawAuthor = function (author, subject, bounds, backBrush, aBrush, _page, trackingHeight, border) {
var borderWidth = this.border.width / 2;
var pen = new PdfPen({ r: 0, g: 0, b: 0 }, 1);
var format = new PdfStringFormat(PdfTextAlignment.left, PdfVerticalAlignment.middle);
var titleRect = [bounds[0] + borderWidth, bounds[1] + borderWidth, bounds[2] - border.width, 20];
if (typeof subject !== 'undefined' && subject !== null && subject !== '') {
titleRect[3] += 20;
trackingHeight = titleRect[3];
this._saveGraphics(_page, PdfBlendMode.hardLight);
if (this._isTransparentColor) {
_page.graphics.drawRectangle({ x: titleRect[0], y: titleRect[1], width: titleRect[2], height: titleRect[3] }, pen);
}
else {
_page.graphics.drawRectangle({ x: titleRect[0], y: titleRect[1], width: titleRect[2], height: titleRect[3] }, pen, backBrush);
}
_page.graphics.restore();
var contentRect = { x: titleRect[0] + 11, y: titleRect[1], width: titleRect[2], height: titleRect[3] / 2 };
this._saveGraphics(this._page, PdfBlendMode.normal);
_page.graphics.drawString(author, this._authorBoldFont, contentRect, null, aBrush, format);
contentRect = { x: contentRect.x, y: (contentRect.y + contentRect.height - 2), width: contentRect.width,
height: titleRect[3] / 2 };
this._drawSubject(subject, contentRect, _page);
_page.graphics.restore();
}
else {
this._saveGraphics(_page, PdfBlendMode.hardLight);
if (this._isTransparentColor) {
_page.graphics.drawRectangle({ x: titleRect[0], y: titleRect[1], width: titleRect[2], height: titleRect[3] }, pen);
}
else {
_page.graphics.drawRectangle({ x: titleRect[0], y: titleRect[1], width: titleRect[2], height: titleRect[3] }, pen, backBrush);
}
_page.graphics.restore();
var contentRect = { x: titleRect[0] + 11, y: titleRect[1], width: titleRect[2], height: titleRect[3] };
this._saveGraphics(_page, PdfBlendMode.normal);
_page.graphics.drawString(author, this._popUpFont, contentRect, null, aBrush, format);
trackingHeight = titleRect[3];
_page.graphics.restore();
}
return trackingHeight;
};
/**
* Draws the subject text inside the provided content rectangle on the given page using the bold author font and left middle alignment.
*
* @private
* @param {string} subject Subject text.
* @param {Rectangle} contentRect Content rectangle.
* @param {PdfPage} _page Target page.
* @returns {void} nothing.
*/
PdfAnnotation.prototype._drawSubject = function (subject, contentRect, _page) {
var format = new PdfStringFormat(PdfTextAlignment.left, PdfVerticalAlignment.middle);
_page.graphics.drawString(subject, this._authorBoldFont, contentRect, null, new PdfBrush({ r: 0, g: 0, b: 0 }), format);
};
/**
* Saves the graphics state and applies transparency with the specified blend mode for subsequent drawing operations.
*
* @private
* @param {PdfPage} _page Target page.
* @param {PdfBlendMode} blendMode Blend mode to apply.
* @returns {void} nothing.
*/
PdfAnnotation.prototype._saveGraphics = function (_page, blendMode) {
_page.graphics.save();
_page.graphics.setTransparency(0.8, 0.8, blendMode);
};
/**
* Formats the given RGB color as a PDF stroke color command string with 3 decimal precision per component.
*
* @private
* @param {PdfColor} color RGB color.
* @returns {string} command PDF color command string.
*/
PdfAnnotation.prototype._getBorderColorString = function (color) {
return (color.r / 255).toFixed(3) + ' ' + (color.g / 255).toFixed(3) + ' ' + (color.b / 255).toFixed(3) + ' rg ';
};
/**
* Converts a JavaScript Date to a PDF date string (D:YYYYMMDDHHmmSSOHH'mm') including the local timezone offset.
*
* @private
* @param {Date} dateTime Input date.
* @returns {string} pdfDate PDF date string.
*/
PdfAnnotation.prototype._dateToString = function (dateTime) {
var year = dateTime.getFullYear();
var month = _pad2(dateTime.getMonth() + 1);
var day = _pad2(dateTime.getDate());
var hours = _pad2(dateTime.getHours());
var mins = _pad2(dateTime.getMinutes());
var secs = _pad2(dateTime.getSeconds());
var utcOffsetMinutes = -dateTime.getTimezoneOffset();
var sign = utcOffsetMinutes >= 0 ? '+' : '-'; // eslint-disable-line
var absMin = Math.abs(utcOffsetMinutes);
var offH = _pad2(Math.floor(absMin / 60));
var offM = _pad2(absMin % 60);
return "D:" + year + month + day + hours + mins + secs + sign + offH + "'" + offM + "'";
};
/**
* Parses a PDF or common date string into a JavaScript Date, handling D: format, slashed dates, and timezone offsets.
*
* @private
* @param {string} date Date string.
* @returns {Date} parsedDate.
*/
PdfAnnotation.prototype._stringToDate = function (date) {
if (!date || typeof date !== 'string') {
return new Date(date); // eslint-disable-line
}
if (date.indexOf('/') !== -1) {
var list = date.split('/');
var year = parseInt(list[2].split(' ')[0], 10);
var month = parseInt(list[0], 10) - 1;
var day = parseInt(list[1], 10);
var timePart = (list[2].split(' ')[1] || '00:00:00').split(':');
var hour = parseInt(timePart[0] || '0', 10);
var minute = parseInt(timePart[1] || '0', 10);
var second = parseInt(timePart[2] || '0', 10);
return new Date(year, month, day, hour, minute, second);
}
if (date.startsWith('D:')) {
date = date.substring(2);
}
var raw = date.replace(/'/g, '').trim();
var y = parseInt(raw.slice(0, 4), 10);
var haveM = raw.length >= 6;
var haveD = raw.length >= 8;
var haveH = raw.length >= 10;
var havem = raw.length >= 12;
var haves = raw.length >= 14;
var m = haveM ? parseInt(raw.slice(4, 6), 10) : 1;
var d = haveD ? parseInt(raw.slice(6, 8), 10) : 1;
var h = haveH ? parseInt(raw.slice(8, 10), 10) : 0;
var min = havem ? parseInt(raw.slice(10, 12), 10) : 0;
var s = haves ? parseInt(raw.slice(12, 14), 10) : 0;
var tzTail = raw.slice(14);
if (/^[+-]\d{2}:\d{2}$/.test(tzTail)) {
tzTail = tzTail.replace(':', '');
}
var hasTz = false;
var tzSign = 0;
var tzH = 0;
var tzM = 0;
if (tzTail) {
if (/^[Zz]$/.test(tzTail)) {
hasTz = true;
tzSign = +1;
tzH = 0;
tzM = 0;
}
else if (/^[+-]\d{2}\d{2}$/.test(tzTail)) {
hasTz = true;
tzSign = tzTail[0] === '+' ? +1 : -1;
tzH = parseInt(tzTail.slice(1, 3), 10);
tzM = parseInt(tzTail.slice(3, 5), 10);
}
else if (/^[+-]\d{2}$/.test(tzTail)) {
hasTz = true;
tzSign = tzTail[0] === '+' ? +1 : -1;
tzH = parseInt(tzTail.slice(1, 3), 10);
tzM = 0;
}
}
if (hasTz) {
var localUTCms = Date.UTC(y, m - 1, d, h, min, s);
var offsetMinutes = tzSign * (tzH * 60 + tzM);
return new Date(localUTCms - offsetMinutes * 60 * 1000);
}
else {
return new Date(y, m - 1, d, h, min, s);
}
};
/**
* Computes the native PDF rectangle array [x, y, right, top] from annotation bounds,
* adjusting for page size and Crop/MediaBox offsets.
*
* @private
* @returns {number[]} rect [x, y, right, top].
*/
PdfAnnotation.prototype._obtainNativeRectangle = function () {
var rect = [this._bounds.x, this._bounds.y, this.bounds.x + this._bounds.width, this.bounds.y + this._bounds.height];
var cropBoxOrMediaBox = this._getCropOrMediaBox();
if (this._page) {
var size = this._page.size;
rect[1] = size.height - rect[3];
if (cropBoxOrMediaBox && cropBoxOrMediaBox.length > 2 && (cropBoxOrMediaBox[0] !== 0 || cropBoxOrMediaBox[1] !== 0)) {
rect[0] += cropBoxOrMediaBox[0];
rect[1] += cropBoxOrMediaBox[1];
}
}
return rect;
};
/**
* Returns a transformed copy of polygon points adjusted by the page CropBox/MediaBox offsets when present.
*
* @private
* @param {Point[]} polygonPoints Points to transform.
* @returns {Point[]} transformedPoints.
*/
PdfAnnotation.prototype._getPoints = function (polygonPoints) {
var cropOrMediaBox = this._getCropOrMediaBox();
var points = polygonPoints ? polygonPoints.map(function (p) { return ({ x: p.x, y: p.y }); }) : []; // eslint-disable-line
if (cropOrMediaBox && cropOrMediaBox.length > 3 && typeof cropOrMediaBox[0] === 'number' && typeof cropOrMediaBox[1] === 'number' &&
(cropOrMediaBox[0] !== 0 || cropOrMediaBox[1] !== 0)) {
for (var j = 0; j < points.length; j++) {
var x = points[j].x;
var y = points[j].y;
points[j].x = x + cropOrMediaBox[0];
if (this._page._pageDictionary.has('MediaBox') && !this._page._pageDictionary.has('CropBox') && cropOrMediaBox[3] === 0 && cropOrMediaBox[1] > 0) {
points[j].y = y + cropOrMediaBox[3];
}
else {
points[j].y = y + cropOrMediaBox[1];
}
}
}
return points;
};
/**
* Retrieves the page CropBox or MediaBox as a normalized array, correcting negative height cases and defaulting to [0, 0, 0, 0].
*
* @private
* @returns {number[]} box [x, y, width, height] or zeros.
*/
PdfAnnotation.prototype._getCropOrMediaBox = function () {
var cropOrMediaBox;
if (this._page && this._page._pageDictionary.has('CropBox')) {
cropOrMediaBox = this._page.cropBox;
}
if (!cropOrMediaBox && this._page && this._page._pageDictionary.has('MediaBox')) {
cropOrMediaBox = this._page.mediaBox;
}
if (cropOrMediaBox && cropOrMediaBox[3] < 0) {
var y = cropOrMediaBox[1];
var height = cropOrMediaBox[3];
cropOrMediaBox[3] = y;
cropOrMediaBox[1] = height;
}
return cropOrMediaBox ? cropOrMediaBox : [0, 0, 0, 0];
};
PdfAnnotation.prototype._getDocumentLayer = function () {
if (this._dictionary.has('OC')) {
var reference = this._dictionary.getRaw('OC');
var page = this._page;
if (reference && page && this._crossReference._document) {
var layerCollection = this._crossReference._document.layers;
if (layerCollection) {
this._isMatched(layerCollection, reference, page);
}
}
}
return this.layer;
};
PdfAnnotation.prototype._isMatched = function (layerCollection, expectedReference, page) {
for (var i = 0; i < layerCollection.count; i++) {
var reference = layerCollection.at(i)._referenceHolder;
if (reference && reference === expectedReference) {
if (layerCollection.at(i).name) {
this._layer = layerCollection.at(i);
break;
}
}
else if (layerCollection.at(i).layers && layerCollection.at(i).layers.count > 0) {
this._isMatched(layerCollection.at(i).layers, expectedReference, page);
}
}
};
/**
* Computes and sets the QuadPoints for text selections from stored bounds, accounting for margins, page height, and Crop/MediaBox offsets.
*
* @private
* @param {Size} pageSize represents the page size.
* @returns {void} nothing.
*/
PdfAnnotation.prototype._setQuadPoints = function (pageSize) {
var textQuadLocation = [];
var pageHeight = pageSize.height;
var margins;
if (this._page && this._page._isNew && this._page._pageSettings && this._page._pageSettings.margins) {
var margin = this._page._pageSettings.margins;
margins = {
left: margin.left,
top: margin.top,
right: margin.right,
bottom: margin.bottom
};
}
else {
margins = { left: 0, top: 0, right: 0, bottom: 0 };
}
if (this.bounds.x !== 0 &&
this.bounds.y !== 0 &&
this.bounds.width !== 0 &&
this.bounds.height !== 0) {
this._boundsCollection[0] = this.bounds;
}
var noofRect = this._quadPoints.length / 8;
var cropOrMediaBox = this._getMediaOrCropBox(this._page);
var isContainscropOrMediaBox = false;
if (!this._isLoaded && cropOrMediaBox && cropOrMediaBox.length > 3 && !this.flatten) {
var cropOrMediaBoxX = cropOrMediaBox[0];
var cropOrMediaBoxY = cropOrMediaBox[1];
if (cropOrMediaBoxX !== 0 || cropOrMediaBoxY !== 0) {
for (var i = 0; i < noofRect; i++) {
var rect = this._boundsCollection[i];
var locationX = rect.x + margins.left + cropOrMediaBoxX;
var locationY = cropOrMediaBoxY + margins.top;
textQuadLocation[0 + i * 8] = locationX + margins.left;
textQuadLocation[1 + i * 8] = pageHeight + locationY - margins.top - rect.y;
textQuadLocation[2 + i * 8] = locationX + rect.width + margins.left;
textQuadLocation[3 + i * 8] = pageHeight + locationY - margins.top - rect.y;
textQuadLocation[4 + i * 8] = locationX + margins.left;
textQuadLocation[5 + i * 8] = textQuadLocation[1 + i * 8] - rect.height;
textQuadLocation[6 + i * 8] = locationX + rect.width + margins.left;
textQuadLocation[7 + i * 8] = textQuadLocation[5 + i * 8];
}
isContainscropOrMediaBox = true;
}
}
if (!isContainscropOrMediaBox && this._boundsCollection.length > 0) {
for (var i = 0; i < noofRect; i++) {
var rect = this._boundsCollection[i];
var locationX = rect.x;
var locationY = rect.y;
textQuadLocation[0 + i * 8] = locationX + margins.left;
textQuadLocation[1 + i * 8] = pageHeight - locationY - margins.top;
textQuadLocation[2 + i * 8] = locationX + rect.width + margins.left;
textQuadLocation[3 + i * 8] = pageHeight - locationY - margins.top;
textQuadLocation[4 + i * 8] = locationX + margins.left;
textQuadLocation[5 + i * 8] = textQuadLocation[1 + i * 8] - rect.height;
textQuadLocation[6 + i * 8] = locationX + rect.width + margins.left;
textQuadLocation[7 + i * 8] = textQuadLocation[5 + i * 8];
}
}
this._points = [];
for (var i = 0; i < textQuadLocation.length; i += 2) {
this._points.push({ x: textQuadLocation[i], y: textQuadLocation[i + 1] });
}
this._dictionary.set('QuadPoints', textQuadLocation);
};
/**
* Creates a PdfTemplate for the requested appearance key by reading AP streams, resolving Matrix/BBox,
* normalizing size, and exporting the stream.
*
* @private
* @param {string} [key] Appearance key ('N' by default).
* @returns {PdfTemplate} template or undefined if not found.
*/
PdfAnnotation.prototype._createTemplate = function (key) {
var template;
if (this._isLoaded) {
if (!key) {
key = 'N';
}
if (this._dictionary.has('AP')) {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has(key)) {
var appearanceStream = dictionary.get(key);
var ref = dictionary.getRaw(key);
if (ref && appearanceStream) {
template = new PdfTemplate();
template._isExported = true;
var templateDictionary = appearanceStream.dictionary;
var matrix = templateDictionary.getArray('Matrix');
var bounds = templateDictionary.getArray('BBox');
if (matrix) {
var mMatrix = [];
for (var i = 0; i < matrix.length; i++) {
var value = matrix[i];
mMatrix[i] = value;
}
if (bounds && bounds.length > 3) {
var rect = _toRectangle(bounds);
var rectangle = this._transformBBox(rect, mMatrix);
template._size = { width: rectangle[2], height: rectangle[3] };
template._templateOriginalSize = { width: rect.width, height: rect.height };
}
if (appearanceStream && typeof appearanceStream.offset === 'number' && appearanceStream.offset !== 0) {
appearanceStream.offset = 0;
}
}
else if (bounds && (bounds[2] === this.bounds.width && bounds[3] === this.bounds.height) || _areArrayEqual(this._dictionary.get('Rect'), bounds)) {
templateDictionary.update('Matrix', [1, 0, 0, 1, -bounds[0], -bounds[1]]);
if (this._dictionary.has('Vertices')) {
template._size = { width: bounds[2], height: bounds[3] };
}
else {
template._size = { width: this.bounds.width, height: this.bounds.height };
this._crossReference._cacheMap.set(ref, appearanceStream);
}
}
else {
var identityMatrix = [1, 0, 0, 1, 0, 0];
var templateSize = this._getTransformMatrix(this._dictionary.get('Rect'), bounds, identityMatrix);
if (this.bounds.width === templateSize[0] && this.bounds.height === templateSize[3]) {
templateDictionary.update('Matrix', [templateSize[0], 0, 0, templateSize[3], 0, 0]);
template._size = { width: templateSize[0], height: templateSize[3] };
this._crossReference._cacheMap.set(ref, appearanceStream);
}
else {
templateDictionary.update('Matrix', [1, 0, 0, 1, -bounds[0], -bounds[1]]);
template._size = { width: bounds[2], height: bounds[3] };
}
}
template._exportStream(dictionary, this._crossReference, key);
}
}
}
}
return template;
};
/**
* Creates a PdfTemplate for the requested appearance key by reading AP streams, resolving Matrix/BBox,
* normalizing size, and exporting the stream.
*
* @private
* @param {number[]} rect Appearance key .
* @param {number[]} bbox Appearance key .
* @param {number[]} matrix matrix for appearance.
* @returns {number[]} template or undefined if not found.
*/
PdfAnnotation.prototype._getTransformMatrix = function (rect, bbox, matrix) {
var _a = this._getAxialAlignedBoundingBox(bbox, matrix), minX = _a[0], minY = _a[1], maxX = _a[2], maxY = _a[3];
if (minX === maxX || minY === maxY) {
return [1, 0, 0, 1, rect[0], rect[1]];
}
var xRatio = (rect[2] - rect[0]) / (maxX - minX);
var yRatio = (rect[3] - rect[1]) / (maxY - minY);
return [xRatio, 0, 0, yRatio, rect[0] - minX * xRatio, rect[1] - minY * yRatio];
};
/**
* Returns the axis aligned bounding box [minX, minY, maxX, maxY] of the rectangle r after applying the transform m.
*
* @private
* @param {number[]} r Rectangle [x0, y0, x1, y1].
* @param {number[]} m 2D affine matrix [a, b, c, d, e, f].
* @returns {number[]} aabb [minX, minY, maxX, maxY].
*/
PdfAnnotation.prototype._getAxialAlignedBoundingBox = function (r, m) {
var p1 = this._applyTransform(r, m);
var p2 = this._applyTransform(r.slice(2, 4), m);
var p3 = this._applyTransform([r[0], r[3]], m);
var p4 = this._applyTransform([r[2], r[1]], m);
return [
Math.min(p1[0], p2[0], p3[0], p4[0]),
Math.min(p1[1], p2[1], p3[1], p4[1]),
Math.max(p1[0], p2[0], p3[0], p4[0]),
Math.max(p1[1], p2[1], p3[1], p4[1])
];
};
/**
* Applies the 2D affine transform m to point p and returns the transformed coordinate.
*
* @private
* @param {number[]} p Point [x, y].
* @param {number[]} m Matrix [a, b, c, d, e, f].
* @returns {number[]} pt [x', y'].
*/
PdfAnnotation.prototype._applyTransform = function (p, m) {
var xt = p[0] * m[0] + p[1] * m[2] + m[4];
var yt = p[0] * m[1] + p[1] * m[3] + m[5];
return [xt, yt];
};
/* eslint-disable */
/**
* Transforms the bounding box through the given matrix and returns the resulting [minX, minY, maxX, maxY] extent.
*
* @private
* @param {{ x: number, y: number, width: number, height: number }} bBoxValue Bounds object.
* @param {number[]} matrix Matrix [a, b, c, d, e, f].
* @returns {number[]} rect [minX, minY, maxX, maxY].
*/
PdfAnnotation.prototype._transformBBox = function (bBoxValue, matrix) {
var xCoordinate = [];
var yCoordinate = [];
var point1 = this._transformPoint(bBoxValue.x, bBoxValue.y + bBoxValue.height, matrix);
xCoordinate[0] = point1[0];
yCoordinate[0] = point1[1];
var point2 = this._transformPoint(bBoxValue.x + bBoxValue.width, bBoxValue.y, matrix);
xCoordinate[1] = point2[0];
yCoordinate[1] = point2[1];
var point3 = this._transformPoint(bBoxValue.x, bBoxValue.y, matrix);
xCoordinate[2] = point3[0];
yCoordinate[2] = point3[1];
var point4 = this._transformPoint(bBoxValue.x + bBoxValue.width, bBoxValue.y + bBoxValue.height, matrix);
xCoordinate[3] = point4[0];
yCoordinate[3] = point4[1];
var rect = [this._minValue(xCoordinate), this._minValue(yCoordinate),
this._maxValue(xCoordinate), this._maxValue(yCoordinate)];
return rect;
};
/* eslint-enable */
/**
* Transforms a point (x, y) using the provided 2D affine matrix and returns the resulting coordinate.
*
* @private
* @param {number} x X coordinate.
* @param {number} y Y coordinate.
* @param {number[]} matrix Matrix [a, b, c, d, e, f].
* @returns {number[]} pt [x', y'].
*/
PdfAnnotation.prototype._transformPoint = function (x, y, matrix) {
var point = [];
point[0] = x * matrix[0] + y * matrix[2] + matrix[4];
point[1] = x * matrix[1] + y * matrix[3] + matrix[5];
return point;
};
/**
* Returns the minimum numeric value from the given array.
*
* @private
* @param {number[]} values Array of numbers.
* @returns {number} min Minimum value.
*/
PdfAnnotation.prototype._minValue = function (values) {
var minimum = values[0];
for (var i = 1; i < values.length; i++) {
if (values[i] < minimum) {
minimum = values[i];
}
}
return minimum;
};
/**
* Returns the maximum numeric value from the given array.
*
* @private
* @param {number[]} values Array of numbers.
* @returns {number} min Maximum value.
*/
PdfAnnotation.prototype._maxValue = function (values) {
var maximum = values[0];
for (var i = 1; i < values.length; i++) {
if (values[i] > maximum) {
maximum = values[i];
}
}
return maximum;
};
/**
* Imports and registers a template under the specified key, ensuring proper crossreference handling and resource export state.
*
* @private
* @param {PdfTemplate} template Template to register.
* @param {string} key Appearance key.
* @returns {void} nothing.
*/
PdfAnnotation.prototype._drawTemplate = function (template, key) {
if (template && key) {
if (template._isExported || template._isResourceExport) {
if (this._crossReference) {
template._crossReference = this._crossReference;
template._importStream(true, template._isResourceExport);
}
else {
template._importStream(false, template._isResourceExport);
}
}
this._customTemplate.set(key, template);
}
};
/**
* Writes all custom templates into the appearance dictionary, allocating new references and updating the cross reference cache.
*
* @private
* @param {_PdfDictionary} appearance Appearance dictionary (AP).
* @returns {void} nothing.
*/
PdfAnnotation.prototype._drawCustomAppearance = function (appearance) {
var _this = this;
this._customTemplate.forEach(function (template, key) {
_removeDuplicateReference(appearance, _this._crossReference, key);
var reference = _this._crossReference._getNextReference();
template._content.reference = reference;
template._content.dictionary._update = true;
_this._crossReference._cacheMap.set(reference, template._content);
appearance.update(key, reference);
});
};
return PdfAnnotation;
}());
export { PdfAnnotation };
/**
* Represents the annotations which have comments and review history.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0);
* // Access the annotation at index 0
* let annotation: PdfComment = page.annotations.at(0) as PdfComment;
* // Gets the comments of annotation
* let comment: PdfPopupAnnotationCollection = annotation.comments;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
var PdfComment = /** @class */ (function (_super) {
__extends(PdfComment, _super);
function PdfComment() {
return _super !== null && _super.apply(this, arguments) || this;
}
Object.defineProperty(PdfComment.prototype, "comments", {
/**
* Gets the comments of the PDF annotation (Read only).
*
* @returns {PdfPopupAnnotationCollection} Annotation comments
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data);
* // Access first page
* let page: PdfPage = document.getPage(0);
* // Access the annotation at index 0
* let annotation: PdfRectangleAnnotation = page.annotations.at(0) as PdfRectangleAnnotation;
* // Gets the comments of the PDF annotation
* let comments: PdfPopupAnnotationCollection = annotation.comments;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (this._comments) {
return this._comments;
}
else {
return this._comments = new PdfPopupAnnotationCollection(this, false);
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfComment.prototype, "reviewHistory", {
/**
* Gets the review history of the PDF annotation (Read only).
*
* @returns {PdfPopupAnnotationCollection} Annotation review history.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data);
* // Access first page
* let page: PdfPage = document.getPage(0);
* // Access the annotation at index 0
* let annotation: PdfRectangleAnnotation = page.annotations.at(0) as PdfRectangleAnnotation;
* // Gets the comments of the PDF annotation
* let comments: PdfPopupAnnotationCollection = annotation.reviewHistory;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (this._reviewHistory) {
return this._reviewHistory;
}
else {
return this._reviewHistory = new PdfPopupAnnotationCollection(this, true);
}
},
enumerable: true,
configurable: true
});
return PdfComment;
}(PdfAnnotation));
export { PdfComment };
/**
* `PdfLineAnnotation` class represents the line annotation objects.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Create a new line annotation with line points
* const annotation: PdfLineAnnotation = new PdfLineAnnotation({x: 10, y: 50}, {x: 250, y: 50});
* // Add annotation to the page
* page.annotations.add(annotation);
* // Destroy the document
* document.destroy();
* ```
*/
var PdfLineAnnotation = /** @class */ (function (_super) {
__extends(PdfLineAnnotation, _super);
function PdfLineAnnotation(startPoint, endPoint, properties) {
var _this = _super.call(this) || this;
/**
* Specifies the measurement unit used for line annotations.
*
* @private
*/
_this._unit = PdfMeasurementUnit.centimeter;
_this._unitString = '';
_this._dictionary = new _PdfDictionary();
_this._dictionary.update('Type', _PdfName.get('Annot'));
_this._dictionary.update('Subtype', _PdfName.get('Line'));
if (startPoint !== null && typeof startPoint !== 'undefined' && endPoint !== null && typeof endPoint !== 'undefined') {
_this.linePoints = [startPoint, endPoint];
}
_this._type = _PdfAnnotationType.lineAnnotation;
if (properties) {
if ('text' in properties && _isNullOrUndefined(properties.text)) {
_this.text = properties.text;
}
if ('author' in properties && _isNullOrUndefined(properties.author)) {
_this.author = properties.author;
}
if ('subject' in properties && _isNullOrUndefined(properties.subject)) {
_this.subject = properties.subject;
}
if ('color' in properties && _isNullOrUndefined(properties.color)) {
_this.color = properties.color;
}
if ('innerColor' in properties && _isNullOrUndefined(properties.innerColor)) {
_this.innerColor = properties.innerColor;
}
if ('lineEndingStyle' in properties && _isNullOrUndefined(properties.lineEndingStyle)) {
_this.lineEndingStyle = properties.lineEndingStyle;
}
if ('opacity' in properties && _isNullOrUndefined(properties.opacity)) {
_this.opacity = properties.opacity;
}
if ('border' in properties && _isNullOrUndefined(properties.border)) {
_this.border = properties.border;
}
if ('measurementUnit' in properties && _isNullOrUndefined(properties.measurementUnit)) {
_this.measure = true;
_this.unit = properties.measurementUnit;
}
}
return _this;
}
Object.defineProperty(PdfLineAnnotation.prototype, "linePoints", {
/**
* Gets the line points of the line annotation.
*
* @returns {Point[]} Line points.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Gets the line points of the line annotation.
* let linePoints: Point[] = annotation.linePoints;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._linePoints === 'undefined' && this._dictionary.has('L')) {
var points = this._dictionary.getArray('L');
if (points.length === 4) {
this._linePoints = [{ x: points[0], y: points[1] }, { x: points[2], y: points[3] }];
}
}
return this._linePoints;
},
/**
* Sets the line points of the line annotation.
*
* @param {Point[]} value Line points.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Sets the line points of the line annotation.
* annotation.linePoints = [{x: 10, y: 50}, {x: 250, y: 50}];
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (Array.isArray(value) && (typeof this._linePoints === 'undefined' || _arePointsNotEqual(value, this._linePoints))) {
if (value.length === 2) {
this._dictionary.update('L', [value[0].x, value[0].y, value[1].x, value[1].y]);
this._linePoints = value;
}
else {
throw new Error('Line points length should be 2.');
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfLineAnnotation.prototype, "leaderExt", {
/**
* Gets the line extension of the line annotation.
*
* @returns {number} Leader line extension.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Gets the line extension of the line annotation.
* let leaderExt: number = annotation.leaderExt;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._leaderExt === 'undefined' && this._dictionary.has('LLE')) {
var leaderExt = this._dictionary.get('LLE');
if (typeof leaderExt !== 'undefined') {
this._leaderExt = leaderExt;
}
}
return this._leaderExt;
},
/**
* Sets the line extension of the line annotation.
*
* @param {number} value Line extension.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Sets the line extension of the line annotation.
* annotation.leaderExt = 4;
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (!Number.isNaN(value)) {
this._dictionary.update('LLE', value);
this._leaderExt = value;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfLineAnnotation.prototype, "leaderLine", {
/**
* Gets the leader line of the line annotation.
*
* @returns {number} Leader line.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Gets the leader line of the line annotation.
* let leaderLine: number = annotation.leaderLine;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._leaderLine === 'undefined' && this._dictionary.has('LL')) {
var leaderLine = this._dictionary.get('LL');
if (typeof leaderLine !== 'undefined') {
this._leaderLine = leaderLine;
}
}
return this._leaderLine;
},
/**
* Sets the leader line of the line annotation.
*
* @param {number} value Leader line.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Sets the leader line of the line annotation.
* annotation.leaderLine = 5;
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (!Number.isNaN(value) && this.leaderExt !== 0) {
this._dictionary.update('LL', value);
this._leaderLine = value;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfLineAnnotation.prototype, "lineEndingStyle", {
/**
* Gets the line ending style of the line annotation.
*
* @returns {PdfAnnotationLineEndingStyle} Line ending style.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Gets the line ending style of the line annotation.
* let lineEndingStyle: PdfAnnotationLineEndingStyle = annotation.lineEndingStyle;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._lineEndingStyle === 'undefined') {
var value = new PdfAnnotationLineEndingStyle();
value._dictionary = this._dictionary;
if (this._dictionary.has('LE')) {
var lineStyles = this._dictionary.getArray('LE');
if (lineStyles && Array.isArray(lineStyles)) {
value._begin = _mapLineEndingStyle(lineStyles[0].name);
value._end = _mapLineEndingStyle(lineStyles[1].name);
}
}
this._lineEndingStyle = value;
}
return this._lineEndingStyle;
},
/**
* Sets the line ending style of the line annotation.
*
* @param {PdfAnnotationLineEndingStyle} value Line ending style.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Sets the line ending style of the line annotation.
* annotation.lineEndingStyle = new PdfAnnotationLineEndingStyle({begin: PdfLineEndingStyle.openArrow, end: PdfLineEndingStyle.closeArrow});
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
var style = this.lineEndingStyle;
if (style.begin !== value.begin || style.end !== value.end) {
style.begin = value.begin;
style.end = value.end;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfLineAnnotation.prototype, "leaderOffset", {
/**
* Gets the leader offset of the line annotation.
*
* @returns {number} Leader offset.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Gets the leader offset value of the line annotation
* let leaderOffset: number = annotation.leaderOffset;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._leaderOffset === 'undefined' && this._dictionary.has('LLO')) {
var leaderOffset = this._dictionary.get('LLO');
if (typeof leaderOffset !== 'undefined' && leaderOffset >= 0) {
this._leaderOffset = leaderOffset;
}
}
return this._leaderOffset;
},
/**
* Sets the leader offset of the line annotation.
*
* @param {number} value Leader line offset.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Sets the leader offset of the line annotation.
* annotation.leaderOffset = 1;
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (!Number.isNaN(value)) {
this._dictionary.update('LLO', value);
this._leaderOffset = value;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfLineAnnotation.prototype, "lineIntent", {
/**
* Gets the line intent of the line annotation.
*
* @returns {PdfLineIntent} Line intent.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Gets the line intent value of the line annotation
* let lineIntent: PdfLineIntent = annotation.lineIntent;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._lineIntent === 'undefined' && this._dictionary.has('IT')) {
var lineIntent = this._dictionary.get('IT');
if (lineIntent) {
this._lineIntent = lineIntent.name === 'LineDimension' ? PdfLineIntent.lineDimension : PdfLineIntent.lineArrow;
}
}
return this._lineIntent;
},
/**
* Sets the line intent of the line annotation.
*
* @param {PdfLineIntent} value Line intent.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Sets the line intent of the line annotation.
* annotation.lineIntent = PdfLineIntent.lineDimension;
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (typeof value !== 'undefined' && value !== this.lineIntent) {
this._lineIntent = value;
this._dictionary.update('IT', _PdfName.get(value === PdfLineIntent.lineDimension ? 'LineDimension' : 'LineArrow'));
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfLineAnnotation.prototype, "measure", {
/**
* Gets the flag to have measurement dictionary of the line annotation.
*
* @returns {boolean} measure.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Gets the flag to have measurement dictionary of the line annotation.
* let measure: boolean = annotation.measure;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._measure === 'undefined') {
this._measure = this._dictionary.has('Measure');
}
return this._measure;
},
/**
* Sets the flag to add measurement dictionary to the line annotation.
*
* @param {boolean} value Measure.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Sets the flag to have measurement dictionary of the line annotation.
* annotation.measure = true;
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value) {
if (!this._isLoaded) {
this._measure = value;
this.caption.cap = true;
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfLineAnnotation.prototype, "unit", {
/**
* Gets the measurement unit of the annotation.
*
* @returns {PdfMeasurementUnit} Measurement unit.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Gets the measurement unit of the annotation.
* let unit: PdfMeasurementUnit = annotation.unit;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (this._isTextUpdated) {
return this._unit;
}
if (typeof this._unit === 'undefined' || this._isLoaded) {
if (this._dictionary.has('Contents')) {
var text = this._dictionary.get('Contents');
this._unitString = text.substring(text.length - 2);
this._unit = _mapMeasurementUnit(this._unitString);
}
else {
this._unit = PdfMeasurementUnit.centimeter;
}
}
return this._unit;
},
/**
* Sets the measurement unit of the line annotation.
*
* @param {PdfMeasurementUnit} value Measurement unit.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Sets the measurement unit of the annotation.
* annotation.unit = PdfMeasurementUnit.centimeter;
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (this._measure) {
if (!this._isLoaded && typeof value !== 'undefined') {
this._unit = value;
}
}
},
enumerable: true,
configurable: true
});
/**
* Loads a line annotation from the given page and dictionary, marks it as loaded, and initializes internal state.
*
* @private
* @param {PdfPage} page Page containing the annotation.
* @param {_PdfDictionary} dictionary Source annotation dictionary.
* @returns {PdfLineAnnotation} annot Loaded line annotation.
*/
PdfLineAnnotation._load = function (page, dictionary) {
var annot = new PdfLineAnnotation();
annot._isLoaded = true;
annot._initialize(page, dictionary);
return annot;
};
/**
* Initializes the line annotation for the specified page and optional source dictionary by delegating to the base initializer.
*
* @private
* @param {PdfPage} page Owning page.
* @param {_PdfDictionary} [dictionary] Optional source dictionary.
* @returns {void} nothing.
*/
PdfLineAnnotation.prototype._initialize = function (page, dictionary) {
_super.prototype._initialize.call(this, page, dictionary);
};
/**
* Finalizes the annotation after creation/load: validates line points, adjusts for Crop/MediaBox offsets, sets defaults, and prepares bounds/appearance.
*
* @private
* @param {boolean} flatten True if invoked during flattening.
* @returns {void} nothing.
*/
PdfLineAnnotation.prototype._postProcess = function (flatten) {
if (typeof this.linePoints === 'undefined' || this.linePoints === null) {
throw new Error('Line points cannot be null or undefined');
}
else {
var cropOrMediaBox = this._getCropOrMediaBox();
if (cropOrMediaBox && cropOrMediaBox.length > 3 && this.linePoints.length > 1 && typeof cropOrMediaBox[0] === 'number' && typeof cropOrMediaBox[1] === 'number' && (cropOrMediaBox[0] !== 0 || cropOrMediaBox[1] !== 0)) {
this._linePoints[0].x += cropOrMediaBox[0];
this._linePoints[0].y += cropOrMediaBox[1];
this._linePoints[1].x += cropOrMediaBox[0];
this._linePoints[1].y += cropOrMediaBox[1];
this._dictionary.update('L', [this._linePoints[0].x, this._linePoints[0].y, this._linePoints[1].x, this._linePoints[1].y]);
}
}
if (!this._dictionary.has('Cap')) {
this._dictionary.set('Cap', false);
}
if (!this._dictionary.has('CP')) {
this._dictionary.set('CP', _PdfName.get('Inline'));
}
if (!this._dictionary.has('LE')) {
this.lineEndingStyle = new PdfAnnotationLineEndingStyle();
}
if (!this._dictionary.has('LL')) {
this.leaderLine = 0;
}
if (!this._dictionary.has('LLE')) {
this.leaderExt = 0;
}
if (!this._dictionary.has('C')) {
this.color = { r: 0, g: 0, b: 0 };
this._isTransparentColor = true;
}
var borderWidth;
if (this._dictionary.has('BS')) {
borderWidth = this.border.width;
}
else {
var dictionary = new _PdfDictionary(this._crossReference);
dictionary.set('Type', _PdfName.get('Border'));
this._dictionary.set('BS', dictionary);
}
if (typeof borderWidth === 'undefined') {
borderWidth = 1;
}
if (this.border.dash === null || typeof this.border.dash === 'undefined') {
this.border.dash = [];
if (this.border.style === PdfBorderStyle.dashed) {
this.border.dash = [3, 1];
}
else if (this.border.style === PdfBorderStyle.dot) {
this.border.dash = [1, 1];
}
}
if (this._measure) {
this._appearanceTemplate = this._createLineMeasureAppearance(flatten);
}
else {
var isUpdated = false;
if (this._setAppearance || (this._customTemplate.has('N'))) {
this._appearanceTemplate = this._createAppearance();
if (this._page._isNew && !(this._flatten || flatten)) {
var boundsArray = this._obtainLineBounds();
var bounds = {
x: boundsArray[0],
y: boundsArray[1], width: boundsArray[2], height: boundsArray[3]
};
this._bounds = bounds;
var updatedBounds = [this._bounds.x,
this._bounds.y,
this._bounds.x + this._bounds.width,
this._bounds.y + this._bounds.height];
this._dictionary.update('Rect', updatedBounds);
isUpdated = true;
}
}
else {
var bounds = this._obtainLineBounds();
var rectangleBounds = _fromRectangle({ x: bounds[0], y: bounds[1], width: bounds[2], height: bounds[3] });
if (this._page._isNew && this._page._pageSettings && this._setAppearance && !this.flatten) {
rectangleBounds = _updateBounds(this, bounds);
}
this.bounds = { x: rectangleBounds[0], y: rectangleBounds[1], width: rectangleBounds[2], height: rectangleBounds[3] };
this._dictionary.update('Rect', rectangleBounds);
isUpdated = true;
}
if (this._dictionary.has('Measure') && !isUpdated) {
var boundsArray = this._obtainLineBounds();
var bounds = { x: boundsArray[0],
y: boundsArray[1], width: boundsArray[2], height: boundsArray[3] };
this._bounds = bounds;
var updatedBounds = void 0;
if (this._page && this._page._isNew && this._page._pageSettings && !this._setAppearance && !this.flatten) {
updatedBounds = _updateBounds(this);
}
else {
updatedBounds = [this._bounds.x,
this._bounds.y,
this._bounds.x + this._bounds.width,
this._bounds.y + this._bounds.height];
}
this._dictionary.update('Rect', updatedBounds);
if (this.flatten && !this.measure && this._page && this._page.size && Array.isArray(this._page.size) &&
this._page.size.length >= 2) {
this._bounds = { x: boundsArray[0], y: this._page.size[1] - (boundsArray[1] + boundsArray[3]),
width: boundsArray[2], height: boundsArray[3] };
}
}
}
};
/**
* Builds or imports the appearance stream depending on state, optionally flattens the annotation (and pop-ups), and updates AP dictionary entries.
*
* @private
* @param {boolean} [isFlatten=false] True if flattening is requested.
* @returns {void} nothing.
*/
PdfLineAnnotation.prototype._doPostProcess = function (isFlatten) {
if (isFlatten === void 0) { isFlatten = false; }
if (this._isLoaded) {
if (this._setAppearance || this._customTemplate.size > 0 || (isFlatten && !this._dictionary.has('AP'))) {
if (this._dictionary.has('Measure')) {
this._appearanceTemplate = this._createLineMeasureAppearance(isFlatten);
}
else {
this._appearanceTemplate = this._createAppearance();
}
}
if (!this._appearanceTemplate && isFlatten && this._dictionary.has('AP')) {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
var appearanceStream = dictionary.get('N');
if (appearanceStream instanceof _PdfBaseStream) {
var reference = dictionary.getRaw('N');
if (reference) {
appearanceStream.reference = reference;
}
this._appearanceTemplate = new PdfTemplate(appearanceStream, this._crossReference);
}
}
}
}
else {
this._postProcess(isFlatten);
if (!this._appearanceTemplate) {
if (isFlatten) {
if (!this._dictionary.has('AP')) {
this._appearanceTemplate = this._createAppearance();
}
else {
var dictionary = this._dictionary.get('AP');
if (dictionary !== null && typeof dictionary !== 'undefined' && dictionary.has('N')) {
var appearanceStream = dictionary.get('N');
if (appearanceStream) {
var reference = dictionary.getRaw('N');
if (reference) {
appearanceStream.reference = reference;
}
this._appearanceTemplate = new PdfTemplate(appearanceStream, this._crossReference);
}
}
}
}
}
}
if (typeof this.flattenPopups !== 'undefined' && this.flattenPopups && isFlatten) {
if (this._isLoaded) {
this._flattenLoadedPopUp();
}
else {
this._flattenPopUp();
}
}
if (isFlatten) {
if (this._appearanceTemplate) {
var isNormalMatrix = this._validateTemplateMatrix(this._appearanceTemplate._content.dictionary);
this._flattenAnnotationTemplate(this._appearanceTemplate, isNormalMatrix, true);
}
else {
this._page.annotations.remove(this);
}
}
else {
var appearance = void 0;
if (this._setAppearance || this._customTemplate.size > 0) {
if (this._dictionary.has('AP')) {
appearance = this._dictionary.get('AP');
}
else {
var reference = this._crossReference._getNextReference();
appearance = new _PdfDictionary(this._crossReference);
appearance._updated = true;
this._crossReference._cacheMap.set(reference, appearance);
this._dictionary.update('AP', reference);
}
}
if (this._customTemplate.size > 0) {
this._drawCustomAppearance(appearance);
}
else if (appearance && this._appearanceTemplate && this._appearanceTemplate._content) {
_removeDuplicateReference(appearance, this._crossReference, 'N');
var reference = this._crossReference._getNextReference();
this._appearanceTemplate._content.dictionary._update = true;
this._appearanceTemplate._content.reference = reference;
this._crossReference._cacheMap.set(reference, this._appearanceTemplate._content);
appearance.update('N', reference);
}
}
};
/**
* Creates the measured line appearance template, draws the line, leaders, end styles, and caption with unit conversion, and updates related dictionary entries.
*
* @private
* @param {boolean} _isFlatten True if called during flattening.
* @returns {PdfTemplate} template Appearance template.
*/
PdfLineAnnotation.prototype._createLineMeasureAppearance = function (_isFlatten) {
var nativeRectangle = [0, 0, 0, 0];
var area = this._convertToUnit();
var linePoints1 = this._obtainLinePoints();
var points = linePoints1.slice(); // shallow copy
var graphicsPath = new PdfPath();
graphicsPath._points = points;
graphicsPath._pathTypes = [0, 1];
var rectPath = graphicsPath._getBounds();
this._bounds = { x: rectPath[0], y: rectPath[1], width: rectPath[2], height: rectPath[3] };
var borderPen = new PdfPen(typeof this.color !== 'undefined' ? this._color : { r: 0, g: 0, b: 0 }, this.border.width);
var backBrush;
if (this.innerColor) {
backBrush = new PdfBrush(this._innerColor);
}
nativeRectangle = this._obtainLineBounds();
var template;
if (this._customTemplate.has('N')) {
template = this._customTemplate.get('N');
var bounds = [nativeRectangle[0],
nativeRectangle[1],
nativeRectangle[0] + nativeRectangle[2],
nativeRectangle[1] + nativeRectangle[3]];
this._dictionary.update('Rect', bounds);
this._bounds = { x: bounds[0], y: bounds[1], width: bounds[2], height: bounds[3] };
}
else {
template = new PdfTemplate(nativeRectangle, this._crossReference);
_setMatrix(template, 0);
var parameter = new _PaintParameter();
template._writeTransformation = false;
var graphics = template.graphics;
parameter.borderPen = borderPen;
if (this.border.style === PdfBorderStyle.dashed) {
parameter.borderPen._dashStyle = PdfDashStyle.dash;
parameter.borderPen._dashPattern = [3, 1];
}
else if (this.border.style === PdfBorderStyle.dot) {
parameter.borderPen._dashStyle = PdfDashStyle.dot;
parameter.borderPen._dashPattern = [1, 1];
}
parameter.backBrush = backBrush;
parameter.foreBrush = new PdfBrush(this.color);
var linePoints = this._obtainLinePoints();
var font = this._obtainFont();
if ((typeof font === 'undefined' || font === null) || (!this._isLoaded && font.size === 1)) {
font = this._lineCaptionFont;
this._pdfFont = font;
}
if (typeof linePoints !== 'undefined' && linePoints.length === 2) {
var format = new PdfStringFormat(PdfTextAlignment.center, PdfVerticalAlignment.middle);
var fontSize = font.measureString(area.toFixed(2) + ' ' + this._unitString, { width: 0, height: 0 }, format, 0, 0);
var angle = this._getAngle(this._linePoints);
var leaderLine = 0;
var lineAngle = 0;
if (this.leaderLine < 0) {
leaderLine = -(this.leaderLine);
lineAngle = angle + 180;
}
else {
leaderLine = this.leaderLine;
lineAngle = angle;
}
var offset = (typeof this.leaderOffset !== 'undefined') ? (leaderLine + this.leaderOffset) : leaderLine;
var startPoint = this._getAxisValue(this._linePoints[0], (lineAngle + 90), offset);
var endPoint = this._getAxisValue(this._linePoints[1], (lineAngle + 90), offset);
var lineDistance = (Math.sqrt(Math.pow((endPoint.x - startPoint.x), 2) +
Math.pow((endPoint.y - startPoint.y), 2)));
var centerWidth = lineDistance / 2 - ((fontSize.width / 2) + this.border.width);
var first = this._getAxisValue(startPoint, angle, centerWidth);
var second = this._getAxisValue(endPoint, (angle + 180), centerWidth);
var start = (this.lineEndingStyle.begin === PdfLineEndingStyle.openArrow ||
this.lineEndingStyle.begin === PdfLineEndingStyle.closedArrow) ?
this._getAxisValue(startPoint, angle, this.border.width) :
startPoint;
var end = (this.lineEndingStyle.end === PdfLineEndingStyle.openArrow ||
this.lineEndingStyle.end === PdfLineEndingStyle.closedArrow) ?
this._getAxisValue(endPoint, angle, -this.border.width) :
endPoint;
var state = void 0;
if (this.opacity && this._opacity < 1) {
state = graphics.save();
graphics.setTransparency(this._opacity);
}
if (this.caption.type === PdfLineCaptionType.top ||
(!this.caption.cap && this.caption.type === PdfLineCaptionType.inline)) {
graphics.drawLine(borderPen, { x: start.x, y: -start.y }, { x: end.x, y: -end.y });
}
else {
graphics.drawLine(borderPen, { x: start.x, y: -start.y }, { x: first.x, y: -first.y });
graphics.drawLine(borderPen, { x: end.x, y: -end.y }, { x: second.x, y: -second.y });
}
if (this.opacity && this._opacity < 1) {
graphics.restore(state);
}
this._drawLineStyle(startPoint, endPoint, graphics, angle, borderPen, backBrush, this.lineEndingStyle, this.border.width);
var leaderExt = (typeof this.leaderExt !== 'undefined' ? this._leaderExt : 0);
var beginLineExt = this._getAxisValue(startPoint, (lineAngle + 90), leaderExt);
graphics.drawLine(borderPen, { x: startPoint.x, y: -startPoint.y }, { x: beginLineExt.x, y: -beginLineExt.y });
var endLineExt = this._getAxisValue(endPoint, (lineAngle + 90), leaderExt);
graphics.drawLine(borderPen, { x: endPoint.x, y: -endPoint.y }, { x: endLineExt.x, y: -endLineExt.y });
var beginLeaderLine = this._getAxisValue(startPoint, (lineAngle - 90), leaderLine);
graphics.drawLine(borderPen, { x: startPoint.x, y: -startPoint.y }, { x: beginLeaderLine.x, y: -beginLeaderLine.y });
var endLeaderLine = this._getAxisValue(endPoint, (lineAngle - 90), leaderLine);
graphics.drawLine(borderPen, { x: endPoint.x, y: -endPoint.y }, { x: endLeaderLine.x, y: -endLeaderLine.y });
var midpoint = lineDistance / 2;
var centerPoint = this._getAxisValue(startPoint, angle, midpoint);
var captionPosition = void 0;
var height = font._getHeight();
if (this.caption.type === PdfLineCaptionType.top) {
captionPosition = this._getAxisValue(centerPoint, (angle + 90), height);
}
else {
captionPosition = this._getAxisValue(centerPoint, (angle + 90), (height / 2));
}
graphics.translateTransform({ x: captionPosition.x, y: -captionPosition.y });
graphics.rotateTransform(-angle);
graphics.drawString(area.toFixed(2) + ' ' + this._unitString, font, { x: (-fontSize.width / 2), y: 0, width: 0, height: 0 }, null, parameter.foreBrush);
graphics.restore();
}
if ((typeof _isFlatten !== 'undefined' && !_isFlatten) || !this._isLoaded) {
template._content.dictionary._updated = true;
var ref = this._crossReference._getNextReference();
this._crossReference._cacheMap.set(ref, template._content);
template._content.reference = ref;
var nativeRectangle1 = [this.bounds.x,
this.bounds.y + this.bounds.height,
this.bounds.width,
this.bounds.height];
var size = this._page.size;
nativeRectangle1[1] = size.height - (this.bounds.y + this.bounds.height);
if (this._isBounds && !this.measure) {
nativeRectangle = nativeRectangle1;
this._dictionary.update('Rect', [nativeRectangle1[0], nativeRectangle1[1], nativeRectangle1[2], nativeRectangle1[3]]);
}
else {
this._dictionary.update('Rect', [nativeRectangle[0], nativeRectangle[1], nativeRectangle[2], nativeRectangle[3]]);
}
var ds = 'font:' +
font._metrics._postScriptName +
' ' +
font._size +
'pt; color:' +
this._colorToHex([this.color.r, this.color.g, this.color.b]);
this._dictionary.update('DS', ds);
if (typeof _isFlatten !== 'undefined' && !_isFlatten) {
if (this._dictionary.has('AP')) {
_removeDuplicateReference(this._dictionary.get('AP'), this._crossReference, 'N');
}
var dic = new _PdfDictionary();
dic.set('N', ref);
dic._updated = true;
this._dictionary.set('AP', dic);
var measureDictionary = this._createMeasureDictionary(this._unitString);
var reference = this._crossReference._getNextReference();
this._crossReference._cacheMap.set(reference, measureDictionary);
measureDictionary._updated = true;
if (this._dictionary.has('Measure')) {
_removeDuplicateReference(this._dictionary, this._crossReference, 'Measure');
}
this._dictionary.update('Measure', reference);
}
var lineStyles = [];
lineStyles.push(_PdfName.get(_reverseMapEndingStyle(this.lineEndingStyle.begin)));
lineStyles.push(_PdfName.get(_reverseMapEndingStyle(this.lineEndingStyle.end)));
this._dictionary.update('LE', lineStyles);
if (this._linePoints !== null) {
this._dictionary.update('L', [this._linePoints[0].x, this._linePoints[0].y, this._linePoints[1].x, this._linePoints[1].y]);
}
else {
throw new Error('LinePoints cannot be null');
}
this._dictionary.update('C', [Number.parseFloat((this.color.r / 255).toFixed(3)),
Number.parseFloat((this.color.g / 255).toFixed(3)),
Number.parseFloat((this.color.b / 255).toFixed(3))]);
var offset = this._dictionary.has('LLO') ? this.leaderOffset : 0;
this._dictionary.update('Subtype', new _PdfName('Line'));
if (this._text && this._text !== '') {
this._dictionary.update('Contents', this._text + ' ' + area.toFixed(2) + ' ' + this._unitString);
}
else {
this._dictionary.update('Contents', area.toFixed(2) + ' ' + this._unitString);
}
this._dictionary.update('IT', new _PdfName('LineDimension'));
this._dictionary.update('LLE', this.leaderExt);
this._dictionary.update('LLO', offset);
if (typeof this.leaderLine !== 'undefined' && this.leaderLine !== null) {
this._dictionary.update('LL', this.leaderLine);
}
this._dictionary.update('CP', _PdfName.get(this.caption.type === PdfLineCaptionType.top ? 'Top' : 'Inline'));
this._dictionary.update('Cap', this.caption.cap);
var bounds = [nativeRectangle[0],
nativeRectangle[1],
nativeRectangle[0] + nativeRectangle[2],
nativeRectangle[1] + nativeRectangle[3]];
this._dictionary.update('Rect', bounds);
this._bounds = { x: bounds[0], y: bounds[1], width: bounds[2], height: bounds[3] };
}
}
return template;
};
/**
* Calculates the signed angle between two points using arctangent and returns the negated result.
*
* @private
* @param {number} startPointX Start X.
* @param {number} startPointY Start Y.
* @param {number} endPointX End X.
* @param {number} endPointY End Y.
* @returns {number} angle Angle in degrees (negated).
*/
PdfLineAnnotation.prototype._calculateAngle = function (startPointX, startPointY, endPointX, endPointY) {
return -(Math.atan2((endPointY - startPointY), (endPointX - startPointX)) * (180 / Math.PI));
};
/**
* Computes the axis-aligned bounds of a line considering leader offset/extension, end styles, and border width.
*
* @private
* @param {Point[]} linePoints Two line points [{x,y},{x,y}].
* @param {number} leaderLineExt Leader line extension length.
* @param {number} leaderLine Leader line length (can be negative).
* @param {number} leaderOffset Offset distance from the line.
* @param {PdfAnnotationLineEndingStyle} lineStyle Line ending styles (begin/end).
* @param {number} borderWidth Stroke width.
* @returns {{ x: number, y: number, width: number, height: number }} bounds Computed bounds.
*/
PdfLineAnnotation.prototype._calculateLineBounds = function (linePoints, leaderLineExt, leaderLine, leaderOffset, lineStyle, borderWidth) {
var bounds = { x: 0, y: 0, width: 0, height: 0 };
if (linePoints && linePoints.length === 2) {
var angle = this._getAngle(linePoints);
var leaderLines = 0;
var lineAngle = 0;
if (leaderLine < 0) {
leaderLines = -(leaderLine);
lineAngle = angle + 180;
}
else {
leaderLines = leaderLine;
lineAngle = angle;
}
var point1 = { x: linePoints[0].x, y: linePoints[0].y };
var point2 = { x: linePoints[1].x, y: linePoints[1].y };
var x1y1 = point1;
var x2y2 = point2;
if (leaderOffset !== 0) {
var offsetPoint1 = this._getAxisValue(x1y1, (lineAngle + 90), leaderOffset);
var offsetPoint2 = this._getAxisValue(x2y2, (lineAngle + 90), leaderOffset);
linePoints[0].x = offsetPoint1.x;
linePoints[0].y = offsetPoint1.y;
linePoints[1].x = offsetPoint2.x;
linePoints[1].y = offsetPoint2.y;
this._dictionary.update('L', [linePoints[0].x, linePoints[0].y, linePoints[1].x, linePoints[1].y]);
}
var startingPoint = this._getAxisValue(x1y1, (lineAngle + 90), leaderLines + leaderOffset);
var endingPoint = this._getAxisValue(x2y2, (lineAngle + 90), leaderLines + leaderOffset);
var beginLineLeader = this._getAxisValue(x1y1, (lineAngle + 90), leaderLineExt + leaderLines + leaderOffset);
var endLineLeader = this._getAxisValue(x2y2, (lineAngle + 90), leaderLineExt + leaderLines + leaderOffset);
var beginLinePoint = this._getLinePoint(lineStyle.begin, borderWidth);
var endLinePoint = this._getLinePoint(lineStyle.end, borderWidth);
var widthX = [];
var heightY = [];
if ((lineAngle >= 45 && lineAngle <= 135) || (lineAngle >= 225 && lineAngle <= 315)) {
widthX[0] = beginLinePoint.y;
heightY[0] = beginLinePoint.x;
widthX[1] = endLinePoint.y;
heightY[1] = endLinePoint.x;
}
else {
widthX[0] = beginLinePoint.x;
heightY[0] = beginLinePoint.y;
widthX[1] = endLinePoint.x;
heightY[1] = endLinePoint.y;
}
var width = Math.max(widthX[0], widthX[1]);
var height = Math.max(heightY[0], heightY[1]);
if (width === 0) {
width = 1;
}
if (height === 0) {
height = 1;
}
if (startingPoint.x === Math.min(startingPoint.x, endingPoint.x)) {
startingPoint.x -= width * borderWidth;
endingPoint.x += width * borderWidth;
startingPoint.x = Math.min(startingPoint.x, linePoints[0].x);
startingPoint.x = Math.min(startingPoint.x, beginLineLeader.x);
endingPoint.x = Math.max(endingPoint.x, linePoints[1].x);
endingPoint.x = Math.max(endingPoint.x, endLineLeader.x);
}
else {
startingPoint.x += width * borderWidth;
endingPoint.x -= width * borderWidth;
startingPoint.x = Math.max(startingPoint.x, linePoints[0].x);
startingPoint.x = Math.max(startingPoint.x, beginLineLeader.x);
endingPoint.x = Math.min(endingPoint.x, linePoints[1].x);
endingPoint.x = Math.min(endingPoint.x, endLineLeader.x);
}
if (startingPoint.y === Math.min(startingPoint.y, endingPoint.y)) {
startingPoint.y -= height * borderWidth;
endingPoint.y += height * borderWidth;
startingPoint.y = Math.min(startingPoint.y, linePoints[0].y);
startingPoint.y = Math.min(startingPoint.y, beginLineLeader.y);
endingPoint.y = Math.max(endingPoint.y, linePoints[1].y);
endingPoint.y = Math.max(endingPoint.y, endLineLeader.y);
}
else {
startingPoint.y += height * borderWidth;
endingPoint.y -= height * borderWidth;
startingPoint.y = Math.max(startingPoint.y, linePoints[0].y);
startingPoint.y = Math.max(startingPoint.y, beginLineLeader.y);
endingPoint.y = Math.min(endingPoint.y, linePoints[1].y);
endingPoint.y = Math.min(endingPoint.y, endLineLeader.y);
}
bounds = this._getBounds([startingPoint, endingPoint]);
}
return bounds;
};
/**
* Returns characteristic half extents for a given line ending style used to expand bounds in x/y.
*
* @private
* @param {PdfLineEndingStyle} style Line ending style.
* @param {number} borderWidth Stroke width.
* @returns {{x: number, y: number}} extents Half extents in x/y.
*/
PdfLineAnnotation.prototype._getLinePoint = function (style, borderWidth) {
var point = { x: 0, y: 0 };
if (style) {
switch (style) {
case PdfLineEndingStyle.square:
case PdfLineEndingStyle.circle:
case PdfLineEndingStyle.diamond:
point.x = 3;
point.y = 3;
break;
case PdfLineEndingStyle.openArrow:
case PdfLineEndingStyle.closedArrow:
point.x = 1;
point.y = 5;
break;
case PdfLineEndingStyle.rOpenArrow:
case PdfLineEndingStyle.rClosedArrow:
point.x = 9 + (borderWidth / 2);
point.y = 5 + (borderWidth / 2);
break;
case PdfLineEndingStyle.slash:
point.x = 5;
point.y = 9;
break;
case PdfLineEndingStyle.butt:
point.x = 1;
point.y = 3;
break;
default:
point.x = 0;
point.y = 0;
break;
}
}
return point;
};
/**
* Computes the minimal axis aligned bounding rectangle that encloses the given points.
*
* @private
* @param {{x: number, y: number}[]} points Points to enclose.
* @returns {{x: number, y: number, width: number, height: number}} bounds Enclosing rectangle.
*/
PdfLineAnnotation.prototype._getBounds = function (points) {
var bounds = { x: 0, y: 0, width: 0, height: 0 };
if (points.length > 0) {
var xmin = points[0].x;
var xmax = points[0].x;
var ymin = points[0].y;
var ymax = points[0].y;
for (var i = 1; i < points.length; ++i) {
var point = points[i];
xmin = Math.min(point.x, xmin);
xmax = Math.max(point.x, xmax);
ymin = Math.min(point.y, ymin);
ymax = Math.max(point.y, ymax);
}
bounds.x = xmin;
bounds.y = ymin;
bounds.width = xmax - xmin;
bounds.height = ymax - ymin;
}
return bounds;
};
/**
* Obtains the padded line bounds from current line points and leader/ending settings and returns them as [x, y, width, height].
*
* @private
* @returns {number[]} bounds Array [x, y, width, height].
*/
PdfLineAnnotation.prototype._obtainLineBounds = function () {
var bounds = this.bounds;
if (typeof this.linePoints !== 'undefined' && this._linePoints.length === 2) {
var leaderOffset = this._dictionary.has('LLO') ? this.leaderOffset : 0;
var leaderExt = this._dictionary.has('LLE') ? this.leaderExt : 0;
var leaderLine = this._dictionary.has('LL') ? this.leaderLine : 0;
bounds = this._calculateLineBounds(this._linePoints, leaderExt, leaderLine, leaderOffset, this.lineEndingStyle, this.border.width);
bounds = { x: bounds.x - 8, y: bounds.y - 8, width: (bounds.width + 2 * 8), height: (bounds.height + 2 * 8) };
}
return [bounds.x, bounds.y, bounds.width, bounds.height];
};
/**
* Creates or reuses the normal appearance template for a line annotation, drawing the line, leaders, end styles, and optional caption.
*
* @private
* @returns {PdfTemplate} returns normal appearance.
*/
PdfLineAnnotation.prototype._createAppearance = function () {
var bounds = this._obtainLineBounds();
var template;
if (this._customTemplate.has('N')) {
template = this._customTemplate.get('N');
}
else {
template = new PdfTemplate(bounds, this._crossReference);
_setMatrix(template, 0);
var parameter = new _PaintParameter();
template._writeTransformation = false;
var graphics = template.graphics;
var pen = new PdfPen(typeof this.color !== 'undefined' ? this._color : { r: 0, g: 0, b: 0 }, this.border.width);
if (this.border.style === PdfBorderStyle.dashed) {
pen._dashStyle = PdfDashStyle.dash;
pen._dashPattern = [3, 1];
}
else if (this.border.style === PdfBorderStyle.dot) {
pen._dashStyle = PdfDashStyle.dot;
pen._dashPattern = [1, 1];
}
if (this.border.style !== PdfBorderStyle.solid && this.border.dash) {
pen._dashPattern = this.border.dash;
}
parameter.borderPen = pen;
parameter.foreBrush = new PdfBrush(this.color);
var brush = void 0;
if (this.innerColor) {
brush = new PdfBrush(this._innerColor);
}
var font = this._obtainFont();
if ((typeof font === 'undefined' || font === null) || (!this._isLoaded && font.size === 1)) {
font = this._lineCaptionFont;
this._pdfFont = font;
}
if (!this.text && !this._dictionary.has('Contents')) {
this.text = this.subject;
}
var format = new PdfStringFormat(PdfTextAlignment.center, PdfVerticalAlignment.middle);
var lineWidth = 0;
if (this.caption.cap) {
lineWidth = font.measureString(this.text ? this.text : '', { width: 0, height: 0 }, format, 0, 0).width; //66.71001;
}
if (typeof this.linePoints !== 'undefined' && this._linePoints.length === 2) {
var angle = this._getAngle(this._linePoints);
var leaderLine = 0;
var lineAngle = 0;
var leaderLineValue = this.leaderLine;
if (leaderLineValue === null || typeof leaderLineValue === 'undefined') {
this._leaderLine = 0;
leaderLineValue = 0;
}
if (leaderLineValue < 0) {
leaderLine = -(leaderLineValue);
lineAngle = angle + 180;
}
else {
leaderLine = leaderLineValue;
lineAngle = angle;
}
var offset = (typeof this.leaderOffset !== 'undefined') ? (leaderLine + this.leaderOffset) : leaderLine;
var startPoint = this._getAxisValue(this._linePoints[0], (lineAngle + 90), offset);
var endPoint = this._getAxisValue(this._linePoints[1], (lineAngle + 90), offset);
var lineDistance = (Math.sqrt(Math.pow((endPoint.x - startPoint.x), 2) +
Math.pow((endPoint.y - startPoint.y), 2)));
var centerWidth = lineDistance / 2 - ((lineWidth / 2) + this.border.width);
var first = this._getAxisValue(startPoint, angle, centerWidth);
var second = this._getAxisValue(endPoint, (angle + 180), centerWidth);
var start = (this.lineEndingStyle.begin === PdfLineEndingStyle.openArrow ||
this.lineEndingStyle.begin === PdfLineEndingStyle.closedArrow) ?
this._getAxisValue(startPoint, angle, this.border.width) :
startPoint;
var end = (this.lineEndingStyle.end === PdfLineEndingStyle.openArrow ||
this.lineEndingStyle.end === PdfLineEndingStyle.closedArrow) ?
this._getAxisValue(endPoint, angle, -this.border.width) :
endPoint;
if (this.opacity && this._opacity < 1) {
var state = graphics.save();
graphics.setTransparency(this._opacity);
this._drawLine(graphics, pen, start, end, first, second);
graphics.restore(state);
}
else {
this._drawLine(graphics, pen, start, end, first, second);
}
this._drawLineStyle(startPoint, endPoint, graphics, angle, pen, brush, this.lineEndingStyle, this.border.width);
var leaderExt = (typeof this.leaderExt !== 'undefined' ? this._leaderExt : 0);
var beginLineExt = this._getAxisValue(startPoint, (lineAngle + 90), leaderExt);
graphics.drawLine(pen, { x: startPoint.x, y: -startPoint.y }, { x: beginLineExt.x, y: -beginLineExt.y });
var endLineExt = this._getAxisValue(endPoint, (lineAngle + 90), leaderExt);
graphics.drawLine(pen, { x: endPoint.x, y: -endPoint.y }, { x: endLineExt.x, y: -endLineExt.y });
var beginLeaderLine = this._getAxisValue(startPoint, (lineAngle - 90), leaderLine);
graphics.drawLine(pen, { x: startPoint.x, y: -startPoint.y }, { x: beginLeaderLine.x, y: -beginLeaderLine.y });
var endLeaderLine = this._getAxisValue(endPoint, (lineAngle - 90), leaderLine);
graphics.drawLine(pen, { x: endPoint.x, y: -endPoint.y }, { x: endLeaderLine.x, y: -endLeaderLine.y });
var midpoint = lineDistance / 2;
var centerPoint = this._getAxisValue(startPoint, angle, midpoint);
var captionPosition = void 0;
var height = font._getHeight();
if (this.caption.type === PdfLineCaptionType.top) {
if (this._measure) {
captionPosition = this._getAxisValue(centerPoint, (angle + 90), 2 * height);
}
else {
captionPosition = this._getAxisValue(centerPoint, (angle + 90), height);
}
}
else {
if (this._measure) {
captionPosition = this._getAxisValue(centerPoint, (angle + 90), 3 * (height / 2));
}
else {
captionPosition = this._getAxisValue(centerPoint, (angle + 90), (height / 2));
}
}
graphics.translateTransform({ x: captionPosition.x, y: -captionPosition.y });
graphics.rotateTransform(-angle);
if (this.caption.cap) {
graphics.drawString(this.text, font, { x: (-lineWidth / 2), y: 0, width: 0, height: 0 }, null, parameter.foreBrush);
}
graphics.restore();
}
}
var rectangleBounds = _fromRectangle({ x: bounds[0], y: bounds[1], width: bounds[2], height: bounds[3] });
this.bounds = { x: rectangleBounds[0], y: rectangleBounds[1], width: rectangleBounds[2], height: rectangleBounds[3] };
if ((!this.measure) && (!this._dictionary.has('Measure'))) {
this._dictionary.update('Rect', [rectangleBounds[0], rectangleBounds[1], rectangleBounds[2], rectangleBounds[3]]);
}
return template;
};
/**
* Draws the line either as a single segment or split around the caption gap when inline captions are enabled.
*
* @private
* @param {PdfGraphics} graphics Target graphics.
* @param {PdfPen} pen Stroke pen.
* @param {Point} start Start point (possibly adjusted).
* @param {Point} end End point (possibly adjusted).
* @param {Point} first First split point around caption.
* @param {Point} second Second split point around caption.
* @returns {void} nothing.
*/
PdfLineAnnotation.prototype._drawLine = function (graphics, pen, start, end, first, second) {
if (typeof this.text === 'undefined' ||
this._text === '' ||
this.caption.type === PdfLineCaptionType.top ||
(!this.caption.cap && this.caption.type === PdfLineCaptionType.inline)) {
graphics.drawLine(pen, { x: start.x, y: -start.y }, { x: end.x, y: -end.y });
}
else {
graphics.drawLine(pen, { x: start.x, y: -start.y }, { x: first.x, y: -first.y });
graphics.drawLine(pen, { x: end.x, y: -end.y }, { x: second.x, y: -second.y });
}
};
/**
* Computes the line length converted from points to the configured measurement unit and returns the numeric value.
*
* @private
* @returns {number} length Line length in selected unit.
*/
PdfLineAnnotation.prototype._convertToUnit = function () {
var points = this._obtainLinePoints();
var flatData = _convertPointToNumberArray(points);
var data = new Array(flatData.length / 2);
var count = 0;
for (var j = 0; j < flatData.length; j = j + 2) {
data[count] = [flatData[j], (flatData[j + 1])];
count++;
}
var distance = Math.sqrt(Math.pow((data[1][0] - data[0][0]), 2) + Math.pow((data[1][1] - data[0][1]), 2));
var value = this._getEqualPdfGraphicsUnit(this.unit, this._unitString);
this._unitString = value.unitString;
return (new _PdfUnitConvertor())._convertUnits(distance, _PdfGraphicsUnit.point, value.graphicsUnit);
};
/**
* Returns a shallow copy of the current line points array.
*
* @private
* @returns {Point[]} points Copy of line points.
*/
PdfLineAnnotation.prototype._obtainLinePoints = function () {
var points = this.linePoints ? this._linePoints.slice() : [];
return points;
};
return PdfLineAnnotation;
}(PdfComment));
export { PdfLineAnnotation };
/**
* `PdfCircleAnnotation` class represents the circle annotation objects.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Create a new circle annotation with circle bounds
* const annotation: PdfCircleAnnotation = new PdfCircleAnnotation({x: 10, y: 10, width: 100, height: 100});
* // Add annotation to the page
* page.annotations.add(annotation);
* // Destroy the document
* document.destroy();
* ```
*/
var PdfCircleAnnotation = /** @class */ (function (_super) {
__extends(PdfCircleAnnotation, _super);
function PdfCircleAnnotation(bounds, properties) {
var _this = _super.call(this) || this;
/**
* Specifies the measurement unit used for circle annotations.
*
* @private
*/
_this._unit = PdfMeasurementUnit.centimeter;
/**
* Determines whether the circle is measured by radius or diameter.
*
* @private
*/
_this._measureType = PdfCircleMeasurementType.diameter;
_this._unitString = '';
_this._dictionary = new _PdfDictionary();
_this._dictionary.update('Type', _PdfName.get('Annot'));
_this._dictionary.update('Subtype', _PdfName.get('Circle'));
if (bounds !== null && typeof bounds !== 'undefined' && typeof bounds.x !== 'undefined' && typeof bounds.y !== 'undefined' && typeof bounds.width !== 'undefined' && typeof bounds.height !== 'undefined') {
_this.bounds = bounds;
}
_this._type = _PdfAnnotationType.circleAnnotation;
if (properties) {
if ('text' in properties && _isNullOrUndefined(properties.text)) {
_this.text = properties.text;
}
if ('author' in properties && _isNullOrUndefined(properties.author)) {
_this.author = properties.author;
}
if ('subject' in properties && _isNullOrUndefined(properties.subject)) {
_this.subject = properties.subject;
}
if ('color' in properties && _isNullOrUndefined(properties.color)) {
_this.color = properties.color;
}
if ('innerColor' in properties && _isNullOrUndefined(properties.innerColor)) {
_this.innerColor = properties.innerColor;
}
if ('opacity' in properties && _isNullOrUndefined(properties.opacity)) {
_this.opacity = properties.opacity;
}
if ('border' in properties && _isNullOrUndefined(properties.border)) {
_this.border = properties.border;
}
if ('measure' in properties && _isNullOrUndefined(properties.measure)) {
var measure = properties.measure;
if ('unit' in measure && _isNullOrUndefined(measure.unit)) {
_this.measure = true;
_this.unit = measure.unit;
}
if ('type' in measure && _isNullOrUndefined(measure.type)) {
_this.measure = true;
_this.measureType = measure.type;
}
}
}
return _this;
}
Object.defineProperty(PdfCircleAnnotation.prototype, "measure", {
/**
* Gets the flag to have measurement dictionary of the circle annotation.
*
* @returns {boolean} measure.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfCircleAnnotation = page.annotations.at(0) as PdfCircleAnnotation;
* // Gets the flag to have measurement dictionary of the circle annotation.
* let measure: boolean = annotation.measure;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (!this._measure) {
this._measure = this._dictionary.has('Measure');
}
return this._measure;
},
/**
* Sets the flag to add measurement dictionary to the annotation.
*
* @param {boolean} value Measure.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfCircleAnnotation = page.annotations.at(0) as PdfCircleAnnotation;
* // Sets the flag to have measurement dictionary of the circle annotation.
* annotation.measure = true;
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value) {
if (!this._isLoaded) {
this._measure = value;
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfCircleAnnotation.prototype, "unit", {
/**
* Gets the measurement unit of the annotation.
*
* @returns {PdfMeasurementUnit} Measurement unit.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfCircleAnnotation = page.annotations.at(0) as PdfCircleAnnotation;
* // Gets the measurement unit of the annotation.
* let unit: PdfMeasurementUnit = annotation.unit;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (this._isTextUpdated) {
return this._unit;
}
if (typeof this._unit === 'undefined' || this._isLoaded) {
if (this._dictionary.has('Contents')) {
var text = this._dictionary.get('Contents');
this._unitString = text.substring(text.length - 2);
this._unit = _mapMeasurementUnit(this._unitString);
}
else {
this._unit = PdfMeasurementUnit.centimeter;
}
}
return this._unit;
},
/**
* Sets the measurement unit of the annotation.
*
* @param {PdfMeasurementUnit} value Measurement unit.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfCircleAnnotation = page.annotations.at(0) as PdfCircleAnnotation;
* // Sets the measurement unit of the annotation.
* annotation.unit = PdfMeasurementUnit.centimeter;
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (this._measure) {
if (!this._isLoaded && typeof value !== 'undefined') {
this._unit = value;
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfCircleAnnotation.prototype, "measureType", {
/**
* Gets the measurement type of the annotation.
*
* @returns {PdfCircleMeasurementType} Measurement type.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfCircleAnnotation = page.annotations.at(0) as PdfCircleAnnotation;
* // Gets the measurement type of the annotation.
* let type: PdfCircleMeasurementType = annotation.type;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (this._dictionary.has('Contents')) {
var text = this._dictionary.get('Contents');
this._unitString = text.substring(text.length - 2);
this._unit = _mapMeasurementUnit(this._unitString);
var value = text.substring(0, text.length - 2);
var converter = new _PdfUnitConvertor();
var radius = converter._convertUnits(this.bounds.width / 2, _PdfGraphicsUnit.point, _mapGraphicsUnit(this._unitString));
if (radius.toString() === value) {
this._measureType = PdfCircleMeasurementType.radius;
}
else {
this._measureType = PdfCircleMeasurementType.diameter;
}
}
return this._measureType;
},
/**
* Sets the measurement type of the annotation.
*
* @param {PdfCircleMeasurementType} value Measurement type.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfCircleAnnotation = page.annotations.at(0) as PdfCircleAnnotation;
* // Sets the measurement type of the annotation.
* annotation.type = PdfCircleMeasurementType.diameter;
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (this._measure) {
if (!this._isLoaded && typeof value !== 'undefined') {
this._measureType = value;
}
}
},
enumerable: true,
configurable: true
});
/**
* Loads a circle annotation from the given page and dictionary, marks it as loaded, and initializes internal state.
*
* @private
* @param {PdfPage} page Page containing the annotation.
* @param {_PdfDictionary} dictionary Source annotation dictionary.
* @returns {PdfCircleAnnotation} annot Loaded circle annotation.
*/
PdfCircleAnnotation._load = function (page, dictionary) {
var annot = new PdfCircleAnnotation();
annot._isLoaded = true;
annot._initialize(page, dictionary);
return annot;
};
/**
* Initializes the circle annotation for the specified page and optional dictionary by delegating to the base initializer.
*
* @private
* @param {PdfPage} page Owning page.
* @param {_PdfDictionary} [dictionary] Optional source dictionary.
* @returns {void} nothing.
*/
PdfCircleAnnotation.prototype._initialize = function (page, dictionary) {
_super.prototype._initialize.call(this, page, dictionary);
};
/**
* Finalizes the annotation setup: validates bounds, ensures BS/color defaults, updates Rect,
* and builds appearance or measure appearance as needed.
*
* @private
* @param {boolean} isFlatten True if invoked during flattening.
* @returns {void} nothing.
*/
PdfCircleAnnotation.prototype._postProcess = function (isFlatten) {
if (typeof this.bounds === 'undefined' || this.bounds === null) {
throw new Error('Bounds cannot be null or undefined');
}
var borderWidth;
if (this._dictionary.has('BS')) {
borderWidth = this.border.width;
}
else {
var dictionary = new _PdfDictionary(this._crossReference);
dictionary.set('Type', _PdfName.get('Border'));
this._dictionary.set('BS', dictionary);
}
if (!this._dictionary.has('C')) {
this.color = { r: 0, g: 0, b: 0 };
this._isTransparentColor = true;
}
if (typeof borderWidth === 'undefined') {
borderWidth = 1;
}
if (this._measure) {
this._appearanceTemplate = this._createCircleMeasureAppearance(isFlatten);
}
else {
this._dictionary.update('Rect', _updateBounds(this));
if (this._setAppearance || (isFlatten && !this._dictionary.has('AP')) || this._customTemplate.size > 0) {
this._appearanceTemplate = this._createCircleAppearance();
}
}
};
/**
* Creates or imports the circle s appearance stream based on state, optionally flattens including pop ups,
* and updates AP entries accordingly.
*
* @private
* @param {boolean} [isFlatten=false] True if flattening is requested.
* @returns {void} nothing.
*/
PdfCircleAnnotation.prototype._doPostProcess = function (isFlatten) {
if (isFlatten === void 0) { isFlatten = false; }
if (this._isLoaded) {
if ((this._setAppearance || this._customTemplate.size > 0) || (isFlatten && !this._dictionary.has('AP'))) {
if (this._dictionary.has('Measure')) {
this._appearanceTemplate = this._createCircleMeasureAppearance(isFlatten);
}
else {
this._appearanceTemplate = this._createCircleAppearance();
}
}
if (!this._appearanceTemplate && isFlatten && this._dictionary.has('AP')) {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
var appearanceStream = dictionary.get('N');
var reference = dictionary.getRaw('N');
if (appearanceStream) {
if (reference) {
appearanceStream.reference = reference;
}
this._appearanceTemplate = new PdfTemplate(appearanceStream, this._crossReference);
}
}
}
}
else {
this._postProcess(isFlatten);
if (!this._appearanceTemplate && isFlatten) {
if (!this._dictionary.has('AP')) {
this._appearanceTemplate = this._createCircleAppearance();
}
else {
var dictionary = this._dictionary.get('AP');
if (dictionary !== null && typeof dictionary !== 'undefined' && dictionary.has('N')) {
var appearanceStream = dictionary.get('N');
var reference = dictionary.getRaw('N');
if (appearanceStream) {
if (reference) {
appearanceStream.reference = reference;
}
this._appearanceTemplate = new PdfTemplate(appearanceStream, this._crossReference);
}
}
}
}
}
if (typeof this.flattenPopups !== 'undefined' && this.flattenPopups && isFlatten) {
if (this._isLoaded) {
this._flattenLoadedPopUp();
}
else {
this._flattenPopUp();
}
}
if (isFlatten) {
if (this._appearanceTemplate) {
var isNormalMatrix = this._validateTemplateMatrix(this._appearanceTemplate._content.dictionary);
this._flattenAnnotationTemplate(this._appearanceTemplate, isNormalMatrix);
}
else {
this._page.annotations.remove(this);
}
}
else if (this._setAppearance || this._customTemplate.size > 0) {
var appearance = void 0;
var crossReference = this._crossReference;
if (this._dictionary.has('AP')) {
appearance = this._dictionary.get('AP');
}
else {
var reference = crossReference._getNextReference();
appearance = new _PdfDictionary(crossReference);
appearance._updated = true;
crossReference._cacheMap.set(reference, appearance);
this._dictionary.update('AP', reference);
}
if (this._customTemplate.size > 0) {
this._drawCustomAppearance(appearance);
}
else {
_removeDuplicateReference(appearance, crossReference, 'N');
var reference = this._crossReference._getNextReference();
this._appearanceTemplate._content.dictionary._update = true;
this._appearanceTemplate._content.reference = reference;
crossReference._cacheMap.set(reference, this._appearanceTemplate._content);
appearance.update('N', reference);
}
}
};
/**
* Creates the measured circle appearance template, draws the ellipse and diameter/radius indicator
* with a caption, and updates related dictionary entries.
*
* @private
* @param {boolean} _isFlatten True if called during flattening.
* @returns {PdfTemplate} template Appearance template.
*/
PdfCircleAnnotation.prototype._createCircleMeasureAppearance = function (_isFlatten) {
var borderWidth = this.border.width;
var dictionary = this._dictionary;
var font = this._obtainFont();
if ((typeof font === 'undefined' || font === null) || (!this._isLoaded && font.size === 1)) {
font = this._circleCaptionFont;
this._pdfFont = font;
}
var area = this._convertToUnit();
var format = new PdfStringFormat(PdfTextAlignment.center, PdfVerticalAlignment.middle);
var str = area.toFixed(2) + ' ' + this._unitString;
var fontsize = font.measureString(str, { width: 0, height: 0 }, format, 0, 0);
var color = this.color ? this.color : { r: 0, g: 0, b: 0 };
var borderPen = new PdfPen(color, borderWidth);
var nativeRectangle = [this.bounds.x,
(this.bounds.y + this.bounds.height),
this.bounds.width,
this.bounds.height];
nativeRectangle[1] = nativeRectangle[1] - nativeRectangle[3];
var template;
if (this._customTemplate.has('N')) {
template = this._customTemplate.get('N');
dictionary.update('Rect', _updateBounds(this));
}
else {
template = new PdfTemplate(nativeRectangle, this._crossReference);
var parameter = new _PaintParameter();
template._writeTransformation = false;
var graphics = template.graphics;
var width = borderWidth / 2;
parameter.borderPen = borderPen;
if (this.innerColor) {
parameter.backBrush = new PdfBrush(this._innerColor);
}
parameter.foreBrush = new PdfBrush(color);
var rect = [nativeRectangle[0],
-nativeRectangle[1] - nativeRectangle[3],
nativeRectangle[2],
nativeRectangle[3]];
graphics.save();
graphics.drawEllipse({ x: rect[0] + width,
y: rect[1] + width,
width: rect[2] - borderWidth,
height: rect[3] - borderWidth }, new PdfPen(color, this.border.width));
if (this._measureType === PdfCircleMeasurementType.diameter) {
graphics.save();
graphics.translateTransform({ x: nativeRectangle[0], y: -nativeRectangle[1] });
var x = (nativeRectangle[3] / 2) - (fontsize.width / 2);
graphics.drawLine(parameter.borderPen, { x: 0,
y: -nativeRectangle[3] / 2 }, { x: nativeRectangle[0] + nativeRectangle[2],
y: -nativeRectangle[3] / 2 });
graphics.translateTransform({ x: x, y: -(nativeRectangle[3] / 2) - font._getHeight() });
graphics.drawString(area.toFixed(2) + ' ' + this._unitString, font, { x: 0, y: 0, width: 0, height: 0 }, null, parameter.foreBrush);
graphics.restore();
}
else {
graphics.save();
graphics.translateTransform({ x: nativeRectangle[0], y: -nativeRectangle[1] });
var x = (nativeRectangle[2] / 2) + ((nativeRectangle[2] / 4) - (fontsize.width / 2));
graphics.drawLine(parameter.borderPen, { x: nativeRectangle[2] / 2,
y: -nativeRectangle[3] / 2 }, { x: nativeRectangle[0] + nativeRectangle[2],
y: -nativeRectangle[3] / 2 });
graphics.translateTransform({ x: x, y: -(nativeRectangle[3] / 2) - font._getHeight() });
graphics.drawString(area.toFixed(2) + ' ' + this._unitString, font, { x: 0, y: 0, width: 0, height: 0 }, null, parameter.foreBrush);
graphics.restore();
}
graphics.restore();
if ((typeof _isFlatten !== 'undefined' && !_isFlatten) || !this._isLoaded) {
if (dictionary.has('AP')) {
_removeDuplicateReference(dictionary.get('AP'), this._crossReference, 'N');
}
var dic = new _PdfDictionary();
graphics._template._content.dictionary._updated = true;
var ref = this._crossReference._getNextReference();
this._crossReference._cacheMap.set(ref, graphics._template._content);
graphics._template._content.reference = ref;
dic.set('N', ref);
dic._updated = true;
dictionary.set('AP', dic);
dictionary.update('Rect', _updateBounds(this));
if (dictionary.has('Measure')) {
_removeDuplicateReference(dictionary, this._crossReference, 'Measure');
}
var measureDictionary = this._createMeasureDictionary(this._unitString);
var reference = this._crossReference._getNextReference();
this._crossReference._cacheMap.set(reference, measureDictionary);
measureDictionary._updated = true;
dictionary.update('Measure', reference);
dictionary.update('Subtype', new _PdfName('Circle'));
if (this._text && this._text !== '') {
dictionary.update('Contents', this._text + ' ' + area.toFixed(2) + ' ' + this._unitString);
}
else {
dictionary.update('Contents', area.toFixed(2) + ' ' + this._unitString);
}
var ds = 'font:' +
font._metrics._postScriptName +
' ' +
font._size +
'pt; color:' +
this._colorToHex([this.color.r, this.color.g, this.color.b]);
dictionary.update('DS', ds);
}
}
return template;
};
/**
* Converts the circles size from points to the configured measurement unit and returns the numeric value.
*
* @private
* @returns {number} value Radius or diameter in the configured unit.
*/
PdfCircleAnnotation.prototype._convertToUnit = function () {
var converter = new _PdfUnitConvertor();
var value = this._getEqualPdfGraphicsUnit(this.unit, this._unitString);
this._unitString = value.unitString;
var radius = converter._convertUnits(this.bounds.width / 2, _PdfGraphicsUnit.point, value.graphicsUnit);
if (this._measureType === PdfCircleMeasurementType.diameter) {
radius = 2 * radius;
}
return radius;
};
return PdfCircleAnnotation;
}(PdfComment));
export { PdfCircleAnnotation };
/**
* `PdfEllipseAnnotation` class represents the ellipse annotation objects.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Create a new ellipse annotation with bounds
* const annotation: PdfEllipseAnnotation = new PdfEllipseAnnotation({x: 10, y: 10, width: 100, height: 100});
* // Add annotation to the page
* page.annotations.add(annotation);
* // Destroy the document
* document.destroy();
* ```
*/
var PdfEllipseAnnotation = /** @class */ (function (_super) {
__extends(PdfEllipseAnnotation, _super);
function PdfEllipseAnnotation(bounds, properties) {
var _this = _super.call(this) || this;
_this._dictionary = new _PdfDictionary();
_this._dictionary.update('Type', _PdfName.get('Annot'));
_this._dictionary.update('Subtype', _PdfName.get('Circle'));
if (bounds !== null && typeof bounds !== 'undefined' && typeof bounds.x !== 'undefined' && typeof bounds.y !== 'undefined' && typeof bounds.width !== 'undefined' && typeof bounds.height !== 'undefined') {
_this.bounds = bounds;
}
_this._type = _PdfAnnotationType.ellipseAnnotation;
if (properties) {
if ('text' in properties && _isNullOrUndefined(properties.text)) {
_this.text = properties.text;
}
if ('author' in properties && _isNullOrUndefined(properties.author)) {
_this.author = properties.author;
}
if ('subject' in properties && _isNullOrUndefined(properties.subject)) {
_this.subject = properties.subject;
}
if ('color' in properties && _isNullOrUndefined(properties.color)) {
_this.color = properties.color;
}
if ('innerColor' in properties && _isNullOrUndefined(properties.innerColor)) {
_this.innerColor = properties.innerColor;
}
if ('opacity' in properties && _isNullOrUndefined(properties.opacity)) {
_this.opacity = properties.opacity;
}
if ('border' in properties && _isNullOrUndefined(properties.border)) {
_this.border = properties.border;
}
}
return _this;
}
/**
* Loads an ellipse annotation from the given page and dictionary, marks it as loaded, and initializes internal state.
*
* @private
* @param {PdfPage} page Page containing the annotation.
* @param {_PdfDictionary} dictionary Source annotation dictionary.
* @returns {PdfEllipseAnnotation} annot Loaded ellipse annotation.
*/
PdfEllipseAnnotation._load = function (page, dictionary) {
var annot = new PdfEllipseAnnotation();
annot._isLoaded = true;
annot._initialize(page, dictionary);
return annot;
};
/**
* Initializes the ellipse annotation for the specified page and optional dictionary by delegating to the base initializer.
*
* @private
* @param {PdfPage} page Owning page.
* @param {_PdfDictionary} [dictionary] Optional source dictionary.
* @returns {void} nothing.
*/
PdfEllipseAnnotation.prototype._initialize = function (page, dictionary) {
_super.prototype._initialize.call(this, page, dictionary);
};
/**
* Finalizes the annotation setup: validates bounds, ensures BS/color defaults, builds appearance when needed,
* and updates the Rect entry.
*
* @private
* @param {boolean} isFlatten True if invoked during flattening.
* @returns {void} nothing.
*/
PdfEllipseAnnotation.prototype._postProcess = function (isFlatten) {
if (typeof this.bounds === 'undefined' || this.bounds === null) {
throw new Error('Bounds cannot be null or undefined');
}
var borderWidth;
if (this._dictionary.has('BS')) {
borderWidth = this.border.width;
}
else {
var dictionary = new _PdfDictionary(this._crossReference);
dictionary.set('Type', _PdfName.get('Border'));
this._dictionary.set('BS', dictionary);
}
if (!this._dictionary.has('C')) {
this.color = { r: 0, g: 0, b: 0 };
this._isTransparentColor = true;
}
if (typeof borderWidth === 'undefined') {
borderWidth = 1;
}
if (this._setAppearance || (isFlatten && !this._dictionary.has('AP')) || this._customTemplate.size > 0) {
this._appearanceTemplate = this._createCircleAppearance();
}
this._dictionary.update('Rect', _updateBounds(this));
};
/**
* Creates or imports the ellipses appearance stream based on state, optionally flattens,
* and updates AP entries accordingly.
*
* @private
* @param {boolean} [isFlatten=false] True if flattening is requested.
* @returns {void} nothing.
*/
PdfEllipseAnnotation.prototype._doPostProcess = function (isFlatten) {
if (isFlatten === void 0) { isFlatten = false; }
if (this._isLoaded) {
if (this._setAppearance || this._customTemplate.size > 0 || (isFlatten && !this._dictionary.has('AP'))) {
this._appearanceTemplate = this._createCircleAppearance();
}
if (!this._appearanceTemplate && isFlatten && this._dictionary.has('AP')) {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
var appearanceStream = dictionary.get('N');
var reference = dictionary.getRaw('N');
if (appearanceStream) {
if (reference) {
appearanceStream.reference = reference;
}
this._appearanceTemplate = new PdfTemplate(appearanceStream, this._crossReference);
}
}
}
}
else {
this._postProcess(isFlatten);
if (!this._appearanceTemplate && isFlatten) {
if (!this._dictionary.has('AP')) {
this._appearanceTemplate = this._createCircleAppearance();
}
else {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
var appearanceStream = dictionary.get('N');
var reference = dictionary.getRaw('N');
if (appearanceStream) {
if (reference) {
appearanceStream.reference = reference;
}
this._appearanceTemplate = new PdfTemplate(appearanceStream, this._crossReference);
}
}
}
}
}
if (typeof this.flattenPopups !== 'undefined' && this.flattenPopups) {
if (this._isLoaded) {
this._flattenLoadedPopUp();
}
else {
this._flattenPopUp();
}
}
if (isFlatten) {
if (this._appearanceTemplate) {
var isNormalMatrix = this._validateTemplateMatrix(this._appearanceTemplate._content.dictionary);
this._flattenAnnotationTemplate(this._appearanceTemplate, isNormalMatrix);
}
else {
this._page.annotations.remove(this);
}
}
else if (this._setAppearance || this._customTemplate.size > 0) {
var appearance = void 0;
var crossReference = this._crossReference;
if (this._dictionary.has('AP')) {
appearance = this._dictionary.get('AP');
}
else {
var reference = crossReference._getNextReference();
appearance = new _PdfDictionary(crossReference);
appearance._updated = true;
crossReference._cacheMap.set(reference, appearance);
this._dictionary.update('AP', reference);
}
if (this._customTemplate.size > 0) {
this._drawCustomAppearance(appearance);
}
else {
_removeDuplicateReference(appearance, crossReference, 'N');
var reference = crossReference._getNextReference();
this._appearanceTemplate._content.dictionary._update = true;
this._appearanceTemplate._content.reference = reference;
crossReference._cacheMap.set(reference, this._appearanceTemplate._content);
appearance.update('N', reference);
}
}
};
return PdfEllipseAnnotation;
}(PdfComment));
export { PdfEllipseAnnotation };
/**
* `PdfSquareAnnotation` class represents the square annotation objects.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Create a new square annotation with bounds
* const annotation: PdfSquareAnnotation = new PdfSquareAnnotation({x: 10, y: 10, width: 100, height: 100});
* // Add annotation to the page
* page.annotations.add(annotation);
* // Destroy the document
* document.destroy();
* ```
*/
var PdfSquareAnnotation = /** @class */ (function (_super) {
__extends(PdfSquareAnnotation, _super);
function PdfSquareAnnotation(bounds, properties) {
var _this = _super.call(this) || this;
/**
* Specifies the measurement unit used for square annotations.
*
* @private
*/
_this._unit = PdfMeasurementUnit.centimeter;
_this._dictionary = new _PdfDictionary();
_this._dictionary.update('Type', _PdfName.get('Annot'));
_this._dictionary.update('Subtype', _PdfName.get('Square'));
if (bounds !== null && typeof bounds !== 'undefined' && typeof bounds.x !== 'undefined' && typeof bounds.y !== 'undefined' && typeof bounds.width !== 'undefined' && typeof bounds.height !== 'undefined') {
_this.bounds = bounds;
}
_this._type = _PdfAnnotationType.squareAnnotation;
if (properties) {
if ('text' in properties && _isNullOrUndefined(properties.text)) {
_this.text = properties.text;
}
if ('author' in properties && _isNullOrUndefined(properties.author)) {
_this.author = properties.author;
}
if ('subject' in properties && _isNullOrUndefined(properties.subject)) {
_this.subject = properties.subject;
}
if ('color' in properties && _isNullOrUndefined(properties.color)) {
_this.color = properties.color;
}
if ('innerColor' in properties && _isNullOrUndefined(properties.innerColor)) {
_this.innerColor = properties.innerColor;
}
if ('opacity' in properties && _isNullOrUndefined(properties.opacity)) {
_this.opacity = properties.opacity;
}
if ('border' in properties && _isNullOrUndefined(properties.border)) {
_this.border = properties.border;
}
if ('measurementUnit' in properties && _isNullOrUndefined(properties.measurementUnit)) {
_this.measure = true;
_this.unit = properties.measurementUnit;
}
}
return _this;
}
Object.defineProperty(PdfSquareAnnotation.prototype, "borderEffect", {
/**
* Gets the border effect of the square annotation.
*
* @returns {PdfBorderEffect} Border effect.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfSquareAnnotation = page.annotations.at(0) as PdfSquareAnnotation;
* // Gets the border effect of the square annotation.
* let borderEffect: PdfBorderEffect = annotation.borderEffect;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._borderEffect === 'undefined') {
var value = new PdfBorderEffect();
value._dictionary = this._dictionary;
if (this._dictionary.has('BE')) {
var dictionary = this._dictionary.get('BE');
value._intensity = dictionary.get('I');
value._style = _mapBorderEffectStyle(dictionary.get('S').name);
}
else {
value._style = PdfBorderEffectStyle.solid;
}
this._borderEffect = value;
}
return this._borderEffect;
},
/**
* Sets the border effect of the square annotation.
*
* @param {PdfBorderEffect} value Border effect.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfSquareAnnotation = page.annotations.at(0) as PdfSquareAnnotation;
* // Sets the border effect of the square annotation.
* annotation.borderEffect.intensity = 1;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (typeof value !== 'undefined') {
this._borderEffect = value;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfSquareAnnotation.prototype, "measure", {
/**
* Gets the flag to have measurement dictionary of the Square annotation.
*
* @returns {boolean} measure.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfSquareAnnotation = page.annotations.at(0) as PdfSquareAnnotation;
* // Gets the flag to have measurement dictionary of the square annotation.
* let measure: boolean = annotation.measure;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._measure === 'undefined' && this._dictionary.has('Measure')) {
this._measure = this._dictionary.get('Measure');
}
return this._measure;
},
/**
* Sets the flag to add measurement dictionary to the annotation.
*
* @param {boolean} value Measure.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfSquareAnnotation = page.annotations.at(0) as PdfSquareAnnotation;
* // Sets the flag to have measurement dictionary of the square annotation.
* annotation.measure = true;
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (typeof value !== 'undefined') {
if (!this._isLoaded) {
this._measure = value;
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfSquareAnnotation.prototype, "unit", {
/**
* Gets the measurement unit of the annotation.
*
* @returns {PdfMeasurementUnit} Measurement unit.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfSquareAnnotation = page.annotations.at(0) as PdfSquareAnnotation;
* // Gets the measurement unit of the annotation.
* let unit: PdfMeasurementUnit = annotation.unit;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (this._isTextUpdated) {
return this._unit;
}
if (typeof this._unit === 'undefined') {
this._unit = PdfMeasurementUnit.centimeter;
if (this._dictionary.has('Contents')) {
var text = this._dictionary.get('Contents');
this._unitString = text.substring(text.length - 2);
this._unit = _mapMeasurementUnit(this._unitString);
}
}
return this._unit;
},
/**
* Sets the measurement unit of the annotation.
*
* @param {PdfMeasurementUnit} value Measurement unit.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfSquareAnnotation = page.annotations.at(0) as PdfSquareAnnotation;
* // Sets the measurement unit of the annotation.
* annotation.unit = PdfMeasurementUnit.centimeter;
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (this._measure) {
if (!this._isLoaded && typeof value !== 'undefined') {
this._unit = value;
}
}
},
enumerable: true,
configurable: true
});
/**
* Loads a square annotation from the given page and dictionary, marks it as loaded, and initializes internal state.
*
* @private
* @param {PdfPage} page Page containing the annotation.
* @param {_PdfDictionary} dictionary Source annotation dictionary.
* @returns {PdfSquareAnnotation} annot Loaded square annotation.
*/
PdfSquareAnnotation._load = function (page, dictionary) {
var annot = new PdfSquareAnnotation();
annot._isLoaded = true;
annot._initialize(page, dictionary);
return annot;
};
/**
* Initializes the square/rectangle annotation for the specified page and optional source dictionary by delegating to the base initializer.
*
* @private
* @param {PdfPage} page Owning page.
* @param {_PdfDictionary} [dictionary] Optional source dictionary.
* @returns {void} nothing.
*/
PdfSquareAnnotation.prototype._initialize = function (page, dictionary) {
_super.prototype._initialize.call(this, page, dictionary);
};
/**
* Finalizes the annotation setup: validates bounds, ensures BS/color defaults, optionally creates appearance or measure appearance,
* updates Rect, and writes BE for cloudy borders.
*
* @private
* @param {boolean} isFlatten True if invoked during flattening.
* @returns {void} nothing.
*/
PdfSquareAnnotation.prototype._postProcess = function (isFlatten) {
if (typeof this.bounds === 'undefined' || this.bounds === null) {
throw new Error('Bounds cannot be null or undefined');
}
var borderWidth;
if (this._dictionary.has('BS')) {
borderWidth = this.border.width;
}
else {
var dictionary = new _PdfDictionary(this._crossReference);
dictionary.set('Type', _PdfName.get('Border'));
this._dictionary.set('BS', dictionary);
}
if (!this._dictionary.has('C')) {
this.color = { r: 0, g: 0, b: 0 };
this._isTransparentColor = true;
}
if (typeof borderWidth === 'undefined') {
borderWidth = 1;
}
if (this._measure) {
this._appearanceTemplate = this._createSquareMeasureAppearance(isFlatten);
}
else {
if (this._setAppearance || (isFlatten && !this._dictionary.has('AP')) || this._customTemplate.size > 0) {
this._appearanceTemplate = this._createRectangleAppearance(this.borderEffect);
}
this._dictionary.update('Rect', _updateBounds(this));
if (typeof this._intensity === 'undefined' &&
typeof this._borderEffect !== 'undefined' &&
this._borderEffect.style === PdfBorderEffectStyle.cloudy) {
var dictionary = new _PdfDictionary(this._crossReference);
dictionary.set('I', this.borderEffect._intensity);
if (this.borderEffect._style === PdfBorderEffectStyle.cloudy) {
dictionary.set('S', _PdfName.get('C'));
}
this._dictionary.update('BE', dictionary);
}
}
};
/**
* Creates or imports the rectangles appearance stream based on state or flattening needs, handles pop-up flattening, and updates AP entries accordingly.
*
* @private
* @param {boolean} [isFlatten=false] True if flattening is requested.
* @returns {void} nothing.
*/
PdfSquareAnnotation.prototype._doPostProcess = function (isFlatten) {
if (isFlatten === void 0) { isFlatten = false; }
if (this._isLoaded) {
if (this._setAppearance || this._customTemplate.size > 0 || (isFlatten && !this._dictionary.has('AP'))) {
if (this._dictionary.has('Measure')) {
this._appearanceTemplate = this._createSquareMeasureAppearance(isFlatten);
}
else {
this._appearanceTemplate = this._createRectangleAppearance(this.borderEffect);
}
}
if (!this._appearanceTemplate && isFlatten && this._dictionary.has('AP')) {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
var appearanceStream = dictionary.get('N');
var reference = dictionary.getRaw('N');
if (appearanceStream) {
if (reference) {
appearanceStream.reference = reference;
}
this._appearanceTemplate = new PdfTemplate(appearanceStream, this._crossReference);
}
}
}
}
else {
this._postProcess(isFlatten);
if (!this._appearanceTemplate && isFlatten) {
if (!this._dictionary.has('AP')) {
this._appearanceTemplate = this._createRectangleAppearance(this.borderEffect);
}
else {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
var appearanceStream = dictionary.get('N');
var reference = dictionary.getRaw('N');
if (appearanceStream) {
if (reference) {
appearanceStream.reference = reference;
}
this._appearanceTemplate = new PdfTemplate(appearanceStream, this._crossReference);
}
}
}
}
}
if (typeof this.flattenPopups !== 'undefined' && this.flattenPopups && !this.measure) {
if (this._isLoaded && !this._dictionary.has('Measure')) {
this._flattenLoadedPopUp();
}
else {
this._flattenPopUp();
}
}
if (isFlatten) {
if (this._appearanceTemplate) {
var isNormalMatrix = this._validateTemplateMatrix(this._appearanceTemplate._content.dictionary);
this._flattenAnnotationTemplate(this._appearanceTemplate, isNormalMatrix);
}
else {
this._page.annotations.remove(this);
}
}
else if (this._setAppearance || this._customTemplate.size > 0) {
var appearance = void 0;
var crossReference = this._crossReference;
if (this._dictionary.has('AP')) {
appearance = this._dictionary.get('AP');
}
else {
var reference = crossReference._getNextReference();
appearance = new _PdfDictionary(this._crossReference);
appearance._updated = true;
crossReference._cacheMap.set(reference, appearance);
this._dictionary.update('AP', reference);
}
if (this._customTemplate.size > 0) {
this._drawCustomAppearance(appearance);
}
else {
_removeDuplicateReference(appearance, crossReference, 'N');
var reference = crossReference._getNextReference();
this._appearanceTemplate._content.dictionary._update = true;
this._appearanceTemplate._content.reference = reference;
crossReference._cacheMap.set(reference, this._appearanceTemplate._content);
appearance.update('N', reference);
}
}
};
/**
* Creates the measured square appearance template, draws the rectangle and caption with area in the configured unit,
* and updates related dictionary entries.
*
* @private
* @param {boolean} _isFlatten True if flattening is requested.
* @returns {PdfTemplate} template Appearance template.
*/
PdfSquareAnnotation.prototype._createSquareMeasureAppearance = function (_isFlatten) {
var borderWidth = this.border.width;
var font = this._obtainFont();
if ((typeof font === 'undefined' || font === null) || (!this._isLoaded && font.size === 1)) {
font = this._circleCaptionFont;
this._pdfFont = font;
}
var area = this._calculateAreaOfSquare();
var format = new PdfStringFormat(PdfTextAlignment.center, PdfVerticalAlignment.middle);
var str = area.toFixed(2) + ' sq ' + this._unitString;
var fontsize = font.measureString(str, { width: 0, height: 0 }, format, 0, 0);
var borderPen = new PdfPen(this.color, borderWidth);
var backBrush;
if (this.innerColor) {
backBrush = new PdfBrush(this._innerColor);
}
var nativeRectangle = [this.bounds.x,
(this.bounds.y + this.bounds.height),
this.bounds.width,
this.bounds.height];
var template;
if (this._customTemplate.has('N')) {
template = this._customTemplate.get('N');
var nativeRectangle1 = [this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height];
var size = this._page.size;
var bounds = this.bounds;
nativeRectangle1[1] = size.height - (bounds.y + bounds.height);
nativeRectangle1[2] = (bounds.x + bounds.width);
nativeRectangle1[3] = size.height - bounds.y;
if (this._isBounds) {
nativeRectangle = nativeRectangle1;
}
if (this._page._isNew && this._page._pageSettings) {
nativeRectangle1 = _updateBounds(this);
}
this._dictionary.update('Rect', [nativeRectangle1[0], nativeRectangle1[1], nativeRectangle1[2], nativeRectangle1[3]]);
}
else {
var appearance = new PdfAppearance({ x: this.bounds.x, y: this.bounds.y, width: this.bounds.width,
height: this.bounds.height }, this);
nativeRectangle[1] = nativeRectangle[1] - nativeRectangle[3];
appearance.normal = new PdfTemplate(nativeRectangle, this._crossReference);
template = appearance.normal;
var parameter = new _PaintParameter();
template._writeTransformation = false;
var graphics = appearance.normal.graphics;
var width = borderWidth / 2;
parameter.borderPen = borderPen;
parameter.backBrush = backBrush;
parameter.foreBrush = new PdfBrush(this.color);
var rect = [nativeRectangle[0],
-nativeRectangle[1] - nativeRectangle[3],
nativeRectangle[2],
nativeRectangle[3]];
graphics.drawRectangle({ x: rect[0] + width,
y: rect[1] + width,
width: rect[2] - borderWidth,
height: rect[3] - borderWidth }, new PdfPen(this.color, this.border.width));
graphics.save();
graphics.translateTransform({ x: nativeRectangle[0], y: -nativeRectangle[1] });
var x = (nativeRectangle[2] / 2) - (fontsize.width / 2);
var y = (nativeRectangle[3] / 2) - (fontsize.height / 2);
graphics.translateTransform({ x: x, y: -y - font._getHeight() });
graphics.drawString((area.toFixed(2) + ' sq ' + this._unitString), font, { x: 0, y: 0, width: 0, height: 0 }, null, parameter.foreBrush);
graphics.restore();
if ((typeof _isFlatten !== 'undefined' && !_isFlatten) || !this._isLoaded) {
if (this._dictionary.has('AP')) {
_removeDuplicateReference(this._dictionary.get('AP'), this._crossReference, 'N');
}
var dic = new _PdfDictionary();
var tem = graphics._template._content;
tem.dictionary._updated = true;
var ref = this._crossReference._getNextReference();
this._crossReference._cacheMap.set(ref, tem);
graphics._template._content.reference = ref;
dic.set('N', ref);
dic._updated = true;
this._dictionary.set('AP', dic);
var nativeRectangle1 = [this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height];
var size = this._page.size;
nativeRectangle1[1] = size.height - (this.bounds.y + this.bounds.height);
nativeRectangle1[2] = (this.bounds.x + this.bounds.width);
nativeRectangle1[3] = size.height - this.bounds.y;
if (this._isBounds) {
nativeRectangle = nativeRectangle1;
}
if (this._page._isNew && this._page._pageSettings) {
nativeRectangle1 = _updateBounds(this);
}
this._dictionary.update('Rect', [nativeRectangle1[0], nativeRectangle1[1], nativeRectangle1[2], nativeRectangle1[3]]);
if (this._dictionary.has('Measure')) {
_removeDuplicateReference(this._dictionary, this._crossReference, 'Measure');
}
var reference = this._crossReference._getNextReference();
var measureDictionary = this._createMeasureDictionary(this._unitString);
this._crossReference._cacheMap.set(reference, measureDictionary);
measureDictionary._updated = true;
this._dictionary.update('Measure', reference);
var ds = 'font:' +
font._metrics._postScriptName +
' ' +
font._size +
'pt; color:' +
this._colorToHex([this.color.r, this.color.g, this.color.b]);
this._dictionary.update('DS', ds);
if (this._text && this._text !== '') {
this._dictionary.update('Contents', this._text + ' ' + area.toFixed(2) + ' sq ' + this._unitString);
}
else {
this._dictionary.update('Contents', area.toFixed(2) + ' sq ' + this._unitString);
}
this._dictionary.update('Subject', ('Area Measurement'));
if (typeof this.subject === 'undefined') {
this._dictionary.update('Subject', ('Area Measurement'));
}
this._dictionary.update('MeasurementTypes', 129);
this._dictionary.update('Subtype', new _PdfName('Square'));
this._dictionary.update('IT', new _PdfName('SquareDimension'));
var elements = this._dictionary.getArray('Rect');
var vertices = new Array(elements.length * 2);
vertices[0] = elements[0];
vertices[1] = elements[3];
vertices[2] = elements[0];
vertices[3] = elements[1];
vertices[4] = elements[2];
vertices[5] = elements[1];
vertices[6] = elements[2];
vertices[7] = elements[3];
this._dictionary.update('Vertices', vertices);
}
}
return template;
};
/**
* Computes the square/rectangle area in the configured measurement unit by converting width/height from points and returning the numeric area.
*
* @private
* @returns {number} area Area in the configured unit.
*/
PdfSquareAnnotation.prototype._calculateAreaOfSquare = function () {
var area;
var converter = new _PdfUnitConvertor();
var value;
if (this.bounds.width === this.bounds.height) {
value = this._getEqualPdfGraphicsUnit(this.unit, this._unitString);
this._unitString = value.unitString;
var width = converter._convertUnits(this.bounds.width, _PdfGraphicsUnit.point, value.graphicsUnit);
area = width * width;
}
else {
value = this._getEqualPdfGraphicsUnit(this.unit, this._unitString);
this._unitString = value.unitString;
var width = converter._convertUnits(this.bounds.width, _PdfGraphicsUnit.point, value.graphicsUnit);
value = this._getEqualPdfGraphicsUnit(this.unit, this._unitString);
this._unitString = value.unitString;
var height = converter._convertUnits(this.bounds.height, _PdfGraphicsUnit.point, value.graphicsUnit);
area = width * height;
}
return area;
};
return PdfSquareAnnotation;
}(PdfComment));
export { PdfSquareAnnotation };
/**
* `PdfRectangleAnnotation` class represents the rectangle annotation objects.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Create a new square annotation with bounds
* const annotation: PdfRectangleAnnotation = new PdfRectangleAnnotation({x: 10, y: 10, width: 200, height: 100});
* // Add annotation to the page
* page.annotations.add(annotation);
* // Destroy the document
* document.destroy();
* ```
*/
var PdfRectangleAnnotation = /** @class */ (function (_super) {
__extends(PdfRectangleAnnotation, _super);
function PdfRectangleAnnotation(bounds, properties) {
var _this = _super.call(this) || this;
_this._dictionary = new _PdfDictionary();
_this._dictionary.update('Type', _PdfName.get('Annot'));
_this._dictionary.update('Subtype', _PdfName.get('Square'));
if (bounds !== null && typeof bounds !== 'undefined' && typeof bounds.x !== 'undefined' && typeof bounds.y !== 'undefined' && typeof bounds.width !== 'undefined' && typeof bounds.height !== 'undefined') {
_this.bounds = bounds;
}
_this._type = _PdfAnnotationType.rectangleAnnotation;
if (properties) {
if ('text' in properties && _isNullOrUndefined(properties.text)) {
_this.text = properties.text;
}
if ('author' in properties && _isNullOrUndefined(properties.author)) {
_this.author = properties.author;
}
if ('subject' in properties && _isNullOrUndefined(properties.subject)) {
_this.subject = properties.subject;
}
if ('color' in properties && _isNullOrUndefined(properties.color)) {
_this.color = properties.color;
}
if ('innerColor' in properties && _isNullOrUndefined(properties.innerColor)) {
_this.innerColor = properties.innerColor;
}
if ('opacity' in properties && _isNullOrUndefined(properties.opacity)) {
_this.opacity = properties.opacity;
}
if ('border' in properties && _isNullOrUndefined(properties.border)) {
_this.border = properties.border;
}
}
return _this;
}
Object.defineProperty(PdfRectangleAnnotation.prototype, "borderEffect", {
/**
* Gets the border effect of the rectangle annotation.
*
* @returns {PdfBorderEffect} Border effect.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfRectangleAnnotation = page.annotations.at(0) as PdfRectangleAnnotation;
* // Gets the border effect of the rectangle annotation.
* let borderEffect: PdfBorderEffect = annotation.borderEffect;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._borderEffect === 'undefined') {
var value = new PdfBorderEffect();
value._dictionary = this._dictionary;
if (this._dictionary.has('BE')) {
var dictionary = this._dictionary.get('BE');
value._intensity = dictionary.get('I');
value._style = _mapBorderEffectStyle(dictionary.get('S').name);
}
else {
value._style = PdfBorderEffectStyle.solid;
}
this._borderEffect = value;
}
return this._borderEffect;
},
/**
* Sets the border effect of the rectangle annotation.
*
* @param {PdfBorderEffect} value Border effect.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfRectangleAnnotation = page.annotations.at(0) as PdfRectangleAnnotation;
* // Sets the border effect of rectangle annotation.
* annotation. borderEffect.style = PdfBorderEffectStyle.cloudy;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (typeof value !== 'undefined') {
this._borderEffect = value;
}
},
enumerable: true,
configurable: true
});
/**
* Loads a rectangle annotation from the given page and dictionary, marks it as loaded, and initializes internal state.
*
* @private
* @param {PdfPage} page Page containing the annotation.
* @param {_PdfDictionary} dictionary Source annotation dictionary.
* @returns {PdfRectangleAnnotation} annot Loaded rectangle annotation.
*/
PdfRectangleAnnotation._load = function (page, dictionary) {
var annot = new PdfRectangleAnnotation();
annot._isLoaded = true;
annot._initialize(page, dictionary);
return annot;
};
/**
* Initializes the annotation for the specified page and optional source dictionary by delegating to the base initializer.
*
* @private
* @param {PdfPage} page Owning page.
* @param {_PdfDictionary} [dictionary] Optional source dictionary.
* @returns {void} nothing.
*/
PdfRectangleAnnotation.prototype._initialize = function (page, dictionary) {
_super.prototype._initialize.call(this, page, dictionary);
};
/**
* Finalizes setup after creation or load: validates bounds, ensures BS/color defaults, updates Rect,
* creates appearance when needed, and writes BE for cloudy borders.
*
* @private
* @param {boolean} isFlatten True if invoked during flattening.
* @returns {void} nothing.
*/
PdfRectangleAnnotation.prototype._postProcess = function (isFlatten) {
if (typeof this.bounds === 'undefined' || this.bounds === null) {
throw new Error('Bounds cannot be null or undefined');
}
var borderWidth;
if (this._dictionary.has('BS')) {
borderWidth = this.border.width;
}
else {
var dic = new _PdfDictionary(this._crossReference);
dic.set('Type', _PdfName.get('Border'));
this._dictionary.set('BS', dic);
}
if (!this._dictionary.has('C')) {
this.color = { r: 0, g: 0, b: 0 };
this._isTransparentColor = true;
}
if (typeof borderWidth === 'undefined') {
borderWidth = 1;
}
this._dictionary.update('Rect', _updateBounds(this));
if (this._setAppearance || this._customTemplate.size > 0 || (isFlatten && !this._dictionary.has('AP'))) {
this._appearanceTemplate = this._createRectangleAppearance(this.borderEffect);
}
if (typeof this._intensity === 'undefined' &&
typeof this._borderEffect !== 'undefined' &&
this._borderEffect.style === PdfBorderEffectStyle.cloudy) {
var dic = new _PdfDictionary(this._crossReference);
dic.set('I', this.borderEffect._intensity);
if (this.borderEffect._style === PdfBorderEffectStyle.cloudy) {
dic.set('S', _PdfName.get('C'));
}
this._dictionary.update('BE', dic);
}
};
/**
* Creates or imports the rectangle appearance based on state or flattening, optionally flattens (and pop-ups), and updates AP entries accordingly.
*
* @private
* @param {boolean} [isFlatten=false] True if flattening is requested.
* @returns {void} nothing.
*/
PdfRectangleAnnotation.prototype._doPostProcess = function (isFlatten) {
if (isFlatten === void 0) { isFlatten = false; }
if (this._isLoaded) {
if (this._setAppearance || this._customTemplate.size > 0 || (isFlatten && !this._dictionary.has('AP'))) {
this._appearanceTemplate = this._createRectangleAppearance(this.borderEffect);
}
if (!this._appearanceTemplate && isFlatten && this._dictionary.has('AP')) {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
var appearanceStream = dictionary.get('N');
var reference = dictionary.getRaw('N');
if (appearanceStream) {
if (reference) {
appearanceStream.reference = reference;
}
this._appearanceTemplate = new PdfTemplate(appearanceStream, this._crossReference);
}
}
}
}
else {
this._postProcess(isFlatten);
if (!this._appearanceTemplate && isFlatten) {
if (!this._dictionary.has('AP')) {
this._appearanceTemplate = this._createRectangleAppearance(this.borderEffect);
}
else {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
var appearanceStream = dictionary.get('N');
var reference = dictionary.getRaw('N');
if (appearanceStream) {
if (reference) {
appearanceStream.reference = reference;
}
this._appearanceTemplate = new PdfTemplate(appearanceStream, this._crossReference);
}
}
}
}
}
if (typeof this.flattenPopups !== 'undefined' && this.flattenPopups) {
if (this._isLoaded) {
this._flattenLoadedPopUp();
}
else {
this._flattenPopUp();
}
}
if (isFlatten) {
if (this._appearanceTemplate) {
var isNormalMatrix = this._validateTemplateMatrix(this._appearanceTemplate._content.dictionary);
if (isNormalMatrix && this._page && this._page.rotation !== PdfRotationAngle.angle0 ||
this._isValidTemplateMatrix(this._appearanceTemplate._content.dictionary, this.bounds, this._appearanceTemplate)) {
this._flattenAnnotationTemplate(this._appearanceTemplate, isNormalMatrix);
}
}
else {
this._page.annotations.remove(this);
}
}
else if (this._setAppearance || this._customTemplate.size > 0) {
var appearance = void 0;
if (this._dictionary.has('AP')) {
appearance = this._dictionary.get('AP');
}
else {
var reference = this._crossReference._getNextReference();
appearance = new _PdfDictionary(this._crossReference);
this._crossReference._cacheMap.set(reference, appearance);
this._dictionary.update('AP', reference);
}
if (this._customTemplate.size > 0) {
this._drawCustomAppearance(appearance);
}
else {
_removeDuplicateReference(appearance, this._crossReference, 'N');
var reference = this._crossReference._getNextReference();
this._crossReference._cacheMap.set(reference, this._appearanceTemplate._content);
appearance.update('N', reference);
}
}
};
/* eslint-disable */
/**
* Verifies whether the templates Matrix/BBox align with the target bounds; if misaligned,
* draws the template directly and removes the annotation.
*
* @private
* @param {_PdfDictionary} dictionary Appearance stream dictionary.
* @param {any} bounds Target bounds on page.
* @param {PdfTemplate} appearanceTemplate Template to draw if misaligned.
* @returns {boolean} isValidMatrix True if matrix is valid; false if drawn & removed.
*/
PdfRectangleAnnotation.prototype._isValidTemplateMatrix = function (dictionary, bounds, appearanceTemplate) {
var isValidMatrix = true;
var pointF = bounds;
if (dictionary && dictionary.has('Matrix')) {
var box = dictionary.getArray('BBox');
var matrix = dictionary.getArray('Matrix');
if (matrix && box && matrix.length > 3 && box.length > 2) {
if (typeof matrix[0] !== 'undefined' &&
typeof matrix[1] !== 'undefined' &&
typeof matrix[2] !== 'undefined' &&
typeof matrix[3] !== 'undefined') {
if (matrix[0] === 1 && matrix[1] === 0 && matrix[2] === 0 && matrix[3] === 1) {
if (typeof box[0] !== 'undefined' &&
typeof box[1] !== 'undefined' &&
typeof box[2] !== 'undefined' &&
typeof box[3] !== 'undefined') {
if (Math.round(box[0]) !== Math.round(-(matrix[4])) && Math.round(box[1]) !== Math.round(-(matrix[5])) ||
box[0] === 0 && Math.round(-(matrix[4])) === 0) {
var graphics = this._page.graphics;
var state = graphics.save();
if (typeof this.opacity !== 'undefined' && this._opacity < 1) {
graphics.setTransparency(this._opacity);
}
pointF.x -= box[0];
pointF.y += box[1];
graphics.drawTemplate(appearanceTemplate, pointF);
graphics.restore(state);
this._page.annotations.remove(this);
isValidMatrix = false;
}
}
}
}
}
}
return isValidMatrix;
};
return PdfRectangleAnnotation;
}(PdfComment));
export { PdfRectangleAnnotation };
/**
* `PdfPolygonAnnotation` class represents the polygon annotation objects.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Create a new polygon annotation with bounds
* const annotation: PdfPolygonAnnotation = new PdfPolygonAnnotation([{x: 100, y: 300}, {x: 150, y: 200}, {x: 300, y: 200}, {x: 350, y: 300}, {x: 300, y: 400}, {x: 150, y: 400}]);
* // Add annotation to the page
* page.annotations.add(annotation);
* // Destroy the document
* document.destroy();
* ```
*/
var PdfPolygonAnnotation = /** @class */ (function (_super) {
__extends(PdfPolygonAnnotation, _super);
function PdfPolygonAnnotation(points, properties) {
var _this = _super.call(this) || this;
_this._dictionary = new _PdfDictionary();
_this._dictionary.update('Type', _PdfName.get('Annot'));
_this._dictionary.update('Subtype', _PdfName.get('Polygon'));
if (typeof points !== 'undefined') {
_this._points = points;
}
_this._type = _PdfAnnotationType.polygonAnnotation;
if (properties) {
if ('text' in properties && _isNullOrUndefined(properties.text)) {
_this.text = properties.text;
}
if ('author' in properties && _isNullOrUndefined(properties.author)) {
_this.author = properties.author;
}
if ('subject' in properties && _isNullOrUndefined(properties.subject)) {
_this.subject = properties.subject;
}
if ('color' in properties && _isNullOrUndefined(properties.color)) {
_this.color = properties.color;
}
if ('innerColor' in properties && _isNullOrUndefined(properties.innerColor)) {
_this.innerColor = properties.innerColor;
}
if ('opacity' in properties && _isNullOrUndefined(properties.opacity)) {
_this.opacity = properties.opacity;
}
if ('border' in properties && _isNullOrUndefined(properties.border)) {
_this.border = properties.border;
}
}
return _this;
}
Object.defineProperty(PdfPolygonAnnotation.prototype, "borderEffect", {
/**
* Gets the border effect of the polygon annotation.
*
* @returns {PdfBorderEffect} Border effect.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfPolygonAnnotation = page.annotations.at(0) as PdfPolygonAnnotation;
* // Gets the border effect of the polygon annotation.
* let borderEffect: PdfBorderEffect = annotation.borderEffect;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._borderEffect === 'undefined') {
var value = new PdfBorderEffect();
value._dictionary = this._dictionary;
if (this._dictionary.has('BE')) {
var dictionary = this._dictionary.get('BE');
value._intensity = dictionary.get('I');
value._style = _mapBorderEffectStyle(dictionary.get('S').name);
}
else {
value._style = PdfBorderEffectStyle.solid;
}
this._borderEffect = value;
}
return this._borderEffect;
},
/**
* Sets the border effect of the polygon annotation.
*
* @param {PdfBorderEffect} value Border effect.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfPolygonAnnotation = page.annotations.at(0) as PdfPolygonAnnotation;
* // Sets the border effect of the polygon annotation
* annotation.borderEffect = new PdfBorderEffect(style: PdfBorderEffectStyle.cloudy);
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (typeof value !== 'undefined') {
this._borderEffect = value;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfPolygonAnnotation.prototype, "lineExtension", {
/**
* Gets the line extension of the polygon annotation.
*
* @returns {number} Line extension.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfPolygonAnnotation = page.annotations.at(0) as PdfPolygonAnnotation;
* // Gets the line extension of the polygon annotation
* let lineExtension: number = annotation.lineExtension;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._lineExtension === 'undefined' && this._dictionary.has('LLE')) {
var lineExt = this._dictionary.get('LLE');
if (typeof lineExt !== 'undefined' && lineExt >= 0) {
this._lineExtension = lineExt;
}
}
return this._lineExtension;
},
/**
* Sets the line extension of the polygon annotation.
*
* @param {number} value Line extension.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfPolygonAnnotation = page.annotations.at(0) as PdfPolygonAnnotation;
* // Sets the line extension of the polygon annotation
* annotation.lineExtension = 5;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (!Number.isNaN(value)) {
if (value >= 0) {
this._dictionary.update('LLE', value);
this._lineExtension = value;
}
else {
throw new Error('LineExtension should be non negative number');
}
}
},
enumerable: true,
configurable: true
});
/**
* Loads a polygon annotation from the given page and dictionary, marks it as loaded, and initializes internal state.
*
* @private
* @param {PdfPage} page The page containing the annotation.
* @param {_PdfDictionary} dictionary The source annotation dictionary.
* @returns {PdfPolygonAnnotation} annot The loaded polygon annotation.
*/
PdfPolygonAnnotation._load = function (page, dictionary) {
var annot = new PdfPolygonAnnotation();
annot._isLoaded = true;
annot._initialize(page, dictionary);
return annot;
};
/**
* Initializes the polygon annotation for the specified page and optional source dictionary by delegating to the base initializer.
*
* @private
* @param {PdfPage} page The page to associate with this annotation.
* @param {_PdfDictionary} [dictionary] Optional source dictionary to load from.
* @returns {void} void No return value.
*/
PdfPolygonAnnotation.prototype._initialize = function (page, dictionary) {
_super.prototype._initialize.call(this, page, dictionary);
};
/**
* Finalizes setup: validates input points, ensures defaults (line extension, color, border), normalizes points with Crop/MediaBox,
* updates Rect/Vertices, and creates appearance when needed.
*
* @private
* @param {boolean} isFlatten Whether the annotation is being flattened.
* @returns {void} void No return value.
*/
PdfPolygonAnnotation.prototype._postProcess = function (isFlatten) {
if (typeof this._points === 'undefined' || this._points === null) {
throw new Error('Points cannot be null or undefined');
}
if (!this._dictionary.has('LLE')) {
this.lineExtension = 0;
}
if (!this._dictionary.has('C')) {
this.color = { r: 0, g: 0, b: 0 };
this._isTransparentColor = true;
}
var borderWidth;
if (this._dictionary.has('BS')) {
borderWidth = this.border.width;
}
else {
var dic = new _PdfDictionary(this._crossReference);
dic.set('Type', _PdfName.get('Border'));
this._dictionary.set('BS', dic);
}
if (typeof borderWidth === 'undefined') {
borderWidth = 1;
}
var array = [];
array.push.apply(array, this._points);
this._points = this._getPoints(this._points);
if (array[0] !== array[array.length - 2] || array[1] !== array[array.length - 1]) {
this._points.push(this._points[0]);
}
var flatData = _convertPointToNumberArray(this._points);
var polygonBounds = this._getBoundsValue(flatData);
var bounds = [polygonBounds.x,
polygonBounds.y,
polygonBounds.x + polygonBounds.width,
polygonBounds.y + polygonBounds.height];
this._dictionary.update('Rect', bounds);
this._dictionary.update('LLE', this._lineExtension);
if (this._setAppearance || (isFlatten && !this._dictionary.has('AP')) || this._customTemplate.size > 0) {
this._appearanceTemplate = this._createPolygonAppearance(isFlatten);
}
var data = _convertPointToNumberArray(this._points);
this._dictionary.update('Vertices', data);
if (typeof this._intensity === 'undefined' &&
typeof this._borderEffect !== 'undefined' &&
this._borderEffect.style === PdfBorderEffectStyle.cloudy) {
var dic = new _PdfDictionary(this._crossReference);
dic.set('I', this.borderEffect._intensity);
if (this.borderEffect._style === PdfBorderEffectStyle.cloudy) {
dic.set('S', _PdfName.get('C'));
}
this._dictionary.update('BE', dic);
}
};
/**
* Builds or imports the polygon appearance depending on state, optionally flattens and normalizes the template matrix,
* and updates AP entries as required.
*
* @private
* @param {boolean} [isFlatten=false] Whether to flatten the annotation.
* @returns {void} void No return value.
*/
PdfPolygonAnnotation.prototype._doPostProcess = function (isFlatten) {
if (isFlatten === void 0) { isFlatten = false; }
this._flatten = isFlatten;
if (this._isLoaded) {
if (this._setAppearance || this._customTemplate.size > 0 || (isFlatten && !this._dictionary.has('AP'))) {
this._appearanceTemplate = this._createPolygonAppearance(isFlatten);
}
if (!this._appearanceTemplate && isFlatten && this._dictionary.has('AP')) {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
var appearanceStream = dictionary.get('N');
var reference = dictionary.getRaw('N');
if (appearanceStream) {
if (reference) {
appearanceStream.reference = reference;
}
this._appearanceTemplate = new PdfTemplate(appearanceStream, this._crossReference);
}
}
}
}
else {
this._postProcess(isFlatten);
if (!this._appearanceTemplate && isFlatten) {
if (this._dictionary.has('AP')) {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
var appearanceStream = dictionary.get('N');
var reference = dictionary.getRaw('N');
if (appearanceStream) {
if (reference) {
appearanceStream.reference = reference;
}
this._appearanceTemplate = new PdfTemplate(appearanceStream, this._crossReference);
}
}
}
}
}
if (typeof this.flattenPopups !== 'undefined' && this.flattenPopups) {
if (this._isLoaded) {
this._flattenLoadedPopUp();
}
}
if (isFlatten) {
if (this._appearanceTemplate) {
var isNormalMatrix = this._validateTemplateMatrix(this._appearanceTemplate._content.dictionary);
if (!this._appearanceTemplate._content.dictionary.has('Matrix')) {
var box = this._appearanceTemplate._content.dictionary.getArray('BBox');
if (box && box.length >= 2) {
this._appearanceTemplate._content.dictionary.update('Matrix', [1, 0, 0, 1, -box[0], -box[1]]);
}
}
this._flattenAnnotationTemplate(this._appearanceTemplate, isNormalMatrix);
}
else {
this._page.annotations.remove(this);
}
}
else if (this._setAppearance || this._customTemplate.size > 0) {
var appearance = void 0;
if (this._dictionary.has('AP')) {
appearance = this._dictionary.get('AP');
}
else {
var reference = this._crossReference._getNextReference();
appearance = new _PdfDictionary(this._crossReference);
appearance._updated = true;
this._crossReference._cacheMap.set(reference, appearance);
this._dictionary.update('AP', reference);
}
if (this._customTemplate.size > 0) {
this._drawCustomAppearance(appearance);
}
else {
_removeDuplicateReference(appearance, this._crossReference, 'N');
var reference = this._crossReference._getNextReference();
this._appearanceTemplate._content.dictionary._update = true;
this._appearanceTemplate._content.reference = reference;
this._crossReference._cacheMap.set(reference, this._appearanceTemplate._content);
appearance.update('N', reference);
}
}
};
/**
* Creates the polygon appearance template; when flattening, draws directly to the page (optionally with cloudy border),
* otherwise builds a normal appearance with rotation and transparency handling.
*
* @private
* @param {boolean} flatten Whether to build a flattening appearance.
* @returns {PdfTemplate} template The created or imported appearance template.
*/
PdfPolygonAnnotation.prototype._createPolygonAppearance = function (flatten) {
if (typeof flatten !== 'undefined' && flatten) {
var template = void 0;
if (this._customTemplate.has('N')) {
template = this._customTemplate.get('N');
var flatData = _convertPointToNumberArray(this._points);
var polygonBounds = this._getBoundsValue(flatData);
this.bounds = { x: polygonBounds.x,
y: this._page.size.height - polygonBounds.y,
width: polygonBounds.width,
height: polygonBounds.height };
}
else {
var borderPen = void 0;
if (this.color && this.border.width > 0) {
borderPen = new PdfPen(this.color, this.border.width);
}
var backgroundBrush = void 0;
if (this.innerColor) {
backgroundBrush = new PdfBrush(this.innerColor);
}
var graphics = this._page.graphics;
if (borderPen || backgroundBrush) {
var state = void 0;
if (typeof this.opacity !== 'undefined' && this._opacity < 1) {
state = graphics.save();
graphics.setTransparency(this._opacity);
}
if (this.borderEffect.intensity !== 0 && this.borderEffect.style === PdfBorderEffectStyle.cloudy) {
var radius = this.borderEffect.intensity * 4 + 0.5 * this.border.width;
var graphicsPath = new PdfPath();
graphicsPath.addPolygon(this._getLinePoints());
this._drawCloudStyle(graphics, backgroundBrush, borderPen, radius, 0.833, graphicsPath._points, false);
}
else {
graphics.drawPolygon(this._getLinePoints(), borderPen, backgroundBrush);
}
if (typeof this.opacity !== 'undefined' && this._opacity < 1) {
graphics.restore(state);
}
}
template = graphics._template;
}
return template;
}
else {
var boundsValue = void 0;
var rect = { x: 0, y: 0, width: 0, height: 0 };
if (typeof this._points === 'undefined' && this._dictionary.has('Vertices')) {
var data = this._dictionary.get('Vertices');
this._points = _convertToPoints(data);
boundsValue = this._getBoundsValue(data);
}
else {
var data = _convertPointToNumberArray(this._points);
boundsValue = this._getBoundsValue(data);
}
if (typeof this._borderEffect !== 'undefined' &&
typeof this.borderEffect.intensity !== 'undefined' && this.borderEffect.intensity !== 0 &&
this._borderEffect.style === PdfBorderEffectStyle.cloudy) {
rect.x = boundsValue.x - (this.borderEffect.intensity * 5) - this.border.width;
rect.y = boundsValue.y - (this.borderEffect.intensity * 5) - this.border.width;
rect.width = boundsValue.width + (this.borderEffect.intensity * 10) + (2 * this.border.width);
rect.height = boundsValue.height + (this.borderEffect.intensity * 10) + (2 * this.border.width);
}
else {
rect.x = boundsValue.x - this.border.width;
rect.y = boundsValue.y - this.border.width;
rect.width = boundsValue.width + (2 * this.border.width);
rect.height = boundsValue.height + (2 * this.border.width);
}
var template = void 0;
if (this._customTemplate.has('N')) {
template = this._customTemplate.get('N');
}
else {
var appearance = new PdfAppearance({ x: rect.x, y: rect.y, width: rect.width, height: rect.height }, this);
appearance.normal = new PdfTemplate([rect.x, rect.y, rect.width, rect.height], this._crossReference);
template = appearance.normal;
_setMatrix(template, this._getRotationAngle());
template._writeTransformation = false;
var graphics = appearance.normal.graphics;
var parameter = new _PaintParameter();
if (this.innerColor) {
parameter.backBrush = new PdfBrush(this._innerColor);
}
if (this.border.width > 0 && this.color) {
parameter.borderPen = new PdfPen(this._color, this.border.width);
}
if (this.color) {
parameter.foreBrush = new PdfBrush(this._color);
}
if (typeof this.opacity !== 'undefined' && this._opacity < 1) {
graphics.save();
graphics.setTransparency(this._opacity);
}
else {
graphics.save();
}
if (_isNullOrUndefined(this.borderEffect) && _isNullOrUndefined(this.borderEffect.intensity) &&
this.borderEffect.intensity !== 0 && this.borderEffect.style === PdfBorderEffectStyle.cloudy) {
var radius = this.borderEffect.intensity * 4 + 0.5 * this.border.width;
var graphicsPath = new PdfPath();
graphicsPath.addPolygon(this._getLinePoints());
this._drawCloudStyle(graphics, parameter.backBrush, parameter.borderPen, radius, 0.833, graphicsPath._points, false);
}
else {
graphics.drawPolygon(this._getLinePoints(), parameter.borderPen, parameter.backBrush);
}
if (typeof this.opacity !== 'undefined' && this._opacity < 1) {
graphics.restore();
}
graphics.restore();
if (this._isBounds) {
template._content.dictionary._updated = true;
if (typeof this.lineExtension === 'number') {
this._dictionary.update('LLE', this.lineExtension);
}
var data = _convertPointToNumberArray(this._points);
this._dictionary.update('Vertices', data);
}
}
this._dictionary.update('Rect', [rect.x, rect.y, rect.x + rect.width, rect.y + rect.height]);
return template;
}
};
/**
* Returns the polygons points transformed into page or appearance space, accounting for page rotation, flattening, and Vertices storage.
*
* @private
* @returns {Point[]} polygonPointArray the transformed polygon points.
*/
PdfPolygonAnnotation.prototype._getLinePoints = function () {
var _this = this;
var polygonPoints;
var pageSize = this._page.size;
var pageHeight = pageSize.height;
var pageWidth = pageSize.width;
if (this._dictionary.has('Vertices') && !this._isBounds) {
var rotation = void 0;
if (this._page._pageDictionary.has('Rotate')) {
rotation = this._page._pageDictionary.get('Rotate');
}
var pageRotation = this._page.rotation;
if (this._page && pageRotation) {
if (pageRotation === PdfRotationAngle.angle90) {
rotation = 90;
}
else if (pageRotation === PdfRotationAngle.angle180) {
rotation = 180;
}
else if (pageRotation === PdfRotationAngle.angle270) {
rotation = 270;
}
}
var linePoints = this._dictionary.getArray('Vertices');
if (linePoints) {
var points = linePoints.slice();
polygonPoints = [];
for (var j = 0; j < points.length; j = j + 2) {
var yValue = this.flatten ? (pageHeight - points[j + 1]) : -points[j + 1];
polygonPoints.push([points[j], yValue]);
}
if (rotation) {
if (rotation === 270) {
polygonPoints.forEach(function (point) {
var x = point[0];
point[0] = point[1];
point[1] = pageWidth - x;
});
}
else if (rotation === 90) {
polygonPoints.forEach(function (point) {
var x = point[0];
if (_this._page._origin[1] !== 0) {
point[0] = pageHeight - (point[1] - pageHeight);
}
else {
point[0] = pageHeight - point[1];
}
point[1] = x;
});
}
else if (rotation === 180) {
polygonPoints.forEach(function (point) {
var x = point[0];
point[0] = pageWidth - x;
point[1] = pageHeight - point[1];
});
}
}
}
}
else if (this._points) {
var points = _convertPointToNumberArray(this._points);
polygonPoints = [];
for (var j = 0; j < points.length; j = j + 2) {
var yValue = this.flatten ? (pageHeight - points[j + 1]) : -points[j + 1];
polygonPoints.push([points[j], yValue]);
}
}
var polygonPointArray = _convertNumberArraysToPoints(polygonPoints);
return polygonPointArray;
};
return PdfPolygonAnnotation;
}(PdfComment));
export { PdfPolygonAnnotation };
/**
* `PdfPolyLineAnnotation` class represents the polyline annotation objects.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Create a new poly line annotation with bounds
* const annotation: PdfPolyLineAnnotation = new PdfPolyLineAnnotation ([{x: 100, y: 300}, {x: 180, y: 250}, {x: 300, y: 260}, {x: 360, y: 320}]);
* // Add annotation to the page
* page.annotations.add(annotation);
* // Destroy the document
* document.destroy();
* ```
*/
var PdfPolyLineAnnotation = /** @class */ (function (_super) {
__extends(PdfPolyLineAnnotation, _super);
function PdfPolyLineAnnotation(points, properties) {
var _this = _super.call(this) || this;
_this._beginLine = PdfLineEndingStyle.none;
_this._endLine = PdfLineEndingStyle.none;
_this._dictionary = new _PdfDictionary();
_this._dictionary.update('Type', _PdfName.get('Annot'));
_this._dictionary.update('Subtype', _PdfName.get('PolyLine'));
if (typeof points !== 'undefined') {
_this._points = points;
}
else {
_this._points = [];
}
_this._type = _PdfAnnotationType.polyLineAnnotation;
if (properties) {
if ('text' in properties && _isNullOrUndefined(properties.text)) {
_this.text = properties.text;
}
if ('author' in properties && _isNullOrUndefined(properties.author)) {
_this.author = properties.author;
}
if ('subject' in properties && _isNullOrUndefined(properties.subject)) {
_this.subject = properties.subject;
}
if ('color' in properties && _isNullOrUndefined(properties.color)) {
_this.color = properties.color;
}
if ('innerColor' in properties && _isNullOrUndefined(properties.innerColor)) {
_this.innerColor = properties.innerColor;
}
if ('lineEndingStyle' in properties && _isNullOrUndefined(properties.lineEndingStyle)) {
_this.beginLineStyle = properties.lineEndingStyle.begin;
_this.endLineStyle = properties.lineEndingStyle.end;
}
if ('opacity' in properties && _isNullOrUndefined(properties.opacity)) {
_this.opacity = properties.opacity;
}
if ('border' in properties && _isNullOrUndefined(properties.border)) {
_this.border = properties.border;
}
}
return _this;
}
Object.defineProperty(PdfPolyLineAnnotation.prototype, "beginLineStyle", {
/**
* Gets the begin line ending style of the annotation.
*
* @returns {PdfLineEndingStyle} Begin line ending style.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfPolyLineAnnotation = page.annotations.at(0) as PdfPolyLineAnnotation;
* // Gets the begin line ending style of the annotation.
* let beginLineStyle: PdfLineEndingStyle = annotation.beginLineStyle;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (this._dictionary.has('LE')) {
var lineStyles = this._dictionary.getArray('LE');
if (lineStyles && Array.isArray(lineStyles)) {
this._beginLine = _mapLineEndingStyle(lineStyles[0].name);
}
}
return this._beginLine;
},
/**
* Sets the begin line ending style of the annotation.
*
* @param {PdfLineEndingStyle} value Begin line ending style.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfPolyLineAnnotation = page.annotations.at(0) as PdfPolyLineAnnotation;
* // Sets the begin line ending style of the annotation.
* annotation.beginLineStyle = PdfLineEndingStyle.slash;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value !== this._beginLine) {
this._beginLine = value;
if (this._dictionary) {
var lineStyle = [];
lineStyle.push(_PdfName.get(_reverseMapEndingStyle(value)));
lineStyle.push(_PdfName.get(_reverseMapEndingStyle(this.endLineStyle)));
this._dictionary.update('LE', lineStyle);
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfPolyLineAnnotation.prototype, "endLineStyle", {
/**
* Gets the end line ending style of the annotation.
*
* @returns {PdfLineEndingStyle} End line ending style.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfPolyLineAnnotation = page.annotations.at(0) as PdfPolyLineAnnotation;
* // Gets the end line ending style of the annotation.
* let endLineStyle: PdfLineEndingStyle = annotation.endLineStyle;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (this._dictionary.has('LE')) {
var lineStyles = this._dictionary.getArray('LE');
if (lineStyles && Array.isArray(lineStyles)) {
this._endLine = _mapLineEndingStyle(lineStyles[1].name);
}
}
return this._endLine;
},
/**
* Sets the end line ending style of the annotation.
*
* @param {PdfLineEndingStyle} value End line ending style.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfPolyLineAnnotation = page.annotations.at(0) as PdfPolyLineAnnotation;
* // Sets the end line ending style of the annotation.
* annotation.endLineStyle = PdfLineEndingStyle.square;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value !== this._endLine) {
this._endLine = value;
if (this._dictionary) {
var lineStyle = [];
lineStyle.push(_PdfName.get(_reverseMapEndingStyle(this.beginLineStyle)));
lineStyle.push(_PdfName.get(_reverseMapEndingStyle(value)));
this._dictionary.update('LE', lineStyle);
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfPolyLineAnnotation.prototype, "lineExtension", {
/**
* Gets the line extension of the square annotation.
*
* @returns {number} Line extension.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfPolyLineAnnotation = page.annotations.at(0) as PdfPolyLineAnnotation;
* // Gets the line extension of annotation.
* let lineExtension: number = annotation.lineExtension;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._lineExtension === 'undefined' && this._dictionary.has('LLE')) {
var lineExt = this._dictionary.get('LLE');
if (typeof lineExt !== 'undefined' && lineExt >= 0) {
this._lineExtension = lineExt;
}
}
return this._lineExtension;
},
/**
* Sets the line extension of the square annotation.
*
* @param {number} value Line extension.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfPolyLineAnnotation = page.annotations.at(0) as PdfPolyLineAnnotation;
* // Sets the line extension of the annotation.
* annotation.lineExtension = 3;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (!Number.isNaN(value)) {
if (value >= 0) {
this._dictionary.update('LLE', value);
this._lineExtension = value;
}
else {
throw new Error('LineExtension should be non negative number');
}
}
},
enumerable: true,
configurable: true
});
/**
* Loads a polyline annotation from the given page and dictionary, marks it as loaded, and initializes internal state.
*
* @private
* @param {PdfPage} page The page that contains this annotation.
* @param {_PdfDictionary} dictionary The source annotation dictionary to load.
* @returns {PdfPolyLineAnnotation} annot The loaded polyline annotation instance.
*/
PdfPolyLineAnnotation._load = function (page, dictionary) {
var annot = new PdfPolyLineAnnotation();
annot._isLoaded = true;
annot._initialize(page, dictionary);
return annot;
};
/**
* Initializes the polyline annotation for the specified page and optional source dictionary by delegating to the base initializer.
*
* @private
* @param {PdfPage} page The page to associate with the annotation.
* @param {_PdfDictionary} [dictionary] Optional source dictionary for loading.
* @returns {void} void No return value.
*/
PdfPolyLineAnnotation.prototype._initialize = function (page, dictionary) {
_super.prototype._initialize.call(this, page, dictionary);
};
/**
* Finalizes setup by validating points, setting defaults for line extension, color, and border,
* computing bounds, updating dictionary entries, and generating appearance when required.
*
* @private
* @param {boolean} isFlatten Whether the annotation is being flattened.
* @returns {void} void No return value.
*/
PdfPolyLineAnnotation.prototype._postProcess = function (isFlatten) {
if (typeof this._points === 'undefined' || this._points === null) {
throw new Error('Points cannot be null or undefined');
}
if (!this._dictionary.has('LLE')) {
this.lineExtension = 0;
}
if (!this._dictionary.has('C')) {
this.color = { r: 0, g: 0, b: 0 };
this._isTransparentColor = true;
}
var borderWidth;
if (this._dictionary.has('BS')) {
borderWidth = this.border.width;
}
else {
var dictionary = new _PdfDictionary(this._crossReference);
dictionary.set('Type', _PdfName.get('Border'));
this._dictionary.set('BS', dictionary);
}
if (typeof borderWidth === 'undefined') {
borderWidth = 1;
}
var points = this._getLinePoints();
var pathTypes = [];
pathTypes.push(0);
for (var i = 1; i < points.length; i++) {
pathTypes.push(1);
}
this._polylinePoints = points;
this._pathTypes = pathTypes;
var path = new PdfPath();
path._points = points;
path._pathTypes = pathTypes;
var newPoints = [];
for (var _i = 0, _a = this._points; _i < _a.length; _i++) {
var pt = _a[_i];
newPoints.push(pt.x, pt.y);
}
this._dictionary.update('Vertices', newPoints);
var lineStyle = [];
lineStyle.push(_PdfName.get(_reverseMapEndingStyle(this.beginLineStyle)));
lineStyle.push(_PdfName.get(_reverseMapEndingStyle(this.endLineStyle)));
this._dictionary.update('LE', lineStyle);
this._dictionary.update('LLE', this._lineExtension);
var data = _convertPointToNumberArray(this._points);
var polyLineBounds = this._getBoundsValue(data);
var rectangle = [polyLineBounds.x,
polyLineBounds.y,
polyLineBounds.x + polyLineBounds.width,
polyLineBounds.y + polyLineBounds.height];
this._dictionary.update('Rect', rectangle);
if (this._setAppearance || (isFlatten && !this._dictionary.has('AP')) || this._customTemplate.size > 0) {
this._appearanceTemplate = this._createPolyLineAppearance(isFlatten);
}
};
/**
* Builds or imports the polyline appearance based on state, handles flattening logic,
* updates AP entries, and draws or replaces templates when needed.
*
* @private
* @param {boolean} [isFlatten=false] Whether to flatten the annotation to page content.
* @returns {void} void No return value.
*/
PdfPolyLineAnnotation.prototype._doPostProcess = function (isFlatten) {
if (isFlatten === void 0) { isFlatten = false; }
this._flatten = isFlatten;
if (this._isLoaded) {
if (this._setAppearance || this._customTemplate.size > 0 || (isFlatten && !this._dictionary.has('AP'))) {
this._appearanceTemplate = this._createPolyLineAppearance(isFlatten);
}
if (!this._appearanceTemplate && isFlatten && this._dictionary.has('AP')) {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
var appearanceStream = dictionary.get('N');
var reference = dictionary.getRaw('N');
if (appearanceStream) {
if (reference) {
appearanceStream.reference = reference;
}
this._appearanceTemplate = new PdfTemplate(appearanceStream, this._crossReference);
}
}
}
}
else {
this._postProcess(isFlatten);
if (!this._appearanceTemplate && isFlatten) {
if (!this._dictionary.has('AP')) {
this._appearanceTemplate = this._createPolyLineAppearance(isFlatten);
}
else {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
var appearanceStream = dictionary.get('N');
var reference = dictionary.getRaw('N');
if (appearanceStream) {
if (reference) {
appearanceStream.reference = reference;
}
this._appearanceTemplate = new PdfTemplate(appearanceStream, this._crossReference);
}
}
}
}
}
if (typeof this.flattenPopups !== 'undefined' && this.flattenPopups) {
if (this._isLoaded) {
this._flattenLoadedPopUp();
}
}
if (isFlatten) {
if (this._appearanceTemplate) {
var isNormalMatrix = this._validateTemplateMatrix(this._appearanceTemplate._content.dictionary);
if (!this._appearanceTemplate._content.dictionary.has('Matrix')) {
var box = this._appearanceTemplate._content.dictionary.getArray('BBox');
if (box) {
this._appearanceTemplate._content.dictionary.update('Matrix', [1, 0, 0, 1, -box[0], -box[1]]);
}
}
this._flattenAnnotationTemplate(this._appearanceTemplate, isNormalMatrix);
}
else {
this._page.annotations.remove(this);
}
}
else if (this._setAppearance || this._customTemplate.size > 0) {
var appearance = void 0;
if (this._dictionary.has('AP')) {
appearance = this._dictionary.get('AP');
}
else {
var reference = this._crossReference._getNextReference();
appearance = new _PdfDictionary(this._crossReference);
appearance._updated = true;
this._crossReference._cacheMap.set(reference, appearance);
this._dictionary.update('AP', reference);
}
if (this._customTemplate.size > 0) {
this._drawCustomAppearance(appearance);
}
else {
_removeDuplicateReference(appearance, this._crossReference, 'N');
var reference = this._crossReference._getNextReference();
this._appearanceTemplate._content.dictionary._update = true;
this._appearanceTemplate._content.reference = reference;
this._crossReference._cacheMap.set(reference, this._appearanceTemplate._content);
appearance.update('N', reference);
}
}
};
/**
* Converts a point from annotation coordinate space into PDF drawing coordinate space by negating the y axis.
*
* @private
* @param {Point} point The point to transform.
* @returns {Point} transformedPoint The transformed point in PDF coordinate space.
*/
PdfPolyLineAnnotation.prototype._transformToPdfCoordinates = function (point) {
return { x: point.x, y: -point.y };
};
/* eslint-disable */
/**
* Expands the provided bounds by the specified border width and returns the updated rectangle.
*
* @private
* @param {{x: number, y: number, width: number, height: number}} boundsValue The original bounds. // eslint-disable-line
* @param {number} borderWidth The border width to expand by.
* @returns {{x: number, y: number, width: number, height: number}} updatedBounds The expanded bounds rectangle.
*/
PdfPolyLineAnnotation.prototype._updateBorder = function (boundsValue, borderWidth) {
return { x: boundsValue.x - borderWidth,
y: boundsValue.y - borderWidth, width: boundsValue.width + (2 * borderWidth),
height: boundsValue.height + (2 * borderWidth) };
};
/* eslint-enable */
/**
* Computes the start and end angles of the polyline based on its transformed points and returns angle values
* along with the transformed endpoints.
*
* @private
* @param {PdfPath} path The path representing the polyline.
* @returns {{startAngle: number, endAngle: number, transformedStart: Point, transformedEnd: Point}} result Angles and transformed endpoints.
*/
PdfPolyLineAnnotation.prototype._prepareStartEndAngle = function (path) {
var transformedStart = this._transformToPdfCoordinates(path._points[0]);
var transformedNext = this._transformToPdfCoordinates(path._points[1]);
var transformedEnd = this._transformToPdfCoordinates(path._points[path._points.length - 1]);
var transformedPrev = this._transformToPdfCoordinates(path._points[path._points.length - 2]);
var startAngle = this._getAngle([transformedStart, transformedNext]);
var endAngle = this._getAngle([transformedPrev, transformedEnd]);
return { startAngle: startAngle, endAngle: endAngle, transformedStart: transformedStart, transformedEnd: transformedEnd };
};
/**
* Creates the polyline appearance template, handling flattening, path construction, border and fill rendering,
* and drawing of start/end line styles.
*
* @private
* @param {boolean} flatten Whether to build a flattening appearance.
* @returns {PdfTemplate} template The created or imported appearance template.
*/
PdfPolyLineAnnotation.prototype._createPolyLineAppearance = function (flatten) {
var color = this.color ? this.color : { r: 0, g: 0, b: 0 };
if (typeof flatten !== 'undefined' && flatten) {
var template = void 0;
if (this._customTemplate.has('N')) {
template = this._customTemplate.get('N');
var data = _convertPointToNumberArray(this._points);
var polyLineBounds = this._getBoundsValue(data);
this.bounds = { x: polyLineBounds.x,
y: this._page.size.height - polyLineBounds.y,
width: polyLineBounds.width,
height: polyLineBounds.height };
}
else {
var borderPen = void 0;
if (this.border.width > 0) {
borderPen = new PdfPen(color, this.border.width);
}
var backBrush = void 0;
if (this.innerColor) {
backBrush = new PdfBrush(this._innerColor);
}
var graphics = this._page.graphics;
if (borderPen) {
var state = void 0;
if (typeof this.opacity !== 'undefined' && this._opacity < 1) {
state = graphics.save();
graphics.setTransparency(this._opacity);
}
var points = this._getLinePoints();
var pathTypes = [];
pathTypes.push(0);
if (points && points.length > 0) {
for (var i = 1; i < points.length; i++) {
pathTypes.push(1);
}
var path = new PdfPath();
path._points = points;
path._pathTypes = pathTypes;
var angles = this._prepareStartEndAngle(path);
var startPoint = this._getAxisValue(angles.transformedStart, angles.startAngle + 90);
var endPoint = this._getAxisValue(angles.transformedEnd, angles.endAngle + 90);
var startPoint1 = startPoint;
var endPoint1 = endPoint;
if (this.beginLineStyle === PdfLineEndingStyle.closedArrow ||
this.beginLineStyle === PdfLineEndingStyle.openArrow) {
startPoint1 = this._getAxisValue(startPoint, angles.startAngle, this.border.width);
path._points[0].x = startPoint1.x;
path._points[0].y = -startPoint1.y;
}
if (this.endLineStyle === PdfLineEndingStyle.closedArrow || this.endLineStyle === PdfLineEndingStyle.openArrow) {
endPoint1 = this._getAxisValue(endPoint, angles.endAngle, -this.border.width);
path._points[path._points.length - 1].x = endPoint1.x;
}
graphics.drawPath(path, borderPen);
if (this.beginLineStyle !== PdfLineEndingStyle.none) {
this._drawLineEndStyle(startPoint, graphics, angles.startAngle, borderPen, backBrush, this.beginLineStyle, this.border.width, true);
}
if (this.endLineStyle !== PdfLineEndingStyle.none) {
this._drawLineEndStyle(endPoint, graphics, angles.endAngle, borderPen, backBrush, this.endLineStyle, this.border.width, false);
}
if (typeof this.opacity !== 'undefined' && this._opacity < 1) {
graphics.restore(state);
}
}
}
template = graphics._template;
}
return template;
}
else {
var rect = { x: 0, y: 0, width: 0, height: 0 };
var data = void 0;
if ((typeof this._points === 'undefined' || (this._points && this._points.length === 0)) && this._dictionary.has('Vertices')) {
data = this._dictionary.get('Vertices');
this._points = _convertToPoints(data);
}
else if (_isPointArray(this._points)) {
data = _convertPointToNumberArray(this._points);
}
rect = this._updateBorder(this._getBoundsValue(data), this.border.width);
var parameter = new _PaintParameter();
if (this.innerColor) {
parameter.backBrush = new PdfBrush(this._innerColor);
}
if (this.border.width > 0 && color) {
parameter.borderPen = new PdfPen(color, this.border.width);
}
if (color) {
parameter.foreBrush = new PdfBrush(color);
}
var path = new PdfPath();
if (typeof this._polylinePoints !== 'undefined' && this._polylinePoints !== null) {
path._points = this._polylinePoints;
}
else {
path._points = this._getLinePoints();
}
if (typeof this._pathTypes !== 'undefined' && this._polylinePoints !== null) {
path._pathTypes = this._pathTypes;
}
else {
this._pathTypes = [];
this._pathTypes.push(0);
for (var i = 1; i < path._points.length; i++) {
this._pathTypes.push(1);
}
path._pathTypes = this._pathTypes;
}
var angles = this._prepareStartEndAngle(path);
var startPoint = this._getAxisValue(angles.transformedStart, angles.startAngle + 90);
var endPoint = this._getAxisValue(angles.transformedEnd, angles.endAngle + 90);
var newStart = startPoint;
var newEnd = endPoint;
if (this.beginLineStyle === PdfLineEndingStyle.closedArrow || this.beginLineStyle === PdfLineEndingStyle.openArrow) {
newStart = this._getAxisValue(startPoint, angles.startAngle, this.border.width);
path._points[0].x = newStart.x;
path._points[0].y = -newStart.y;
}
if (this.endLineStyle === PdfLineEndingStyle.closedArrow || this.endLineStyle === PdfLineEndingStyle.openArrow) {
newEnd = this._getAxisValue(endPoint, angles.endAngle, -this.border.width);
path._points[path._points.length - 1].x = newEnd.x;
}
var beginLineStyleBounds = void 0;
if (this.beginLineStyle !== PdfLineEndingStyle.none) {
beginLineStyleBounds = this._getBoundsFromLineEndStyle(startPoint, angles.startAngle, parameter.borderPen, this.beginLineStyle, this.border.width, true);
rect = this._getCombinedRectangleBounds(rect, beginLineStyleBounds);
}
var endLineStyleBounds = void 0;
if (this.endLineStyle !== PdfLineEndingStyle.none) {
endLineStyleBounds = this._getBoundsFromLineEndStyle(endPoint, angles.endAngle, parameter.borderPen, this.endLineStyle, this.border.width, false);
rect = this._getCombinedRectangleBounds(rect, endLineStyleBounds);
}
var template = void 0;
if (this._customTemplate.has('N')) {
template = this._customTemplate.get('N');
}
else {
var appearance = new PdfAppearance({ x: rect.x, y: rect.y, width: rect.width, height: rect.height }, this);
appearance.normal = new PdfTemplate([rect.x, rect.y, rect.width, rect.height], this._crossReference);
template = appearance.normal;
_setMatrix(template, 0);
template._writeTransformation = false;
var graphics = appearance.normal.graphics;
if (typeof this.opacity !== 'undefined' && this._opacity < 1) {
graphics.save();
graphics.setTransparency(this._opacity);
}
else {
graphics.save();
}
graphics.drawPath(path, parameter.borderPen);
if (this.beginLineStyle !== PdfLineEndingStyle.none) {
this._drawLineEndStyle(startPoint, graphics, angles.startAngle, parameter.borderPen, parameter.backBrush, this.beginLineStyle, this.border.width, true);
}
if (this.endLineStyle !== PdfLineEndingStyle.none) {
this._drawLineEndStyle(endPoint, graphics, angles.endAngle, parameter.borderPen, parameter.backBrush, this.endLineStyle, this.border.width, false);
}
if (typeof this.opacity !== 'undefined' && this._opacity < 1) {
graphics.restore();
}
graphics.restore();
if (this._isBounds) {
template._content.dictionary._updated = true;
this._dictionary.update('LE', [_PdfName.get(_reverseMapEndingStyle(this.beginLineStyle)), _PdfName.get(_reverseMapEndingStyle(this.endLineStyle))]);
this._dictionary.update('LLE', this.lineExtension);
var vertices_1 = [];
this._points.forEach(function (point) {
vertices_1.push(point.x, point.y);
});
this._dictionary.update('Vertices', vertices_1);
}
}
this._dictionary.update('Rect', [rect.x, rect.y, rect.x + rect.width, rect.y + rect.height]);
return template;
}
};
/**
* Returns the polylines points transformed into page or annotation space, accounting for Vertices usage,
* page rotation, and flattening conditions.
*
* @private
* @returns {Point[]} points The transformed polyline points.
*/
PdfPolyLineAnnotation.prototype._getLinePoints = function () {
var pageSize = this._page.size;
var pageHeight = pageSize.height;
var points = [];
if (this._dictionary.has('Vertices') && !this._isBounds && (!this._setAppearance || (this._setAppearance && this.flatten))) {
var linePoints = this._dictionary.getArray('Vertices');
if (linePoints) {
for (var j = 0; j < linePoints.length; j += 2) {
points.push({
x: linePoints[j],
y: pageHeight - linePoints[j + 1]
});
}
}
}
else if (this._points) {
this._points = this._getPoints(this._points);
var polyLinepoints_1 = [];
this._points.forEach(function (pt) {
polyLinepoints_1.push(pt.x, pt.y);
});
for (var j = 0; j < polyLinepoints_1.length; j += 2) {
var yValue = this.flatten ? (pageHeight - polyLinepoints_1[j + 1]) : -polyLinepoints_1[j + 1];
points.push({
x: polyLinepoints_1[j],
y: yValue
});
}
}
return points;
};
return PdfPolyLineAnnotation;
}(PdfComment));
export { PdfPolyLineAnnotation };
/**
* `PdfAngleMeasurementAnnotation` class represents the angle measurement annotation objects.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Create a new angle measurement annotation
* const annotation: PdfAngleMeasurementAnnotation = new PdfAngleMeasurementAnnotation({x: 100, y: 700}, {x: 150, y: 650}, {x: 100, y: 600});
* // Add annotation to the page
* page.annotations.add(annotation);
* // Destroy the document
* document.destroy();
* ```
*/
var PdfAngleMeasurementAnnotation = /** @class */ (function (_super) {
__extends(PdfAngleMeasurementAnnotation, _super);
function PdfAngleMeasurementAnnotation(startPoint, midPoint, endPoint, properties) {
var _this = _super.call(this) || this;
/**
* Stores the points used to define the angle for measurement.
*
* @private
*/
_this._linePoints = [];
_this._firstIntersectionPoint = [0, 0];
_this._secondIntersectionPoint = [0, 0];
_this._dictionary = new _PdfDictionary();
_this._dictionary.update('Type', _PdfName.get('Annot'));
_this._dictionary.update('Subtype', _PdfName.get('PolyLine'));
if (startPoint && midPoint && endPoint) {
_this._pointArray = [startPoint, midPoint, endPoint];
}
if (Array.isArray(_this._pointArray) && _this._pointArray.length > 3) {
throw new Error('Points length should not be greater than 3');
}
_this._linePoints = [];
if (Array.isArray(_this._pointArray) && _this._pointArray.length > 0) {
_this._pointArray.forEach(function (point) {
_this._linePoints.push(point.x);
_this._linePoints.push(point.y);
});
}
_this._type = _PdfAnnotationType.angleMeasurementAnnotation;
if (properties) {
if ('text' in properties && _isNullOrUndefined(properties.text)) {
_this.text = properties.text;
}
if ('author' in properties && _isNullOrUndefined(properties.author)) {
_this.author = properties.author;
}
if ('subject' in properties && _isNullOrUndefined(properties.subject)) {
_this.subject = properties.subject;
}
if ('color' in properties && _isNullOrUndefined(properties.color)) {
_this.color = properties.color;
}
if ('opacity' in properties && _isNullOrUndefined(properties.opacity)) {
_this.opacity = properties.opacity;
}
if ('border' in properties && _isNullOrUndefined(properties.border)) {
_this.border = properties.border;
}
}
return _this;
}
Object.defineProperty(PdfAngleMeasurementAnnotation.prototype, "measure", {
/**
* Gets the flag to have measurement dictionary of the angle measurement annotation.
*
* @returns {boolean} measure.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfAngleMeasurementAnnotation = page.annotations.at(0) as PdfAngleMeasurementAnnotation;
* // Gets the flag to have measurement dictionary of the angle annotation.
* let measure: boolean = annotation.measure;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._measure === 'undefined' && this._dictionary.has('Measure')) {
this._measure = this._dictionary.get('Measure');
}
return this._measure;
},
/**
* Sets the flag to add measurement dictionary to the annotation.
*
* @param {boolean} value Measure.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfAngleMeasurementAnnotation = page.annotations.at(0) as PdfAngleMeasurementAnnotation;
* // Sets the flag to add measurement dictionary to the annotation.
* annotation.measure = true;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value && !this._isLoaded) {
this._measure = value;
this.caption.cap = true;
}
},
enumerable: true,
configurable: true
});
/**
* Loads an angle measurement annotation from the given page and dictionary, marks it as loaded, and initializes internal state.
*
* @private
* @param {PdfPage} page The page that contains the annotation.
* @param {_PdfDictionary} dictionary The source annotation dictionary to load.
* @returns {PdfAngleMeasurementAnnotation} annot The loaded angle measurement annotation instance.
*/
PdfAngleMeasurementAnnotation._load = function (page, dictionary) {
var annot = new PdfAngleMeasurementAnnotation();
annot._isLoaded = true;
annot._initialize(page, dictionary);
return annot;
};
/**
* Initializes the angle measurement annotation for the specified page and optional source dictionary by delegating to the base initializer.
*
* @private
* @param {PdfPage} page The page to associate with the annotation.
* @param {_PdfDictionary} [dictionary] Optional source dictionary for loading.
* @returns {void} void No return value.
*/
PdfAngleMeasurementAnnotation.prototype._initialize = function (page, dictionary) {
_super.prototype._initialize.call(this, page, dictionary);
};
/**
* Finalizes setup by validating points, ensuring BS/color defaults, setting a fallback border width, and generating the angle measurement appearance.
*
* @private
* @returns {void} void No return value.
*/
PdfAngleMeasurementAnnotation.prototype._postProcess = function () {
if (!this._pointArray) {
throw new Error('Points cannot be null or undefined');
}
var borderWidth;
if (this._dictionary.has('BS')) {
borderWidth = this.border.width;
}
else {
var dictionary = new _PdfDictionary(this._crossReference);
dictionary.set('Type', _PdfName.get('Border'));
this._dictionary.set('BS', dictionary);
}
if (!this._dictionary.has('C')) {
this.color = { r: 0, g: 0, b: 0 };
this._isTransparentColor = true;
}
if (typeof borderWidth === 'undefined') {
borderWidth = 1;
}
this._appearanceTemplate = this._createAngleMeasureAppearance();
};
/**
* Builds or imports the angle measurement appearance based on state and flattening, updates AP entries, or flattens the template when required.
*
* @private
* @param {boolean} [isFlatten=false] Whether to flatten the annotation to page content.
* @returns {void} void No return value.
*/
PdfAngleMeasurementAnnotation.prototype._doPostProcess = function (isFlatten) {
if (isFlatten === void 0) { isFlatten = false; }
if (this._isLoaded) {
if (!isFlatten && (this._setAppearance || this._customTemplate.size > 0)) {
this._appearanceTemplate = this._createAngleMeasureAppearance();
}
if (!this._appearanceTemplate && isFlatten && this._dictionary.has('AP')) {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
var appearanceStream = dictionary.get('N');
var reference = dictionary.getRaw('N');
if (appearanceStream) {
if (reference) {
appearanceStream.reference = reference;
}
this._appearanceTemplate = new PdfTemplate(appearanceStream, this._crossReference);
}
}
}
}
else {
this._postProcess();
if (!this._appearanceTemplate) {
if (isFlatten) {
if (!this._dictionary.has('AP')) {
this._appearanceTemplate = this._createAngleMeasureAppearance();
}
else {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
var appearanceStream = dictionary.get('N');
var reference = dictionary.getRaw('N');
if (appearanceStream) {
if (reference) {
appearanceStream.reference = reference;
}
this._appearanceTemplate = new PdfTemplate(appearanceStream, this._crossReference);
}
}
}
}
}
}
if (isFlatten) {
if (this._appearanceTemplate) {
var isNormalMatrix = this._validateTemplateMatrix(this._appearanceTemplate._content.dictionary);
if (!this._appearanceTemplate._content.dictionary.has('Matrix')) {
var box = this._appearanceTemplate._content.dictionary.getArray('BBox');
if (box) {
this._appearanceTemplate._content.dictionary.update('Matrix', [1, 0, 0, 1, -box[0], -box[1]]);
}
}
this._flattenAnnotationTemplate(this._appearanceTemplate, isNormalMatrix);
}
else {
this._page.annotations.remove(this);
}
}
else if (this._setAppearance || this._customTemplate.size > 0) {
var appearance = void 0;
if (this._dictionary.has('AP')) {
appearance = this._dictionary.get('AP');
}
else {
var reference = this._crossReference._getNextReference();
appearance = new _PdfDictionary(this._crossReference);
appearance._updated = true;
this._crossReference._cacheMap.set(reference, appearance);
this._dictionary.update('AP', reference);
}
if (this._customTemplate.size > 0) {
this._drawCustomAppearance(appearance);
}
else {
_removeDuplicateReference(appearance, this._crossReference, 'N');
var reference = this._crossReference._getNextReference();
this._appearanceTemplate._content.dictionary._update = true;
this._appearanceTemplate._content.reference = reference;
this._crossReference._cacheMap.set(reference, this._appearanceTemplate._content);
appearance.update('N', reference);
}
}
};
/**
* Creates the angle measurement appearance template, computes the angle/caption, writes measurement metadata, draws the polyline and arc, and updates AP/Rect entries.
*
* @private
* @returns {PdfTemplate} template The created or imported appearance template.
*/
PdfAngleMeasurementAnnotation.prototype._createAngleMeasureAppearance = function () {
var borderWidth = this.border.width;
var font = this._obtainFont();
if ((typeof font === 'undefined' || font === null) || (!this._isLoaded && font.size === 1)) {
font = this._circleCaptionFont;
this._pdfFont = font;
}
var format = new PdfStringFormat(PdfTextAlignment.center, PdfVerticalAlignment.middle);
var angle = (this._calculateAngle() * (180.0 / Math.PI));
if (angle < 0) {
angle = -angle;
}
if (angle > 180) {
angle = 360 - angle;
}
this._dictionary.update('Vertices', this._linePoints);
var ds = 'font:' +
font._metrics._postScriptName +
' ' +
font._size +
'pt; color:' +
this._colorToHex([this.color.r, this.color.g, this.color.b]);
this._dictionary.update('DS', ds);
if (this.text === (' ' + angle.toFixed(2) + '°')) {
this._dictionary.update('Contents', this.text);
}
else if (this.text) {
this._dictionary.update('Contents', this.text);
}
if (typeof this.subject === 'undefined') {
this._dictionary.update('Subject', 'Angle Measurement');
}
this._dictionary.update('MeasurementTypes', 1152);
this._dictionary.update('Subtype', new _PdfName('PolyLine'));
this._dictionary.update('IT', new _PdfName('PolyLineAngle'));
var measureDictionary = new _PdfDictionary();
var d = [];
var t = [];
var a = [];
var x = [];
var v = [];
measureDictionary.set('Type', _PdfName.get('measureDictionary'));
measureDictionary.set('R', '1 in = 1 in');
measureDictionary.set('Subtype', 'RL');
measureDictionary.set('TargetUnitConversion', 0.1388889);
var dDictionary = new _PdfDictionary();
dDictionary.set('U', 'in');
dDictionary.set('Type', 'NumberFormat');
dDictionary.set('C', 1);
dDictionary.set('D', 1);
dDictionary.set('SS', '');
d.push(dDictionary);
var tDictionary = new _PdfDictionary();
tDictionary.set('U', '°');
tDictionary.set('Type', 'NumberFormat');
tDictionary.set('C', 1);
tDictionary.set('D', 1);
tDictionary.set('FD', true);
tDictionary.set('SS', '');
t.push(tDictionary);
var aDictionary = new _PdfDictionary();
aDictionary.set('U', 'sq in');
aDictionary.set('Type', 'NumberFormat');
aDictionary.set('C', 1);
aDictionary.set('D', 1);
aDictionary.set('FD', true);
aDictionary.set('SS', '');
a.push(aDictionary);
var vDictionary = new _PdfDictionary();
vDictionary.set('U', 'cu in');
vDictionary.set('Type', 'NumberFormat');
vDictionary.set('C', 1);
vDictionary.set('D', 1);
vDictionary.set('FD', true);
vDictionary.set('SS', '');
v.push(vDictionary);
var xDictionary = new _PdfDictionary();
xDictionary.set('U', 'in');
xDictionary.set('Type', 'NumberFormat');
xDictionary.set('C', 1);
xDictionary.set('D', 1);
xDictionary.set('SS', '');
x.push(xDictionary);
measureDictionary.set('D', d);
measureDictionary.set('T', t);
measureDictionary.set('A', a);
measureDictionary.set('X', x);
measureDictionary.set('V', v);
if (this._dictionary.has('Measure')) {
_removeDuplicateReference(this._dictionary, this._crossReference, 'Measure');
}
var reference = this._crossReference._getNextReference();
this._crossReference._cacheMap.set(reference, measureDictionary);
measureDictionary._updated = true;
this._dictionary.update('Measure', reference);
var rectValue = [0, 0, 0, 0];
var boundsValue = this._getAngleBoundsValue();
var points = this._obtainLinePoints();
var pathTypes = [];
pathTypes.push(0);
for (var i = 1; i < points.length; i++) {
pathTypes.push(1);
}
var graphicspath = new PdfPath();
graphicspath.addRectangle({ x: points[1][0] - this._radius,
y: -(points[1][1] + this._radius),
width: 2 * this._radius,
height: 2 * this._radius });
var size = font.measureString(angle.toString() + '°', { width: 0, height: 0 }, format, 0, 0);
var midPoint = [(this._firstIntersectionPoint[0] + this._secondIntersectionPoint[0]) / 2,
((this._firstIntersectionPoint[1] + this._secondIntersectionPoint[1]) / 2)];
var center = [points[1][0], -points[1][1]];
var x1 = points[1][0] + this._radius * Math.cos((this._startAngle + (this._sweepAngle / 2)) * (Math.PI / 180.0));
var y = points[1][1] + this._radius * Math.sin((this._startAngle + (this._sweepAngle / 2)) * (Math.PI / 180.0));
var start = [midPoint[0], midPoint[1]];
var xDiff = start[0] - center[0];
var yDiff = start[1] - center[1];
var midpointAngle = ((Math.atan2(yDiff, xDiff)) * (180.0 / Math.PI));
var left = false;
var right = false;
var up = false;
var down = false;
if (midpointAngle > 0) {
if (midpointAngle < 45) {
right = true;
}
else if (midpointAngle >= 45 && midpointAngle < 135) {
up = true;
}
else {
left = true;
}
}
else {
midpointAngle = -midpointAngle;
if (midpointAngle === 0) {
(new PdfPath()).addRectangle({ x: boundsValue[0], y: boundsValue[1], width: boundsValue[2], height: boundsValue[3] });
}
else if (midpointAngle < 45) {
right = true;
}
else if (midpointAngle >= 45 && midpointAngle < 135) {
down = true;
}
else {
left = true;
}
}
if (rectValue[0] === 0 && rectValue[1] === 0 && rectValue[2] === 0 && rectValue[3] === 0) {
rectValue = boundsValue;
this.bounds = { x: boundsValue[0], y: boundsValue[1], width: boundsValue[2], height: boundsValue[3] };
}
var path = new PdfPath();
path._pathTypes = pathTypes;
path._points = points.map(function (p) { return ({ x: p[0], y: p[1] }); }); // eslint-disable-line
this._dictionary.set('Rect', [rectValue[0], rectValue[1], rectValue[0] + rectValue[2], rectValue[1] + rectValue[3]]);
var template;
if (this._customTemplate.has('N')) {
template = this._customTemplate.get('N');
}
else {
var appearance = new PdfAppearance({ x: boundsValue[0], y: boundsValue[1], width: boundsValue[2],
height: boundsValue[3] }, this);
appearance.normal = new PdfTemplate(rectValue, this._crossReference);
template = appearance.normal;
template._writeTransformation = false;
var graphics = appearance.normal.graphics;
var width = borderWidth / 2;
var pen = new PdfPen(this._color, width);
if (this.border.style === PdfBorderStyle.dashed) {
pen._dashStyle = PdfDashStyle.dash;
}
var brush = new PdfBrush(this._color);
graphics.save();
graphics.drawPath(path, pen);
path.addArc({ x: points[1][0] - this._radius,
y: points[1][1] - this._radius,
width: 2 * this._radius,
height: 2 * this._radius }, this._startAngle, this._sweepAngle);
if (up) {
graphics.drawString(angle.toString() + '°', font, { x: x1 - (size.width / 2), y: -(-y + font._getHeight() + 2), width: 0, height: 0 }, null, brush);
}
else if (right) {
graphics.drawString(angle.toString() + '°', font, { x: x1 + 2, y: -(-y + font._getHeight() / 2), width: 0, height: 0 }, null, brush);
}
else if (left) {
graphics.drawString(angle.toString() + '°', font, { x: x1 - size.width - 2, y: -(-y + font._getHeight() / 2), width: 0, height: 0 }, null, brush);
}
else if (down) {
graphics.drawString(angle.toString() + '°', font, { x: x1 - (size.width / 2), y: (y + 2), width: 0, height: 0 }, null, brush);
}
graphics.restore();
graphics._template._content.dictionary._updated = true;
var reference1 = this._crossReference._getNextReference();
this._crossReference._cacheMap.set(reference1, graphics._template._content);
graphics._template._content.reference = reference1;
if (this._dictionary.has('AP')) {
_removeDuplicateReference(this._dictionary.get('AP'), this._crossReference, 'N');
}
var appearanceDictionary = new _PdfDictionary();
appearanceDictionary.set('N', reference1);
appearanceDictionary._updated = true;
this._dictionary.set('AP', appearanceDictionary);
}
return template;
};
/**
* Calculates and returns the axis-aligned bounds of the angle polyline after Y-axis normalization.
*
* @private
* @returns {number[]} bounds The [x, y, width, height] bounds array.
*/
PdfAngleMeasurementAnnotation.prototype._getAngleBoundsValue = function () {
var points = this._obtainLinePoints();
for (var i = 0; i < points.length; i++) {
points[i][1] = -points[i][1];
}
var path = new PdfPath();
path._points = points.map(function (p) { return ({ x: p[0], y: p[1] }); }); // eslint-disable-line
path._pathTypes = [0, 1, 1];
return path._getBounds();
};
/**
* Returns the three angle-defining points as [x, y] arrays with PDF coordinate Y inversion applied.
*
* @private
* @returns {Array<number[]>} collection The three points as [x, y] arrays.
*/
PdfAngleMeasurementAnnotation.prototype._obtainLinePoints = function () {
var points;
var collection;
if (this._linePoints) {
points = this._linePoints.slice();
collection = new Array(points.length / 2);
var count = 0;
for (var j = 0; j < points.length; j = j + 2) {
collection[count] = [points[j], -points[j + 1]];
count++;
}
}
return collection;
};
/**
* Computes the interior angle at the vertex, determines arc start/sweep angles using line circle intersections, and returns the signed angle in radians.
*
* @private
* @returns {number} angle The signed interior angle in radians.
*/
PdfAngleMeasurementAnnotation.prototype._calculateAngle = function () {
var points = [0, 0];
if (typeof this._linePoints !== 'undefined' && this._linePoints.length === 0 && this._isLoaded) {
if (this._dictionary.has('Vertices')) {
this._linePoints = this._dictionary.get('Vertices');
}
}
points = this._linePoints.slice();
var collection = [];
for (var j = 0; j < points.length; j = j + 2) {
collection.push([points[j], points[j + 1]]);
}
var point1 = collection[0];
var point2 = collection[1];
var point3 = collection[2];
var firstLineDistance = Math.sqrt(Math.pow((point2[0] - point1[0]), 2) + Math.pow((point2[1] - point1[1]), 2));
var secondLineDistance = Math.sqrt(Math.pow((point2[0] - point3[0]), 2) + Math.pow((point2[1] - point3[1]), 2));
this._radius = Math.min(firstLineDistance, secondLineDistance) / 4;
var graphicsPath = new PdfPath();
graphicsPath._points = collection.map(function (p) { return ({ x: p[0], y: p[1] }); }); // eslint-disable-line
graphicsPath._pathTypes = [0, 1, 1];
var intersectionPoint1;
var intersectionPoint2;
var value = this._findLineCircleIntersectionPoints(point2[0], point2[1], this._radius, point1, point2, intersectionPoint1, intersectionPoint2);
intersectionPoint1 = value.first;
intersectionPoint2 = value.second;
if (this._firstIntersectionPoint[0] === 0 && this._firstIntersectionPoint[1] === 0) {
this._firstIntersectionPoint = intersectionPoint2;
}
intersectionPoint1 = [0, 0];
intersectionPoint2 = [0, 0];
value = this._findLineCircleIntersectionPoints(point2[0], point2[1], this._radius, point3, point2, intersectionPoint1, intersectionPoint2);
intersectionPoint1 = value.first;
intersectionPoint2 = value.second;
if (this._secondIntersectionPoint[0] === 0 && this._secondIntersectionPoint[1] === 0) {
this._secondIntersectionPoint = intersectionPoint2;
}
var xDiff = this._firstIntersectionPoint[0] - point2[0];
var yDiff = this._firstIntersectionPoint[1] - point2[1];
var startAngle = (Math.atan2(yDiff, xDiff) * (180.0 / Math.PI));
xDiff = this._secondIntersectionPoint[0] - point2[0];
yDiff = this._secondIntersectionPoint[1] - point2[1];
var sweepAngle = (Math.atan2(yDiff, xDiff) * (180.0 / Math.PI));
startAngle = startAngle > 0 ? startAngle = 360 - startAngle : -startAngle;
sweepAngle = sweepAngle > 0 ? sweepAngle = 360 - sweepAngle : -sweepAngle;
if (startAngle === 180 && sweepAngle === 0) {
this._startAngle = startAngle;
this._sweepAngle = 180;
}
else if (startAngle === 0 && sweepAngle === 180) {
this._startAngle = sweepAngle;
this._sweepAngle = 180;
}
else if (startAngle < 180) {
if (startAngle > sweepAngle) {
this._startAngle = sweepAngle;
this._sweepAngle = startAngle - sweepAngle;
}
else if (startAngle + 180 < sweepAngle) {
this._startAngle = sweepAngle;
this._sweepAngle = (360 - sweepAngle) + startAngle;
}
else {
this._startAngle = startAngle;
this._sweepAngle = sweepAngle - startAngle;
}
}
else {
if (startAngle < sweepAngle) {
this._startAngle = startAngle;
this._sweepAngle = sweepAngle - startAngle;
}
else if (startAngle - 180 > sweepAngle) {
this._startAngle = startAngle;
this._sweepAngle = (360 - startAngle) + sweepAngle;
}
else {
this._startAngle = sweepAngle;
this._sweepAngle = startAngle - sweepAngle;
}
}
return (Math.atan2((point3[0] - point2[0]), (point3[1] - point2[1])) -
Math.atan2((point1[0] - point2[0]), (point1[1] - point2[1])));
};
/**
* Finds the intersection points between a line segment and a circle centered at centerX, centerY with the given radius and returns both intersections.
*
* @private
* @param {number} centerX X-coordinate of the circle center.
* @param {number} centerY Y-coordinate of the circle center.
* @param {number} radius Circle radius.
* @param {number[]} point1 First point of the segment [x, y].
* @param {number[]} point2 Second point of the segment [x, y].
* @param {number[]} intersection1 Output first intersection [x, y].
* @param {number[]} intersection2 Output second intersection [x, y].
* @returns {{first: number[], second: number[]}} result The pair of intersections {first, second}.
*/
PdfAngleMeasurementAnnotation.prototype._findLineCircleIntersectionPoints = function (centerX, centerY, radius, point1, point2, intersection1, intersection2) {
var dx = point2[0] - point1[0];
var dy = point2[1] - point1[1];
var a = dx * dx + dy * dy;
var b = 2 * (dx * (point1[0] - centerX) + dy * (point1[1] - centerY));
var c = (point1[0] - centerX) * (point1[0] - centerX) + (point1[1] - centerY) * (point1[1] - centerY) - radius * radius;
var e = b * b - 4 * a * c;
if ((a <= 0.0000001) || (e < 0)) {
intersection1 = [Number.NaN, Number.NaN];
intersection2 = [Number.NaN, Number.NaN];
}
else if (e === 0) {
var t = -b / (2 * a);
intersection1 = [point1[0] + t * dx, point1[1] + t * dy];
intersection2 = [Number.NaN, Number.NaN];
}
else {
var t = ((-b + Math.sqrt(e)) / (2 * a));
intersection1 = [point1[0] + t * dx, point1[1] + t * dy];
t = ((-b - Math.sqrt(e)) / (2 * a));
intersection2 = [point1[0] + t * dx, point1[1] + t * dy];
}
return { first: intersection1, second: intersection2 };
};
return PdfAngleMeasurementAnnotation;
}(PdfComment));
export { PdfAngleMeasurementAnnotation };
/**
* `PdfInkAnnotation` class represents the ink annotation objects.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Create a new ink annotation with the bounds and ink points
* const annotation: PdfInkAnnotation = new PdfInkAnnotation({x: 0, y: 0, width: 300, height: 400}, [{x: 40, y: 300}, {x: 60, y: 100}, {x: 40, y: 50}, {x: 40, y: 300}]);
* // Add annotation to the page
* page.annotations.add(annotation);
* // Destroy the document
* document.destroy();
* ```
*/
var PdfInkAnnotation = /** @class */ (function (_super) {
__extends(PdfInkAnnotation, _super);
function PdfInkAnnotation(bounds, points, properties) {
var _this = _super.call(this) || this;
_this._inkPointsCollection = [];
_this._previousCollection = [];
/**
* Indicates whether the ink annotation has been modified.
*
* @private
*/
_this._isModified = false;
/**
* Enables or disables interactive control points for editing.
*
* @private
*/
_this._isEnableControlPoints = true;
_this._dictionary = new _PdfDictionary();
_this._dictionary.update('Type', _PdfName.get('Annot'));
_this._dictionary.update('Subtype', _PdfName.get('Ink'));
if (typeof points !== 'undefined') {
_this._points = [{ x: bounds.x, y: bounds.y }, { x: bounds.width, y: bounds.height }];
_this.bounds = bounds;
}
if (typeof points !== 'undefined') {
_this._linePoints = points;
}
_this._type = _PdfAnnotationType.inkAnnotation;
if (properties) {
if ('text' in properties && _isNullOrUndefined(properties.text)) {
_this.text = properties.text;
}
if ('author' in properties && _isNullOrUndefined(properties.author)) {
_this.author = properties.author;
}
if ('subject' in properties && _isNullOrUndefined(properties.subject)) {
_this.subject = properties.subject;
}
if ('color' in properties && _isNullOrUndefined(properties.color)) {
_this.color = properties.color;
}
if ('thickness' in properties && _isNullOrUndefined(properties.thickness)) {
_this.border.width = properties.thickness;
}
if ('opacity' in properties && _isNullOrUndefined(properties.opacity)) {
_this.opacity = properties.opacity;
}
if ('pointsCollection' in properties && _isNullOrUndefined(properties.pointsCollection)) {
_this.inkPointsCollection = properties.pointsCollection;
}
}
return _this;
}
Object.defineProperty(PdfInkAnnotation.prototype, "inkPointsCollection", {
/**
* Gets the ink points collection of the annotation.
*
* @returns {Array<Point[]>} Ink points collection.
*
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfInkAnnotation = page.annotations.at(0) as PdfInkAnnotation;
* // Get the ink points collection of the annotation
* let inkPointsCollection: Array<Point[]> = annotation.inkPointsCollection;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (this._inkPointsCollection.length === 0 && this._dictionary.has('InkList')) {
var inkList = this._dictionary.get('InkList');
if (Array.isArray(inkList) && inkList.length > 0) {
var cropOrMediaBox = this._getMediaOrCropBox(this._page);
var cropX_1 = cropOrMediaBox && cropOrMediaBox.length > 0 ? cropOrMediaBox[0] : 0;
var cropY_1 = cropOrMediaBox && cropOrMediaBox.length > 1 ? cropOrMediaBox[1] : 0;
if (cropX_1 !== 0 || cropY_1 !== 0) {
var adjusted = inkList.map(function (stroke) {
var result = stroke.slice();
for (var k = 0; k < result.length; k += 2) {
result[k] = result[k] - cropX_1;
result[k + 1] = result[k + 1] - cropY_1;
}
return result;
});
this._inkPointsCollection = _convertNumberToPointArrays(adjusted);
}
else {
this._inkPointsCollection = _convertNumberToPointArrays(inkList);
}
}
}
return this._inkPointsCollection;
},
/**
* Sets the ink points collection of the annotation.
*
* @param {Array<Point[]>} value Ink points collection.
*
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* // Create a new ink annotation
* const annotation: PdfInkAnnotation = new PdfInkAnnotation([0, 0, 300, 400], [{x: 40, y: 300}, {x: 60, y: 100}, {x: 40, y: 50}, {x: 40, y: 300}]);
* // Set the ink points collection of the annotation
* annotation.inkPointsCollection = [[{x: 422, y: 690}, {x: 412, y: 708}, {x: 408, y: 715}, {x: 403, y: 720}, {x: 400, y: 725}], [{x: 420, y: 725}, {x: 420, y: 715}, {x: 415, y: 705}, {x: 400, y: 690}, {x: 405, y: 695}]];
* // Add annotation to the page
* page.annotations.add(annotation);
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (Array.isArray(value) && value.length > 0 && value !== this._inkPointsCollection) {
this._inkPointsCollection = value;
this._isModified = true;
if (this._isLoaded) {
this._dictionary.update('InkList', _convertPointsToNumberArrays(value));
}
}
},
enumerable: true,
configurable: true
});
/**
* Loads an ink annotation from the given page and dictionary, marks it as loaded, and initializes internal state.
*
* @private
* @param {PdfPage} page The page that contains the annotation.
* @param {_PdfDictionary} dictionary The source annotation dictionary to load.
* @returns {PdfInkAnnotation} annot The loaded ink annotation instance.
*/
PdfInkAnnotation._load = function (page, dictionary) {
var annot = new PdfInkAnnotation();
annot._isLoaded = true;
annot._initialize(page, dictionary);
return annot;
};
/**
* Initializes the ink annotation for the specified page and optional source dictionary by delegating to the base initializer.
*
* @private
* @param {PdfPage} page The page to associate with the annotation.
* @param {_PdfDictionary} [dictionary] Optional source dictionary for loading.
* @returns {void} void No return value.
*/
PdfInkAnnotation.prototype._initialize = function (page, dictionary) {
_super.prototype._initialize.call(this, page, dictionary);
};
/**
* Finalizes setup by validating points, ensuring BS/color defaults, computing bounds from ink data, updating Rect, and creating or attaching the appearance stream.
*
* @private
* @returns {void} void No return value.
*/
PdfInkAnnotation.prototype._postProcess = function () {
if (typeof this._points === 'undefined' || this._points === null) {
throw new Error('Points cannot be null or undefined');
}
var borderWidth;
if (this._dictionary.has('BS')) {
borderWidth = this.border.width;
}
else {
var dictionary = new _PdfDictionary(this._crossReference);
dictionary.set('Type', _PdfName.get('Border'));
this._dictionary.set('BS', dictionary);
}
if (!this._dictionary.has('C')) {
this.color = { r: 0, g: 0, b: 0 };
this._isTransparentColor = true;
}
if (typeof borderWidth === 'undefined') {
borderWidth = 1;
}
var nativeRectangle = this._addInkPoints();
var bounds = [nativeRectangle.x,
nativeRectangle.y,
nativeRectangle.x + nativeRectangle.width,
nativeRectangle.y + nativeRectangle.height];
this._dictionary.update('Rect', bounds);
if (this._setAppearance || this._customTemplate.size > 0) {
var appearanceDictionary = void 0;
if (this._dictionary.has('AP')) {
appearanceDictionary = this._dictionary.get('AP');
}
else {
var reference = this._crossReference._getNextReference();
appearanceDictionary = new _PdfDictionary(this._crossReference);
this._crossReference._cacheMap.set(reference, appearanceDictionary);
this._dictionary.update('AP', reference);
}
if (this._customTemplate.size > 0) {
this._appearanceTemplate = this._customTemplate.get('N');
this._drawCustomAppearance(appearanceDictionary);
}
else {
_removeDuplicateReference(this._dictionary.get('AP'), this._crossReference, 'N');
var appearance = new PdfAppearance(nativeRectangle, this);
appearance.normal = new PdfTemplate(nativeRectangle, this._crossReference);
var template = appearance.normal;
_setMatrix(template, 0, this);
template._writeTransformation = false;
this._appearanceTemplate = this._createInkAppearance(template);
this._appearanceTemplate._content.dictionary._updated = true;
var reference = this._crossReference._getNextReference();
this._crossReference._cacheMap.set(reference, this._appearanceTemplate._content);
this._appearanceTemplate._content.reference = reference;
appearanceDictionary.set('N', reference);
appearanceDictionary._updated = true;
}
}
};
/**
* Builds or imports the ink appearance based on state and flattening, updates AP entries, adjusts Rect, and optionally flattens the annotation and its popup.
*
* @private
* @param {boolean} [isFlatten=false] Whether to flatten the annotation into page content.
* @returns {void} void No return value.
*/
PdfInkAnnotation.prototype._doPostProcess = function (isFlatten) {
if (isFlatten === void 0) { isFlatten = false; }
this._isFlatten = isFlatten;
if (this._isLoaded) {
if (this._setAppearance || this._customTemplate.size > 0 || (isFlatten && !this._dictionary.has('AP'))) {
if (this._inkPointsCollection.length === 0) {
this._inkPointsCollection = _convertNumberToPointArrays(this._obtainInkListCollection());
}
var rect = this._getInkBoundsValue();
if (this._customTemplate.size > 0) {
this._appearanceTemplate = this._customTemplate.get('N');
}
else {
var template = new PdfTemplate(rect, this._crossReference);
var box = template._content.dictionary.getArray('BBox');
var angle = this._getRotationAngle();
if (box && angle !== null && typeof angle !== 'undefined') {
template._content.dictionary.set('Matrix', [1, 0, 0, 1, -box[0], -box[1]]);
}
template._writeTransformation = false;
this._appearanceTemplate = this._createInkAppearance(template);
}
this._dictionary.update('Rect', [rect[0], rect[1], rect[0] + rect[2], rect[1] + rect[3]]);
if (!isFlatten) {
var appearance = void 0;
if (this._dictionary.has('AP')) {
appearance = this._dictionary.get('AP');
}
else {
var reference = this._crossReference._getNextReference();
appearance = new _PdfDictionary(this._crossReference);
appearance._updated = true;
this._crossReference._cacheMap.set(reference, appearance);
this._dictionary.update('AP', reference);
}
if (this._customTemplate.size > 0) {
this._drawCustomAppearance(appearance);
}
else {
_removeDuplicateReference(appearance, this._crossReference, 'N');
this._appearanceTemplate._content.dictionary._updated = true;
var reference = this._crossReference._getNextReference();
this._crossReference._cacheMap.set(reference, this._appearanceTemplate._content);
this._appearanceTemplate._content.reference = reference;
appearance.set('N', reference);
appearance._updated = true;
}
}
}
else if (!this._appearanceTemplate && isFlatten && this._dictionary.has('AP')) {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
var appearanceStream = dictionary.get('N');
var reference = dictionary.getRaw('N');
if (appearanceStream) {
if (reference) {
appearanceStream.reference = reference;
}
this._appearanceTemplate = new PdfTemplate(appearanceStream, this._crossReference);
}
}
}
}
else {
this._postProcess();
if (!this._appearanceTemplate && isFlatten) {
if (this._dictionary.has('AP')) {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
var appearanceStream = dictionary.get('N');
var reference = dictionary.getRaw('N');
if (appearanceStream) {
if (reference) {
appearanceStream.reference = reference;
}
this._appearanceTemplate = new PdfTemplate(appearanceStream, this._crossReference);
}
}
}
else {
if (this._inkPointsCollection.length === 0) {
this._inkPointsCollection = _convertNumberToPointArrays(this._obtainInkListCollection());
}
var rect = this._getInkBoundsValue();
var template = new PdfTemplate(rect, this._crossReference);
_setMatrix(template, this._getRotationAngle(), this);
template._writeTransformation = false;
this._appearanceTemplate = this._createInkAppearance(template);
this._dictionary.update('Rect', [rect[0], rect[1], rect[0] + rect[2], rect[1] + rect[3]]);
}
}
}
if (typeof this.flattenPopups !== 'undefined' && this.flattenPopups) {
if (this._isLoaded) {
this._flattenLoadedPopUp();
}
else {
this._flattenPopUp();
}
}
if (isFlatten) {
if (this._appearanceTemplate &&
this._appearanceTemplate._size !== null &&
typeof this._appearanceTemplate._size !== 'undefined') {
var isNormalMatrix = this._validateTemplateMatrix(this._appearanceTemplate._content.dictionary);
var box = void 0;
var matrix = void 0;
if (this._appearanceTemplate._content.dictionary.has('BBox')) {
box = this._appearanceTemplate._content.dictionary.getArray('BBox');
}
if (this._appearanceTemplate._content.dictionary.has('Matrix')) {
matrix = this._appearanceTemplate._content.dictionary.getArray('Matrix');
}
if (box && matrix && (box[0] !== -matrix[4] || box[1] !== -matrix[5])) {
this._appearanceTemplate._content.dictionary.update('Matrix', [1, 0, 0, 1, -box[0], -box[1]]);
}
this._flattenAnnotationTemplate(this._appearanceTemplate, isNormalMatrix);
}
else {
this._page.annotations.remove(this);
}
if (!this.flattenPopups && this._dictionary.has('Popup')) {
var reference = this._dictionary.getRaw('Popup');
if (this._page._pageDictionary.has('Annots')) {
var annots = this._page._pageDictionary.getRaw('Annots'); // eslint-disable-line
if (annots && Array.isArray(annots) && annots.length > 0) {
var index = annots.indexOf(reference);
if (index >= 0) {
this._page.annotations.removeAt(index);
}
}
}
}
}
};
/**
* Renders the ink strokes into the provided template, handling dots/lines/bezier paths, opacity, and pen settings (e.g., round caps when loaded).
*
* @private
* @param {PdfTemplate} template The template into which the ink appearance is drawn.
* @returns {PdfTemplate} template The same template after drawing content.
*/
PdfInkAnnotation.prototype._createInkAppearance = function (template) {
var graphics = template.graphics;
if (this.inkPointsCollection !== null &&
this.inkPointsCollection.length > 0 &&
this.color !== null &&
typeof this._color !== 'undefined') {
for (var l = 0; l < this.inkPointsCollection.length; l++) {
var isDot = false;
var inkPointsCollection = _convertPointsToNumberArrays(this.inkPointsCollection);
var inkPoints = inkPointsCollection[l];
if (inkPoints.length === 2) {
var locx = inkPoints[0] - 0.5;
var locy = inkPoints[1] - 0.5;
var locw = inkPoints[0] + 0.5;
var loch = inkPoints[1] + 0.5;
inkPoints = [locx, locy, locw, loch];
isDot = true;
}
var point = new Array(inkPoints.length / 2);
var count = 0;
for (var j = 0; j < inkPoints.length; j = j + 2) {
point[count] = [inkPoints[j], inkPoints[j + 1]];
count++;
}
var pathPointCont = count + (count * 2) - 2;
var pathPoints = new Array(pathPointCont);
if (this._isEnableControlPoints) {
var p1 = [];
var p2 = [];
var value = this._getControlPoints(point, p1, p2);
p1 = value.controlP1;
p2 = value.controlP2;
var index = 0;
for (var i = 0; i < pathPointCont - 1; i = i + 3) {
pathPoints[i] = point[index];
pathPoints[i + 1] = p1[index];
pathPoints[i + 2] = p2[index];
index++;
}
}
else {
if (count % 3 === 1) {
pathPointCont = count;
pathPoints = new Array(pathPointCont);
pathPoints = point;
}
else if (count % 3 === 0) {
pathPointCont = count + 1;
pathPoints = new Array(pathPointCont);
for (var i = 0; i < point.length; i++) {
pathPoints[i] = point[i];
}
}
else {
pathPointCont = count + 2;
pathPoints = new Array(pathPointCont);
for (var i = 0; i < point.length; i++) {
pathPoints[i] = point[i];
}
pathPoints[pathPointCont - 2] = point[point.length - 2];
}
}
pathPoints[pathPointCont - 1] = point[point.length - 1];
if (pathPoints !== null) {
var pointsCollection = pathPoints;
for (var k = 0; k < pointsCollection.length; k++) {
var point_1 = pointsCollection[k];
pointsCollection[k] = [point_1[0], (-point_1[1])];
}
var path1 = new PdfPath();
var path2 = null;
if (isDot) {
var width = point[1][0] - point[0][0];
var height = point[1][1] - point[0][1];
path1.addEllipse({ x: point[0][0] + (0.5), y: -(point[0][1] + height + (0.5)), width: width, height: height });
path2 = new PdfPath();
path2._pathTypes = path1._pathTypes;
path2._points = path1._points;
}
else if (point.length === 2) {
path1.addLine({ x: point[0][0], y: -point[0][1] }, { x: point[1][0], y: -point[1][1] });
path2 = new PdfPath();
path2._pathTypes = path1._pathTypes;
path2._points = path1._points;
}
else {
path1._addBezierPoints(pointsCollection);
path2 = new PdfPath();
path2._pathTypes = path1._pathTypes;
path2._points = _convertNumberArraysToPoints(pointsCollection);
}
var borderPen = new PdfPen(this.color, this.border.width);
if (this._isLoaded) {
borderPen._lineCap = PdfLineCap.round;
}
if (typeof this.opacity !== 'undefined' && this._opacity < 1) {
var state = graphics.save();
graphics.setTransparency(this._opacity);
graphics.drawPath(path2, borderPen);
graphics.restore(state);
}
else {
graphics.drawPath(path2, borderPen);
}
}
}
if (this._isFlatten) {
if (this._page && this._page._isNew && this._page._pageSettings && this._page._pageSettings.margins) {
var margins = this._page._pageSettings.margins;
this.bounds = {
x: this.bounds.x - margins.left,
y: this._page.size.height - (this.bounds.y + this.bounds.height) - margins.top,
width: this.bounds.width,
height: this.bounds.height
};
}
else {
this.bounds = { x: this.bounds.x,
y: (this._page.size.height - (this.bounds.y + this.bounds.height)), width: this.bounds.width,
height: this.bounds.height };
}
}
}
return template;
};
/* eslint-disable */
/**
* Computes cubic Bézier control points for a sequence of knots to produce a smooth ink spline, returning paired control point arrays.
*
* @private
* @param {number[][]} point The knot points as [x,y] pairs.
* @param {number[][]} p1 Output array for the first control points.
* @param {number[][]} p2 Output array for the second control points.
* @returns {{ controlP1: Array<number[]>, controlP2: Array<number[]> }} result The paired control points.
*/
PdfInkAnnotation.prototype._getControlPoints = function (point, p1, p2) {
if (point === null) {
throw new Error('pointCollection');
}
var pointCount = point.length - 1;
if (pointCount < 1) {
throw new Error('At least two knot PointFs required pointCollection');
}
if (pointCount === 1) {
p1 = [[((2 * point[0][0] + point[1][0]) / 3), ((2 * point[0][1] + point[1][1]) / 3)]];
p2 = [[(2 * p1[0][0] - point[0][0]), (2 * p1[0][1] - point[0][1])]];
}
var rightVector = [];
for (var i = 1; i < pointCount - 1; ++i) {
rightVector[i] = 4 * point[i][0] + 2 * point[i + 1][0];
}
rightVector[0] = point[0][0] + 2 * point[1][0];
rightVector[pointCount - 1] = (8 * point[pointCount - 1][0] + point[pointCount][0]) / 2.0;
var xValue = this._getSingleControlPoint(rightVector);
for (var i = 1; i < pointCount - 1; ++i) {
rightVector[i] = 4 * point[i][1] + 2 * point[i + 1][1];
}
rightVector[0] = point[0][1] + 2 * point[1][1];
rightVector[pointCount - 1] = (8 * point[pointCount - 1][1] + point[pointCount][1]) / 2.0;
var yValue = this._getSingleControlPoint(rightVector);
p1 = new Array(pointCount);
p2 = new Array(pointCount);
for (var i = 0; i < pointCount; ++i) {
p1[i] = [xValue[i], yValue[i]];
if (i < pointCount - 1) {
p2[i] = [2 * point[i + 1][0] - xValue[i + 1], 2 * point[i + 1][1] - yValue[i + 1]];
}
else {
var x = (point[pointCount][0] + xValue[pointCount - 1]) / 2;
var y = (point[pointCount][1] + yValue[pointCount - 1]) / 2;
p2[i] = [x, y];
}
}
return { controlP1: p1, controlP2: p2 };
};
/* eslint-enable */
/**
* Solves a tridiagonal system to compute a single set of control point components from the right-hand side vector.
*
* @private
* @param {number[]} rightVector The right-hand side vector.
* @returns {number[]} vector The computed control point components.
*/
PdfInkAnnotation.prototype._getSingleControlPoint = function (rightVector) {
var count = rightVector.length;
var vector = [];
var tmpVector = [];
var divisor = 2.0;
vector[0] = rightVector[0] / divisor;
for (var i = 1; i < count; i++) {
tmpVector[i] = 1 / divisor;
divisor = (i < count - 1 ? 4.0 : 3.5) - tmpVector[i];
vector[i] = (rightVector[i] - vector[i - 1]) / divisor;
}
for (var i = 1; i < count; i++) {
vector[count - i - 1] -= tmpVector[count - i] * vector[count - i];
}
return vector;
};
/**
* Updates the InkList from current ink collections (respecting Crop/MediaBox offsets), synchronizes previous/modified state, and returns the resulting bounds.
*
* @private
* @returns {Rectangle} bounds The resulting bounds after updating the InkList.
*/
PdfInkAnnotation.prototype._addInkPoints = function () {
var _this = this;
var _a;
var inkCollection = [];
if (this._linePoints !== null && (this._previousCollection.length === 0 || this._isModified)) {
this._inkPointsCollection.unshift(this._linePoints);
}
if (this.inkPointsCollection.length === 0 && this._previousCollection.length > 0) {
this._inkPointsCollection = this._previousCollection;
}
var isEqual = _checkInkPoints(this._inkPointsCollection, this._previousCollection);
var inkPointsData = _convertPointsToNumberArrays(this._inkPointsCollection);
if (inkPointsData !== null && inkPointsData.length > 0 && !isEqual) {
inkPointsData.forEach(function (inkPoint) {
var inkList = inkPoint.slice();
inkCollection.push(inkList);
});
this._dictionary.update('InkList', inkCollection);
}
if (this._inkPointsCollection.length > 0 && (!isEqual || this._isModified)) {
(_a = this._previousCollection).push.apply(_a, this._inkPointsCollection);
this._isModified = false;
}
var cropOrMediaBox = this._getCropOrMediaBox();
var containsCropOrMediaBox = false;
if (cropOrMediaBox && cropOrMediaBox.length > 3 && typeof cropOrMediaBox[0] === 'number' && typeof cropOrMediaBox[1] === 'number' && (cropOrMediaBox[0] !== 0 || cropOrMediaBox[1] !== 0)) {
containsCropOrMediaBox = true;
inkCollection.forEach(function (inkList, i) {
var modifiedInkList = inkList;
for (var j = 0; j < inkList.length; j += 2) {
var x = inkList[j];
var y = inkList[j + 1];
x = x + cropOrMediaBox[0];
if (_this._page._pageDictionary.has('MediaBox') && !_this._page._pageDictionary.has('CropBox') &&
cropOrMediaBox[3] === 0 && cropOrMediaBox[1] > 0) {
y = y + cropOrMediaBox[3];
}
else {
y = y + cropOrMediaBox[1];
}
modifiedInkList[j] = x;
modifiedInkList[j + 1] = y;
inkCollection[i] = modifiedInkList;
}
});
this._dictionary.update('InkList', inkCollection);
}
if (this._isEnableControlPoints || containsCropOrMediaBox) {
var result = this._getInkBoundsValue(inkCollection);
return { x: result[0], y: result[1], width: result[2], height: result[3] };
}
else {
if (!this._isFlatten) {
this._updateInkListCollection(inkCollection);
}
return this.bounds;
}
};
/**
* Converts a flat numeric InkList into a collection of Point arrays and stores it in the ink points collection.
*
* @private
* @param {Array<number[]>} inkCollection The InkList numeric collection per stroke.
* @returns {void} void No return value.
*/
PdfInkAnnotation.prototype._updateInkListCollection = function (inkCollection) {
var pointCollection = inkCollection.map(function (innerArray) {
var points = [];
for (var i = 0; i < innerArray.length; i += 2) {
points.push({ x: innerArray[i], y: innerArray[i + 1] });
}
return points;
});
this._inkPointsCollection = pointCollection;
};
/**
* Calculates and returns the bounding rectangle for the current ink strokes, padding for border width when needed and updating the annotation bounds.
*
* @private
* @param {Array<number[]>} [inkCollection] Optional numeric InkList to base bounds on.
* @returns {number[]} bounds The [x, y, width, height] bounds of the ink.
*/
PdfInkAnnotation.prototype._getInkBoundsValue = function (inkCollection) {
var bounds = [0, 0, 0, 0];
if (this._points && this._points.length > 0) {
var firstPoint = this._points[0];
if (typeof firstPoint.x === 'number' && typeof firstPoint.y === 'number') {
if (this._points.length > 1) {
var secondPoint = this._points[1];
if (typeof secondPoint.x === 'number' && typeof secondPoint.y === 'number') {
this.bounds = {
x: firstPoint.x,
y: firstPoint.y,
width: secondPoint.x,
height: secondPoint.y
};
}
else {
this.bounds = { x: firstPoint.x, y: firstPoint.y, width: 0, height: 0 };
}
}
else {
this.bounds = { x: firstPoint.x, y: firstPoint.y, width: 0, height: 0 };
}
}
}
bounds = [this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height];
var borderWidth = this.border.width;
if (this._inkPointsCollection !== null) {
if (this._inkPointsCollection.length > 0) {
var termsList_1 = [];
var inkPointsCollection = _convertPointsToNumberArrays(this._inkPointsCollection);
inkPointsCollection.forEach(function (subList) {
if (subList !== null) {
if (subList.length % 2 === 0) {
termsList_1.push.apply(termsList_1, subList);
}
}
});
var isTwoPoints = false;
if (!this._isLoaded && termsList_1.length === 2) {
isTwoPoints = true;
termsList_1.push((termsList_1[0] + 1));
termsList_1.push((termsList_1[1] + 1));
}
var pointCollection = new Array(termsList_1.length / 2);
var count = 0;
for (var j = 0; j < termsList_1.length; j = j + 2) {
pointCollection[count] = [termsList_1[j],
termsList_1[j + 1]];
count++;
}
if (this._isLoaded) {
if (pointCollection.length > 0) {
var xMin_1 = 0;
var yMin_1 = 0;
var xMax_1 = 0;
var yMax_1 = 0;
var first_1 = true;
pointCollection.forEach(function (point) {
if (first_1) {
xMin_1 = point[0];
yMin_1 = point[1];
first_1 = false;
}
else {
if (point[0] < xMin_1) {
xMin_1 = point[0];
}
else if (point[0] > xMax_1) {
xMax_1 = point[0];
}
if (point[1] < yMin_1) {
yMin_1 = point[1];
}
else if (point[1] > yMax_1) {
yMax_1 = point[1];
}
}
});
bounds = [xMin_1, yMin_1, xMax_1 - xMin_1, yMax_1 - yMin_1];
this.bounds = { x: bounds[0], y: bounds[1], width: bounds[2], height: bounds[3] };
if (this._isFlatten || this._setAppearance) {
bounds[0] = this.bounds.x - borderWidth;
bounds[1] = this.bounds.y - borderWidth;
bounds[2] = this.bounds.width + (2 * borderWidth);
bounds[3] = this.bounds.height + (2 * borderWidth);
}
}
else {
if (this._points) {
bounds = _convertPointToNumberArray(this._points);
}
else if (pointCollection.length > 0) {
bounds = this._dictionary.get('Rect');
}
else {
bounds = [this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height];
}
}
}
else if (inkCollection) {
bounds = this._calculateInkBounds(pointCollection, bounds, borderWidth, isTwoPoints, inkCollection);
}
else {
bounds = this._calculateInkBounds(pointCollection, bounds, borderWidth, isTwoPoints);
}
if (Array.isArray(bounds) && bounds.length > 0) {
var x = typeof bounds[0] === 'number' ? bounds[0] : 0;
var y = typeof bounds[1] === 'number' ? bounds[1] : 0;
var width = typeof bounds[2] === 'number' ? bounds[2] : 0;
var height = typeof bounds[3] === 'number' ? bounds[3] : 0;
this.bounds = { x: x, y: y, width: width, height: height };
}
}
}
return bounds;
};
PdfInkAnnotation.prototype._calculateInkBounds = function (pointCollection, bounds, borderWidth, isTwoPoints, inkCollection) {
if (pointCollection.length > 5) {
var xMin_2 = 0;
var yMin_2 = 0;
var xMax_2 = 0;
var yMax_2 = 0;
var first_2 = true;
pointCollection.forEach(function (point) {
if (first_2) {
xMin_2 = point[0];
yMin_2 = point[1];
xMax_2 = point[0];
yMax_2 = point[1];
first_2 = false;
}
else {
if (point[0] < xMin_2) {
xMin_2 = point[0];
}
else if (point[0] > xMax_2) {
xMax_2 = point[0];
}
if (point[1] < yMin_2) {
yMin_2 = point[1];
}
else if (point[1] > yMax_2) {
yMax_2 = point[1];
}
}
});
var cropOrMediaBox = this._getCropOrMediaBox();
if (bounds[2] < xMax_2) {
xMax_2 = bounds[2];
}
else if (cropOrMediaBox) {
xMax_2 = xMax_2 - xMin_2;
}
if (bounds[3] < yMax_2) {
yMax_2 = bounds[3];
}
else if (cropOrMediaBox) {
yMax_2 = yMax_2 - yMin_2;
}
if (cropOrMediaBox) {
xMin_2 = xMin_2 + cropOrMediaBox[0];
yMin_2 = yMin_2 + cropOrMediaBox[1];
}
bounds = [xMin_2, yMin_2, xMax_2, yMax_2];
if (this._isFlatten || this._setAppearance) {
var factor = isTwoPoints ? 2 : 3;
bounds[0] = bounds[0] - borderWidth;
bounds[1] = bounds[1] - borderWidth;
bounds[2] = bounds[2] + (factor * borderWidth);
bounds[3] = bounds[3] + (factor * borderWidth);
}
}
else {
if (typeof this._points === 'undefined' && pointCollection.length > 0) {
bounds = this._dictionary.get('Rect');
}
else {
bounds = _convertPointToNumberArray(this._points);
}
}
if (!this._isFlatten && inkCollection) {
this._updateInkListCollection(inkCollection);
}
return bounds;
};
/**
* Retrieves the InkList from the annotation dictionary and flattens each strokes coordinate pairs into number arrays, preserving perstroke grouping.
*
* @private
* @returns {Array<number[]>} path The InkList as flat number arrays per stroke.
*/
PdfInkAnnotation.prototype._obtainInkListCollection = function () {
var path = [];
if (this._dictionary.has('InkList')) {
var inkList = this._dictionary.getArray('InkList');
var list = [];
for (var i = 0; i < inkList.length; i++) {
var innerList = inkList[i];
for (var j = 0; j < innerList.length; j++) {
list.push(innerList[j]);
}
path.push(list);
if (list.length === innerList.length) {
list = [];
}
}
}
return path;
};
return PdfInkAnnotation;
}(PdfComment));
export { PdfInkAnnotation };
/**
* `PdfPopupAnnotation` class represents the popup annotation objects.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Create a new popup annotation
* const annotation: PdfPopupAnnotation = new PdfPopupAnnotation('Test popup annotation', {x: 10, y: 40, width: 30, height: 30});
* // Add annotation to the page
* page.annotations.add(annotation);
* // Destroy the document
* document.destroy();
* ```
*/
var PdfPopupAnnotation = /** @class */ (function (_super) {
__extends(PdfPopupAnnotation, _super);
function PdfPopupAnnotation(arg1, bounds, properties) {
var _this = _super.call(this) || this;
/**
* Specifies the icon used to represent the popup annotation.
*
* @private
*/
_this._icon = PdfPopupIcon.note;
_this._iconString = '';
/**
* Defines the state model (e.g., review status) of the annotation.
*
* @private
*/
_this._stateModel = PdfAnnotationStateModel.none;
/**
* Indicates the current state within the state model.
*
* @private
*/
_this._state = PdfAnnotationState.none;
/**
* Specifies whether the popup is initially open.
*
* @private
*/
_this._open = false;
/**
* Indicates whether this popup participates in review workflows.
*
* @private
*/
_this._isReview = false;
/**
* Flags whether this popup is a comment entry.
*
* @private
*/
_this._isComment = false;
/**
* Stores the first half of the vector drawing commands for the comment icon.
*
* @private
*/
_this._comment = 'q 1 1 1 rg 0 i 1 w 4 M 1 j 0 J []0 d 1 0 0 1 9 5.0908 cm 7.74 12.616 m -7.74 12.616 l -8.274 12.616 -8.707 12.184 -8.707 11.649 c h f Q 0 G ';
/**
* Stores the second half of the vector drawing commands for the comment icon.
*
* @private
*/
_this._commentSecondHalf = '0 i 0.60 w 4 M 1 j 0 J [0 100]1 d 1 0 0 1 9 5.0908 cm 4.1 1.71 m -0.54 -2.29 l -0.54 1.71 l -5.5 1.71 l -5.5 14.42 l 10.5 14.42 l 10.5 1.71 l 4.1 1.71 l -2.33 9.66 m 7.34 9.66 l 7.34 8.83 l -2.33 8.83 l -2.33 9.66 l -2.33 7.28 m 5.88 7.28 l 5.88 6.46 l -2.33 6.46 l -2.33 7.28 l 14.9 23.1235 m -14.9 23.1235 l -14.9 -20.345 l 14.9 -20.345 l 14.9 23.1235 l b ';
/**
* Stores the vector drawing commands for the note icon.
*
* @private
*/
_this._note = '0 G 0 i 0.61 w 4 M 0 j 0 J []0 d q 1 0 0 1 16.959 1.3672 cm 0 0 m 0 -0.434 -0.352 -0.785 -0.784 -0.785 c -14.911 -0.785 l -15.345 -0.785 -15.696 -0.434 -15.696 0 c -15.696 17.266 l -15.696 17.699 -15.345 18.051 -14.911 18.051 c -0.784 18.051 l -0.352 18.051 0 17.699 0 17.266 c h b Q q 1 0 0 1 4.4023 13.9243 cm 0 0 m 9.418 0 l S Q q 1 0 0 1 4.4019 11.2207 cm 0 0 m 9.418 0 l S Q q 1 0 0 1 4.4023 8.5176 cm 0 0 m 9.418 0 l S Q q 1 0 0 1 4.4023 5.8135 cm 0 0 m 9.418 0 l S Q ';
/**
* Stores the first half of the vector path for the help icon.
*
* @private
*/
_this._help = 'q 1 1 1 rg 0 i 1 w 4 M 1 j 0 J []0 d 1 0 0 1 12.1465 10.5137 cm -2.146 9.403 m -7.589 9.403 -12.001 4.99 -12.001 -0.453 c -12.001 -5.895 -7.589 -10.309 -2.146 -10.309 c 3.296 -10.309 7.709 -5.895 7.709 -0.453 c 7.709 4.99 3.296 9.403 -2.146 9.403 c h f Q ';
/**
* Stores the second half of the vector path for the help icon.
*
* @private
*/
_this._helpSecondHalf = ' 0 G 0 i 0.59 w 4 M 1 j 0 J []0 d 1 0 0 1 12.1465 10.5137 cm 0 0 m -0.682 -0.756 -0.958 -1.472 -0.938 -2.302 c -0.938 -2.632 l -3.385 -2.632 l -3.403 -2.154 l -3.459 -1.216 -3.147 -0.259 -2.316 0.716 c -1.729 1.433 -1.251 2.022 -1.251 2.647 c -1.251 3.291 -1.674 3.715 -2.594 3.751 c -3.202 3.751 -3.937 3.531 -4.417 3.2 c -5.041 5.205 l -4.361 5.591 -3.274 5.959 -1.968 5.959 c 0.46 5.959 1.563 4.616 1.563 3.089 c 1.563 1.691 0.699 0.771 0 0 c -2.227 -6.863 m -2.245 -6.863 l -3.202 -6.863 -3.864 -6.146 -3.864 -5.189 c -3.864 -4.196 -3.182 -3.516 -2.227 -3.516 c -1.233 -3.516 -0.589 -4.196 -0.57 -5.189 c -0.57 -6.146 -1.233 -6.863 -2.227 -6.863 c -2.146 9.403 m -7.589 9.403 -12.001 4.99 -12.001 -0.453 c -12.001 -5.895 -7.589 -10.309 -2.146 -10.309 c 3.296 -10.309 7.709 -5.895 7.709 -0.453 c 7.709 4.99 3.296 9.403 -2.146 9.403 c b ';
/**
* Stores the vector path definition for the insert icon.
*
* @private
*/
_this._insert = ' 0 i 0.59 w 4 M 0 j 0 J []0 d 1 0 0 1 8.5386 19.8545 cm 0 0 m -8.39 -19.719 l 8.388 -19.719 l h B ';
/**
* Stores the first half of the vector path for the key icon.
*
* @private
*/
_this._key = 'q 1 1 1 rg 0 i 1 w 4 M 1 j 0 J []0 d 1 0 0 1 6.5 12.6729 cm 0.001 5.138 m -2.543 5.138 -4.604 3.077 -4.604 0.534 c -4.604 -1.368 -3.449 -3.001 -1.802 -3.702 c -1.802 -4.712 l -0.795 -5.719 l -1.896 -6.82 l -0.677 -8.039 l -1.595 -8.958 l -0.602 -9.949 l -1.479 -10.829 l -0.085 -12.483 l 1.728 -10.931 l 1.728 -3.732 l 1.737 -3.728 1.75 -3.724 1.76 -3.721 c 3.429 -3.03 4.604 -1.385 4.604 0.534 c 4.604 3.077 2.542 5.138 0.001 5.138 c f Q ';
/**
* Stores the second half of the vector path for the key icon.
*
* @private
*/
_this._keySecondHalf = ' 0 G 0 i 0.59 w 4 M 1 j 0 J []0 d 1 0 0 1 6.5 12.6729 cm 0 0 m -1.076 0 -1.95 0.874 -1.95 1.95 c -1.95 3.028 -1.076 3.306 0 3.306 c 1.077 3.306 1.95 3.028 1.95 1.95 c 1.95 0.874 1.077 0 0 0 c 0.001 5.138 m -2.543 5.138 -4.604 3.077 -4.604 0.534 c -4.604 -1.368 -3.449 -3.001 -1.802 -3.702 c -1.802 -4.712 l -0.795 -5.719 l -1.896 -6.82 l -0.677 -8.039 l -1.595 -8.958 l -0.602 -9.949 l -1.479 -10.829 l -0.085 -12.483 l 1.728 -10.931 l 1.728 -3.732 l 1.737 -3.728 1.75 -3.724 1.76 -3.721 c 3.429 -3.03 4.604 -1.385 4.604 0.534 c 4.604 3.077 2.542 5.138 0.001 5.138 c b ';
/**
* Stores the first half of the vector path for the new paragraph icon.
*
* @private
*/
_this._newParagraph = '1 0.819611 0 rg 0 G 0 i 0.58 w 4 M 0 j 0 J []0 d ';
/**
* Stores the second half of the vector path for the new paragraph icon.
*
* @private
*/
_this._newParagraphSecondHalf = ' 0 G 0 i 0.59 w 4 M 1 j 0 J []0 d q 1 0 0 1 6.4995 20 cm 0 0 m -6.205 -12.713 l 6.205 -12.713 l h b Q q 1 0 0 1 1.1909 6.2949 cm 0 0 m 1.278 0 l 1.353 0 1.362 -0.02 1.391 -0.066 c 2.128 -1.363 3.78 -4.275 3.966 -4.713 c 3.985 -4.713 l 3.976 -4.453 3.957 -3.91 3.957 -3.137 c 3.957 -0.076 l 3.957 -0.02 3.976 0 4.041 0 c 4.956 0 l 5.021 0 5.04 -0.029 5.04 -0.084 c 5.04 -6.049 l 5.04 -6.113 5.021 -6.133 4.947 -6.133 c 3.695 -6.133 l 3.621 -6.133 3.611 -6.113 3.574 -6.066 c 3.052 -4.955 1.353 -2.063 0.971 -1.186 c 0.961 -1.186 l 0.999 -1.68 0.999 -2.146 1.008 -3.025 c 1.008 -6.049 l 1.008 -6.104 0.989 -6.133 0.933 -6.133 c 0.009 -6.133 l -0.046 -6.133 -0.075 -6.123 -0.075 -6.049 c -0.075 -0.066 l -0.075 -0.02 -0.056 0 0 0 c f Q q 1 0 0 1 9.1367 3.0273 cm 0 0 m 0.075 0 0.215 -0.008 0.645 -0.008 c 1.4 -0.008 2.119 0.281 2.119 1.213 c 2.119 1.969 1.633 2.381 0.737 2.381 c 0.354 2.381 0.075 2.371 0 2.361 c h -1.146 3.201 m -1.146 3.238 -1.129 3.268 -1.082 3.268 c -0.709 3.275 0.02 3.285 0.729 3.285 c 2.613 3.285 3.248 2.314 3.258 1.232 c 3.258 -0.27 2.007 -0.914 0.607 -0.914 c 0.327 -0.914 0.057 -0.914 0 -0.904 c 0 -2.789 l 0 -2.836 -0.019 -2.865 -0.074 -2.865 c -1.082 -2.865 l -1.119 -2.865 -1.146 -2.846 -1.146 -2.799 c h f Q ';
/**
* Stores the first half of the vector path for the paragraph icon.
*
* @private
*/
_this._paragraph = 'q 1 1 1 rg 0 i 1 w 4 M 1 j 0 J []0 d 1 0 0 1 19.6973 10.0005 cm 0 0 m 0 -5.336 -4.326 -9.662 -9.663 -9.662 c -14.998 -9.662 -19.324 -5.336 -19.324 0 c -19.324 5.335 -14.998 9.662 -9.663 9.662 c -4.326 9.662 0 5.335 0 0 c h f Q ';
/**
* Stores the second half of the vector path for the paragraph icon.
*
* @private
*/
_this._paragraphSecondHalf = '0 G 0 i 0.59 w 4 M 1 j 0 J []0 d q 1 0 0 1 19.6973 10.0005 cm 0 0 m 0 -5.336 -4.326 -9.662 -9.663 -9.662 c -14.998 -9.662 -19.324 -5.336 -19.324 0 c -19.324 5.335 -14.998 9.662 -9.663 9.662 c -4.326 9.662 0 5.335 0 0 c h S Q q 1 0 0 1 11.6787 2.6582 cm 0 0 m -1.141 0 l -1.227 0 -1.244 0.052 -1.227 0.139 c -0.656 1.157 -0.52 2.505 -0.52 3.317 c -0.52 3.594 l -2.833 3.783 -5.441 4.838 -5.441 8.309 c -5.441 10.778 -3.714 12.626 -0.57 13.024 c -0.535 13.508 -0.381 14.129 -0.242 14.389 c -0.207 14.44 -0.174 14.475 -0.104 14.475 c 1.088 14.475 l 1.156 14.475 1.191 14.458 1.175 14.372 c 1.105 14.095 0.881 13.127 0.881 12.402 c 0.881 9.431 0.932 7.324 0.95 4.06 c 0.95 2.298 0.708 0.813 0.189 0.07 c 0.155 0.034 0.103 0 0 0 c b Q ';
_this._dictionary = new _PdfDictionary();
_this._dictionary.update('Type', _PdfName.get('Annot'));
_this._dictionary.update('Subtype', _PdfName.get('Text'));
if (arg1 !== null && typeof arg1 !== 'undefined' && typeof arg1 === 'string') {
_this.text = arg1;
}
else if (arg1 && typeof arg1 === 'object') {
properties = arg1;
}
if (bounds) {
_this.bounds = bounds;
}
_this._type = _PdfAnnotationType.popupAnnotation;
if (properties) {
if ('author' in properties && _isNullOrUndefined(properties.author)) {
_this.author = properties.author;
}
if ('subject' in properties && _isNullOrUndefined(properties.subject)) {
_this.subject = properties.subject;
}
if ('color' in properties && _isNullOrUndefined(properties.color)) {
_this.color = properties.color;
}
if ('icon' in properties && _isNullOrUndefined(properties.icon)) {
_this.icon = properties.icon;
}
if ('open' in properties && _isNullOrUndefined(properties.open)) {
_this.open = properties.open;
}
if ('state' in properties && _isNullOrUndefined(properties.state)) {
_this.state = properties.state;
}
if ('stateModel' in properties && _isNullOrUndefined(properties.stateModel)) {
_this.stateModel = properties.stateModel;
}
}
return _this;
}
Object.defineProperty(PdfPopupAnnotation.prototype, "open", {
/**
* Gets the boolean flag indicating whether annotation has open or not.
*
* @returns {boolean} Caption.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfPopupAnnotation = page.annotations.at(0) as PdfPopupAnnotation;
* // Gets the boolean flag indicating whether annotation has open or not.
* let open: boolean = annotation.open;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (this._dictionary.has('Open')) {
this._open = this._dictionary.get('Open');
}
return this._open;
},
/**
* Sets the boolean flag indicating whether annotation has open or not.
*
* @param {boolean} value Open.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfPopupAnnotation = page.annotations.at(0) as PdfPopupAnnotation;
* // Sets the boolean flag indicating whether annotation has open or not.
* annotation.open = true;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (typeof value !== 'undefined') {
this._open = value;
this._dictionary.update('Open', this._open);
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfPopupAnnotation.prototype, "icon", {
/**
* Gets the icon type of the popup annotation.
*
* @returns {PdfPopupIcon} Annotation icon.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfPopupAnnotation = page.annotations.at(0) as PdfPopupAnnotation;
* // Gets the icon type of the popup annotation.
* let icon: PdfPopupIcon = annotation.icon;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (this._dictionary.has('Name')) {
this._icon = _mapPopupIcon(this._dictionary.get('Name').name);
}
return this._icon;
},
/**
* Sets the icon type of the popup annotation.
*
* @param {PdfPopupIcon} value Annotation icon.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfPopupAnnotation = page.annotations.at(0) as PdfPopupAnnotation;
* // Sets the icon type of the popup annotation.
* annotation.icon = PdfPopupIcon.newParagraph;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (typeof value !== 'undefined') {
this._icon = value;
this._dictionary.update('Name', _PdfName.get(this._obtainIconName(this._icon)));
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfPopupAnnotation.prototype, "stateModel", {
/**
* Gets the state model of the popup annotation.
*
* @returns {PdfAnnotationStateModel} Annotation State Model.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfPopupAnnotation = page.annotations.at(0) as PdfPopupAnnotation;
* // Gets the state model of the popup annotation.
* let stateModel: PdfAnnotationStateModel = annotation.stateModel;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (this._dictionary.has('StateModel')) {
this._stateModel = _mapAnnotationStateModel(this._dictionary.get('StateModel'));
}
return this._stateModel;
},
/**
* Sets the state model of the popup annotation.
*
* @param {PdfAnnotationStateModel} value Annotation State Model.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfPopupAnnotation = page.annotations.at(0) as PdfPopupAnnotation;
* // Sets the state model of the popup annotation.
* annotation.stateModel = PdfAnnotationStateModel.marked;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (typeof value !== 'undefined') {
this._stateModel = value;
this._dictionary.update('StateModel', _reverseMapAnnotationStateModel(this._stateModel));
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfPopupAnnotation.prototype, "state", {
/**
* Gets the state of the popup annotation.
*
* @returns {PdfAnnotationState} Annotation State.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfPopupAnnotation = page.annotations.at(0) as PdfPopupAnnotation;
* // Gets the state of the popup annotation.
* let state: PdfAnnotationState = annotation.state;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (this._dictionary.has('State')) {
this._state = _mapAnnotationState(this._dictionary.get('State'));
}
return this._state;
},
/**
* Sets the state of the popup annotation.
*
* @param {PdfAnnotationState} value Annotation State.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfPopupAnnotation = page.annotations.at(0) as PdfPopupAnnotation;
* // Sets the state of the popup annotation.
* annotation.state = PdfAnnotationState.completed;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (typeof value !== 'undefined') {
this._state = value;
this._dictionary.update('State', _reverseMapAnnotationState(this._state));
}
},
enumerable: true,
configurable: true
});
/**
* Loads a popup annotation from the given page and dictionary, marks it as loaded, initializes state, and sets review/comment flags from IRT.
*
* @private
* @param {PdfPage} page The page that contains the annotation.
* @param {_PdfDictionary} dictionary The source annotation dictionary to load.
* @returns {PdfPopupAnnotation} annot The loaded popup annotation instance.
*/
PdfPopupAnnotation._load = function (page, dictionary) {
var annot = new PdfPopupAnnotation();
annot._isLoaded = true;
annot._initialize(page, dictionary);
if (dictionary.has('IRT')) {
annot._isReview = _checkReview(dictionary);
if (!annot._isReview) {
annot._isComment = _checkComment(dictionary);
}
}
return annot;
};
/**
* Initializes the popup annotation for the specified page and optional source dictionary by delegating to the base initializer.
*
* @private
* @param {PdfPage} page The page to associate with the annotation.
* @param {_PdfDictionary} [dictionary] Optional source dictionary for loading.
* @returns {void} void No return value.
*/
PdfPopupAnnotation.prototype._initialize = function (page, dictionary) {
_super.prototype._initialize.call(this, page, dictionary);
};
/**
* Completes setup by validating bounds, ensuring BS default, updating Rect, and creating or attaching the appearance stream when required.
*
* @private
* @returns {void} void No return value.
*/
PdfPopupAnnotation.prototype._postProcess = function () {
if (typeof this.bounds === 'undefined' || this.bounds === null) {
this._bounds = { x: 0, y: 0, width: 0, height: 0 };
}
var borderWidth;
if (this._dictionary.has('BS')) {
borderWidth = this.border.width;
}
else {
var dictionary = new _PdfDictionary(this._crossReference);
dictionary.set('Type', _PdfName.get('Border'));
this._dictionary.set('BS', dictionary);
}
if (typeof borderWidth === 'undefined') {
borderWidth = 1;
}
var rectangle = [this.bounds.x, this.bounds.y, (this.bounds.x + this.bounds.width),
(this.bounds.y + this.bounds.height)];
this._dictionary.update('Rect', rectangle);
if (this._setAppearance || this._customTemplate.size > 0) {
var appearance = void 0;
if (this._dictionary.has('AP')) {
appearance = this._dictionary.get('AP');
}
else {
var reference = this._crossReference._getNextReference();
appearance = new _PdfDictionary(this._crossReference);
this._crossReference._cacheMap.set(reference, appearance);
this._dictionary.update('AP', reference);
}
if (this._customTemplate.size > 0) {
this._appearanceTemplate = this._customTemplate.get('N');
this._drawCustomAppearance(appearance);
}
else {
this._appearanceTemplate = this._createPopupAppearance();
if (this._appearanceTemplate) {
_removeDuplicateReference(this._dictionary.get('AP'), this._crossReference, 'N');
this._appearanceTemplate._content.dictionary._updated = true;
var reference = this._crossReference._getNextReference();
this._crossReference._cacheMap.set(reference, this._appearanceTemplate._content);
this._appearanceTemplate._content.reference = reference;
appearance.set('N', reference);
appearance._updated = true;
}
}
}
this._dictionary.update('Rect', _updateBounds(this));
};
/**
* Builds or imports the popup appearance as needed, optionally draws it during flattening, flattens the template, and removes the annotation when done.
*
* @private
* @param {boolean} [isFlatten=false] Whether to flatten the annotation to page content.
* @returns {void} void No return value.
*/
PdfPopupAnnotation.prototype._doPostProcess = function (isFlatten) {
if (isFlatten === void 0) { isFlatten = false; }
if (this._isLoaded) {
if (!this._appearanceTemplate && this._isFlattenPopups && this._dictionary.has('AP')) {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
var appearanceStream = dictionary.get('N');
var reference = dictionary.getRaw('N');
if (appearanceStream) {
if (reference) {
appearanceStream.reference = reference;
}
this._appearanceTemplate = new PdfTemplate(appearanceStream, this._crossReference);
}
if (this._appearanceTemplate !== null) {
var state = this._page.graphics.save();
if (this.opacity < 1) {
this._page.graphics.setTransparency(this.opacity);
}
this._page.graphics.drawTemplate(this._appearanceTemplate, this.bounds);
this._page.graphics.restore(state);
}
}
}
}
else {
this._postProcess();
if (!this._appearanceTemplate) {
if (isFlatten) {
if (!this._dictionary.has('AP')) {
this._appearanceTemplate = this._createPopupAppearance();
}
else {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
var appearanceStream = dictionary.get('N');
var reference = dictionary.getRaw('N');
if (appearanceStream) {
if (reference) {
appearanceStream.reference = reference;
}
this._appearanceTemplate = new PdfTemplate(appearanceStream, this._crossReference);
}
}
}
}
}
}
if (typeof this.flattenPopups !== 'undefined' && this.flattenPopups && this.flatten) {
if (this._isLoaded) {
this._flattenLoadedPopUp();
}
else {
this._flattenPopUp();
}
}
if (isFlatten && this._appearanceTemplate) {
var isNormalMatrix = this._validateTemplateMatrix(this._appearanceTemplate._content.dictionary);
this._flattenAnnotationTemplate(this._appearanceTemplate, isNormalMatrix);
}
if (isFlatten) {
this._removeAnnotation(this._page, this);
}
};
/**
* Creates the popup appearance template and writes the icon’s drawing commands (with optional color and opacity) based on the selected popup icon.
*
* @private
* @returns {PdfTemplate} template The created appearance template.
*/
PdfPopupAnnotation.prototype._createPopupAppearance = function () {
var nativeRectangle = [0, 0, this.bounds.width, this.bounds.height];
var template = new PdfTemplate(nativeRectangle, this._crossReference);
var graphics = template.graphics;
graphics._sw._clear();
if (this.opacity < 1) {
graphics.save();
graphics.setTransparency(this.opacity);
}
switch (this.icon) {
case PdfPopupIcon.comment:
graphics._sw._write(this._comment);
if (this.color) {
graphics._sw._setColorSpace([this.color.r, this.color.g, this.color.b], _PdfColorSpace.rgb, false);
}
graphics._sw._write(this._commentSecondHalf);
break;
case PdfPopupIcon.paragraph:
graphics._sw._write(this._paragraph);
if (this.color) {
graphics._sw._setColorSpace([this.color.r, this.color.g, this.color.b], _PdfColorSpace.rgb, false);
}
graphics._sw._write(this._paragraphSecondHalf);
break;
case PdfPopupIcon.help:
graphics._sw._write(this._help);
if (this.color) {
graphics._sw._setColorSpace([this.color.r, this.color.g, this.color.b], _PdfColorSpace.rgb, false);
}
graphics._sw._write(this._helpSecondHalf);
break;
case PdfPopupIcon.note:
if (this.color) {
graphics._sw._setColorSpace([this.color.r, this.color.g, this.color.b], _PdfColorSpace.rgb, false);
}
graphics._sw._write(this._note);
break;
case PdfPopupIcon.insert:
graphics._sw._write('0 G ');
if (this.color) {
graphics._sw._setColorSpace([this.color.r, this.color.g, this.color.b], _PdfColorSpace.rgb, false);
}
graphics._sw._write(this._insert);
break;
case PdfPopupIcon.key:
graphics._sw._write(this._key);
if (this.color) {
graphics._sw._setColorSpace([this.color.r, this.color.g, this.color.b], _PdfColorSpace.rgb, false);
}
graphics._sw._write(this._keySecondHalf);
break;
case PdfPopupIcon.newParagraph:
graphics._sw._write(this._newParagraph);
if (this.color) {
graphics._sw._setColorSpace([this.color.r, this.color.g, this.color.b], _PdfColorSpace.rgb, false);
}
graphics._sw._write(this._newParagraphSecondHalf);
break;
}
if (this.opacity < 1) {
graphics.restore();
}
return template;
};
/**
* Maps the popup icon enum to its canonical name string and returns it.
*
* @private
* @param {PdfPopupIcon} icon The popup icon enum value.
* @returns {string} iconName The canonical icon name.
*/
PdfPopupAnnotation.prototype._obtainIconName = function (icon) {
switch (icon) {
case PdfPopupIcon.note:
this._iconString = 'Note';
break;
case PdfPopupIcon.comment:
this._iconString = 'Comment';
break;
case PdfPopupIcon.help:
this._iconString = 'Help';
break;
case PdfPopupIcon.insert:
this._iconString = 'Insert';
break;
case PdfPopupIcon.key:
this._iconString = 'Key';
break;
case PdfPopupIcon.newParagraph:
this._iconString = 'NewParagraph';
break;
case PdfPopupIcon.paragraph:
this._iconString = 'Paragraph';
break;
}
return this._iconString;
};
return PdfPopupAnnotation;
}(PdfComment));
export { PdfPopupAnnotation };
/**
* `PdfFileLinkAnnotation` class represents the link annotation objects.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Create a new file link annotation
* let annotation: PdfFileLinkAnnotation = new PdfFileLinkAnnotation({x: 10, y: 40, width: 30, height: 30}, "image.png");
* // Add annotation to the page
* page.annotations.add(annotation);
* // Destroy the document
* document.destroy();
* ```
*/
var PdfFileLinkAnnotation = /** @class */ (function (_super) {
__extends(PdfFileLinkAnnotation, _super);
function PdfFileLinkAnnotation(bounds, fileName, properties) {
var _this = _super.call(this) || this;
_this._dictionary = new _PdfDictionary();
_this._dictionary.update('Type', _PdfName.get('Annot'));
_this._dictionary.update('Subtype', _PdfName.get('Link'));
if (bounds) {
_this.bounds = bounds;
}
if (typeof fileName !== 'undefined' && fileName !== null) {
_this._fileName = fileName;
}
_this._type = _PdfAnnotationType.fileLinkAnnotation;
if (properties) {
if ('text' in properties && _isNullOrUndefined(properties.text)) {
_this.text = properties.text;
}
if ('author' in properties && _isNullOrUndefined(properties.author)) {
_this.author = properties.author;
}
if ('subject' in properties && _isNullOrUndefined(properties.subject)) {
_this.subject = properties.subject;
}
if ('color' in properties && _isNullOrUndefined(properties.color)) {
_this.color = properties.color;
}
if ('opacity' in properties && _isNullOrUndefined(properties.opacity)) {
_this.opacity = properties.opacity;
}
if ('action' in properties && _isNullOrUndefined(properties.action)) {
_this.action = properties.action;
}
}
return _this;
}
Object.defineProperty(PdfFileLinkAnnotation.prototype, "action", {
/**
* Gets the action of the annotation.
*
* @returns {string} Action.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfFileLinkAnnotation = page.annotations.at(0) as PdfFileLinkAnnotation;
* // Gets the action of the annotation.
* let action: string = annotation.action;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
var _this = this;
if (typeof this._action === 'undefined' && this._dictionary.has('A')) {
var dictionary = this._dictionary.get('A');
if (dictionary && dictionary.has('Next')) {
var action = dictionary.get('Next');
if (Array.isArray(action)) {
action.forEach(function (reference) {
if (reference && reference instanceof _PdfReference) {
var actionDictionary = _this._crossReference._fetch(reference);
if (actionDictionary.has('JS')) {
_this._action = actionDictionary.get('JS');
}
}
});
}
}
}
return this._action;
},
/**
* Sets the action of the annotation.
*
* @param {string} value Action.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfFileLinkAnnotation = page.annotations.at(0) as PdfFileLinkAnnotation;
* // Sets the action of the annotation.
* annotation.action = "app.alert('Launching file');";
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
var _this = this;
if (!this._isLoaded && typeof value === 'string') {
this._action = value;
}
if (this._isLoaded && typeof value === 'string') {
if (this.action !== value && this._dictionary.has('A')) {
var dictionary = this._dictionary.get('A');
if (dictionary && dictionary.has('Next')) {
var action = dictionary.get('Next');
if (Array.isArray(action)) {
action.forEach(function (reference) {
if (reference && reference instanceof _PdfReference) {
var actionDictionary = _this._crossReference._fetch(reference);
if (actionDictionary.has('JS')) {
actionDictionary.update('JS', value);
_this._action = value;
_this._dictionary._updated = true;
}
}
});
}
}
}
}
},
enumerable: true,
configurable: true
});
/**
* Loads a file link annotation from the given page and dictionary, marks it as loaded, and initializes internal state.
*
* @private
* @param {PdfPage} page The page that contains the annotation.
* @param {_PdfDictionary} dictionary The source annotation dictionary to load.
* @returns {PdfFileLinkAnnotation} annot The loaded file link annotation instance.
*/
PdfFileLinkAnnotation._load = function (page, dictionary) {
var annot = new PdfFileLinkAnnotation();
annot._isLoaded = true;
annot._initialize(page, dictionary);
return annot;
};
/**
* Initializes the file link annotation for the specified page and optional source dictionary by delegating to the base initializer.
*
* @private
* @param {PdfPage} page The page to associate with the annotation.
* @param {_PdfDictionary} [dictionary] Optional source dictionary for loading.
* @returns {void} void No return value.
*/
PdfFileLinkAnnotation.prototype._initialize = function (page, dictionary) {
_super.prototype._initialize.call(this, page, dictionary);
};
/**
* Finalizes the annotation setup: validates bounds, ensures BS defaults, applies the launch action, and updates the Rect entry.
*
* @private
* @returns {void} void No return value.
*/
PdfFileLinkAnnotation.prototype._postProcess = function () {
if (typeof this.bounds === 'undefined' || this.bounds === null) {
throw new Error('Bounds cannot be null or undefined');
}
var borderWidth;
if (this._dictionary.has('BS')) {
borderWidth = this.border.width;
}
else {
var dictionary = new _PdfDictionary(this._crossReference);
dictionary.set('Type', _PdfName.get('Border'));
this._dictionary.set('BS', dictionary);
}
if (typeof borderWidth === 'undefined') {
borderWidth = 1;
}
this._addAction();
this._dictionary.update('Rect', _updateBounds(this));
};
/**
* Builds and assigns the annotations launch action dictionary, removes outdated references, and attaches optional JavaScript or nested actions.
*
* @private
* @returns {void} void No return value.
*/
PdfFileLinkAnnotation.prototype._addAction = function () {
var _this = this;
if (this._dictionary.has('A')) {
var action = this._dictionary.get('A');
if (action) {
if (typeof this._action !== 'undefined' && this._action !== null && action.has('Next')) {
var nextAction = action.get('Next');
if (Array.isArray(nextAction) && nextAction.length > 0) {
nextAction.forEach(function (reference) {
if (reference && reference instanceof _PdfReference && reference._isNew) {
_this._crossReference._cacheMap.delete(reference);
}
});
}
}
if (action.has('F')) {
_removeDuplicateReference(action, this._crossReference, 'F');
}
}
_removeDuplicateReference(this._dictionary, this._crossReference, 'A');
}
var dictionary = new _PdfDictionary();
dictionary.set('Type', _PdfName.get('Action'));
dictionary.set('S', _PdfName.get('Launch'));
var fileDictionary = new _PdfDictionary();
fileDictionary.set('Type', _PdfName.get('Filespec'));
fileDictionary.set('UF', this._fileName);
if (typeof this._action !== 'undefined' && this._action !== null) {
var actionDictionary = new _PdfDictionary();
actionDictionary.set('Type', _PdfName.get('Action'));
actionDictionary.set('S', _PdfName.get('JavaScript'));
actionDictionary.set('JS', this._action);
var ref = this._crossReference._getNextReference();
this._crossReference._cacheMap.set(ref, actionDictionary);
actionDictionary._updated = true;
dictionary.set('Next', [ref]);
}
var reference = this._crossReference._getNextReference();
this._crossReference._cacheMap.set(reference, fileDictionary);
fileDictionary._updated = true;
dictionary.set('F', reference);
dictionary._updated = true;
this._dictionary.set('A', dictionary);
};
/**
* Performs post processing after load or flattening, importing or generating appearance streams and flattening or removing the annotation when required.
*
* @private
* @param {boolean} [isFlatten=false] Whether to flatten the annotation to page content.
* @returns {void} void No return value.
*/
PdfFileLinkAnnotation.prototype._doPostProcess = function (isFlatten) {
if (isFlatten === void 0) { isFlatten = false; }
if (!this._isLoaded) {
this._postProcess();
}
if (isFlatten) {
var appearanceStream = void 0;
if (this._dictionary.has('AP')) {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
appearanceStream = dictionary.get('N');
var reference = dictionary.getRaw('N');
if (reference && appearanceStream) {
appearanceStream.reference = reference;
}
}
}
if (appearanceStream) {
var template = new PdfTemplate(appearanceStream, this._crossReference);
var isNormalMatrix = this._validateTemplateMatrix(template._content.dictionary);
this._flattenAnnotationTemplate(template, isNormalMatrix);
}
else {
this._removeAnnotation(this._page, this);
}
}
};
return PdfFileLinkAnnotation;
}(PdfAnnotation));
export { PdfFileLinkAnnotation };
/**
* `PdfUriAnnotation` class represents the URI annotation objects.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Create a new URI annotation
* let annotation: PdfUriAnnotation = new PdfUriAnnotation({x: 100, y: 150, width: 200, height: 100}, 'http://www.google.com');
* // Add annotation to the page
* page.annotations.add(annotation);
* // Destroy the document
* document.destroy();
* ```
*/
var PdfUriAnnotation = /** @class */ (function (_super) {
__extends(PdfUriAnnotation, _super);
function PdfUriAnnotation(bounds, uri, properties) {
var _this = _super.call(this) || this;
_this._dictionary = new _PdfDictionary();
_this._dictionary.update('Type', _PdfName.get('Annot'));
_this._dictionary.update('Subtype', _PdfName.get('Link'));
if (bounds) {
_this.bounds = bounds;
}
if (typeof uri !== 'undefined' && uri !== null) {
_this._uri = uri;
}
_this._type = _PdfAnnotationType.uriAnnotation;
if (properties) {
if ('text' in properties && _isNullOrUndefined(properties.text)) {
_this.text = properties.text;
}
if ('author' in properties && _isNullOrUndefined(properties.author)) {
_this.author = properties.author;
}
if ('subject' in properties && _isNullOrUndefined(properties.subject)) {
_this.subject = properties.subject;
}
if ('color' in properties && _isNullOrUndefined(properties.color)) {
_this.color = properties.color;
}
if ('innerColor' in properties && _isNullOrUndefined(properties.innerColor)) {
_this.innerColor = properties.innerColor;
}
if ('opacity' in properties && _isNullOrUndefined(properties.opacity)) {
_this.opacity = properties.opacity;
}
if ('border' in properties && _isNullOrUndefined(properties.border)) {
_this.border = properties.border;
}
}
return _this;
}
Object.defineProperty(PdfUriAnnotation.prototype, "uri", {
/**
* Gets the uri of the annotation.
*
* @returns {string} Uri.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfUriAnnotation = page.annotations.at(0) as PdfUriAnnotation;
* // Gets the uri of the annotation.
* let uri: string = annotation.uri;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._uri === 'undefined' && this._dictionary.has('A')) {
var linkDict = this._dictionary.get('A');
if (linkDict.has('URI')) {
this._uri = linkDict.get('URI');
}
}
return this._uri;
},
/**
* Sets the uri of the annotation.
*
* @param {string} value Uri.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Create a new URI annotation
* let annotation: PdfUriAnnotation = new PdfUriAnnotation(100, 150, 200, 100);
* // Sets the uri of the annotation
* annotation.uri = 'http://www.google.com';
* // Add annotation to the page
* page.annotations.add(annotation);
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (typeof value === 'string') {
if (this._isLoaded && this._dictionary.has('A') && value !== this.uri) {
var linkDict = this._dictionary.get('A');
if (linkDict.has('URI')) {
this._uri = value;
linkDict.update('URI', value);
this._dictionary._updated = true;
}
}
else {
this._uri = value;
}
}
},
enumerable: true,
configurable: true
});
/**
* Loads a URI link annotation from the given page and dictionary, marks it as loaded, and initializes internal state.
*
* @private
* @param {PdfPage} page The page that contains the annotation.
* @param {_PdfDictionary} dictionary The source annotation dictionary to load.
* @returns {PdfUriAnnotation} annot The loaded URI annotation instance.
*/
PdfUriAnnotation._load = function (page, dictionary) {
var annot = new PdfUriAnnotation();
annot._isLoaded = true;
annot._initialize(page, dictionary);
return annot;
};
/**
* Initializes the URI link annotation for the specified page and optional source dictionary by delegating to the base initializer.
*
* @private
* @param {PdfPage} page The page to associate with the annotation.
* @param {_PdfDictionary} [dictionary] Optional source dictionary for loading.
* @returns {void} void No return value.
*/
PdfUriAnnotation.prototype._initialize = function (page, dictionary) {
_super.prototype._initialize.call(this, page, dictionary);
};
/**
* Finalizes the annotation setup: validates bounds, ensures BS defaults, applies the URI action, and updates the Rect entry.
*
* @private
* @returns {void} void No return value.
*/
PdfUriAnnotation.prototype._postProcess = function () {
if (typeof this.bounds === 'undefined' || this.bounds === null) {
throw new Error('Bounds cannot be null or undefined');
}
var borderWidth;
if (this._dictionary.has('BS')) {
borderWidth = this.border.width;
}
else {
var dictionary = new _PdfDictionary(this._crossReference);
dictionary.set('Type', _PdfName.get('Border'));
this._dictionary.set('BS', dictionary);
}
if (typeof borderWidth === 'undefined') {
borderWidth = 1;
}
this._addAction();
this._dictionary.update('Rect', _updateBounds(this));
};
/**
* Creates and assigns the URI action dictionary (S=URI, URI value) and updates the Border array on the annotation.
*
* @private
* @returns {void} void No return value.
*/
PdfUriAnnotation.prototype._addAction = function () {
var dictionary = new _PdfDictionary();
dictionary.set('Type', _PdfName.get('Action'));
dictionary.set('S', _PdfName.get('URI'));
if (typeof this._uri !== 'undefined') {
dictionary.set('URI', this._uri);
}
dictionary._updated = true;
this._dictionary.set('A', dictionary);
this._dictionary.update('Border', [this.border.hRadius, this.border.vRadius, this.border.width]);
};
/**
* Performs post-processing after load or during flattening: imports or generates the appearance stream and flattens or removes the annotation as needed.
*
* @private
* @param {boolean} [isFlatten=false] Whether to flatten the annotation to page content.
* @returns {void} void No return value.
*/
PdfUriAnnotation.prototype._doPostProcess = function (isFlatten) {
if (isFlatten === void 0) { isFlatten = false; }
if (!this._isLoaded) {
this._postProcess();
}
if (isFlatten) {
var appearanceStream = void 0;
if (this._dictionary.has('AP')) {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
appearanceStream = dictionary.get('N');
var reference = dictionary.getRaw('N');
if (reference && appearanceStream) {
appearanceStream.reference = reference;
}
}
}
if (appearanceStream) {
var template = new PdfTemplate(appearanceStream, this._crossReference);
var isNormalMatrix = this._validateTemplateMatrix(template._content.dictionary);
this._flattenAnnotationTemplate(template, isNormalMatrix);
}
else {
this._removeAnnotation(this._page, this);
}
}
};
return PdfUriAnnotation;
}(PdfAnnotation));
export { PdfUriAnnotation };
/**
* `PdfDocumentLinkAnnotation` class represents the document link annotation objects.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Create a new document link annotation
* let annotation: PdfDocumentLinkAnnotation = new PdfDocumentLinkAnnotation({x: 100, y: 150, width: 40, height: 60});
* // Add annotation to the page
* page.annotations.add(annotation);
* // Destroy the document
* document.destroy();
* ```
*/
var PdfDocumentLinkAnnotation = /** @class */ (function (_super) {
__extends(PdfDocumentLinkAnnotation, _super);
function PdfDocumentLinkAnnotation(bounds, destination, properties) {
var _this = _super.call(this) || this;
_this._dictionary = new _PdfDictionary();
_this._dictionary.update('Type', _PdfName.get('Annot'));
_this._dictionary.update('Subtype', _PdfName.get('Link'));
if (bounds !== null && typeof bounds !== 'undefined') {
_this.bounds = bounds;
}
if (destination !== null && typeof destination !== 'undefined') {
_this.destination = destination;
}
_this._type = _PdfAnnotationType.documentLinkAnnotation;
if (properties) {
if ('text' in properties && _isNullOrUndefined(properties.text)) {
_this.text = properties.text;
}
if ('author' in properties && _isNullOrUndefined(properties.author)) {
_this.author = properties.author;
}
if ('subject' in properties && _isNullOrUndefined(properties.subject)) {
_this.subject = properties.subject;
}
if ('color' in properties && _isNullOrUndefined(properties.color)) {
_this.color = properties.color;
}
if ('innerColor' in properties && _isNullOrUndefined(properties.innerColor)) {
_this.innerColor = properties.innerColor;
}
if ('opacity' in properties && _isNullOrUndefined(properties.opacity)) {
_this.opacity = properties.opacity;
}
if ('border' in properties && _isNullOrUndefined(properties.border)) {
_this.border = properties.border;
}
}
return _this;
}
Object.defineProperty(PdfDocumentLinkAnnotation.prototype, "destination", {
/**
* Gets the destination of the annotation.
*
* @returns {PdfDestination} Destination.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfDocumentLinkAnnotation = page.annotations.at(0) as PdfDocumentLinkAnnotation;
* // Gets the destination of the annotation.
* let destination: PdfDestination =annotation.destination;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (this._isLoaded && !this._destination) {
var destinationHelper = void 0;
if (this._dictionary.has('Dest')) {
destinationHelper = new _PdfDestinationHelper(this._dictionary, 'Dest');
this.destination = destinationHelper._obtainDestination();
}
else if (!this._destination && this._dictionary.has('A')) {
var action = this._dictionary.get('A');
if (action && action instanceof _PdfDictionary && action.has('D')) {
destinationHelper = new _PdfDestinationHelper(action, 'D');
this.destination = destinationHelper._obtainDestination();
}
}
}
return this._destination;
},
/**
* Sets the destination of the annotation.
*
* @param {PdfDestination} value Destination.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Access first page
* let page: PdfPage = document.getPage(0);
* // Access the annotation at index 0
* let annotation: PdfDocumentLinkAnnotation = page.annotations.at(0) as PdfDocumentLinkAnnotation;
* // Initializes a new instance of the `PdfDestination` class.
* let destination: PdfDestination = new PdfDestination();
* // Sets the zoom factor.
* destination.zoom = 20;
* // Sets the page where the destination is situated.
* destination.page = page;
* // Sets the mode of the destination.
* destination.mode = PdfDestinationMode.fitToPage;
* // Sets the location of the destination.
* destination.location = {x: 20, y: 20};
* // Sets the bounds of the destination.
* destination.destinationBounds = {x: 20, y: 20, width: 100, height: 50};
* // Sets destination to document link annotation.
* annotation.destination = destination;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value) {
this._destination = value;
if (this._isLoaded) {
this._destination._initializePrimitive();
}
}
},
enumerable: true,
configurable: true
});
/**
* Loads a document link annotation from the given page and dictionary, marks it as loaded, and initializes internal state.
*
* @private
* @param {PdfPage} page The page that contains the annotation.
* @param {_PdfDictionary} dictionary The source annotation dictionary to load.
* @returns {PdfDocumentLinkAnnotation} annot The loaded document-link annotation instance.
*/
PdfDocumentLinkAnnotation._load = function (page, dictionary) {
var annot = new PdfDocumentLinkAnnotation();
annot._isLoaded = true;
annot._initialize(page, dictionary);
return annot;
};
/**
* Initializes the document link annotation for the specified page and optional source dictionary by delegating to the base initializer.
*
* @private
* @param {PdfPage} page The page to associate with the annotation.
* @param {_PdfDictionary} [dictionary] Optional source dictionary for loading.
* @returns {void} void No return value.
*/
PdfDocumentLinkAnnotation.prototype._initialize = function (page, dictionary) {
_super.prototype._initialize.call(this, page, dictionary);
};
/**
* Finalizes setup by validating bounds, assigning the destination entry if present, and updating the Rect value.
*
* @private
* @returns {void} void No return value.
*/
PdfDocumentLinkAnnotation.prototype._postProcess = function () {
if (typeof this.bounds === 'undefined' || this.bounds === null) {
throw new Error('Bounds cannot be null or undefined');
}
this._addDocument();
this._dictionary.update('Rect', _updateBounds(this));
};
/**
* Writes the annotations destination array into the dictionary when a destination is defined.
*
* @private
* @returns {void} void No return value.
*/
PdfDocumentLinkAnnotation.prototype._addDocument = function () {
if (this.destination) {
this._dictionary.set('Dest', this.destination._array);
}
};
/**
* Completes post processing after load or during flattening, updating Dest when needed and flattening or removing the annotation based on appearance availability.
*
* @private
* @param {boolean} [isFlatten=false] Whether to flatten the annotation to page content.
* @returns {void} void No return value.
*/
PdfDocumentLinkAnnotation.prototype._doPostProcess = function (isFlatten) {
if (isFlatten === void 0) { isFlatten = false; }
if (!this._isLoaded) {
this._postProcess();
}
else if (this._destination) {
this._dictionary.update('Dest', this._destination._array);
}
if (isFlatten) {
var appearanceStream = void 0;
if (this._dictionary.has('AP')) {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
appearanceStream = dictionary.get('N');
var reference = dictionary.getRaw('N');
if (reference && appearanceStream) {
appearanceStream.reference = reference;
}
}
}
if (appearanceStream) {
var template = new PdfTemplate(appearanceStream, this._crossReference);
var isNormalMatrix = this._validateTemplateMatrix(template._content.dictionary);
this._flattenAnnotationTemplate(template, isNormalMatrix);
}
else {
this._removeAnnotation(this._page, this);
}
}
};
return PdfDocumentLinkAnnotation;
}(PdfAnnotation));
export { PdfDocumentLinkAnnotation };
/**
* `PdfTextWebLinkAnnotation` class represents the link annotation objects.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Create a new PDF string format
* const format: PdfStringFormat = new PdfStringFormat(PdfTextAlignment.left, PdfVerticalAlignment.top);
* // Create a new standard font
* const font: PdfStandardFont = new PdfStandardFont(PdfFontFamily.helvetica, 10, PdfFontStyle.regular);
* // Get the text size
* let size: number[] = font.measureString("Syncfusion Site", format, {width: 0, height: 0}, 0, 0);
* // Create a new text web link annotation
* let annot: PdfTextWebLinkAnnotation = new PdfTextWebLinkAnnotation({x: 50, y: 40, width: size.width, height: size.height}, {r: 0, g: 0, b: 0}, {r: 165, g: 42, b: 42}, 1);
* // Add annotation to the page
* page.annotations.add(annotation);
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
var PdfTextWebLinkAnnotation = /** @class */ (function (_super) {
__extends(PdfTextWebLinkAnnotation, _super);
function PdfTextWebLinkAnnotation(bounds, brushColor, penColor, penWidth, properties) {
var _this = _super.call(this) || this;
_this._isActionAdded = false;
_this._dictionary = new _PdfDictionary();
_this._dictionary.update('Type', _PdfName.get('Annot'));
_this._dictionary.update('Subtype', _PdfName.get('Link'));
if (bounds) {
_this.bounds = bounds;
}
_this._textWebLink = (properties && typeof properties.text !== 'undefined' && properties.text !== null) ? properties.text : '';
if (typeof brushColor !== 'undefined' && brushColor !== null) {
_this._brush = new PdfBrush(brushColor);
}
if (typeof penColor !== 'undefined' && penColor !== null) {
_this._pen = new PdfPen(penColor, penWidth ? penWidth : 1);
}
_this._type = _PdfAnnotationType.textWebLinkAnnotation;
if (properties) {
if ('url' in properties && _isNullOrUndefined(properties.url)) {
_this.url = properties.url;
}
if ('font' in properties && _isNullOrUndefined(properties.font)) {
_this.font = properties.font;
}
if ('text' in properties && _isNullOrUndefined(properties.text)) {
_this.text = properties.text;
}
if ('author' in properties && _isNullOrUndefined(properties.author)) {
_this.author = properties.author;
}
if ('subject' in properties && _isNullOrUndefined(properties.subject)) {
_this.subject = properties.subject;
}
if ('color' in properties && _isNullOrUndefined(properties.color)) {
_this.color = properties.color;
}
if ('opacity' in properties && _isNullOrUndefined(properties.opacity)) {
_this.opacity = properties.opacity;
}
if ('border' in properties && _isNullOrUndefined(properties.border)) {
_this.border = properties.border;
}
}
return _this;
}
Object.defineProperty(PdfTextWebLinkAnnotation.prototype, "font", {
/**
* Gets the font of the annotation.
*
* @returns {PdfFont} font.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfTextWebLinkAnnotation = page.annotations.at(0) as PdfTextWebLinkAnnotation;
* // Gets the font of the annotation.
* let font: PdfFont = annotation.font;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
return this._font;
},
/**
* Sets the font of the annotation.
*
* @param {PdfFont} value font.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfTextWebLinkAnnotation = page.annotations.at(0) as PdfTextWebLinkAnnotation;
* // Sets the font of the annotation.
* annotation.font = document.embedFont(PdfFontFamily.helvetica, 10, PdfFontStyle.regular);
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
this._font = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfTextWebLinkAnnotation.prototype, "url", {
/**
* Gets the url of the annotation.
*
* @returns {string} Url.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfTextWebLinkAnnotation = page.annotations.at(0) as PdfTextWebLinkAnnotation;
* // Gets the URL of the annotation.
* let url: string = annotation.url;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._url === 'undefined' && this._dictionary.has('A')) {
var linkDict = this._dictionary.get('A');
if (linkDict.has('URI')) {
this._url = linkDict.get('URI');
}
}
return this._url;
},
/**
* Sets the url of the annotation.
*
* @param {string} value Url.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfTextWebLinkAnnotation = page.annotations.at(0) as PdfTextWebLinkAnnotation;
* // Sets the URL of the annotation.
* annotation.url = 'http://www.syncfusion.com';
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (typeof value === 'string') {
if (this._isLoaded && this._dictionary.has('A')) {
var linkSource = this._dictionary._get('A'); // eslint-disable-line
var linkDict = this._dictionary.get('A');
if (linkDict && linkDict.has('URI')) {
this._url = value;
linkDict.update('URI', value);
if (!(linkSource instanceof _PdfReference)) {
this._dictionary._updated = linkDict._updated;
}
}
}
else {
this._url = value;
}
}
},
enumerable: true,
configurable: true
});
/**
* Loads a text weblink annotation from the given page and dictionary, marks it as loaded, and initializes internal state.
*
* @private
* @param {PdfPage} page The page that contains the annotation.
* @param {_PdfDictionary} dictionary The source annotation dictionary to load.
* @returns {PdfTextWebLinkAnnotation} annot The loaded text web link annotation instance.
*/
PdfTextWebLinkAnnotation._load = function (page, dictionary) {
var annot = new PdfTextWebLinkAnnotation();
annot._isLoaded = true;
annot._initialize(page, dictionary);
return annot;
};
/**
* Initializes the text weblink annotation for the specified page and optional source dictionary by delegating to the base initializer.
*
* @private
* @param {PdfPage} page The page to associate with the annotation.
* @param {_PdfDictionary} [dictionary] Optional source dictionary for loading.
* @returns {void} void No return value.
*/
PdfTextWebLinkAnnotation.prototype._initialize = function (page, dictionary) {
_super.prototype._initialize.call(this, page, dictionary);
};
/**
* Finalizes setup by validating bounds, adding the URI action once, and updating the annotation rectangle.
*
* @private
* @returns {void} void No return value.
*/
PdfTextWebLinkAnnotation.prototype._postProcess = function () {
if (typeof this.bounds === 'undefined' || this.bounds === null) {
throw new Error('Bounds cannot be null or undefined');
}
if (!this._isActionAdded) {
this._addAction();
this._isActionAdded = true;
}
this._dictionary.update('Rect', _updateBounds(this));
};
/**
* Draws the link text on the page using the configured font and colors, creates the URI action dictionary, and disables the visible border.
*
* @private
* @returns {void} void No return value.
*/
PdfTextWebLinkAnnotation.prototype._addAction = function () {
var rect = [this.bounds.x, this.bounds.y, this.bounds.width, this.bounds.height];
if (typeof this.font === 'undefined' || this.font === null) {
this.font = this._lineCaptionFont;
}
var format = new PdfStringFormat(PdfTextAlignment.left, PdfVerticalAlignment.top);
this._page.graphics.drawString(this._textWebLink, this.font, { x: rect[0], y: rect[1],
width: rect[2], height: rect[3] }, this._pen, this._brush, format);
var dictionary = new _PdfDictionary();
dictionary.set('Type', _PdfName.get('Action'));
dictionary.set('S', _PdfName.get('URI'));
if (typeof this._url !== 'undefined') {
dictionary.set('URI', this._url);
}
dictionary._updated = true;
this._dictionary.set('A', dictionary);
this._dictionary.update('Border', [0, 0, 0]);
};
/**
* Performs final processing after load or during flattening, importing and flattening the appearance stream when available or removing the annotation if none exists.
*
* @private
* @param {boolean} [isFlatten=false] Whether to flatten the annotation to page content.
* @returns {void} void No return value.
*/
PdfTextWebLinkAnnotation.prototype._doPostProcess = function (isFlatten) {
if (isFlatten === void 0) { isFlatten = false; }
if (!this._isLoaded) {
this._postProcess();
}
if (isFlatten) {
var appearanceStream = void 0;
if (this._dictionary.has('AP')) {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
appearanceStream = dictionary.get('N');
var reference = dictionary.getRaw('N');
if (reference && appearanceStream) {
appearanceStream.reference = reference;
}
}
}
if (appearanceStream) {
var template = new PdfTemplate(appearanceStream, this._crossReference);
var isNormalMatrix = this._validateTemplateMatrix(template._content.dictionary);
this._flattenAnnotationTemplate(template, isNormalMatrix);
}
else {
this._removeAnnotation(this._page, this);
}
}
};
return PdfTextWebLinkAnnotation;
}(PdfAnnotation));
export { PdfTextWebLinkAnnotation };
/**
* `PdfAttachmentAnnotation` class represents the attachment annotation objects.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Create a new attachment annotation
* const annotation: PdfAttachmentAnnotation = new PdfAttachmentAnnotation({x: 300, y: 200, width: 30, height: 30}, 'Nature.jpg', imageData);
* // Add annotation to the page
* page.annotations.add(annotation);
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
var PdfAttachmentAnnotation = /** @class */ (function (_super) {
__extends(PdfAttachmentAnnotation, _super);
function PdfAttachmentAnnotation(bounds, fileName, data, properties) {
var _this = _super.call(this) || this;
/**
* Specifies the icon used to display the file attachment.
*
* @private
*/
_this._icon = PdfAttachmentIcon.pushPin;
_this._iconString = '';
_this._dictionary = new _PdfDictionary();
_this._dictionary.update('Type', _PdfName.get('Annot'));
_this._dictionary.update('Subtype', _PdfName.get('FileAttachment'));
if (bounds) {
_this.bounds = bounds;
}
if (typeof fileName !== 'undefined') {
_this._fileName = fileName;
}
_this._stream = new _PdfStream(typeof data === 'string' ? _decode(data) : data);
_this._type = _PdfAnnotationType.fileAttachmentAnnotation;
if (properties) {
if ('icon' in properties && _isNullOrUndefined(properties.icon)) {
_this.icon = properties.icon;
}
if ('text' in properties && _isNullOrUndefined(properties.text)) {
_this.text = properties.text;
}
if ('author' in properties && _isNullOrUndefined(properties.author)) {
_this.author = properties.author;
}
if ('subject' in properties && _isNullOrUndefined(properties.subject)) {
_this.subject = properties.subject;
}
if ('color' in properties && _isNullOrUndefined(properties.color)) {
_this.color = properties.color;
}
if ('opacity' in properties && _isNullOrUndefined(properties.opacity)) {
_this.opacity = properties.opacity;
}
if ('border' in properties && _isNullOrUndefined(properties.border)) {
_this.border = properties.border;
}
}
return _this;
}
Object.defineProperty(PdfAttachmentAnnotation.prototype, "icon", {
/**
* Gets the icon type of the attachment annotation.
*
* @returns {PdfAttachmentIcon} Annotation icon.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfAttachmentAnnotation = page.annotations.at(0) as PdfAttachmentAnnotation;
* // Gets the icon type of the attachment annotation.
* let icon: PdfAttachmentIcon = annotation.icon;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (this._dictionary.has('Name')) {
this._icon = _mapAttachmentIcon(this._dictionary.get('Name').name);
}
return this._icon;
},
/**
* Sets the icon type of the attachment annotation.
*
* @param {PdfAttachmentIcon} value Annotation icon.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfAttachmentAnnotation = page.annotations.at(0) as PdfAttachmentAnnotation;
* // Sets the icon type of the attachment annotation.
* annotation.icon = PdfAttachmentIcon.pushPin;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (typeof value !== 'undefined') {
this._icon = value;
this._dictionary.update('Name', _PdfName.get(this._obtainIconName(this._icon)));
}
},
enumerable: true,
configurable: true
});
/**
* Loads an attachment annotation from the given page and dictionary, marks it as loaded, and initializes internal state.
*
* @private
* @param {PdfPage} page The page that contains the annotation.
* @param {_PdfDictionary} dictionary The source annotation dictionary to load.
* @returns {PdfAttachmentAnnotation} annot The loaded attachment annotation instance.
*/
PdfAttachmentAnnotation._load = function (page, dictionary) {
var annot = new PdfAttachmentAnnotation();
annot._isLoaded = true;
annot._initialize(page, dictionary);
return annot;
};
/**
* Initializes the attachment annotation for the specified page and optional source dictionary by delegating to the base initializer.
*
* @private
* @param {PdfPage} page The page to associate with the annotation.
* @param {_PdfDictionary} [dictionary] Optional source dictionary for loading.
* @returns {void} void No return value.
*/
PdfAttachmentAnnotation.prototype._initialize = function (page, dictionary) {
_super.prototype._initialize.call(this, page, dictionary);
};
/**
* Finalizes annotation setup by validating bounds, updating the Rect entry, and creating or updating the embedded file attachment.
*
* @private
* @returns {void} void No return value.
*/
PdfAttachmentAnnotation.prototype._postProcess = function () {
if (typeof this.bounds === 'undefined' || this.bounds === null) {
throw new Error('Bounds cannot be null or undefined');
}
this._dictionary.update('Rect', _updateBounds(this));
this._addAttachment();
};
/**
* Creates or updates the embedded file specification, writes the embedded file stream, assigns references, and updates the FS entry in the dictionary.
*
* @private
* @returns {void} void No return value.
*/
PdfAttachmentAnnotation.prototype._addAttachment = function () {
if (this._dictionary.has('FS')) {
var fileSpecification = this._dictionary.get('FS');
if (fileSpecification && fileSpecification.has('EF')) {
var embeddedFile = fileSpecification.get('EF');
if (embeddedFile && embeddedFile.has('F')) {
_removeDuplicateReference(embeddedFile, this._crossReference, 'F');
}
}
_removeDuplicateReference(this._dictionary, this._crossReference, 'FS');
}
var fileSpectDictionary = new _PdfDictionary();
fileSpectDictionary.set('Type', _PdfName.get('Filespec'));
fileSpectDictionary.set('Desc', this._fileName);
fileSpectDictionary.set('F', this._fileName);
fileSpectDictionary.set('UF', this._fileName);
var fileDictionary = new _PdfDictionary();
fileDictionary.set('Type', _PdfName.get('EmbeddedFile'));
var paramsDictionary = new _PdfDictionary();
var dateTime = new Date();
paramsDictionary.set('CreationDate', dateTime.toTimeString());
paramsDictionary.set('ModDate', new Date().toTimeString());
paramsDictionary.set('Size', this._stream.length);
fileDictionary.set('Params', paramsDictionary);
this._stream.dictionary = new _PdfDictionary();
this._stream.dictionary = fileDictionary;
fileDictionary._crossReference = this._crossReference;
var char1 = this._crossReference._newLine.charCodeAt(0);
var char2 = this._crossReference._newLine.charCodeAt(1);
var buffer = [char1, char2, 37, 80, 68, 70, 45];
fileDictionary._crossReference._writeObject(this._stream, buffer);
var reference = this._crossReference._getNextReference();
this._crossReference._cacheMap.set(reference, this._stream);
fileDictionary._updated = true;
var efileDictionary = new _PdfDictionary();
efileDictionary.set('F', reference);
fileSpectDictionary.set('EF', efileDictionary);
var fsReference = this._crossReference._getNextReference();
this._crossReference._cacheMap.set(fsReference, fileSpectDictionary);
fileSpectDictionary._updated = true;
this._dictionary.update('FS', fsReference);
};
/**
* Performs post processing after loading or during flattening by importing or generating the appearance stream and flattening or removing the annotation when needed.
*
* @private
* @param {boolean} [isFlatten=false] Whether to flatten the annotation to page content.
* @returns {void} void No return value.
*/
PdfAttachmentAnnotation.prototype._doPostProcess = function (isFlatten) {
if (isFlatten === void 0) { isFlatten = false; }
if (!this._isLoaded) {
this._postProcess();
}
if (isFlatten) {
var appearanceStream = void 0;
if (this._dictionary.has('AP')) {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
appearanceStream = dictionary.get('N');
var reference = dictionary.getRaw('N');
if (reference && appearanceStream) {
appearanceStream.reference = reference;
}
}
}
if (appearanceStream) {
var template = new PdfTemplate(appearanceStream, this._crossReference);
var isNormalMatrix = this._validateTemplateMatrix(template._content.dictionary);
this._flattenAnnotationTemplate(template, isNormalMatrix);
}
else {
this._removeAnnotation(this._page, this);
}
}
};
/**
* Maps the attachment icon enum value to its corresponding standard icon name string and returns it.
*
* @private
* @param {PdfAttachmentIcon} icon The attachment icon value.
* @returns {string} iconName The canonical icon name.
*/
PdfAttachmentAnnotation.prototype._obtainIconName = function (icon) {
switch (icon) {
case PdfAttachmentIcon.pushPin:
this._iconString = 'PushPin';
break;
case PdfAttachmentIcon.tag:
this._iconString = 'Tag';
break;
case PdfAttachmentIcon.graph:
this._iconString = 'Graph';
break;
case PdfAttachmentIcon.paperClip:
this._iconString = 'Paperclip';
break;
}
return this._iconString;
};
return PdfAttachmentAnnotation;
}(PdfComment));
export { PdfAttachmentAnnotation };
/**
* `Pdf3DAnnotation` class represents the 3D annotation objects.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Access first page
* let page: PdfPage = document.getPage(0);
* // Access the annotation at index 0
* let annotation: Pdf3DAnnotation = page.annotations.at(0) as Pdf3DAnnotation;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
var Pdf3DAnnotation = /** @class */ (function (_super) {
__extends(Pdf3DAnnotation, _super);
/**
* Initializes a new instance of the `Pdf3DAnnotation` class.
*
* @private
*/
function Pdf3DAnnotation() {
var _this = _super.call(this) || this;
_this._type = _PdfAnnotationType.movieAnnotation;
return _this;
}
/**
* Loads a 3D annotation from the given page and dictionary, marks it as loaded, and initializes internal state.
*
* @private
* @param {PdfPage} page The page that contains the annotation.
* @param {_PdfDictionary} dictionary The source annotation dictionary to load.
* @returns {Pdf3DAnnotation} annot The loaded 3D annotation instance.
*/
Pdf3DAnnotation._load = function (page, dictionary) {
var annot = new Pdf3DAnnotation();
annot._isLoaded = true;
annot._initialize(page, dictionary);
return annot;
};
/**
* Initializes the 3D annotation for the specified page and optional source dictionary by delegating to the base initializer.
*
* @private
* @param {PdfPage} page The page to associate with the annotation.
* @param {_PdfDictionary} [dictionary] Optional source dictionary for loading.
* @returns {void} void No return value.
*/
Pdf3DAnnotation.prototype._initialize = function (page, dictionary) {
_super.prototype._initialize.call(this, page, dictionary);
};
/**
* Performs post processing during flattening by importing the appearance stream when available or removing the annotation when none exists.
*
* @private
* @param {boolean} [isFlatten=false] Whether to flatten the annotation to page content.
* @returns {void} void No return value.
*/
Pdf3DAnnotation.prototype._doPostProcess = function (isFlatten) {
if (isFlatten === void 0) { isFlatten = false; }
if (isFlatten) {
var appearanceStream = void 0;
if (this._dictionary.has('AP')) {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
appearanceStream = dictionary.get('N');
var reference = dictionary.getRaw('N');
if (reference && appearanceStream) {
appearanceStream.reference = reference;
}
}
}
if (appearanceStream) {
var template = new PdfTemplate(appearanceStream, this._crossReference);
var isNormalMatrix = this._validateTemplateMatrix(template._content.dictionary);
this._flattenAnnotationTemplate(template, isNormalMatrix);
}
else {
this._removeAnnotation(this._page, this);
}
}
};
return Pdf3DAnnotation;
}(PdfAnnotation));
export { Pdf3DAnnotation };
/**
* `PdfTextMarkupAnnotation` class represents the text markup annotation objects.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Create a new text markup annotation
* let annotation: PdfTextMarkupAnnotation = new PdfTextMarkupAnnotation('Text markup', {x: 50, y: 100, width: 100, height: 50});
* // Add annotation to the page
* page.annotations.add(annotation);
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
var PdfTextMarkupAnnotation = /** @class */ (function (_super) {
__extends(PdfTextMarkupAnnotation, _super);
function PdfTextMarkupAnnotation(text, bounds, properties) {
var _this = _super.call(this) || this;
/**
* Defines the text markup type (highlight, underline, etc.).
*
* @private
*/
_this._textMarkupType = PdfTextMarkupAnnotationType.highlight;
_this._dictionary = new _PdfDictionary();
_this._dictionary.update('Type', _PdfName.get('Annot'));
if (typeof text !== 'undefined') {
_this._text = text;
}
if (bounds) {
_this.bounds = bounds;
}
_this._type = _PdfAnnotationType.textMarkupAnnotation;
if (properties) {
if ('boundsCollection' in properties && _isNullOrUndefined(properties.boundsCollection)) {
_this.boundsCollection = properties.boundsCollection;
}
if ('author' in properties && _isNullOrUndefined(properties.author)) {
_this.author = properties.author;
}
if ('subject' in properties && _isNullOrUndefined(properties.subject)) {
_this.subject = properties.subject;
}
if ('innerColor' in properties && _isNullOrUndefined(properties.innerColor)) {
_this.innerColor = properties.innerColor;
}
if ('textMarkUpColor' in properties && _isNullOrUndefined(properties.textMarkUpColor)) {
_this.textMarkUpColor = properties.textMarkUpColor;
}
if ('textMarkupType' in properties && _isNullOrUndefined(properties.textMarkupType)) {
_this.textMarkupType = properties.textMarkupType;
}
if ('opacity' in properties && _isNullOrUndefined(properties.opacity)) {
_this.opacity = properties.opacity;
}
if ('border' in properties && _isNullOrUndefined(properties.border)) {
_this.border = properties.border;
}
}
return _this;
}
Object.defineProperty(PdfTextMarkupAnnotation.prototype, "bounds", {
/**
* Gets the bounds of the text markup annotation.
*
* @returns {Rectangle} Bounds.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfTextMarkupAnnotation = page.annotations.at(0) as PdfTextMarkupAnnotation;
* // Gets the bounds of the annotation.
* let bounds: Rectangle = annotation.bounds;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (this._isLoaded) {
this._bounds = _calculateBounds(this._dictionary, this._page);
}
return this._bounds;
},
/**
* Sets the bounds of the text markup annotation.
*
* @param {Rectangle} value bounds.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfTextMarkupAnnotation = page.annotations.at(0) as PdfTextMarkupAnnotation;
* // Sets the bounds of the annotation.
* annotation.bounds = {x: 10, y: 10, width: 150, height: 5};
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value) {
if (this._isLoaded) {
if ((value.x !== this.bounds.x) || (value.y !== this.bounds.y) ||
(value.width !== this.bounds.width) || (value.height !== this.bounds.height)) {
var size = this._page.size;
if (size) {
var y = size.height - (value.y + value.height);
var height = y + value.height;
this._dictionary.update('Rect', [value.x, y, value.x + value.width, height]);
this._bounds = value;
this._isChanged = true;
}
}
}
else {
this._bounds = value;
var nativeRectangle = this._obtainNativeRectangle();
this._dictionary.update('Rect', _fromRectangle({ x: nativeRectangle[0], y: nativeRectangle[1], width: nativeRectangle[2], height: nativeRectangle[3] }));
this._isChanged = true;
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfTextMarkupAnnotation.prototype, "textMarkUpColor", {
/**
* Gets the text markup color of the annotation.
*
* @returns {PdfColor} Text markup color as R, G, B color array in between 0 to 255.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfTextMarkupAnnotation = page.annotations.at(0) as PdfTextMarkupAnnotation;
* // Gets the textMarkUp Color type of the attachment annotation.
* let textMarkUpColor: PdfColor = annotation.textMarkUpColor;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._textMarkUpColor === 'undefined' && this._dictionary.has('C')) {
this._textMarkUpColor = _parseColor(this._dictionary.getArray('C'));
}
return this._textMarkUpColor;
},
/**
* Sets the text markup color of the annotation.
*
* @param {PdfColor} value R, G, B color values in between 0 to 255.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfTextMarkupAnnotation = page.annotations.at(0) as PdfTextMarkupAnnotation;
* // Sets the textMarkUp Color type of the attachment annotation.
* annotation.textMarkUpColor = {r: 255, g: 255, b: 255};
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value) {
var extColor = this.color;
if (!this._isLoaded ||
typeof extColor === 'undefined' ||
(extColor.r !== value.r || extColor.g !== value.g || extColor.b !== value.b)) {
this._color = value;
this._textMarkUpColor = value;
this._dictionary.update('C', [Number.parseFloat((value.r / 255).toFixed(3)),
Number.parseFloat((value.g / 255).toFixed(3)),
Number.parseFloat((value.b / 255).toFixed(3))]);
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfTextMarkupAnnotation.prototype, "textMarkupType", {
/**
* Gets the markup type of the annotation.
*
* @returns {PdfTextMarkupAnnotationType} Markup type.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfTextMarkupAnnotation = page.annotations.at(0) as PdfTextMarkupAnnotation;
* // Gets the markup type of the annotation.
* let textMarkupType: PdfTextMarkupAnnotationType = annotation.textMarkupType;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (this._dictionary.has('Subtype')) {
var text = this._dictionary.get('Subtype');
this._textMarkupType = _mapMarkupAnnotationType(text.name);
}
return this._textMarkupType;
},
/**
* Sets the markup type of the annotation.
*
* @param {PdfTextMarkupAnnotationType} value Markup type.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfTextMarkupAnnotation = page.annotations.at(0) as PdfTextMarkupAnnotation;
* // Sets the markup type of the annotation.
* annotation.textMarkupType = PdfTextMarkupAnnotationType.squiggly;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (typeof value !== 'undefined') {
this._textMarkupType = value;
this._dictionary.update('Subtype', _PdfName.get(_reverseMarkupAnnotationType(value)));
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfTextMarkupAnnotation.prototype, "boundsCollection", {
/**
* Gets the markup bounds collection of the annotation.
*
* @returns {Array<Rectangle>} Markup bounds.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfTextMarkupAnnotation = page.annotations.at(0) as PdfTextMarkupAnnotation;
* // Gets the markup bounds collection of the annotation.
* let boundsCollection : Array<Rectangle> = annotation.boundsCollection;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (!this._isLoaded) {
return this._boundsCollection;
}
var collection = [];
if (!this._dictionary.has('QuadPoints')) {
return collection;
}
var points = this._dictionary.getArray('QuadPoints');
if (!points || points.length === 0) {
return collection;
}
var cropOrMediaBox = this._getMediaOrCropBox(this._page);
var cropX = cropOrMediaBox && cropOrMediaBox.length > 0 ? cropOrMediaBox[0] : 0;
var cropY = cropOrMediaBox && cropOrMediaBox.length > 1 ? cropOrMediaBox[1] : 0;
var pageHeight = this._page.size.height;
var count = points.length / 8;
for (var i = 0; i < count; i++) {
var base = i * 8;
var dx = points[base + 4] - points[base];
var dy = points[base + 5] - points[base + 1];
var height = Math.sqrt((dx * dx) + (dy * dy));
dx = points[base + 6] - points[base + 4];
dy = points[base + 7] - points[base + 5];
var width = Math.sqrt((dx * dx) + (dy * dy));
var x = points[base] - cropX;
var y = pageHeight - points[base + 1] - cropY;
collection.push({
x: x,
y: y,
width: width,
height: height
});
}
return collection;
},
/**
* Sets the markup bounds collection of the annotation.
*
* @param {Array<Rectangle>} value Markup bounds.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfTextMarkupAnnotation = page.annotations.at(0) as PdfTextMarkupAnnotation;
* // Sets the markup bounds collection of the annotation.
* annotation.boundsCollection = [{x: 50, y: 50, width: 100, height: 100}, {x: 201, y: 101, width: 61, height: 31}, {x: 101, y: 401, width: 61, height: 31}];
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
var _a;
if (!this._isLoaded && typeof value !== 'undefined') {
if (value.length > 0) {
this._quadPoints = new Array((value.length * 8));
(_a = this._boundsCollection).push.apply(_a, value);
}
else {
this._quadPoints = new Array(8);
this._boundsCollection = value;
}
this._isChanged = true;
}
if (this._isLoaded && typeof value !== 'undefined') {
var isChanged = false;
if (this.boundsCollection.length === value.length) {
for (var i = 0; i < value.length; i++) {
var rectA = value[i];
var rectB = this.boundsCollection[i];
if (rectA.x !== rectB.x || rectA.y !== rectB.y || rectA.width !== rectB.width || rectA.height !== rectB.height) {
isChanged = true;
break;
}
}
}
else {
isChanged = true;
}
if (isChanged) {
this._quadPoints = new Array(value.length * 8);
var pageHeight = this._page.size.height;
for (var i = 0; i < value.length; i++) {
var rect = value[i];
this._quadPoints[0 + i * 8] = rect.x;
this._quadPoints[1 + i * 8] = pageHeight - rect.y;
this._quadPoints[2 + i * 8] = rect.x + rect.width;
this._quadPoints[3 + i * 8] = pageHeight - rect.y;
this._quadPoints[4 + i * 8] = rect.x;
this._quadPoints[5 + i * 8] = this._quadPoints[1 + i * 8] - rect.height;
this._quadPoints[6 + i * 8] = rect.x + rect.width;
this._quadPoints[7 + i * 8] = this._quadPoints[5 + i * 8];
}
this._dictionary.update('QuadPoints', this._quadPoints);
this._isChanged = true;
}
}
},
enumerable: true,
configurable: true
});
/**
* Loads a textmarkup annotation from the given page and dictionary and initializes it as a loaded instance.
*
* @private
* @param {PdfPage} page The page that contains the annotation.
* @param {_PdfDictionary} dictionary The source annotation dictionary.
* @returns {PdfTextMarkupAnnotation} The loaded text markup annotation instance.
*/
PdfTextMarkupAnnotation._load = function (page, dictionary) {
var annot = new PdfTextMarkupAnnotation();
annot._isLoaded = true;
annot._initialize(page, dictionary);
return annot;
};
/**
* Computes the native rectangle adjusted for page size and Crop/MediaBox offsets, including newpage settings.
*
* @private
* @returns {number[]} The native rectangle as [x, y, width, height].
*/
PdfTextMarkupAnnotation.prototype._obtainNativeRectangle = function () {
var nativeRectangle = [this._bounds.x, this._bounds.y + this._bounds.height, this._bounds.width, this._bounds.height];
var cropOrMediaBox;
if (this._page && !this._page._isNew) {
var size = this._page.size;
nativeRectangle[1] = size.height - nativeRectangle[1];
cropOrMediaBox = this._getCropOrMediaBox();
}
else if (this._page && this._page._isNew) {
var size = this._page._getActualBounds(this._page._pageSettings);
nativeRectangle[0] += size[0];
nativeRectangle[1] = this._page._pageSettings.size.height - (size[1] + nativeRectangle[1]);
cropOrMediaBox = this._getCropOrMediaBox();
}
if (cropOrMediaBox) {
if (cropOrMediaBox[3] < 0) {
var yCrop = cropOrMediaBox[1];
var heightCrop = cropOrMediaBox[3];
cropOrMediaBox[1] = heightCrop;
cropOrMediaBox[3] = yCrop;
}
if (cropOrMediaBox.length > 2 && (cropOrMediaBox[0] !== 0 || cropOrMediaBox[1] !== 0)) {
nativeRectangle[0] += cropOrMediaBox[0];
if (this._page && this._page._pageDictionary.has('MediaBox') && !this._page._pageDictionary.has('CropBox') && cropOrMediaBox[1] > 0 && cropOrMediaBox[3] === 0) {
nativeRectangle[1] += cropOrMediaBox[3];
}
else {
nativeRectangle[1] += cropOrMediaBox[1];
}
}
}
return nativeRectangle;
};
/**
* Initializes the text markup annotation for the specified page and optional source dictionary.
*
* @private
* @param {PdfPage} page The page to associate with this annotation.
* @param {_PdfDictionary} [dictionary] Optional source dictionary to import from.
* @returns {void} No return value.
*/
PdfTextMarkupAnnotation.prototype._initialize = function (page, dictionary) {
_super.prototype._initialize.call(this, page, dictionary);
};
/**
* Validates bounds, ensures defaults (BS/color), sets subtype, updates QuadPoints/Rect, and creates/attaches the appearance.
*
* @private
* @returns {void} No return value.
*/
PdfTextMarkupAnnotation.prototype._postProcess = function () {
if (typeof this.bounds === 'undefined' || this.bounds === null) {
throw new Error('Bounds cannot be null or undefined');
}
var borderWidth;
if (this._dictionary.has('BS')) {
borderWidth = this.border.width;
}
else {
var dictionary = new _PdfDictionary(this._crossReference);
dictionary.set('Type', _PdfName.get('Border'));
dictionary.set('W', this.border.width);
this._dictionary.set('BS', dictionary);
}
if (typeof borderWidth === 'undefined') {
borderWidth = 1;
}
if (!this._dictionary.has('C')) {
this._isTransparentColor = true;
}
var size = this._page.size;
this._dictionary.update('Subtype', _PdfName.get(_reverseMarkupAnnotationType(this._textMarkupType)));
if (this._isChanged) {
this._setQuadPoints(size);
this._dictionary.update('Rect', _updateBounds(this));
}
if (this._setAppearance) {
this._appearanceTemplate = this._createMarkupAppearance();
if (!this._isLoaded && this._boundsCollection.length > 1 && this._isChanged) {
var native = this._obtainNativeRectangle();
this._dictionary.update('Rect', [native[0], native[1], native[0] + native[2], native[1] + native[3]]);
}
if (this._dictionary.has('AP')) {
_removeDuplicateReference(this._dictionary.get('AP'), this._crossReference, 'N');
}
var dictionary = new _PdfDictionary();
this._appearanceTemplate._content.dictionary._updated = true;
var reference = this._crossReference._getNextReference();
this._crossReference._cacheMap.set(reference, this._appearanceTemplate._content);
this._appearanceTemplate._content.reference = reference;
dictionary.set('N', reference);
dictionary._updated = true;
this._dictionary.set('AP', dictionary);
}
if (typeof this._text !== 'undefined' && this._text !== null) {
this._dictionary.set('Contents', this._text);
}
this._isChanged = false;
};
/**
* Completes post processing by creating/importing the appearance stream as needed and flattening or removing the annotation when requested.
*
* @private
* @param {boolean} [isFlatten=false] When true, flattens the annotation into page content and removes it.
* @returns {void} No return value.
*/
PdfTextMarkupAnnotation.prototype._doPostProcess = function (isFlatten) {
if (isFlatten === void 0) { isFlatten = false; }
if (this._isLoaded) {
if (this._setAppearance || (isFlatten && !this._dictionary.has('AP'))) {
this._appearanceTemplate = this._createMarkupAppearance();
if (!isFlatten) {
if (this._dictionary.has('AP')) {
_removeDuplicateReference(this._dictionary.get('AP'), this._crossReference, 'N');
}
var dictionary = new _PdfDictionary();
this._appearanceTemplate._content.dictionary._updated = true;
var reference = this._crossReference._getNextReference();
this._crossReference._cacheMap.set(reference, this._appearanceTemplate._content);
this._appearanceTemplate._content.reference = reference;
dictionary.set('N', reference);
dictionary._updated = true;
this._dictionary.set('AP', dictionary);
}
}
if (!this._appearanceTemplate && isFlatten && this._dictionary.has('AP')) {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
var appearanceStream = dictionary.get('N');
if (appearanceStream) {
var reference = dictionary.getRaw('N');
if (reference) {
appearanceStream.reference = reference;
}
this._appearanceTemplate = new PdfTemplate(appearanceStream, this._crossReference);
}
}
}
}
else {
this._postProcess();
if (!this._appearanceTemplate) {
if (isFlatten) {
if (!this._dictionary.has('AP')) {
this._appearanceTemplate = this._createMarkupAppearance();
}
else {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
var appearanceStream = dictionary.get('N');
if (appearanceStream) {
var reference = dictionary.getRaw('N');
if (reference) {
appearanceStream.reference = reference;
}
this._appearanceTemplate = new PdfTemplate(appearanceStream, this._crossReference);
}
}
}
}
}
}
if (typeof this.flattenPopups !== 'undefined' && this.flattenPopups) {
if (this._isLoaded) {
this._flattenLoadedPopUp();
}
else {
this._flattenPopUp();
}
}
if (isFlatten && this._appearanceTemplate) {
var isNormalMatrix = this._validateTemplateMatrix(this._appearanceTemplate._content.dictionary);
if (!this._appearanceTemplate._content.dictionary.has('Matrix') && !this._isLoaded) {
var box = this._appearanceTemplate._content.dictionary.getArray('BBox');
if (box) {
this._appearanceTemplate._content.dictionary.update('Matrix', [1, 0, 0, 1, -box[0], -box[1]]);
}
}
if (isNormalMatrix && typeof this._page.rotation !== 'undefined' && this._page.rotation !== PdfRotationAngle.angle0) {
this._flattenAnnotationTemplate(this._appearanceTemplate, isNormalMatrix);
}
else if (isNormalMatrix && this._validateTemplateMatrix(this._appearanceTemplate._content.dictionary, this._appearanceTemplate)) {
this._flattenAnnotationTemplate(this._appearanceTemplate, isNormalMatrix);
}
else if (!this._dictionary.has('AP') && this._appearanceTemplate) {
this._flattenAnnotationTemplate(this._appearanceTemplate, isNormalMatrix);
}
}
if (isFlatten) {
this._page.annotations.remove(this);
}
};
/**
* Creates the markup appearance template using current QuadPoints/bounds and draws highlight/underline/strikeout/squiggly visuals.
*
* @private
* @returns {PdfTemplate} The generated appearance template.
*/
PdfTextMarkupAnnotation.prototype._createMarkupAppearance = function () {
var width = 0;
var height = 0;
var rectangle;
if (this.boundsCollection.length > 1) {
var pdfPath = new PdfPath();
for (var i = 0; i < this.boundsCollection.length; i++) {
var bounds = [];
bounds[0] = this.boundsCollection[i].x;
bounds[1] = this.boundsCollection[i].y;
bounds[2] = this.boundsCollection[i].width;
bounds[3] = this.boundsCollection[i].height;
pdfPath.addRectangle({ x: bounds[0], y: bounds[1], width: bounds[2], height: bounds[3] });
}
var rect = pdfPath._getBounds();
rectangle = { x: rect[0], y: rect[1], width: rect[2], height: rect[3] };
this.bounds = rectangle;
width = rectangle.width;
height = rectangle.height;
}
else {
if (this._dictionary.has('QuadPoints')) {
var quadPoints = this._dictionary.get('QuadPoints');
if (this._quadPoints !== null) {
for (var i = 0; i < (quadPoints.length / 8); i++) {
if (this._isLoaded) {
var point = [];
for (var k = 0; k < quadPoints.length;) {
var x1 = quadPoints[k];
var y1 = quadPoints[k + 1];
point.push({ x: x1, y: y1 });
k += 2;
}
var path = new PdfPath();
path._addLines(point);
var rect = path._getBounds();
rectangle = { x: rect[0], y: rect[1], width: rect[2], height: rect[3] };
width = rectangle.width;
height = rectangle.height;
}
else {
var x = Math.floor(quadPoints[4 + (i * 8)]) - Math.floor(quadPoints[0 + (i * 8)]);
var y = Math.floor(quadPoints[5 + (i * 8)]) - Math.floor(quadPoints[1 + (i * 8)]);
height = Math.sqrt((x * x) + (y * y));
x = Math.floor(quadPoints[6 + (i * 8)]) - Math.floor(quadPoints[4 + (i * 8)]);
y = Math.floor(quadPoints[7 + (i * 8)]) - Math.floor(quadPoints[5 + (i * 8)]);
width = Math.sqrt((x * x) + (y * y));
this.bounds = { x: this.bounds.x, y: this.bounds.y, width: width, height: height };
}
}
}
}
}
var nativeRectangle = [0, 0, width, height];
var template = new PdfTemplate(nativeRectangle, this._crossReference);
_setMatrix(template, this._getRotationAngle());
var graphics = template.graphics;
if (typeof this.opacity !== 'undefined') {
graphics.setTransparency(this.opacity, this.opacity, PdfBlendMode.multiply);
}
if (this.textMarkUpColor) {
var pdfPen = new PdfPen(this.textMarkUpColor, this.border.width);
var brush = new PdfBrush(this.textMarkUpColor);
var x1 = 0;
var y1 = 0;
var w1 = 0;
var h1 = 0;
if (this.boundsCollection.length > 1) {
for (var i = 0; i < this.boundsCollection.length; i++) {
var bounds = [];
bounds[0] = this.boundsCollection[i].x;
bounds[1] = this.boundsCollection[i].y;
bounds[2] = this.boundsCollection[i].width;
bounds[3] = this.boundsCollection[i].height;
if (this.textMarkupType === PdfTextMarkupAnnotationType.highlight) {
graphics.drawRectangle({ x: bounds[0] - rectangle.x, y: bounds[1] - rectangle.y,
width: bounds[2], height: bounds[3] }, brush);
}
else if (this.textMarkupType === PdfTextMarkupAnnotationType.underline) {
x1 = bounds[0] - rectangle.x;
y1 = (bounds[1] - rectangle.y) + (bounds[3] - ((bounds[3] / 2) / 3));
w1 = bounds[2] + (bounds[0] - rectangle.x);
h1 = (bounds[1] - rectangle.y) + (bounds[3] - ((bounds[3] / 2) / 3));
graphics.drawLine(pdfPen, { x: x1, y: y1 }, { x: w1, y: h1 });
}
else if (this.textMarkupType === PdfTextMarkupAnnotationType.strikeOut) {
x1 = bounds[0] - rectangle.x;
y1 = (bounds[1] - rectangle.y) + (bounds[3] - (bounds[3] / 2));
w1 = bounds[2] + (bounds[0] - rectangle.x);
h1 = (bounds[1] - rectangle.y) + (bounds[3] - (bounds[3] / 2));
graphics.drawLine(pdfPen, { x: x1, y: y1 }, { x: w1, y: h1 });
}
else if (this.textMarkupType === PdfTextMarkupAnnotationType.squiggly) {
pdfPen._width = bounds[3] * 0.02;
graphics.save();
graphics.translateTransform({ x: bounds[0] - rectangle.x, y: (bounds[1] - rectangle.y) });
graphics.setClip({ x: 0, y: 0, width: bounds[2], height: bounds[3] });
graphics.drawPath(this._drawSquiggly(bounds[2], bounds[3]), pdfPen);
graphics.restore();
}
}
}
else {
if (this.textMarkupType === PdfTextMarkupAnnotationType.highlight) {
graphics.drawRectangle({ x: 0, y: 0, width: width, height: height }, brush);
}
else if (this.textMarkupType === PdfTextMarkupAnnotationType.underline) {
graphics.drawLine(pdfPen, { x: 0, y: height - ((height / 2) / 3) }, { x: width, y: height - ((height / 2) / 3) });
}
else if (this.textMarkupType === PdfTextMarkupAnnotationType.strikeOut) {
graphics.drawLine(pdfPen, { x: 0, y: height / 2 }, { x: width, y: height / 2 });
}
else if (this.textMarkupType === PdfTextMarkupAnnotationType.squiggly) {
pdfPen._width = height * 0.02;
graphics.drawPath(this._drawSquiggly(Math.round(width), Math.round(height)), pdfPen);
}
if (this._isLoaded) {
var defaultRect = [rectangle.x, rectangle.y, rectangle.x + rectangle.width, rectangle.y + rectangle.height];
var rect = this._setAppearance ? _updateBounds(this) : defaultRect;
this._dictionary.update('Rect', rect);
}
}
}
return template;
};
/**
* Generates a squiggly underline path sized to the given width and height using alternating zigzag points.
*
* @private
* @param {number} width The total width available for the squiggly stroke.
* @param {number} height The height of the squiggly area (influences amplitude/pen width).
* @returns {PdfPath} The constructed squiggly path.
*/
PdfTextMarkupAnnotation.prototype._drawSquiggly = function (width, height) {
if (Math.floor(width) % 2 !== 0 || Math.round(width) > width) {
width = Math.floor(width) + 1;
}
var path = new PdfPath();
var pathPoints = [];
var pathPointsCount = Math.ceil((width / height) * 16);
var length = width / (pathPointsCount / 2);
var location = parseFloat(((length + length) * 0.6).toFixed(2));
var zigZag = location;
var x = 0;
for (var i = 0; i < pathPointsCount; i++) {
var y = ((height - location) + zigZag) - (height * 0.02);
var temp = { x: x, y: parseFloat(y.toFixed(2)) };
pathPoints.push(temp);
zigZag = zigZag === 0 ? location : 0;
x += length;
}
path._addLines(pathPoints);
return path;
};
return PdfTextMarkupAnnotation;
}(PdfComment));
export { PdfTextMarkupAnnotation };
/**
* `PdfWatermarkAnnotation` class represents the watermark annotation objects.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Create a new water mark annotation
* const annotation: PdfWatermarkAnnotation = new PdfWatermarkAnnotation('Water Mark', {x: 50, y: 100, width: 100, height: 50});
* // Set the color of the annotation
* annotation.color = {r: 0, g: 0, b: 0};
* // Add annotation to the page
* page.annotations.add(annotation);
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
var PdfWatermarkAnnotation = /** @class */ (function (_super) {
__extends(PdfWatermarkAnnotation, _super);
function PdfWatermarkAnnotation(text, bounds, properties) {
var _this = _super.call(this) || this;
/**
* Holds the watermark display text.
*
* @private
*/
_this._watermarkText = '';
if (text !== null && typeof text !== 'undefined' && bounds) {
initializeTelemetryFeature('Watermark', 'PDFLibrary');
}
_this._dictionary = new _PdfDictionary();
_this._dictionary.update('Type', _PdfName.get('Annot'));
_this._dictionary.update('Subtype', _PdfName.get('Watermark'));
if (typeof text !== 'undefined') {
_this._watermarkText = text;
_this.text = text;
}
if (bounds) {
_this.bounds = bounds;
}
_this._type = _PdfAnnotationType.watermarkAnnotation;
if (properties) {
if ('author' in properties && _isNullOrUndefined(properties.author)) {
_this.author = properties.author;
}
if ('subject' in properties && _isNullOrUndefined(properties.subject)) {
_this.subject = properties.subject;
}
if ('color' in properties && _isNullOrUndefined(properties.color)) {
_this.color = properties.color;
}
if ('innerColor' in properties && _isNullOrUndefined(properties.innerColor)) {
_this.innerColor = properties.innerColor;
}
if ('opacity' in properties && _isNullOrUndefined(properties.opacity)) {
_this.opacity = properties.opacity;
}
if ('border' in properties && _isNullOrUndefined(properties.border)) {
_this.border = properties.border;
}
}
return _this;
}
/**
* Loads a watermark annotation from the given page and dictionary and initializes it as a loaded instance.
*
* @private
* @param {PdfPage} page The page that contains the annotation.
* @param {_PdfDictionary} dictionary The source annotation dictionary.
* @returns {PdfWatermarkAnnotation} The loaded watermark annotation instance.
*/
PdfWatermarkAnnotation._load = function (page, dictionary) {
var annot = new PdfWatermarkAnnotation();
annot._isLoaded = true;
annot._initialize(page, dictionary);
return annot;
};
/**
* Initializes the watermark annotation for the specified page and optional source dictionary.
*
* @private
* @param {PdfPage} page The page to associate with this annotation.
* @param {_PdfDictionary} [dictionary] Optional source dictionary to import from.
* @returns {void} No return value.
*/
PdfWatermarkAnnotation.prototype._initialize = function (page, dictionary) {
_super.prototype._initialize.call(this, page, dictionary);
};
/**
* Finalizes setup: validates bounds, ensures BS/color defaults, creates the watermark appearance, updates Rect, and sets CA opacity if provided.
*
* @private
* @returns {void} No return value.
*/
PdfWatermarkAnnotation.prototype._postProcess = function () {
if (typeof this.bounds === 'undefined' || this.bounds === null) {
throw new Error('Bounds cannot be null or undefined');
}
var borderWidth;
if (this._dictionary.has('BS')) {
borderWidth = this.border.width;
}
else {
var dictionary = new _PdfDictionary(this._crossReference);
dictionary.set('Type', _PdfName.get('Border'));
this._dictionary.set('BS', dictionary);
}
if (typeof borderWidth === 'undefined') {
borderWidth = 1;
}
if (typeof this.color === 'undefined') {
this.color = { r: 0, g: 0, b: 0 };
}
this._appearanceTemplate = this._createWatermarkAppearance();
this._dictionary.update('Rect', _updateBounds(this));
if (typeof this.opacity !== 'undefined' && this._opacity !== 1.0) {
this._dictionary.set('CA', this._opacity);
}
};
PdfWatermarkAnnotation.prototype._createWatermarkAppearance = function () {
var font = this._obtainFont();
if ((typeof font === 'undefined' || font === null) || ((!this._isLoaded || (this._page && this._page._isDuplicate)) && font.size === 1)) {
font = this._lineCaptionFont;
this._pdfFont = font;
}
this._rotateAngle = this._getRotationAngle();
if (typeof this.rotationAngle !== 'undefined' && this._rotate !== PdfRotationAngle.angle0 || this._rotateAngle !== PdfRotationAngle.angle0) {
if (this._rotateAngle === 0) {
this._rotateAngle = this.rotationAngle * 90;
}
this.bounds = this._getRotatedBounds(this.bounds, this._rotateAngle);
}
var nativeRectangle = [0, 0, this.bounds.width, this.bounds.height];
var appearance = new PdfAppearance({ x: 0, y: 0, width: this.bounds.width, height: this.bounds.height }, this);
appearance.normal = new PdfTemplate(nativeRectangle, this._crossReference);
var template = appearance.normal;
_setMatrix(template, this._rotateAngle);
var graphics = appearance.normal.graphics;
var width = this.border.width / 2;
var format = new PdfStringFormat(PdfTextAlignment.left, PdfVerticalAlignment.top);
var borderPen = new PdfPen(this.color, width);
var backBrush;
if (this.innerColor) {
backBrush = new PdfBrush(this._innerColor);
}
if (this._isLoaded) {
if (this._dictionary.has('Contents')) {
this._watermarkText = this._dictionary.get('Contents');
}
this._dictionary.update('Contents', this._watermarkText);
}
else {
this._dictionary.update('Contents', this._watermarkText);
}
if (typeof this._watermarkText !== 'undefined') {
graphics.drawString(this._watermarkText, font, { x: 0, y: 0, width: 0, height: 0 }, borderPen, backBrush, format);
}
if (this._dictionary.has('AP')) {
var dictionary_1 = this._dictionary.get('AP'); // eslint-disable-line
if (dictionary_1 && dictionary_1 instanceof _PdfDictionary) {
_removeDuplicateReference(dictionary_1, this._crossReference, 'N');
}
}
var dictionary = new _PdfDictionary();
graphics._template._content.dictionary._updated = true;
var reference = this._crossReference._getNextReference();
this._crossReference._cacheMap.set(reference, graphics._template._content);
graphics._template._content.reference = reference;
dictionary.set('N', reference);
dictionary._updated = true;
this._dictionary.set('AP', dictionary);
return template;
};
/**
* Completes watermark post processing by creating/importing the appearance stream and flattening or removing the annotation as requested.
*
* @private
* @param {boolean} [isFlatten=false] When true, flattens the annotation into page content, otherwise updates AP entries.
* @returns {void} No return value.
*/
PdfWatermarkAnnotation.prototype._doPostProcess = function (isFlatten) {
if (isFlatten === void 0) { isFlatten = false; }
if (this._isLoaded) {
if (!isFlatten) {
this._appearanceTemplate = this._createWatermarkAppearance();
}
if (!this._appearanceTemplate && isFlatten && this._dictionary.has('AP')) {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
var appearanceStream = dictionary.get('N');
if (appearanceStream) {
var reference = dictionary.getRaw('N');
if (reference) {
appearanceStream.reference = reference;
}
this._appearanceTemplate = new PdfTemplate(appearanceStream, this._crossReference);
}
}
}
}
else {
this._postProcess();
if (!this._appearanceTemplate) {
if (isFlatten) {
if (!this._dictionary.has('AP')) {
this._appearanceTemplate = this._createWatermarkAppearance();
}
else {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
var appearanceStream = dictionary.get('N');
if (appearanceStream) {
var reference = dictionary.getRaw('N');
if (reference) {
appearanceStream.reference = reference;
}
this._appearanceTemplate = new PdfTemplate(appearanceStream, this._crossReference);
}
}
}
}
}
}
if (isFlatten && this._appearanceTemplate) {
var isNormalMatrix = this._validateTemplateMatrix(this._appearanceTemplate._content.dictionary);
if (!this._appearanceTemplate._content.dictionary.has('Matrix')) {
var box = this._appearanceTemplate._content.dictionary.getArray('BBox');
if (box) {
this._appearanceTemplate._content.dictionary.update('Matrix', [1, 0, 0, 1, -box[0], -box[1]]);
}
}
this._flattenAnnotationTemplate(this._appearanceTemplate, isNormalMatrix);
}
else if (isFlatten) {
this._page.annotations.remove(this);
}
};
return PdfWatermarkAnnotation;
}(PdfAnnotation));
export { PdfWatermarkAnnotation };
/**
* `PdfRubberStampAnnotation` class represents the rubber stamp annotation objects.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Create a new rubber stamp annotation
* const annotation: PdfRubberStampAnnotation = new PdfRubberStampAnnotation ({x: 50, y: 100, width: 100, height: 50});
* // Add annotation to the page
* page.annotations.add(annotation);
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
var PdfRubberStampAnnotation = /** @class */ (function (_super) {
__extends(PdfRubberStampAnnotation, _super);
function PdfRubberStampAnnotation(bounds, properties) {
var _this = _super.call(this) || this;
/**
* Specifies the rubber stamp icon to render.
*
* @private
*/
_this._icon = PdfRubberStampAnnotationIcon.draft;
_this._stampWidth = 0;
_this._iconString = '';
_this.rotateAngle = 0;
/**
* When true, adjusts bounds to account for rotation effects.
*
* @private
*/
_this._alterRotateBounds = true;
/**
* Font used when generating the stamp appearance content.
*
* @private
*/
_this._stampAppearanceFont = new PdfStandardFont(PdfFontFamily.helvetica, 20, PdfFontStyle.italic | PdfFontStyle.bold);
_this._dictionary = new _PdfDictionary();
_this._dictionary.update('Type', _PdfName.get('Annot'));
_this._dictionary.update('Subtype', _PdfName.get('Stamp'));
if (bounds) {
_this.bounds = bounds;
}
_this._type = _PdfAnnotationType.rubberStampAnnotation;
if (properties) {
if ('text' in properties && _isNullOrUndefined(properties.text)) {
_this.text = properties.text;
}
if ('author' in properties && _isNullOrUndefined(properties.author)) {
_this.author = properties.author;
}
if ('subject' in properties && _isNullOrUndefined(properties.subject)) {
_this.subject = properties.subject;
}
if ('color' in properties && _isNullOrUndefined(properties.color)) {
_this.color = properties.color;
}
if ('innerColor' in properties && _isNullOrUndefined(properties.innerColor)) {
_this.innerColor = properties.innerColor;
}
if ('icon' in properties && _isNullOrUndefined(properties.icon)) {
_this.icon = properties.icon;
}
if ('opacity' in properties && _isNullOrUndefined(properties.opacity)) {
_this.opacity = properties.opacity;
}
if ('border' in properties && _isNullOrUndefined(properties.border)) {
_this.border = properties.border;
}
}
return _this;
}
Object.defineProperty(PdfRubberStampAnnotation.prototype, "icon", {
/**
* Gets the icon type of the rubber stamp annotation.
*
* @returns {PdfRubberStampAnnotationIcon} Annotation icon.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfRubberStampAnnotation = page.annotations.at(0) as PdfRubberStampAnnotation;
* // Gets the icon type of the rubber stamp annotation.
* let icon: PdfRubberStampAnnotationIcon = annotation.icon;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (this._dictionary.has('Name')) {
this._icon = _mapRubberStampIcon(this._dictionary.get('Name').name);
}
return this._icon;
},
/**
* Sets the icon type of the rubber stamp annotation.
*
* @param {PdfRubberStampAnnotationIcon} value Annotation icon.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfRubberStampAnnotation = page.annotations.at(0) as PdfRubberStampAnnotation;
* // Sets the icon type of the rubber stamp annotation.
* annotation.icon = PdfRubberStampAnnotationIcon.completed;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (typeof value !== 'undefined') {
this._icon = value;
this._dictionary.update('Name', _PdfName.get('#' + this._obtainIconName(this._icon).replace(/\s+/g, '')));
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfRubberStampAnnotation.prototype, "appearance", {
/**
* Get the appearance of the rubber stamp annotation. (Read only)
*
* @returns {PdfAppearance} Returns the appearance of the annotation.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Create a new rubber stamp annotation
* const annotation: PdfRubberStampAnnotation = new PdfRubberStampAnnotation({x: 50, y: 100, width: 100, height: 50});
* // Get the appearance of the annotation
* let appearance: PdfAppearance = annotation.appearance;
* // Access the normal template of the appearance
* let template: PdfTemplate = appearance.normal;
* // Create new image object by using JPEG image data as Base64 string format
* let image: PdfImage = new PdfBitmap('/9j/4AAQSkZJRgABAQEAkACQAAD/4....QB//Z');
* // Draw the image as the custom appearance for the annotation
* template.graphics.drawImage(image, {x: 0, y: 0, width: 100, height: 50});
* // Add annotation to the page
* page.annotations.add(annotation);
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (this._isLoaded) {
return null;
}
if (typeof this._appearance === 'undefined') {
var nativeRectangle = { x: 0, y: 0, width: this.bounds.width, height: this.bounds.height };
this._appearance = new PdfAppearance(nativeRectangle, this);
this._appearance.normal = new PdfTemplate(nativeRectangle, this._crossReference);
}
return this._appearance;
},
enumerable: true,
configurable: true
});
/**
* Create an appearance template for a rubber stamp annotation.
*
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfRubberStampAnnotation = page.annotations.at(0) as PdfRubberStampAnnotation;
* // Gets the appearance template of the annotation.
* let template: PdfTemplate = annotation.createTemplate();
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*
* @returns {PdfTemplate} Returns the appearance template of the annotation.
*/
PdfRubberStampAnnotation.prototype.createTemplate = function () {
var template = this._createTemplate();
if (typeof template === 'undefined') {
template = this._createRubberStampAppearance();
}
return template;
};
Object.defineProperty(PdfRubberStampAnnotation.prototype, "_innerTemplateBounds", {
/**
* Returns the inner appearance bounds for a loaded stamp, aligning its x/y with the annotations current bounds.
*
* @private
* @returns {{x: number, y: number, width: number, height: number}} The inner appearance rectangle.
*/
get: function () {
var innerBounds;
if (this._isLoaded) {
innerBounds = this._obtainInnerBounds();
innerBounds.x = this.bounds.x;
innerBounds.y = this.bounds.y;
}
return innerBounds;
},
enumerable: true,
configurable: true
});
/**
* Loads a rubberstamp annotation from the given page and dictionary and initializes it as a loaded instance.
*
* @private
* @param {PdfPage} page The page that contains the annotation.
* @param {_PdfDictionary} dictionary The source annotation dictionary.
* @returns {PdfRubberStampAnnotation} The loaded rubberstamp annotation instance.
*/
PdfRubberStampAnnotation._load = function (page, dictionary) {
var annot = new PdfRubberStampAnnotation();
annot._isLoaded = true;
annot._initialize(page, dictionary);
return annot;
};
/**
* Initializes the rubber stamp annotation for the specified page and optional source dictionary.
*
* @private
* @param {PdfPage} page The page to associate with this annotation.
* @param {_PdfDictionary} [dictionary] Optional source dictionary to import from.
* @returns {void} No return value.
*/
PdfRubberStampAnnotation.prototype._initialize = function (page, dictionary) {
_super.prototype._initialize.call(this, page, dictionary);
};
/**
* Finalizes setup by ensuring BS/color defaults and either parsing an existing AP stream or creating a new rubberstamp appearance.
*
* @private
* @returns {void} No return value.
*/
PdfRubberStampAnnotation.prototype._postProcess = function () {
var borderWidth;
if (this._dictionary.has('BS')) {
borderWidth = this.border.width;
}
else {
var dictionary = new _PdfDictionary(this._crossReference);
dictionary.set('Type', _PdfName.get('Border'));
this._dictionary.set('BS', dictionary);
}
if (typeof borderWidth === 'undefined') {
borderWidth = 1;
}
if (!this._dictionary.has('C')) {
this._isTransparentColor = true;
}
if (this._dictionary.has('AP') && this._isLoaded) {
this._parseStampAppearance();
}
else {
this._appearanceTemplate = this._createRubberStampAppearance();
}
};
/**
* Creates, parses, or imports the stamp appearance based on export/flatten/rotation state, handles popup flattening, and flattens or removes the annotation when needed.
*
* @private
* @param {boolean} [isFlatten=false] When true, flattens the annotation into page content and removes the annotation entry.
* @returns {void} No return value.
*/
PdfRubberStampAnnotation.prototype._doPostProcess = function (isFlatten) {
if (isFlatten === void 0) { isFlatten = false; }
var isTransformBBox = false;
if (this._isLoaded && (this._setAppearance || isFlatten || this._isExport)) {
if ((!isFlatten && !this._isExport) || this._setAppearance || this._isRotated) {
this._appearanceTemplate = this._createRubberStampAppearance();
}
if (!this._appearanceTemplate && (this._isExport || isFlatten) && this._dictionary.has('AP')) {
isTransformBBox = this._parseStampAppearance();
}
}
else {
if (!(this._isImported && this._dictionary.has('AP'))) {
this._postProcess();
}
if ((!this._appearanceTemplate) && (isFlatten || this._isImported)) {
if (!this._dictionary.has('AP')) {
this._appearanceTemplate = this._createRubberStampAppearance();
}
else {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
var appearanceStream = dictionary.get('N');
if (appearanceStream) {
var reference = dictionary.getRaw('N');
if (reference) {
appearanceStream.reference = reference;
}
this._appearanceTemplate = new PdfTemplate(appearanceStream, this._crossReference);
}
}
}
}
}
if (typeof this.flattenPopups !== 'undefined' && this.flattenPopups) {
if (this._isLoaded) {
this._flattenLoadedPopUp();
}
else {
this._flattenPopUp();
}
}
if (isFlatten && this._appearanceTemplate) {
var isNormalMatrix = this._validateTemplateMatrix(this._appearanceTemplate._content.dictionary);
if (!this._appearanceTemplate._content.dictionary.has('Matrix')) {
var box = this._appearanceTemplate._content.dictionary.getArray('BBox');
if (box) {
this._appearanceTemplate._content.dictionary.update('Matrix', [1, 0, 0, 1, -box[0], -box[1]]);
}
}
if (isTransformBBox) {
this._flattenAnnotationTemplate(this._appearanceTemplate, isTransformBBox);
}
else {
this._flattenAnnotationTemplate(this._appearanceTemplate, isNormalMatrix);
}
}
else if (isFlatten) {
this._page.annotations.remove(this);
}
};
/**
* Parses the normal appearance stream (AP/N), resolves rotation and BBox/Matrix, updates the template size, and indicates if BBox transformation is required.
*
* @private
* @returns {boolean} True when the BBox must be transformed during flattening; otherwise, false.
*/
PdfRubberStampAnnotation.prototype._parseStampAppearance = function () {
var isTransformBBox = false;
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
var appearanceStream = dictionary.get('N');
if (appearanceStream) {
var reference = dictionary.getRaw('N');
if (reference) {
appearanceStream.reference = reference;
}
var isStamp = false;
if (this._type === _PdfAnnotationType.rubberStampAnnotation) {
var isRotated = false;
var size = void 0;
var rect = void 0;
if (appearanceStream) {
isRotated = (this._page.rotation === PdfRotationAngle.angle0 &&
this.rotationAngle === PdfRotationAngle.angle0);
if (!isRotated) {
isRotated = (this._page.rotation !== PdfRotationAngle.angle0 &&
this.rotationAngle === PdfRotationAngle.angle0);
}
}
this._appearanceTemplate = new PdfTemplate(appearanceStream, this._crossReference);
isStamp = true;
isTransformBBox = isRotated ? true : false;
if (isTransformBBox && appearanceStream instanceof _PdfBaseStream) {
var matrix = appearanceStream.dictionary.getArray('Matrix');
if (matrix) {
var mMatrix = matrix.slice();
var bounds = appearanceStream.dictionary.getArray('BBox');
if (bounds && bounds.length > 3) {
rect = _toRectangle(bounds);
var rectangle = this._transformBBox(rect, mMatrix);
size = [rectangle[2], rectangle[3]];
this._appearanceTemplate._size = { width: size[0], height: size[1] };
}
else {
size = [rect.width, rect.height];
}
}
}
else if (rect) {
size = [rect.width, rect.height];
}
}
if (!isStamp) {
this._appearanceTemplate = new PdfTemplate(appearanceStream, this._crossReference);
}
}
}
return isTransformBBox;
};
/**
* Builds the rubber stamp appearance (icon name, rotation, drawing), registers the AP stream/reference, updates Border and Rect, and returns the template.
*
* @private
* @returns {PdfTemplate} The generated appearance template.
*/
PdfRubberStampAnnotation.prototype._createRubberStampAppearance = function () {
var nativeRectangle = { x: 0, y: 0, width: this.bounds.width, height: this.bounds.height };
var appearance;
if (this._appearance) {
appearance = this._appearance;
if (!this._dictionary.has('Name')) {
this._dictionary.update('Name', _PdfName.get('#23CustomStamp'));
}
}
else {
this._iconString = this._obtainIconName(this.icon);
this._dictionary.update('Name', _PdfName.get('#23' + this._iconString.replace(/\s+/g, '')));
appearance = new PdfAppearance(nativeRectangle, this);
appearance.normal = new PdfTemplate(nativeRectangle, this._crossReference);
}
var template = appearance.normal;
if (this._alterRotateBounds && typeof this._rotate !== 'undefined' && (this._rotate !== PdfRotationAngle.angle0 || this._getRotationAngle() !== 0)) {
this.rotateAngle = this._getRotationAngle();
if (this.rotateAngle === 0) {
this.rotateAngle = this.rotationAngle * 90;
}
this.bounds = this._getRotatedBounds(this.bounds, this.rotate);
}
else {
this.rotateAngle = this._getRotationAngle();
}
_setMatrix(template, this.rotate, this);
if (!this._appearance) {
this._drawStampAppearance(template);
}
var hasAppearanceReference;
var appearanceReference;
if (this._dictionary && this._dictionary.has('AP')) {
var appearance_1 = this._dictionary.get('AP');
if (appearance_1 && appearance_1.has('N')) {
appearanceReference = appearance_1.getRaw('N');
if (appearanceReference instanceof _PdfReference) {
this._crossReference._cacheMap.delete(appearanceReference);
hasAppearanceReference = true;
}
}
}
var dictionary = new _PdfDictionary();
template._content.dictionary._updated = true;
if (!hasAppearanceReference) {
appearanceReference = this._crossReference._getNextReference();
}
this._crossReference._cacheMap.set(appearanceReference, template._content);
template._content.reference = appearanceReference;
dictionary.set('N', appearanceReference);
dictionary._updated = true;
this._dictionary.set('AP', dictionary);
this._dictionary.set('Border', [this.border.hRadius, this.border.vRadius, this.border.width]);
this._dictionary.update('Rect', _updateBounds(this));
return template;
};
/**
* Renders the rubberstamp artwork into the provided template using scaling, transparency, and the configured appearance font.
*
* @private
* @param {PdfTemplate} template The template whose graphics will receive the rendered stamp.
* @returns {void} No return value.
*/
PdfRubberStampAnnotation.prototype._drawStampAppearance = function (template) {
var stringFormat = new PdfStringFormat();
stringFormat.alignment = PdfTextAlignment.center;
stringFormat.lineAlignment = PdfVerticalAlignment.middle;
var backBrush = new PdfBrush(this._obtainBackGroundColor());
var borderPen = new PdfPen(this._obtainBorderColor(), this.border.width);
var graphics = template.graphics;
graphics.save();
graphics.scaleTransform(template._size.width / (this._stampWidth + 4), (template._size.height / 28));
var rubberFont = this._stampAppearanceFont;
if (typeof this.opacity !== 'undefined' && this._opacity < 1) {
graphics.setTransparency(this._opacity);
}
this._drawRubberStamp(graphics, borderPen, backBrush, rubberFont, stringFormat);
graphics.restore();
};
/**
* Maps the rubberstamp icon enum to its display name and updates the baseline stamp width for layout.
*
* @private
* @param {PdfRubberStampAnnotationIcon} icon The icon enum value.
* @returns {string} The human readable icon name.
*/
PdfRubberStampAnnotation.prototype._obtainIconName = function (icon) {
switch (icon) {
case PdfRubberStampAnnotationIcon.approved:
this._iconString = 'Approved';
this._stampWidth = 126;
break;
case PdfRubberStampAnnotationIcon.asIs:
this._iconString = 'As Is';
this._stampWidth = 75;
break;
case PdfRubberStampAnnotationIcon.confidential:
this._iconString = 'Confidential';
this._stampWidth = 166;
break;
case PdfRubberStampAnnotationIcon.departmental:
this._iconString = 'Departmental';
this._stampWidth = 186;
break;
case PdfRubberStampAnnotationIcon.draft:
this._iconString = 'Draft';
this._stampWidth = 90;
break;
case PdfRubberStampAnnotationIcon.experimental:
this._iconString = 'Experimental';
this._stampWidth = 176;
break;
case PdfRubberStampAnnotationIcon.expired:
this._iconString = 'Expired';
this._stampWidth = 116;
break;
case PdfRubberStampAnnotationIcon.final:
this._iconString = 'Final';
this._stampWidth = 90;
break;
case PdfRubberStampAnnotationIcon.forComment:
this._iconString = 'For Comment';
this._stampWidth = 166;
break;
case PdfRubberStampAnnotationIcon.forPublicRelease:
this._iconString = 'For Public Release';
this._stampWidth = 240;
break;
case PdfRubberStampAnnotationIcon.notApproved:
this._iconString = 'Not Approved';
this._stampWidth = 186;
break;
case PdfRubberStampAnnotationIcon.notForPublicRelease:
this._iconString = 'Not For Public Release';
this._stampWidth = 290;
break;
case PdfRubberStampAnnotationIcon.sold:
this._iconString = 'Sold';
this._stampWidth = 75;
break;
case PdfRubberStampAnnotationIcon.topSecret:
this._iconString = 'Top Secret';
this._stampWidth = 146;
break;
case PdfRubberStampAnnotationIcon.completed:
this._iconString = 'Completed';
this._stampWidth = 136;
break;
case PdfRubberStampAnnotationIcon.void:
this._iconString = 'Void';
this._stampWidth = 75;
break;
case PdfRubberStampAnnotationIcon.informationOnly:
this._iconString = 'Information Only';
this._stampWidth = 230;
break;
case PdfRubberStampAnnotationIcon.preliminaryResults:
this._iconString = 'Preliminary Results';
this._stampWidth = 260;
break;
}
return this._iconString;
};
/**
* Returns the background color for the current stamp icon category (approval/warning/neutral palette).
*
* @private
* @returns {PdfColor} The background color.
*/
PdfRubberStampAnnotation.prototype._obtainBackGroundColor = function () {
var color;
var red;
var green;
var blue;
if (this._icon === PdfRubberStampAnnotationIcon.notApproved ||
this._icon === PdfRubberStampAnnotationIcon.void) {
red = 251;
green = 222;
blue = 221;
color = { r: red, g: green, b: blue };
}
else if (this._icon === PdfRubberStampAnnotationIcon.approved ||
this._icon === PdfRubberStampAnnotationIcon.final ||
this._icon === PdfRubberStampAnnotationIcon.completed) {
red = 229;
green = 238;
blue = 222;
color = { r: red, g: green, b: blue };
}
else {
red = 219;
green = 227;
blue = 240;
color = { r: red, g: green, b: blue };
}
return color;
};
/**
* Returns the border/text color for the current stamp icon category (approval/warning/neutral palette).
*
* @private
* @returns {PdfColor} The border and text color.
*/
PdfRubberStampAnnotation.prototype._obtainBorderColor = function () {
var color;
var red;
var green;
var blue;
if (this._icon === PdfRubberStampAnnotationIcon.notApproved ||
this._icon === PdfRubberStampAnnotationIcon.void) {
red = 151;
green = 23;
blue = 15;
color = { r: red, g: green, b: blue };
}
else if (this._icon === PdfRubberStampAnnotationIcon.approved ||
this._icon === PdfRubberStampAnnotationIcon.final ||
this._icon === PdfRubberStampAnnotationIcon.completed) {
red = 73;
green = 110;
blue = 38;
color = { r: red, g: green, b: blue };
}
else {
red = 24;
green = 37;
blue = 100;
color = { r: red, g: green, b: blue };
}
return color;
};
/**
* Draws the rounded stamp shape and centered uppercase label using the provided pen, brush, and font.
*
* @private
* @param {PdfGraphics} graphics The graphics context to draw on.
* @param {PdfPen} pen The outline pen for the rounded rectangle.
* @param {PdfBrush} brush The fill brush for the rounded rectangle.
* @param {PdfStandardFont} font The font used to render the stamp text.
* @param {PdfStringFormat} format The string format for alignment.
* @returns {void} No return value.
*/
PdfRubberStampAnnotation.prototype._drawRubberStamp = function (graphics, pen, brush, font, format) {
var bounds = { x: 2, y: 1, width: this._stampWidth, height: 26 };
graphics.drawRoundedRectangle(bounds, 3, pen, brush);
var pdfBrush = new PdfBrush(this._obtainBorderColor());
graphics.drawString(this._iconString.toUpperCase(), font, bounds, null, pdfBrush, format);
};
/**
* Extracts and returns the inner bounds from the normal appearance streams BBox if present.
*
* @private
* @returns {{x: number, y: number, width: number, height: number}} The inner bounds rectangle, or zeros when unavailable.
*/
PdfRubberStampAnnotation.prototype._obtainInnerBounds = function () {
var bounds = { x: 0, y: 0, width: 0, height: 0 };
if (this._dictionary && this._dictionary.has('AP')) {
var appearanceDictionary = this._dictionary.get('AP');
if (appearanceDictionary && appearanceDictionary.has('N')) {
var normalAppearance = appearanceDictionary.get('N');
if (normalAppearance && typeof normalAppearance.dictionary !== 'undefined') {
var normalAppearanceDictionary = normalAppearance.dictionary;
if (normalAppearanceDictionary.has('BBox')) {
var values = normalAppearanceDictionary.getArray('BBox');
if (values && values.length === 4) {
bounds = _toRectangle(values);
}
}
}
}
}
return bounds;
};
return PdfRubberStampAnnotation;
}(PdfComment));
export { PdfRubberStampAnnotation };
/**
* `PdfSoundAnnotation` class represents the sound annotation objects.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Access first page
* let page: PdfPage = document.getPage(0);
* // Access the annotation at index 0
* let annotation: PdfSoundAnnotation = page.annotations.at(0) as PdfSoundAnnotation;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
var PdfSoundAnnotation = /** @class */ (function (_super) {
__extends(PdfSoundAnnotation, _super);
/**
* Initializes a new instance of the `PdfSoundAnnotation` class.
*
* @private
*/
function PdfSoundAnnotation() {
var _this = _super.call(this) || this;
_this._type = _PdfAnnotationType.soundAnnotation;
return _this;
}
/**
* Loads a sound annotation from the given page and dictionary and initializes it as a loaded instance.
*
* @private
* @param {PdfPage} page The page that contains the annotation.
* @param {_PdfDictionary} dictionary The source annotation dictionary.
* @returns {PdfSoundAnnotation} The loaded sound annotation instance.
*/
PdfSoundAnnotation._load = function (page, dictionary) {
var annot = new PdfSoundAnnotation();
annot._isLoaded = true;
annot._initialize(page, dictionary);
return annot;
};
/**
* Loads a sound annotation from the given page and dictionary and initializes it as a loaded instance.
*
* @private
* @param {PdfPage} page The page that contains the annotation.
* @param {_PdfDictionary} dictionary The source annotation dictionary.
* @returns {void} nothing.
*/
PdfSoundAnnotation.prototype._initialize = function (page, dictionary) {
_super.prototype._initialize.call(this, page, dictionary);
};
/**
* Performs flattening for sound annotations by importing the appearance stream when available or removing the annotation if none exists.
*
* @private
* @param {boolean} [isFlatten=false] When true, attempts to flatten the annotation into the page; otherwise, no action.
* @returns {void} No return value.
*/
PdfSoundAnnotation.prototype._doPostProcess = function (isFlatten) {
if (isFlatten === void 0) { isFlatten = false; }
if (isFlatten) {
var appearanceStream = void 0;
if (this._dictionary.has('AP')) {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
appearanceStream = dictionary.get('N');
var reference = dictionary.getRaw('N');
if (reference && appearanceStream) {
appearanceStream.reference = reference;
}
}
}
if (appearanceStream) {
var template = new PdfTemplate(appearanceStream, this._crossReference);
var isNormalMatrix = this._validateTemplateMatrix(template._content.dictionary);
this._flattenAnnotationTemplate(template, isNormalMatrix);
}
else {
this._removeAnnotation(this._page, this);
}
}
};
return PdfSoundAnnotation;
}(PdfComment));
export { PdfSoundAnnotation };
/**
* `PdfFreeTextAnnotation` class represents the free text annotation objects.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Create a new free text annotation
* const annotation: PdfFreeTextAnnotation = new PdfFreeTextAnnotation({x: 50, y: 100, width: 100, height: 50});
* // Add annotation to the page
* page.annotations.add(annotation);
* // Destroy the document
* document.destroy();
* ```
*/
var PdfFreeTextAnnotation = /** @class */ (function (_super) {
__extends(PdfFreeTextAnnotation, _super);
function PdfFreeTextAnnotation(bounds, properties) {
var _this = _super.call(this) || this;
/**
* Stores an optional intent description string for the annotation.
*
* @private
*/
_this._intentString = '';
/**
* Default font used for markup elements within the free text annotation.
*
* @private
*/
_this._markUpFont = new PdfStandardFont(PdfFontFamily.helvetica, 7, PdfFontStyle.regular);
_this._textAlignment = PdfTextAlignment.left;
_this._cropBoxValueX = 0;
_this._cropBoxValueY = 0;
_this._dictionary = new _PdfDictionary();
_this._dictionary.update('Type', _PdfName.get('Annot'));
_this._dictionary.update('Subtype', _PdfName.get('FreeText'));
if (bounds) {
_this.bounds = bounds;
}
_this._isContentUpdated = false;
_this._type = _PdfAnnotationType.freeTextAnnotation;
_this._parsedXMLData = [];
if (properties) {
if ('text' in properties && _isNullOrUndefined(properties.text)) {
_this.text = properties.text;
}
if ('author' in properties && _isNullOrUndefined(properties.author)) {
_this.author = properties.author;
}
if ('subject' in properties && _isNullOrUndefined(properties.subject)) {
_this.subject = properties.subject;
}
if ('textMarkUpColor' in properties && _isNullOrUndefined(properties.textMarkUpColor)) {
_this.textMarkUpColor = properties.textMarkUpColor;
}
if ('innerColor' in properties && _isNullOrUndefined(properties.innerColor)) {
_this.innerColor = properties.innerColor;
}
if ('lineEndingStyle' in properties && _isNullOrUndefined(properties.lineEndingStyle)) {
_this.lineEndingStyle = properties.lineEndingStyle;
}
if ('opacity' in properties && _isNullOrUndefined(properties.opacity)) {
_this.opacity = properties.opacity;
}
if ('border' in properties && _isNullOrUndefined(properties.border)) {
_this.border = properties.border;
}
if ('borderColor' in properties && _isNullOrUndefined(properties.borderColor)) {
_this.borderColor = properties.borderColor;
}
if ('annotationIntent' in properties && _isNullOrUndefined(properties.annotationIntent)) {
_this.annotationIntent = properties.annotationIntent;
}
if ('textAlignment' in properties && _isNullOrUndefined(properties.textAlignment)) {
_this.textAlignment = properties.textAlignment;
}
if ('font' in properties && _isNullOrUndefined(properties.font)) {
_this.font = properties.font;
}
if ('calloutLines' in properties && _isNullOrUndefined(properties.calloutLines)) {
_this.calloutLines = properties.calloutLines;
}
}
return _this;
}
Object.defineProperty(PdfFreeTextAnnotation.prototype, "calloutLines", {
/**
* Gets the callout lines of the free text annotation.
*
* @returns {Array<Point>} Callout lines.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfFreeTextAnnotation= page.annotations.at(0) as PdfFreeTextAnnotation;
* // Gets the callout lines of the free text annotation.
* let calloutLines: Array<Point[]> = annotation.calloutLines;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (this._calloutLines === null || typeof this._calloutLines === 'undefined') {
this._calloutLines = this._getCalloutLinePoints();
}
return this._calloutLines;
},
/**
* Sets the callout lines of the free text annotation.
*
* @param {Array<Point>} value Callout lines.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfFreeTextAnnotation = page.annotations.at(0) as PdfFreeTextAnnotation;
* // Sets the callout lines of the free text annotation.
* annotation.calloutLines = [{x: 100, y: 450}, {x: 100, y: 200}, {x: 100, y: 150}];
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (!this._isLoaded) {
this._calloutLines = value;
return;
}
var isChanged = false;
if (this._isLoaded && value.length >= 2) {
if (this._calloutLines.length === value.length) {
for (var i = 0; i < value.length; i++) {
var newPoint = value[i];
var oldPoint = this._calloutLines[i];
if (newPoint.x !== oldPoint.x || newPoint.y !== oldPoint.y) {
isChanged = true;
break;
}
}
}
else {
isChanged = true;
}
}
if (isChanged) {
var pageHeight = this._page.size.height;
var lines = [];
for (var i = 0; i < value.length; i++) {
lines.push(value[i].x + this._cropBoxValueX);
lines.push((pageHeight + this._cropBoxValueY) - value[i].y);
}
this._calloutLines = value;
this._dictionary.update('CL', lines);
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfFreeTextAnnotation.prototype, "lineEndingStyle", {
/**
* Gets the line ending style of the annotation.
*
* @returns {PdfLineEndingStyle} Line ending style.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfFreeTextAnnotation = page.annotations.at(0) as PdfFreeTextAnnotation;
* // Gets the Line ending style of the annotation.
* let lineEndingStyle: PdfLineEndingStyle = annotation.lineEndingStyle;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (this._isLoaded) {
this._lineEndingStyle = this._obtainLineEndingStyle();
}
else if (typeof this._lineEndingStyle === 'undefined') {
this._lineEndingStyle = PdfLineEndingStyle.none;
}
return this._lineEndingStyle;
},
/**
* Sets the line ending style of the line annotation.
*
* @param {PdfLineEndingStyle} value Line ending style.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfFreeTextAnnotation = page.annotations.at(0) as PdfFreeTextAnnotation;
* // Sets the line ending style of the line annotation.
* annotation.lineEndingStyle = PdfLineEndingStyle.closedArrow;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (typeof value !== 'undefined') {
this._dictionary.update('LE', _PdfName.get(_reverseMapEndingStyle(value)));
}
this._lineEndingStyle = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfFreeTextAnnotation.prototype, "textMarkUpColor", {
/**
* Gets the text markup color of the annotation.
*
* @returns {PdfColor} Text markup color as R, G, B color array in between 0 to 255.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfFreeTextAnnotation = page.annotations.at(0) as PdfFreeTextAnnotation;
* // Gets the text markup color of the annotation.
* let textMarkUpColor: PdfColor = annotation.textMarkUpColor;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._textMarkUpColor === 'undefined') {
var color = void 0;
if (this._dictionary.has('TextColor')) {
this._textMarkUpColor = _parseColor(this._dictionary.getArray('TextColor'));
return this._textMarkUpColor;
}
if (this._dictionary.has('DS')) {
var collections = this._dictionary.get('DS').split(';');
for (var i = 0; i < collections.length; i++) {
if (collections[i].indexOf('color') !== -1) {
color = collections[i].split(':')[1];
if (color.startsWith('#')) {
color = color.substring(1);
}
this._textMarkUpColor = _convertToColor(color);
}
}
}
if (!this._textMarkUpColor && this._dictionary.has('RC')) {
var rcBrush = void 0;
var rcColor = void 0;
if (this._parsedXMLData.length > 0 && this._parsedXMLData[3]) {
rcBrush = this._parsedXMLData[3];
rcColor = rcBrush._color;
this._textMarkUpColor = rcColor;
}
}
if (this._isLoaded && !this._textMarkUpColor && this._dictionary.has('DA')) {
this._textMarkUpColor = this._obtainColor();
}
else if (!this._isLoaded && !this._textMarkUpColor) {
this._textMarkUpColor = { r: 0, g: 0, b: 0 };
}
}
return this._textMarkUpColor;
},
/**
* Sets the text markup color of the annotation.
*
* @param {PdfColor} value R, G, B color values in between 0 to 255.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfFreeTextAnnotation = page.annotations.at(0) as PdfFreeTextAnnotation;
* // Sets the text markup color of the annotation.
* annotation.textMarkUpColor = {r: 200, g: 200, b: 200};
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value) {
this._textMarkUpColor = value;
this._updateStyle(this.font, value, this.textAlignment);
}
this._isContentUpdated = true;
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfFreeTextAnnotation.prototype, "textAlignment", {
/**
* Gets the text alignment of the annotation.
*
* @returns {PdfTextAlignment} Text alignment.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfFreeTextAnnotation = page.annotations.at(0) as PdfFreeTextAnnotation;
* // Gets the text alignment of the annotation.
* let textAlignment: PdfTextAlignment = annotation.textAlignment;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (this._dictionary.has('Q')) {
this._textAlignment = this._dictionary.get('Q');
}
else if (this._dictionary.has('RC')) {
var rcAlignment = void 0;
if (this._parsedXMLData.length > 0 && this._parsedXMLData[1]) {
rcAlignment = this._parsedXMLData[1];
this._textAlignment = rcAlignment;
}
}
return this._textAlignment;
},
/**
* Sets the text alignment of the annotation.
*
* @param {PdfTextAlignment} value Text alignment.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfFreeTextAnnotation = page.annotations.at(0) as PdfFreeTextAnnotation;
* // Sets the text alignment of the annotation.
* annotation.textAlignment = PdfTextAlignment.justify;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (this._textAlignment !== value) {
this._dictionary.update('Q', value);
}
this._textAlignment = value;
this._isContentUpdated = true;
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfFreeTextAnnotation.prototype, "font", {
/**
* Gets the font of the annotation.
*
* @returns {PdfFont} font.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfFreeTextAnnotation = page.annotations.at(0) as PdfFreeTextAnnotation;
* // Gets the font of the annotation.
* let font: PdfFont = annotation.font;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (!this._font) {
this._font = this._obtainFont();
if ((this._font === null || typeof this._font === 'undefined') || (!this._isLoaded && this._font.size === 1)) {
this._font = this._markUpFont;
}
}
return this._font;
},
/**
* Sets the font of the annotation.
*
* @param {PdfFont} value font.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfFreeTextAnnotation = page.annotations.at(0) as PdfFreeTextAnnotation;
* // Sets the font of the annotation.
* annotation.font = document.embedFont(PdfFontFamily.helvetica, 10, PdfFontStyle.regular);
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
this._font = value;
this._isContentUpdated = true;
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfFreeTextAnnotation.prototype, "borderColor", {
/**
* Gets the border color of the annotation.
*
* @returns {PdfColor} R, G, B color values in between 0 to 255.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfFreeTextAnnotation = page.annotations.at(0) as PdfFreeTextAnnotation;
* // Gets the border color of the annotation.
* let borderColor: PdfColor = annotation.borderColor;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._borderColor === 'undefined' && this._dictionary.has('DA')) {
this._borderColor = this._obtainColor();
}
return this._borderColor;
},
/**
* Sets the border color of the annotation.
*
* @param {PdfColor} value R, G, B color values in between 0 to 255.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfFreeTextAnnotation = page.annotations.at(0) as PdfFreeTextAnnotation;
* // Sets the border color of the annotation.
* annotation.borderColor = {r: 150, g: 150, b: 150};
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value) {
this._borderColor = value;
this._dictionary.update('DA', this._getBorderColorString(this.borderColor));
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfFreeTextAnnotation.prototype, "annotationIntent", {
/**
* Gets the intent of the annotation.
*
* @returns {PdfAnnotationIntent} Annotation intent.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfFreeTextAnnotation = page.annotations.at(0) as PdfFreeTextAnnotation;
* // Gets the intent of the annotation.
* let annotationIntent: PdfAnnotationIntent = annotation.annotationIntent;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._annotationIntent === 'undefined' || this._annotationIntent === null) {
if (this._dictionary.has('IT')) {
this._annotationIntent = _mapAnnotationIntent(this._dictionary.get('IT').name);
}
else {
this._annotationIntent = PdfAnnotationIntent.none;
}
}
return this._annotationIntent;
},
/**
* Sets the intent of the annotation.
*
* @param {PdfAnnotationIntent} value Annotation intent.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfFreeTextAnnotation = page.annotations.at(0) as PdfFreeTextAnnotation;
* // Sets the intent of the annotation.
* annotation.annotationIntent = PdfAnnotationIntent.freeTextTypeWriter;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (typeof value !== 'undefined') {
this._annotationIntent = value;
if ((typeof this.subject === 'undefined' || this.subject === 'null')
&& value === PdfAnnotationIntent.none &&
(!this._calloutLines || (this._calloutLines && this._calloutLines.length === 0))) {
this._dictionary.update('Subj', 'Text Box');
}
else {
this._dictionary.update('IT', _PdfName.get(this._obtainAnnotationIntent(this._annotationIntent)));
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfFreeTextAnnotation.prototype, "_mkDictionary", {
/**
* Returns the annotations MK appearance characteristics dictionary if present.
*
* @private
* @returns {_PdfDictionary} The MK dictionary or undefined when absent.
*/
get: function () {
var value;
if (this._dictionary.has('MK')) {
value = this._dictionary.get('MK');
}
return value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfFreeTextAnnotation.prototype, "_innerBounds", {
/**
* Computes and returns the inner text box bounds, aligning to the annotations position and honoring callout lines.
*
* @private
* @returns {{x: number, y: number, width: number, height: number}} The inner text box rectangle.
*/
get: function () {
var borderWidth = this.border.width / 2;
var nativeRectangle = this._obtainAppearanceBounds();
var parameter = new _PaintParameter();
var borderColor = this._obtainColor();
var borderPen = new PdfPen(borderColor, this.border.width);
if (this.border.width > 0) {
parameter.borderPen = borderPen;
}
var rectangle = this._obtainStyle(borderPen, nativeRectangle, borderWidth, parameter);
if (this.calloutLines && this._calloutLines.length > 0) {
this._innerTextBoxBounds = { x: rectangle[0], y: this._page.size.height - (rectangle[1] + rectangle[3]),
width: rectangle[2], height: rectangle[3] };
}
return this._innerTextBoxBounds;
},
enumerable: true,
configurable: true
});
/**
* Loads a free text annotation from the given page and dictionary, marks it as loaded, parses RC if present, and initializes internal state.
*
* @private
* @param {PdfPage} page The page that contains the annotation.
* @param {_PdfDictionary} dictionary The source annotation dictionary.
* @returns {PdfFreeTextAnnotation} The loaded free text annotation instance.
*/
PdfFreeTextAnnotation._load = function (page, dictionary) {
var annot = new PdfFreeTextAnnotation();
annot._isLoaded = true;
annot._initialize(page, dictionary);
if (dictionary.has('RC')) {
annot._parsedXMLData = annot._parseMarkupLanguageData(dictionary.get('RC'));
}
return annot;
};
/**
* Sets the free text internal padding values used to insert text within the annotation rectangle.
*
* @private
* @param {_PdfPaddings} paddings The paddings to apply (left/top/right/bottom).
* @returns {void} No return value.
*/
PdfFreeTextAnnotation.prototype._setPaddings = function (paddings) {
this._paddings = paddings;
};
/**
* Initializes the free text annotation for the specified page and optional source dictionary.
*
* @private
* @param {PdfPage} page The page to associate with this annotation.
* @param {_PdfDictionary} [dictionary] Optional source dictionary to import from.
* @returns {void} No return value.
*/
PdfFreeTextAnnotation.prototype._initialize = function (page, dictionary) {
_super.prototype._initialize.call(this, page, dictionary);
};
/**
* Finalizes setup: validates bounds, ensures BS/color defaults, captures Crop/MediaBox offsets, creates appearance when needed, and persists the dictionary for non flattened cases.
*
* @private
* @param {boolean} isFlatten When true, prepares for flattening by generating appearance immediately.
* @returns {void} No return value.
*/
PdfFreeTextAnnotation.prototype._postProcess = function (isFlatten) {
if (typeof this.bounds === 'undefined' || this.bounds === null) {
throw new Error('Bounds cannot be null or undefined');
}
var borderWidth;
if (this._dictionary.has('BS')) {
borderWidth = this.border.width;
}
else {
var dictionary = new _PdfDictionary(this._crossReference);
dictionary.set('Type', _PdfName.get('Border'));
this._dictionary.set('BS', dictionary);
}
if (typeof borderWidth === 'undefined') {
borderWidth = 1;
}
if (!this._dictionary.has('C')) {
this._isTransparentColor = true;
}
var cropOrMediaBox = this._getCropOrMediaBox();
if (cropOrMediaBox && cropOrMediaBox.length > 3 && typeof cropOrMediaBox[0] === 'number' && typeof cropOrMediaBox[1] === 'number' && (cropOrMediaBox[0] !== 0 || cropOrMediaBox[1] !== 0)) {
this._cropBoxValueX = cropOrMediaBox[0];
this._cropBoxValueY = cropOrMediaBox[1];
}
if (isFlatten || this._setAppearance || this._customTemplate.size > 0) {
this._appearanceTemplate = this._createAppearance();
}
if (!isFlatten) {
this._dictionary.update('Rect', _updateBounds(this));
this._saveFreeTextDictionary();
}
};
/**
* Builds or imports the appearance based on state/flattening, flattens when appropriate, updates style if RC changed, and writes AP entries for non flattened output.
*
* @private
* @param {boolean} [isFlatten=false] When true, flattens the annotation into page content and removes it.
* @returns {void} No return value.
*/
PdfFreeTextAnnotation.prototype._doPostProcess = function (isFlatten) {
if (isFlatten === void 0) { isFlatten = false; }
if (this._isLoaded) {
if (this._setAppearance || this._customTemplate.size > 0 || (isFlatten && !this._dictionary.has('AP'))) {
this._appearanceTemplate = this._createAppearance();
}
if (!this._appearanceTemplate && isFlatten && this._dictionary.has('AP')) {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
var appearanceStream = dictionary.get('N');
if (appearanceStream) {
var reference = dictionary.getRaw('N');
if (reference) {
appearanceStream.reference = reference;
}
this._appearanceTemplate = new PdfTemplate(appearanceStream, this._crossReference);
}
}
}
}
else {
this._postProcess(isFlatten);
if (!this._appearanceTemplate && isFlatten) {
if (!this._dictionary.has('AP')) {
this._appearanceTemplate = this._createAppearance();
}
else {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
var appearanceStream = dictionary.get('N');
if (appearanceStream) {
var reference = dictionary.getRaw('N');
if (reference) {
appearanceStream.reference = reference;
}
this._appearanceTemplate = new PdfTemplate(appearanceStream, this._crossReference);
}
}
}
}
}
if (typeof this.flattenPopups !== 'undefined' && this.flattenPopups) {
if (this._isLoaded) {
this._flattenLoadedPopUp();
}
else {
this._flattenPopUp();
}
}
if (isFlatten && this._appearanceTemplate) {
var isNormalMatrix = this._validateTemplateMatrix(this._appearanceTemplate._content.dictionary);
if (!this._appearanceTemplate._content.dictionary.has('Matrix') && !this._isLoaded) {
var box = this._appearanceTemplate._content.dictionary.getArray('BBox');
if (box) {
this._appearanceTemplate._content.dictionary.update('Matrix', [1, 0, 0, 1, -box[0], -box[1]]);
}
}
if (isNormalMatrix && typeof this._page.rotation !== 'undefined' && this._page.rotation !== PdfRotationAngle.angle0) {
this._flattenAnnotationTemplate(this._appearanceTemplate, isNormalMatrix);
}
else if (this._appearanceTemplate && !this._dictionary.has('AP')) {
this._flattenAnnotationTemplate(this._appearanceTemplate, isNormalMatrix);
}
else if (this._dictionary.has('AP')) {
if (this._isValidTemplateMatrix(this._appearanceTemplate._content.dictionary, this.bounds, this._appearanceTemplate)) {
this._flattenAnnotationTemplate(this._appearanceTemplate, isNormalMatrix);
}
}
}
else if (isFlatten) {
this._page.annotations.remove(this);
}
if (this._dictionary.has('RC') && this._isContentUpdated) {
this._updateStyle(this.font, this._textMarkUpColor, this.textAlignment);
}
if (!isFlatten && (this._setAppearance || this._customTemplate.size > 0)) {
var appearance = void 0;
var crossReference = this._crossReference;
if (this._dictionary.has('AP')) {
appearance = this._dictionary.get('AP');
}
else {
var reference = crossReference._getNextReference();
appearance = new _PdfDictionary(crossReference);
crossReference._cacheMap.set(reference, appearance);
appearance._updated = true;
this._dictionary.update('AP', reference);
}
if (this._customTemplate.size > 0) {
this._drawCustomAppearance(appearance);
}
else {
_removeDuplicateReference(appearance, crossReference, 'N');
var reference = crossReference._getNextReference();
crossReference._cacheMap.set(reference, this._appearanceTemplate._content);
this._appearanceTemplate._content.dictionary._update = true;
this._appearanceTemplate._content.reference = reference;
appearance.update('N', reference);
}
}
};
/* eslint-disable */
/**
* Validates the template Matrix/BBox against target bounds; if misaligned, draws directly to page and removes the annotation.
*
* @private
* @param {_PdfDictionary} dictionary The appearance stream dictionary to validate.
* @param {any} bounds The target placement rectangle.
* @param {PdfTemplate} appearanceTemplate The template to draw when fixing placement.
* @returns {boolean} True if the template matrix is valid; otherwise, false.
*/
PdfFreeTextAnnotation.prototype._isValidTemplateMatrix = function (dictionary, bounds, appearanceTemplate) {
var isValidMatrix = true;
var pointF = bounds;
if (dictionary && dictionary.has('Matrix')) {
var box = dictionary.getArray('BBox');
var matrix = dictionary.getArray('Matrix');
if (matrix && box && matrix.length > 3 && box.length > 2) {
if (typeof matrix[0] !== 'undefined' &&
typeof matrix[1] !== 'undefined' &&
typeof matrix[2] !== 'undefined' &&
typeof matrix[3] !== 'undefined') {
if (matrix[0] === 1 && matrix[1] === 0 && matrix[2] === 0 && matrix[3] === 1) {
if (typeof box[0] !== 'undefined' &&
typeof box[1] !== 'undefined' &&
typeof box[2] !== 'undefined' &&
typeof box[3] !== 'undefined') {
if (Math.round(box[0]) !== Math.round(-(matrix[4])) && Math.round(box[1]) !== Math.round(-(matrix[5])) ||
box[0] === 0 && Math.round(-(matrix[4])) === 0) {
var graphics = this._page.graphics;
var state = graphics.save();
if (typeof this.opacity !== 'undefined' && this._opacity < 1) {
graphics.setTransparency(this._opacity);
}
pointF.x -= box[0];
pointF.y += box[1];
graphics.drawTemplate(appearanceTemplate, pointF);
graphics.restore(state);
this._page.annotations.remove(this);
isValidMatrix = false;
}
}
}
}
}
}
return isValidMatrix;
};
/* eslint-enable */
/**
* Creates the free text appearance template, applies rotation/opacity, updates RD/Rect, and returns the template.
*
* @private
* @returns {PdfTemplate} The generated appearance template.
*/
PdfFreeTextAnnotation.prototype._createAppearance = function () {
var template;
var margins;
if (this._page && this._page._pageSettings && this._page._pageSettings.margins) {
margins = this._page._pageSettings.margins;
}
if (this._customTemplate.has('N')) {
template = this._customTemplate.get('N');
}
else {
var borderWidth = this.border.width / 2;
var nativeRectangle = this._obtainAppearanceBounds();
var rotationAngle = this.rotate;
if (rotationAngle === 0 || rotationAngle === 90 || rotationAngle === 180 || rotationAngle === 270) {
this._isAllRotation = false;
}
if (rotationAngle > 0 && this._isAllRotation) {
template = new PdfTemplate([0, 0, nativeRectangle[2], nativeRectangle[3]], this._crossReference);
}
else {
template = new PdfTemplate(nativeRectangle, this._crossReference);
}
var box = template._content.dictionary.getArray('BBox');
var angle = this._getRotationAngle();
if (box && angle !== null && typeof angle !== 'undefined') {
template._content.dictionary.set('Matrix', [1, 0, 0, 1, -box[0], -box[1]]);
}
var parameter = new _PaintParameter();
var text = this._obtainText();
template._writeTransformation = false;
var graphics = template.graphics;
var alignment = this._obtainTextAlignment();
var borderColor = this._obtainColor();
var borderPen = new PdfPen(borderColor, this.border.width);
if (this.border.width > 0) {
parameter.borderPen = borderPen;
}
var rectangle = this._obtainStyle(borderPen, nativeRectangle, borderWidth, parameter);
if (this.color) {
parameter.foreBrush = new PdfBrush(this._color);
}
var textColor = this.textMarkUpColor ? this._textMarkUpColor : { r: 0, g: 0, b: 0 };
parameter.backBrush = new PdfBrush(textColor);
parameter.borderWidth = this.border.width;
if (this.calloutLines && this._calloutLines.length >= 2) {
this._drawCallOuts(graphics, borderPen);
if (this._isLoaded && typeof this._lineEndingStyle === 'undefined') {
this._lineEndingStyle = this.lineEndingStyle;
}
if (this._lineEndingStyle !== PdfLineEndingStyle.none) {
var rawPoints = this._obtainLinePoints();
var linePoints = [];
for (var i = 0; i < rawPoints.length; i += 2) {
linePoints.push({ x: rawPoints[i], y: rawPoints[i + 1] });
}
var angle_1 = this._getAngle(linePoints);
var endPoint = this._getAxisValue({ x: rawPoints[2], y: rawPoints[3] }, 90, 0);
this._drawLineEndStyle(endPoint, graphics, angle_1, borderPen, parameter.foreBrush, this.lineEndingStyle, this.border.width, false);
}
if (!this._dictionary.has('RD')) {
rectangle = [this.bounds.x + (margins ? margins.left : 0),
-((this._page.size.height - (this.bounds.y + this.bounds.height + (margins ? margins.top : 0)))),
this.bounds.width,
-this.bounds.height];
}
else {
rectangle = [rectangle[0], -rectangle[1], rectangle[2], -rectangle[3]];
}
rectangle[0] = rectangle[0] + this._cropBoxValueX;
rectangle[1] = rectangle[1] - this._cropBoxValueY;
this._calculateRectangle(rectangle);
parameter.bounds = { x: rectangle[0], y: rectangle[1], width: rectangle[2], height: rectangle[3] };
}
else {
rectangle = [rectangle[0], -rectangle[1], rectangle[2], -rectangle[3]];
parameter.bounds = { x: rectangle[0], y: rectangle[1], width: rectangle[2], height: rectangle[3] };
}
var outerRectangle = this._obtainAppearanceBounds();
var value = [rectangle[0] - outerRectangle[0],
(-(rectangle[1])) - outerRectangle[1], rectangle[2] - outerRectangle[2],
(((-rectangle[1]) - outerRectangle[1]) + (-rectangle[3])) - outerRectangle[3]];
for (var i = 0; i < value.length; i++) {
if (value[i] < 0) {
value[i] = -value[i];
}
}
this._dictionary.update('RD', value);
if (this.opacity && this._opacity < 1) {
graphics.save();
graphics.setTransparency(this._opacity);
}
if (this.rotationAngle && this._rotate !== PdfRotationAngle.angle0) {
graphics.save();
}
this._drawFreeTextRectangle(graphics, parameter, rectangle, alignment);
if (text) {
this._drawFreeMarkUpText(graphics, parameter, rectangle, text, alignment);
}
if (this.opacity && this._opacity < 1) {
graphics.restore();
}
if (this.rotationAngle && this._rotate !== PdfRotationAngle.angle0) {
graphics.restore();
}
}
var bounds = this._obtainAppearanceBounds();
if (this.flatten) {
this._bounds = { x: bounds[0] - (margins ? margins.left : 0), y: (this._page.size.height - (bounds[1] + bounds[3]) -
(margins ? margins.top : 0)), width: bounds[2], height: bounds[3] };
}
this._dictionary.set('Rect', [bounds[0], bounds[1], bounds[0] + bounds[2], bounds[1] + bounds[3]]);
return template;
};
/**
* Calculates and updates the RD array by comparing inner and outer appearance bounds.
*
* @private
* @param {number[]} innerRectangle The inner rectangle [x, y, w, h] in appearance coordinates.
* @returns {void} No return value.
*/
PdfFreeTextAnnotation.prototype._calculateRectangle = function (innerRectangle) {
var outerRectangle = this._obtainAppearanceBounds();
var value = [innerRectangle[0] - outerRectangle[0],
(-(innerRectangle[1])) - outerRectangle[1], innerRectangle[2] - outerRectangle[2],
(((-innerRectangle[1]) - outerRectangle[1]) + (-innerRectangle[3])) - outerRectangle[3]];
for (var i = 0; i < 4; i++) {
if (value[i] < 0) {
value[i] = -value[i];
}
}
this._dictionary.set('RD', value);
};
/**
* Maps the annotation intent enum to its PDF intent name string and returns it.
*
* @private
* @param {PdfAnnotationIntent} _annotationIntent The intent enum to map.
* @returns {string} The PDF intent name (e.g., 'FreeTextCallout').
*/
PdfFreeTextAnnotation.prototype._obtainAnnotationIntent = function (_annotationIntent) {
switch (_annotationIntent) {
case PdfAnnotationIntent.freeTextCallout:
this._intentString = 'FreeTextCallout';
break;
case PdfAnnotationIntent.freeTextTypeWriter:
this._intentString = 'FreeTextTypeWriter';
break;
}
return this._intentString;
};
/**
* Resolves the effective font including RC overrides when present and returns a mapped PdfFont instance.
*
* @private
* @returns {PdfFont} The resolved font for rendering.
*/
PdfFreeTextAnnotation.prototype._obtainFont = function () {
var fontData = this._obtainFontDetails();
if (this._parsedXMLData.length > 0 && this._dictionary.has('RC')) {
var rcFont = void 0;
if (this._parsedXMLData.length > 0 && this._parsedXMLData[0]) {
rcFont = this._parsedXMLData[0];
}
if (rcFont instanceof PdfStandardFont) {
var font = rcFont;
fontData.size = font.size;
fontData.style = font.style;
fontData.name = this._getFontFamily(font._fontFamily);
}
else if (rcFont instanceof PdfCjkStandardFont) {
var font = rcFont;
fontData.size = font.size;
fontData.style = font.style;
fontData.name = font._fontFamily.toString();
}
}
return _mapFont(fontData.name, fontData.size, fontData.style, this);
};
/**
* Maps a PdfFontFamily numeric identifier to its canonical font family name.
*
* @private
* @param {number} value The numeric PdfFontFamily value.
* @returns {string} The canonical font family name.
*/
PdfFreeTextAnnotation.prototype._getFontFamily = function (value) {
var index = Math.floor(value);
switch (index) {
case PdfFontFamily.helvetica:
return 'Helvetica';
case PdfFontFamily.courier:
return 'Courier';
case PdfFontFamily.timesRoman:
return 'TimesRoman';
case PdfFontFamily.symbol:
return 'Symbol';
case PdfFontFamily.zapfDingbats:
return 'ZapfDingbats';
default:
return 'Helvetica';
}
};
/**
* Updates DS and RC with font, color, alignment, and decoration styles derived from the provided font and brush.
*
* @private
* @param {PdfFont} font The font to encode into DS/RC.
* @param {PdfColor} color The RGB text color to apply.
* @param {PdfTextAlignment} alignment The paragraph alignment for text.
* @returns {void} No return value.
*/
PdfFreeTextAnnotation.prototype._updateStyle = function (font, color, alignment) {
var textMarkUpColor;
if (color) {
textMarkUpColor = [color.r, color.g, color.b];
}
var fontName = font._metrics._name.includes('Times') ? 'Times' : font._metrics._name;
var ds = 'font:' +
fontName +
' ' +
font.size +
'pt;style:' + _reverseMapPdfFontStyle(font.style) +
';color:' +
this._colorToHex(textMarkUpColor);
this._dictionary.update('DS', ds);
var body = '<?xml version="1.0"?><body xmlns="http://www.w3.org/1999/xhtml" style="font:'
+ fontName + ' ' + font.size + 'pt;font-weight:'
+ (font.isBold ? 'bold' : 'normal') + ';color:' + this._colorToHex(textMarkUpColor) + '"><p dir="ltr">';
var textAlignment;
var alignmentText;
if (alignment !== null && typeof alignment !== 'undefined') {
switch (alignment) {
case PdfTextAlignment.left:
alignmentText = 'left';
break;
case PdfTextAlignment.center:
alignmentText = 'center';
break;
case PdfTextAlignment.right:
alignmentText = 'right';
break;
case PdfTextAlignment.justify:
alignmentText = 'justify';
break;
}
if (alignmentText) {
textAlignment = 'text-align:' + alignmentText + ';';
}
}
var decorationText = '';
var textDecoration;
var italic = 'font-style:italic';
var bold = 'font-style:bold';
if (font.isUnderline) {
decorationText = font.isStrikeout ? 'text-decoration:word line-through' : 'text-decoration:word';
if (font.isItalic) {
decorationText += ';' + italic;
}
else if (font.isBold) {
decorationText += ';' + bold;
}
}
else if (font.isStrikeout) {
decorationText = 'text-decoration:line-through';
if (font.isItalic) {
decorationText += ';' + italic;
}
else if (font.isBold) {
decorationText += ';' + bold;
}
}
else {
if (font.isItalic) {
decorationText += italic;
}
else if (font.isBold) {
decorationText += bold;
}
}
if (decorationText !== '') {
textDecoration = '<span style = "' + textAlignment + decorationText + '">' + (this.text ? this._getXmlFormattedString(this.text) : '') + '</span>';
}
else {
textDecoration = '<span style = "' + textAlignment + '">' + (this.text ? this._getXmlFormattedString(this.text) : '') + '</span>';
}
this._dictionary.update('RC', body + textDecoration + '</p></body>');
};
/**
* Draws the free text content within the computed bounds, applying padding, rotation handling, and string formatting.
*
* @private
* @param {PdfGraphics} graphics The graphics context.
* @param {_PaintParameter} parameter Paint parameters (pens/brushes/bounds).
* @param {number[]} rectangle The drawing rectangle [x, y, w, h] (appearance coords).
* @param {string} text The text to render.
* @param {PdfTextAlignment} alignment The line alignment (left/center/right/justify).
* @returns {void} No return value.
*/
PdfFreeTextAnnotation.prototype._drawFreeMarkUpText = function (graphics, parameter, rectangle, text, alignment) {
var isRotation = false;
var angle = this.rotate;
if (this.rotationAngle === PdfRotationAngle.angle90 && !this._isAllRotation) {
rectangle = [-rectangle[1], rectangle[0], -rectangle[3], rectangle[2]];
}
else if (this.rotationAngle === PdfRotationAngle.angle180 && !this._isAllRotation) {
rectangle = [-(rectangle[2] + rectangle[0]), -rectangle[1], rectangle[2], -rectangle[3]];
}
else if (this.rotationAngle === PdfRotationAngle.angle270 && !this._isAllRotation) {
rectangle = [(rectangle[1] + rectangle[3]), -(rectangle[0] + rectangle[2]), -rectangle[3], rectangle[2]];
}
else if (angle === 0 && !this._isAllRotation) {
rectangle = [rectangle[0], (rectangle[1] + rectangle[3]), rectangle[2], rectangle[3]];
}
if ((typeof this._font === 'undefined' || this._font === null) || (!this._isLoaded && this._font.size === 1)) {
this._font = this._markUpFont;
}
if (angle > 0 && this._isAllRotation) {
isRotation = true;
var bounds_1 = this.bounds;
var format = new PdfStringFormat(PdfTextAlignment.center, PdfVerticalAlignment.middle);
var textSize = this._font.measureString(text, { width: 0, height: 0 }, format, 0, 0);
if (angle > 0 && angle <= 91) {
graphics.translateTransform({ x: textSize.height, y: -bounds_1.height });
}
else if (angle > 91 && angle <= 181) {
graphics.translateTransform({ x: bounds_1.width - textSize.height, y: -(bounds_1.height - textSize.height) });
}
else if (angle > 181 && angle <= 271) {
graphics.translateTransform({ x: bounds_1.width - textSize.height, y: -textSize.height });
}
else if (angle > 271 && angle < 360) {
graphics.translateTransform({ x: textSize.height, y: -textSize.height });
}
graphics.rotateTransform(angle);
parameter.bounds = { x: 0, y: 0, width: parameter.bounds.width, height: parameter.bounds.height };
}
var bounds = [rectangle[0], rectangle[1], rectangle[2], rectangle[3]]; // eslint-disable-line
if (this._paddings && !this._isLoaded) {
var left = this._paddings._left;
var top_3 = this._paddings._top;
var right = this._paddings._right + this._paddings._left;
var bottom = this._paddings._top + this._paddings._bottom;
if (parameter.borderWidth > 0) {
var first = rectangle[0] + (parameter.borderWidth + left);
var second = rectangle[1] + (parameter.borderWidth + top_3);
var third = rectangle[2] - ((parameter.borderWidth * 2) + right);
var forth = void 0;
if (rectangle[3] > 0) {
forth = rectangle[3] - ((parameter.borderWidth * 2) + bottom);
}
else {
forth = -rectangle[3] - ((parameter.borderWidth * 2) + bottom);
}
rectangle = [first, second, third, forth];
}
else {
var first = rectangle[0] + left;
var second = rectangle[1] + top_3;
var third = rectangle[2] - right;
var forth = void 0;
if (rectangle[3] > 0) {
forth = rectangle[3] - bottom;
}
else {
forth = -rectangle[3] - bottom;
}
rectangle = [first, second, third, forth];
}
}
else if (parameter.borderWidth > 0) {
rectangle = [rectangle[0] + (parameter.borderWidth * 1.5),
rectangle[1] + (parameter.borderWidth * 1.5),
rectangle[2] - (parameter.borderWidth * 3),
(rectangle[3] > 0) ? (rectangle[3] - (parameter.borderWidth * 3)) : (-rectangle[3] - (parameter.borderWidth * 3))];
}
this._drawFreeTextAnnotation(graphics, parameter, text, this._font, rectangle, true, alignment, isRotation);
};
/**
* Renders the text box background/border or cloud appearance with rotation handling, then delegates text rendering.
*
* @private
* @param {PdfGraphics} graphics The graphics context.
* @param {_PaintParameter} parameter Paint parameters (pens/brushes/bounds).
* @param {number[]} rectangle The rectangle [x, y, w, h] (appearance coords).
* @param {PdfTextAlignment} alignment Text alignment for content drawing.
* @returns {void} No return value.
*/
PdfFreeTextAnnotation.prototype._drawFreeTextRectangle = function (graphics, parameter, rectangle, alignment) {
var isRotation = false;
if (this._dictionary.has('BE')) {
for (var i = 0; i < rectangle.length; i++) {
if (rectangle[i] < 0) {
rectangle[i] = -rectangle[i];
}
}
this._drawAppearance(graphics, parameter, rectangle);
if (this.rotationAngle === PdfRotationAngle.angle90 && !this._isAllRotation) {
graphics.rotateTransform(-90);
}
else if (this.rotationAngle === PdfRotationAngle.angle180 && !this._isAllRotation) {
graphics.rotateTransform(-180);
}
else if (this.rotationAngle === PdfRotationAngle.angle270 && !this._isAllRotation) {
graphics.rotateTransform(-270);
}
}
else {
if (this.rotationAngle === PdfRotationAngle.angle90 && !this._isAllRotation) {
graphics.rotateTransform(-90);
parameter.bounds = { x: -rectangle[1], y: rectangle[2] + rectangle[0], width: -rectangle[3], height: -rectangle[2] };
}
else if (this.rotationAngle === PdfRotationAngle.angle180 && !this._isAllRotation) {
graphics.rotateTransform(-180);
parameter.bounds = { x: -(rectangle[2] + rectangle[0]), y: -(rectangle[3] + rectangle[1]),
width: rectangle[2], height: rectangle[3] };
}
else if (this.rotationAngle === PdfRotationAngle.angle270 && !this._isAllRotation) {
graphics.rotateTransform(-270);
parameter.bounds = { x: rectangle[1] + rectangle[3], y: -rectangle[0], width: -rectangle[3], height: -rectangle[2] };
}
if (parameter.borderWidth > 0 && !this._isAllRotation) {
rectangle = [parameter.bounds.x, parameter.bounds.y, parameter.bounds.width, parameter.bounds.height];
}
this._drawFreeTextAnnotation(graphics, parameter, '', this._font, rectangle, false, alignment, isRotation);
}
};
/**
* Draws the cloud style rectangle appearance when BE/I is set by constructing a path and invoking the cloud drawer.
*
* @private
* @param {PdfGraphics} graphics The graphics context.
* @param {_PaintParameter} parameter Paint parameters including brushes and pen.
* @param {number[]} rectangle The rectangle [x, y, w, h] to outline/fill.
* @returns {void} No return value.
*/
PdfFreeTextAnnotation.prototype._drawAppearance = function (graphics, parameter, rectangle) {
var graphicsPath = new PdfPath();
graphicsPath.addRectangle({ x: rectangle[0], y: rectangle[1], width: rectangle[2], height: rectangle[3] });
if (this._dictionary.has('BE')) {
var dictionary = this._dictionary.get('BE');
if (dictionary && dictionary.has('I')) {
var value = dictionary.get('I');
var radius = value === 1 ? 4 : 9;
this._drawCloudStyle(graphics, parameter.foreBrush, parameter.borderPen, radius, 0.833, graphicsPath._points, true);
}
}
};
/**
* Draws the free text annotation: either the filled rectangle or the text string using the specified font, brushes, and bounds.
*
* @private
* @param {PdfGraphics} g The graphics context.
* @param {_PaintParameter} parameter Paint parameters containing pens/brushes/bounds.
* @param {string} text The text to render; empty to draw only background/border.
* @param {PdfFont} font The font to use for text rendering.
* @param {number[]} rectangle The drawing rectangle [x, y, w, h].
* @param {boolean} isSkipDrawRectangle When true, skips drawing the rectangle and draws only text.
* @param {PdfTextAlignment} alignment The text alignment inside the rectangle.
* @param {boolean} isRotation When true, the text is drawn with rotation transforms applied.
* @returns {void} No return value.
*/
PdfFreeTextAnnotation.prototype._drawFreeTextAnnotation = function (g, parameter, text, font, rectangle, isSkipDrawRectangle, alignment, isRotation) {
if (!isSkipDrawRectangle) {
g.drawRectangle({ x: rectangle[0], y: rectangle[1], width: rectangle[2],
height: rectangle[3] }, parameter.borderPen, parameter.foreBrush);
}
else {
var format = new PdfStringFormat();
format.lineAlignment = PdfVerticalAlignment.top;
format.alignment = alignment;
format.lineSpacing = 0;
format.lineLimit = false;
if (isRotation) {
g.drawString(text, font, parameter.bounds, parameter.backBrush, format);
}
else {
g.drawString(text, font, { x: rectangle[0], y: rectangle[1], width: rectangle[2],
height: rectangle[3] }, parameter.backBrush, format);
}
}
};
/**
* Retrieves callout line points from the CL entry and converts them into page coordinates.
*
* @private
* @returns {Array<Point>} The callout polyline points as page coordinates.
*/
PdfFreeTextAnnotation.prototype._getCalloutLinePoints = function () {
if (this._dictionary.has('CL')) {
var calloutLinepoints = this._dictionary.getArray('CL');
if (calloutLinepoints) {
this._calloutLines = [];
for (var i = 0; i < calloutLinepoints.length; i += 2) {
var point = { x: calloutLinepoints[i], y: this._page.size.height - calloutLinepoints[i + 1] };
this._calloutLines.push(point);
}
}
}
return this._calloutLines;
};
/**
* Computes the appearance bounding box from callout lines and the text box and returns it as [x, y, w, h].
*
* @private
* @returns {number[]} The appearance bounds [x, y, width, height].
*/
PdfFreeTextAnnotation.prototype._obtainAppearanceBounds = function () {
var bounds = [0, 0, 0, 0];
if (this.calloutLines && this._calloutLines.length > 0) {
var path = new PdfPath();
var pointArray = [];
var length_2 = this._calloutLines.length === 2 ? 2 : 3;
for (var i = 0; i < length_2; i++) {
pointArray.push({ x: 0, y: 0 });
}
if (this._calloutLines.length >= 2) {
this._obtainCallOutsNative();
for (var i = 0; i < this._calloutLines.length && i < 3; i++) {
pointArray[i] = {
x: this._calloutsClone[i][0],
y: this._calloutsClone[i][1]
};
}
}
if (pointArray.length > 0) {
if (this.lineEndingStyle !== PdfLineEndingStyle.none) {
this._expandAppearance(pointArray);
}
path._addLines(pointArray);
}
bounds = path._getBounds();
var margin = void 0;
if (this._page && this._page._pageSettings && this._page._pageSettings.margins) {
margin = this._page._pageSettings.margins;
}
if (this._page && this._page._isNew) {
path.addRectangle({ x: (this.bounds.x + this._cropBoxValueX + margin.left) - 2,
y: ((this._page.size.height + this._cropBoxValueY) - (this.bounds.y + this.bounds.height + margin.top)) - 2,
width: this.bounds.width + (2 * 2),
height: this.bounds.height + (2 * 2) });
}
else {
path.addRectangle({ x: (this.bounds.x + this._cropBoxValueX) - 2,
y: ((this._page.size.height + this._cropBoxValueY) - (this.bounds.y + this.bounds.height)) - 2,
width: this.bounds.width + (2 * 2),
height: this.bounds.height + (2 * 2) });
}
bounds = path._getBounds();
}
else {
if (this._page) {
if (this._page._isNew) {
var margins = this._page._pageSettings.margins;
bounds = [this.bounds.x + margins.left,
(this._page.size.height - (this.bounds.y + this.bounds.height + margins.top)),
this.bounds.width,
this.bounds.height];
}
else {
bounds = [this.bounds.x + this._cropBoxValueX,
((this._page.size.height + this._cropBoxValueY) - (this.bounds.y + this.bounds.height)),
this.bounds.width,
this.bounds.height];
}
}
}
return bounds;
};
/**
* Converts callout line points to native appearance coordinates considering margins and Crop/MediaBox offsets.
*
* @private
* @returns {void} No return value.
*/
PdfFreeTextAnnotation.prototype._obtainCallOutsNative = function () {
if (this.calloutLines && this._calloutLines.length > 0) {
var size = this._page.size;
var margin = void 0;
if (this._page && this._page._pageSettings && this._page._pageSettings.margins) {
margin = this._page._pageSettings.margins;
}
this._calloutsClone = [];
for (var i = 0; i < this._calloutLines.length; i++) {
this._calloutsClone.push([this._calloutLines[i].x + (margin ? margin.left : 0) + this._cropBoxValueX,
(size.height + this._cropBoxValueY) - (this._calloutLines[i].y + (margin ? margin.top : 0))]);
}
}
};
/**
* Returns the two callout line endpoints as a flat [x1, y1, x2, y2] array in native coordinates.
*
* @private
* @returns {number[]} The endpoints in appearance coordinates.
*/
PdfFreeTextAnnotation.prototype._obtainLinePoints = function () {
var pageHeight = this._page.size.height;
return [this.calloutLines[1].x + this._cropBoxValueX,
(pageHeight + this._cropBoxValueY) - this.calloutLines[1].y,
this.calloutLines[0].x + this._cropBoxValueX,
(pageHeight + this._cropBoxValueY) - this.calloutLines[0].y];
};
/**
* Reads the LE entry and returns the mapped PdfLineEndingStyle for the callout line.
*
* @private
* @returns {PdfLineEndingStyle} The resolved line ending style.
*/
PdfFreeTextAnnotation.prototype._obtainLineEndingStyle = function () {
var lineEndingStyle;
if (this._dictionary.has('LE')) {
var endingStyle = this._dictionary.get('LE'); // eslint-disable-line
if (endingStyle instanceof _PdfName) {
endingStyle = endingStyle.name;
}
lineEndingStyle = _mapLineEndingStyle(endingStyle);
}
return lineEndingStyle;
};
/**
* Obtains the display text from Contents or RC backup, caching it in the instance when found.
*
* @private
* @returns {string} The resolved text content (may be empty).
*/
PdfFreeTextAnnotation.prototype._obtainText = function () {
var text = '';
var isContent = this._dictionary.has('Contents');
if (isContent) {
var markUpText = this._dictionary.get('Contents');
if (markUpText) {
text = markUpText;
}
if (text && text !== '') {
this._text = text;
}
return text;
}
else if (this._dictionary.has('RC') && !isContent && text === null) {
text = this._rcText;
return text;
}
return text;
};
/**
* Determines the text alignment from Q, RC, or DS entries and returns the resolved PdfTextAlignment.
*
* @private
* @returns {PdfTextAlignment} The resolved text alignment.
*/
PdfFreeTextAnnotation.prototype._obtainTextAlignment = function () {
var textAlignment = PdfTextAlignment.left;
var hasAlignment;
if (this._dictionary.has('Q')) {
var value = this._dictionary.get('Q');
if (typeof value !== 'undefined') {
textAlignment = value;
hasAlignment = true;
}
}
else if (this._dictionary.has('RC')) {
if (this._parsedXMLData.length > 0 && this._parsedXMLData[1]) {
var rcAlignment = this._parsedXMLData[1];
textAlignment = rcAlignment;
hasAlignment = true;
}
}
if (!hasAlignment && this._dictionary.has('DS')) {
var value = this._dictionary.get('DS');
var collections = value.split(';');
collections.forEach(function (collectionItem) {
if (collectionItem.indexOf('text-align') !== -1) {
switch (collectionItem) {
case 'left':
textAlignment = PdfTextAlignment.left;
break;
case 'right':
textAlignment = PdfTextAlignment.right;
break;
case 'center':
textAlignment = PdfTextAlignment.center;
break;
case 'justify':
textAlignment = PdfTextAlignment.justify;
break;
}
}
});
}
return textAlignment;
};
/**
* Resolves the border/text color from DA/MK/BC when loaded or from the configured border color when creating.
*
* @private
* @returns {PdfColor} The resolved RGB color.
*/
PdfFreeTextAnnotation.prototype._obtainColor = function () {
var color;
if (this._isLoaded) {
if (this._dictionary.has('DA')) {
var entry = this._dictionary.get('DA');
if (Array.isArray(entry) && entry.length > 0) {
color = { r: entry[0], g: entry[1], b: entry[2] };
}
else if (typeof entry === 'string') {
this._da = new _PdfDefaultAppearance(entry);
color = this._da.color;
}
}
else if (this._dictionary.has('MK')) {
var mkDict = this._mkDictionary;
if (mkDict && mkDict.has('BC')) {
color = _parseColor(mkDict.getArray('BC'));
}
}
else {
color = { r: 0, g: 0, b: 0 };
}
}
else {
color = this._borderColor ? this._borderColor : { r: 0, g: 0, b: 0 };
}
return color;
};
/**
* Expands the first callout point outward to accommodate end styles and border thickness relative to the text box.
*
* @private
* @param {Point[]} pointArray The callout points to adjust (mutated in place).
* @returns {void} No return value.
*/
PdfFreeTextAnnotation.prototype._expandAppearance = function (pointArray) {
var pointY = pointArray[0].y;
var pointX = pointArray[0].x;
if (!this._isLoaded) {
pointY = this._page.size.height - pointY;
}
if (pointY > this.bounds.y) {
if (this.lineEndingStyle !== PdfLineEndingStyle.openArrow) {
pointArray[0].y -= (this.border.width * 11);
}
}
else {
pointArray[0].y += (this.border.width * 11);
}
if (pointX <= this.bounds.x) {
pointArray[0].x -= (this.border.width * 11);
}
else {
pointArray[0].x += (this.border.width * 11);
}
};
/**
* Draws the callout polyline path derived from the callout points using the specified border pen.
*
* @private
* @param {PdfGraphics} graphics The graphics context.
* @param {PdfPen} borderPen The pen used to draw the callout path.
* @returns {void} No return value.
*/
PdfFreeTextAnnotation.prototype._drawCallOuts = function (graphics, borderPen) {
var path = new PdfPath();
var pointArray = [];
var length = this._calloutLines.length === 2 ? 2 : 3;
for (var i = 0; i < length; i++) {
pointArray.push({ x: 0, y: 0 });
}
if (this._calloutLines.length >= 2) {
this._obtainCallOutsNative();
for (var i = 0; i < this._calloutLines.length && i < 3; i++) {
pointArray[i] = {
x: this._calloutsClone[i][0],
y: -this._calloutsClone[i][1]
};
}
}
if (pointArray.length > 0) {
path._addLines(pointArray);
}
graphics.drawPath(path, borderPen);
};
/**
* Persists the free text dictionary entries (Contents, Q, Subj/IT, DS, DA, CL, Rect) based on current state and intent.
*
* @private
* @returns {void} No return value.
*/
PdfFreeTextAnnotation.prototype._saveFreeTextDictionary = function () {
if ((typeof this.font === 'undefined' || this.font === null) || (!this._isLoaded && this.font.size === 1)) {
this.font = this._markUpFont;
}
if (typeof this.text === 'string' && this.text !== null) {
this._dictionary.update('Contents', this.text);
}
if (this._isLoaded) {
this._textAlignment = this.textAlignment;
}
this._dictionary.update('Q', this._textAlignment);
if ((typeof this.subject === 'undefined' || this.subject === 'null')
&& this.annotationIntent === PdfAnnotationIntent.none &&
(!this._calloutLines || (this._calloutLines && this._calloutLines.length === 0))) {
this._dictionary.update('Subj', 'Text Box');
}
else {
if ((this._calloutLines && this._calloutLines.length >= 2) &&
this.annotationIntent === PdfAnnotationIntent.none) {
this._annotationIntent = PdfAnnotationIntent.freeTextCallout;
}
this._dictionary.update('IT', _PdfName.get(this._obtainAnnotationIntent(this._annotationIntent)));
}
this._updateStyle(this.font, this.textMarkUpColor, this._textAlignment);
this._dictionary.update('DA', this._getBorderColorString(this.borderColor ? this._borderColor : { r: 0, g: 0, b: 0 }));
if (this._calloutLines && this._calloutLines.length >= 2) {
var pageHeight = this._page.size.height;
var lines = [];
for (var i = 0; i < this._calloutLines.length && i < 3; i++) {
lines.push(this._calloutLines[i].x + this._cropBoxValueX);
lines.push((pageHeight + this._cropBoxValueY) - this._calloutLines[i].y);
}
this._dictionary.update('CL', lines);
}
if (this._setAppearance) {
var rect = this._obtainAppearanceBounds();
this._dictionary.update('Rect', [rect[0], rect[1], rect[0] + rect[2], rect[1] + rect[3]]);
}
};
/**
* Escapes XML sensitive characters (&, <, >) in the provided markup text for RC storage.
*
* @private
* @param {string} markupText The raw markup text to escape.
* @returns {string} The escaped XML safe string.
*/
PdfFreeTextAnnotation.prototype._getXmlFormattedString = function (markupText) {
markupText = markupText.replace('&', '&');
markupText = markupText.replace('<', '<');
markupText = markupText.replace('>', '>');
return markupText;
};
/**
* Parses RC XHTML content to extract style directives, resolve fonts/brushes/alignment, and populate the parsed XML font collection.
*
* @private
* @param {string} rcContent The RC XHTML content to parse.
* @returns {any[]} A collection of [font, alignment, namespaceURI, brush] entries.
*/
PdfFreeTextAnnotation.prototype._parseMarkupLanguageData = function (rcContent) {
var _this = this;
var fontStyle = PdfFontStyle.regular;
var fontCollection = []; // eslint-disable-line
var brush = null;
var fontName = '';
var content = rcContent;
var contentText = this._dictionary.has('Contents') ? this._dictionary.get('Contents') : '';
var hasSymbol = false;
var xdocument; // eslint-disable-line
hasSymbol = contentText.split('').some(function (char) { return _this._isSymbol(char); });
if (!hasSymbol) {
if (content !== null && typeof content !== 'undefined') {
xdocument = (new DOMParser()).parseFromString(content, 'text/xml');
var root = xdocument.documentElement;
var nameSpaceURI = (root && root.namespaceURI) || '';
if (root) {
var styleMap = this._collectStyles(root);
var input = void 0;
if (styleMap.size > 0) {
input = this._extractStylesToInput(styleMap);
var fontDetails_1 = this._getFontDetails(input, this.font.size, this.textAlignment, fontStyle, brush); // eslint-disable-line
var _a = this._updateFontProperties(fontDetails_1, fontName, fontStyle, brush), updatedFontName_1 = _a.fontName, updatedFontStyle_1 = _a.fontStyle, updatedBrush_1 = _a.brush;
var obtainFont_1 = _mapFont(updatedFontName_1, this.font._size, updatedFontStyle_1, this);
fontCollection = this._fontCollection(fontCollection, obtainFont_1, nameSpaceURI, this._textAlignment, updatedBrush_1);
}
else if (styleMap.size === 0 && this._dictionary.has('DS')) {
var stringValue = this._dictionary.get('DS');
input = stringValue.split(';') || [];
}
fontStyle = this.font.style;
var fontDetails = this._getFontDetails(input, this.font.size, this.textAlignment, fontStyle, brush); // eslint-disable-line
var _b = this._updateFontProperties(fontDetails, fontName, fontStyle, brush), updatedFontName = _b.fontName, updatedFontStyle = _b.fontStyle, updatedBrush = _b.brush;
var obtainFont = _mapFont(updatedFontName, this.font._size, updatedFontStyle, this);
this._font = obtainFont;
fontCollection = this._fontCollection(fontCollection, obtainFont, nameSpaceURI, this._textAlignment, updatedBrush);
}
}
}
this._parsedXMLData = fontCollection;
return fontCollection;
};
/**
* Traverses the XHTML DOM and collects inline style attributes per tag into a style map.
*
* @private
* @param {HTMLElement} root The root element to traverse.
* @param {Map<string, string[]>} [styleMap] Optional existing map to append into.
* @returns {Map<string, string[]>} The populated map of tagName → style declarations.
*/
PdfFreeTextAnnotation.prototype._collectStyles = function (root, styleMap) {
if (styleMap === void 0) { styleMap = new Map(); }
if (!root) {
return styleMap;
}
var tagName = root.tagName.toLowerCase();
var styleAttribute = root.getAttribute('style');
if (styleAttribute) {
var styleArray = styleAttribute.split(';').map(function (s) { return s.trim(); }).filter(Boolean); // eslint-disable-line
styleMap.set(tagName, styleArray);
}
var childNode = root.firstElementChild;
while (childNode) {
this._collectStyles(childNode, styleMap);
childNode = childNode.nextElementSibling;
}
return styleMap;
};
/**
* Flattens the collected style map into a string array of CSS property declarations.
*
* @private
* @param {Map<string, string[]>} styleMap The map of style declarations per tag.
* @returns {string[]} The flattened CSS declarations.
*/
PdfFreeTextAnnotation.prototype._extractStylesToInput = function (styleMap) {
var input = [];
styleMap.forEach(function (styleArray) {
input.push.apply(input, styleArray);
});
return input;
};
/**
* Returns true if the character is in common symbol Unicode ranges used for special glyphs.
*
* @private
* @param {string} char The character to test.
* @returns {boolean} True if the character is a symbol glyph; otherwise, false.
*/
PdfFreeTextAnnotation.prototype._isSymbol = function (char) {
var code = char.charCodeAt(0);
if (char === '_' || char === '+' || char === '-' || char === '*' || char === '=') {
return false;
}
return ((code >= 0x20A0 && code <= 0x20CF) ||
(code >= 0x2200 && code <= 0x22FF) ||
(code >= 0x2A00 && code <= 0x2AFF) ||
(code >= 0x2100 && code <= 0x214F) ||
(code >= 0x2300 && code <= 0x23FF) ||
(code === 0x2B50));
};
/**
* Applies parsed style properties to update font name/size/style, text alignment, brush, and spacerun content, returning the updated values.
*
* @private
* @param {Map<string, any>} fontDetails The parsed font/style details map.
* @param {string} fontName The current font family name.
* @param {PdfFontStyle} fontStyle The current font style flags.
* @param {PdfBrush} brush The current text brush (may be updated).
* @returns {{ fontName: string, fontStyle: PdfFontStyle, brush: PdfBrush }} The updated font properties.
*/
PdfFreeTextAnnotation.prototype._updateFontProperties = function (fontDetails, fontName, fontStyle, brush) {
var _this = this;
var styleValue;
var next;
fontDetails.forEach(function (value, property) {
switch (property) {
case 'font-family':
fontName = value;
break;
case 'font-size':
_this.font._size = parseFloat(value);
break;
case 'font-style':
case 'font-weight':
case 'text-decoration':
styleValue = parseFloat(value);
next = _this._getStyles(styleValue);
fontStyle = _this._maxStyle(fontStyle, next);
break;
case 'text-align':
_this._textAlignment = _this._parseTextAlignment(value);
break;
case 'color':
brush = value;
break;
case 'xfa-spacerun':
_this._rcText = value;
break;
}
});
return { fontName: fontName, fontStyle: fontStyle, brush: brush };
};
/**
* Converts a bitmask value into a PdfFontStyle subset with regular as fallback.
*
* @private
* @param {number} value The bitmask to convert.
* @returns {PdfFontStyle} The mapped PdfFontStyle.
*/
PdfFreeTextAnnotation.prototype._getStyles = function (value) {
var allowedMask = PdfFontStyle.bold | PdfFontStyle.italic | PdfFontStyle.underline | PdfFontStyle.strikeout;
var masked = value & allowedMask;
return (masked === 0 ? PdfFontStyle.regular : masked);
};
/**
* Returns the maximum PdfFontStyle value between two style flags.
*
* @private
* @param {PdfFontStyle} a The first style flag.
* @param {PdfFontStyle} b The second style flag.
* @returns {PdfFontStyle} The dominant style flag.
*/
PdfFreeTextAnnotation.prototype._maxStyle = function (a, b) {
return (a >= b ? a : b);
};
/**
* Parses a numeric alignment value and returns the corresponding PdfTextAlignment enum.
*
* @private
* @param {string} value The numeric alignment value as a string.
* @returns {PdfTextAlignment} The parsed alignment (left/center/right/justify).
*/
PdfFreeTextAnnotation.prototype._parseTextAlignment = function (value) {
var alignmentValue = parseFloat(value);
switch (alignmentValue) {
case 0: return PdfTextAlignment.left;
case 1: return PdfTextAlignment.center;
case 2: return PdfTextAlignment.right;
case 3: return PdfTextAlignment.justify;
default: return PdfTextAlignment.left;
}
};
/**
* Parses a list of CSS declarations into effective font details, color brush, and alignment, returning them in a detail map.
*
* @private
* @param {string[]} input The CSS declarations.
* @param {number} fontSize The current font size used as fallback.
* @param {PdfTextAlignment} textAlignment The current text alignment used as fallback.
* @param {PdfFontStyle} fontStyle The current font style flags used as fallback.
* @param {PdfBrush} brush The current brush used as fallback.
* @returns {Map<string, any>} A map containing resolved font properties and brush.
*/
PdfFreeTextAnnotation.prototype._getFontDetails = function (input, fontSize, textAlignment, fontStyle, brush) {
var _this = this;
var fontDetails = new Map(); // eslint-disable-line
input.forEach(function (element) {
var _a = element.split(':').map(function (item) { return item.trim(); }), property = _a[0], value = _a[1];
if (property && value) {
switch (property.toLowerCase()) {
case 'font':
_this._parseFont(value, fontDetails);
break;
case 'font-size':
fontSize = _this._parseFontSize(value);
fontDetails.set('font-size', fontSize);
break;
case 'font-weight':
fontStyle = _this._parseFontWeight(value, fontStyle);
fontDetails.set('font-weight', fontStyle);
break;
case 'font-family':
fontDetails.set('font-family', _this._parseFontFamily(value));
break;
case 'color':
brush = new PdfBrush(_this._rgbStringToArray(value));
fontDetails.set('color', brush);
break;
case 'font-style':
fontStyle = _this._parseFontStyle(value, fontStyle);
fontDetails.set('font-style', fontStyle);
break;
case 'text-decoration':
fontStyle = _this._parseTextDecoration(value, fontStyle);
fontDetails.set('text-decoration', fontStyle);
break;
case 'text-align':
textAlignment = _this._parseTextAlign(value);
fontDetails.set('text-align', textAlignment);
break;
case 'xfa-spacerun':
_this._rcText = value.length > 1 && value.includes('yes') ? _this._rcText + ' ' : _this._rcText;
fontDetails.set('xfa-spacerun', _this._rcText);
break;
}
}
});
return fontDetails;
};
/**
* Parses a composite CSS font shorthand into family and size, updating the font details map.
*
* @private
* @param {string} value The CSS font shorthand value.
* @param {Map<string, any>} fontDetails The map to receive parsed properties.
* @returns {void} No return value.
*/
PdfFreeTextAnnotation.prototype._parseFont = function (value, fontDetails) {
var fontParts = value.split(' ').map(function (item) { return item.trim(); });
var fontName = '';
fontParts.forEach(function (part) {
if (part && !part.endsWith('pt')) {
fontName += part + ' ';
}
else if (part.endsWith('pt')) {
fontDetails.set('font-size', parseFloat(part.replace('pt', '').replace(',', '.').trim()));
}
});
fontDetails.set('font-family', fontName.trim().replace(/['",]/g, ''));
};
/**
* Parses a CSS point size string (e.g., '12pt') into a numeric value.
*
* @private
* @param {string} value The CSS point size string.
* @returns {number} The parsed size in points.
*/
PdfFreeTextAnnotation.prototype._parseFontSize = function (value) {
if (value.endsWith('pt')) {
return parseFloat(value.replace('pt', '').replace(',', '.').trim());
}
return 0;
};
/**
* Updates the PdfFontStyle with bold when the font weight property indicates bold.
*
* @private
* @param {string} value The CSS font weight value.
* @param {PdfFontStyle} fontStyle The current font style flags.
* @returns {PdfFontStyle} The updated font style flags.
*/
PdfFreeTextAnnotation.prototype._parseFontWeight = function (value, fontStyle) {
if (value.includes('bold')) {
fontStyle |= PdfFontStyle.bold;
}
return fontStyle;
};
/**
* Normalizes a CSS font family string by trimming surrounding quotes.
*
* @private
* @param {string} value The CSS font-family value.
* @returns {string} The normalized font family name.
*/
PdfFreeTextAnnotation.prototype._parseFontFamily = function (value) {
return value.replace(/^'+|'+$/g, '').trim();
};
/**
* Applies font style flags (regular/underline/strikeout/italic/bold) based on the CSS font style value.
*
* @private
* @param {string} value The CSS font style value.
* @param {PdfFontStyle} fontStyle The current font style flags.
* @returns {PdfFontStyle} The updated font style flags.
*/
PdfFreeTextAnnotation.prototype._parseFontStyle = function (value, fontStyle) {
if (value.includes('normal') || value.includes('regular')) {
fontStyle |= PdfFontStyle.regular;
}
if (value.includes('underline')) {
fontStyle |= PdfFontStyle.underline;
}
if (value.includes('strikeout')) {
fontStyle |= PdfFontStyle.strikeout;
}
if (value.includes('italic')) {
fontStyle |= PdfFontStyle.italic;
}
if (value.includes('bold')) {
fontStyle |= PdfFontStyle.bold;
}
return fontStyle;
};
/**
* Applies underline/strikeout flags according to the CSS text decoration value.
*
* @private
* @param {string} value The CSS text decoration value.
* @param {PdfFontStyle} fontStyle The current font style flags.
* @returns {PdfFontStyle} The updated font style flags.
*/
PdfFreeTextAnnotation.prototype._parseTextDecoration = function (value, fontStyle) {
if (value.includes('word') || value.includes('underline')) {
fontStyle |= PdfFontStyle.underline;
}
if (value.includes('line-through')) {
fontStyle |= PdfFontStyle.strikeout;
}
return fontStyle;
};
/**
* Parses a CSS text align string into a PdfTextAlignment enum value.
*
* @private
* @param {string} value The CSS text align value.
* @returns {PdfTextAlignment} The parsed alignment enum.
*/
PdfFreeTextAnnotation.prototype._parseTextAlign = function (value) {
switch (value.trim().toLowerCase()) {
case 'left': return PdfTextAlignment.left;
case 'right': return PdfTextAlignment.right;
case 'center': return PdfTextAlignment.center;
case 'justify': return PdfTextAlignment.justify;
default: return PdfTextAlignment.left;
}
};
/**
* Converts a CSS color string to a PdfColor object or throws on invalid format.
*
* @private
* @param {string} rgbString The CSS color string (rgb(r,g,b) or #RRGGBB).
* @returns {PdfColor} The parsed RGB color.
*/
PdfFreeTextAnnotation.prototype._rgbStringToArray = function (rgbString) {
var rgbRegex = /^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/;
var rgbMatch = rgbString.match(rgbRegex);
if (rgbMatch) {
var r = parseInt(rgbMatch[1], 10);
var g = parseInt(rgbMatch[2], 10);
var b = parseInt(rgbMatch[3], 10);
return { r: r, g: g, b: b };
}
var hexRegex = /^#([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})$/;
var hexMatch = rgbString.match(hexRegex);
if (hexMatch) {
var r = parseInt(hexMatch[1], 16);
var g = parseInt(hexMatch[2], 16);
var b = parseInt(hexMatch[3], 16);
return { r: r, g: g, b: b };
}
throw new Error('Invalid RGB string format');
};
/**
* Appends the resolved font, alignment, namespace URI, and brush to the running parsed XML font collection and returns it.
*
* @private
* @param {any[]} fontCollection The existing collection to append to.
* @param {PdfFont} font The resolved font instance.
* @param {string} nameSpaceUri The namespace URI found in RC.
* @param {PdfTextAlignment} alignment The text alignment value.
* @param {PdfBrush} brush The resolved brush.
* @returns {any[]} The updated font collection.
*/
PdfFreeTextAnnotation.prototype._fontCollection = function (fontCollection, font, nameSpaceUri, alignment, brush) {
return fontCollection.concat([font, alignment, nameSpaceUri, brush]);
};
return PdfFreeTextAnnotation;
}(PdfComment));
export { PdfFreeTextAnnotation };
/**
* `PdfRedactionAnnotation` class represents the redaction annotation objects.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Create a new redaction annotation
* const annotation: PdfRedactionAnnotation = new PdfRedactionAnnotation({x: 50, y: 100, width: 100, height: 50});
* // Add annotation to the page
* page.annotations.add(annotation);
* // Destroy the document
* document.destroy();
* ```
*/
var PdfRedactionAnnotation = /** @class */ (function (_super) {
__extends(PdfRedactionAnnotation, _super);
function PdfRedactionAnnotation(bounds, properties) {
var _this = _super.call(this) || this;
_this._textAlignment = PdfTextAlignment.left;
_this._dictionary = new _PdfDictionary();
_this._dictionary.update('Type', _PdfName.get('Annot'));
_this._dictionary.update('Subtype', _PdfName.get('Redact'));
if (bounds) {
_this.bounds = bounds;
if (properties) {
if (_isNullOrUndefined(properties.borderColor)) {
_this.borderColor = properties.borderColor;
}
if (_isNullOrUndefined(properties.repeatText)) {
_this.repeatText = properties.repeatText;
}
if (_isNullOrUndefined(properties.overlayText)) {
_this.overlayText = properties.overlayText;
}
if (properties.font) {
_this.font = properties.font;
}
if (_isNullOrUndefined(properties.textColor)) {
_this.textColor = properties.textColor;
}
if (_isNullOrUndefined(properties.appearanceFillColor)) {
_this.appearanceFillColor = properties.appearanceFillColor;
}
if (_isNullOrUndefined(properties.innerColor)) {
_this.innerColor = properties.innerColor;
}
if (_isNullOrUndefined(properties.textAlignment)) {
_this.textAlignment = properties.textAlignment;
}
if (_isNullOrUndefined(properties.text)) {
_this.text = properties.text;
}
if (_isNullOrUndefined(properties.author)) {
_this.author = properties.author;
}
if (_isNullOrUndefined(properties.subject)) {
_this.subject = properties.subject;
}
if (_isNullOrUndefined(properties.opacity)) {
_this.opacity = properties.opacity;
}
if (_isNullOrUndefined(properties.boundsCollection) &&
Array.isArray(properties.boundsCollection) && properties.boundsCollection.length > 0) {
_this.boundsCollection = properties.boundsCollection;
}
}
}
_this._type = _PdfAnnotationType.redactionAnnotation;
return _this;
}
Object.defineProperty(PdfRedactionAnnotation.prototype, "repeatText", {
/**
* Gets the boolean flag indicating whether annotation has repeat text or not.
*
* @returns {boolean} repeat text.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfRedactionAnnotation = page.annotations.at(0) as PdfRedactionAnnotation;
* // Gets the boolean flag indicating whether annotation has repeat text or not.
* let repeatText: boolean = annotation. repeatText;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._repeat === 'undefined' && this._dictionary.has('Repeat')) {
this._repeat = this._dictionary.get('Repeat');
}
return this._repeat;
},
/**
* Sets the boolean flag indicating whether annotation has repeat text or not.
*
* @param {boolean} value repeat text.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfRedactionAnnotation = page.annotations.at(0) as PdfRedactionAnnotation;
* // Sets the boolean flag indicating whether annotation has repeat text or not.
* annotation.repeatText = false;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value !== this._repeat) {
this._repeat = value;
if (this._dictionary) {
this._dictionary.update('Repeat', value);
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfRedactionAnnotation.prototype, "textAlignment", {
/**
* Gets the text alignment of the annotation.
*
* @returns {PdfTextAlignment} Text alignment.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfRedactionAnnotation = page.annotations.at(0) as PdfRedactionAnnotation;
* // Gets the text alignment of the annotation.
* let textAlignment: PdfTextAlignment = annotation.textAlignment;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (this._dictionary.has('Q')) {
this._textAlignment = this._dictionary.get('Q');
}
return this._textAlignment;
},
/**
* Sets the text alignment of the annotation.
*
* @param {PdfTextAlignment} value Text alignment.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfRedactionAnnotation = page.annotations.at(0) as PdfRedactionAnnotation;
* // Sets the text alignment of the annotation.
* annotation.textAlignment = PdfTextAlignment.justify;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (typeof value !== 'undefined' && value !== null && this._textAlignment !== value) {
this._dictionary.update('Q', value);
}
this._textAlignment = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfRedactionAnnotation.prototype, "textColor", {
/**
* Gets the text color of the annotation.
*
* @returns {PdfColor} R, G, B color values in between 0 to 255.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfRedactionAnnotation = page.annotations.at(0) as PdfRedactionAnnotation;
* // Gets the text color of the annotation.
* let textColor : PdfColor = annotation.textColor;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._textColor === 'undefined' && this._dictionary.has('C')) {
this._textColor = _parseColor(this._dictionary.getArray('C'));
}
return this._textColor;
},
/**
* Sets the text color of the annotation.
*
* @param {PdfColor} value R, G, B color values in between 0 to 255.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfRedactionAnnotation = page.annotations.at(0) as PdfRedactionAnnotation;
* // Sets the text color of the annotation.
* annotation.textColor = {r: 255, g: 255, b: 255};
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value) {
var extColor = this.textColor;
if (!this._isLoaded || typeof extColor === 'undefined' || (extColor.r !== value.r || extColor.g !== value.g || extColor.b !== value.b)) {
this._textColor = value;
this._dictionary.update('C', [Number.parseFloat((value.r / 255).toFixed(3)),
Number.parseFloat((value.g / 255).toFixed(3)),
Number.parseFloat((value.b / 255).toFixed(3))]);
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfRedactionAnnotation.prototype, "borderColor", {
/**
* Gets the border color of the annotation.
*
* @returns {PdfColor} R, G, B color values in between 0 to 255.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfRedactionAnnotation = page.annotations.at(0) as PdfRedactionAnnotation;
* // Gets the border color of the annotation.
* let borderColor: PdfColor = annotation.borderColor;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._borderColor === 'undefined' && this._dictionary.has('OC')) {
this._borderColor = _parseColor(this._dictionary.getArray('OC'));
}
return this._borderColor;
},
/**
* Sets the border color of the annotation.
*
* @param {PdfColor} value R, G, B color values in between 0 to 255.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfRedactionAnnotation = page.annotations.at(0) as PdfRedactionAnnotation;
* // Sets the border color of the annotation.
* annotation.borderColor = {r: 255, g: 255, b: 255};
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value) {
var extColor = this.borderColor;
if (!this._isLoaded || typeof extColor === 'undefined' || (extColor.r !== value.r || extColor.g !== value.g || extColor.b !== value.b)) {
this._borderColor = value;
this._dictionary.update('OC', [Number.parseFloat((value.r / 255).toFixed(3)),
Number.parseFloat((value.g / 255).toFixed(3)),
Number.parseFloat((value.b / 255).toFixed(3))]);
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfRedactionAnnotation.prototype, "overlayText", {
/**
* Gets the overlay text of the annotation.
*
* @returns {string} overlay text.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfRedactionAnnotation = page.annotations.at(0) as PdfRedactionAnnotation;
* // Gets the overlay text of the annotation.
* let overlayText: string = annotation.overlayText;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._overlayText === 'undefined' && this._dictionary.has('OverlayText')) {
this._overlayText = this._dictionary.get('OverlayText');
}
return this._overlayText;
},
/**
* Sets the overlay text of the annotation.
*
* @param {string} value overlay text.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfRedactionAnnotation = page.annotations.at(0) as PdfRedactionAnnotation;
* // Sets the overlay text of the annotation.
* annotation.overlayText = 'syncfusion';
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (typeof value === 'string') {
this._dictionary.update('OverlayText', value);
this._overlayText = value;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfRedactionAnnotation.prototype, "font", {
/**
* Gets the font of the annotation.
*
* @returns {PdfFont} font.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfRedactionAnnotation = page.annotations.at(0) as PdfRedactionAnnotation;
* // Gets the font of the annotation.
* let font: PdfFont = annotation.font;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (!this._font) {
this._font = this._obtainFont();
}
return this._font;
},
/**
* Sets the font of the annotation.
*
* @param {PdfFont} value font.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfRedactionAnnotation = page.annotations.at(0) as PdfRedactionAnnotation;
* // Sets the font of the annotation.
* annotation.font = document.embedFont(PdfFontFamily.helvetica, 10, PdfFontStyle.regular);
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
this._font = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfRedactionAnnotation.prototype, "appearanceFillColor", {
/**
* Gets the appearance fill color of the annotation.
*
* @returns {PdfColor} R, G, B color values in between 0 to 255.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfRedactionAnnotation = page.annotations.at(0) as PdfRedactionAnnotation;
* // Gets the appearance fill color of the annotation.
* let appearanceFillColor: PdfColor = annotation.appearanceFillColor;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if ((this._appearanceFillColor === null || typeof this._appearanceFillColor === 'undefined') &&
this._dictionary.has('AFC')) {
var fillColor = this._dictionary.getArray('AFC');
if (fillColor) {
this._appearanceFillColor = _parseColor(fillColor);
}
}
return this._appearanceFillColor;
},
/**
* Sets the appearance fill color of the annotation.
*
* @param {PdfColor} value R, G, B color values in between 0 to 255.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfRedactionAnnotation = page.annotations.at(0) as PdfRedactionAnnotation;
* // Sets the appearance fill color of the annotation.
* annotation.appearanceFillColor = {r: 255, g: 255, b: 255};
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value) {
var extColor = this.appearanceFillColor;
if (!this._isLoaded || typeof extColor === 'undefined' || (extColor.r !== value.r ||
extColor.g !== value.g || extColor.b !== value.b)) {
this._appearanceFillColor = value;
this._dictionary.update('AFC', [Number.parseFloat((value.r / 255).toFixed(3)),
Number.parseFloat((value.g / 255).toFixed(3)),
Number.parseFloat((value.b / 255).toFixed(3))]);
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfRedactionAnnotation.prototype, "boundsCollection", {
/**
* Gets the bounds collection of the annotation.
*
* @returns {Array<Rectangle>} bounds collection.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfRedactionAnnotation = page.annotations.at(0) as PdfRedactionAnnotation;
* // Gets the bounds collection of the annotation.
* let boundsCollection: Array<Rectangle> = annotation.boundsCollection;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (this._isLoaded) {
var collection = [];
if (this._dictionary.has('QuadPoints')) {
var points = this._dictionary.getArray('QuadPoints');
if (points && points.length > 0) {
var cropOrMediaBox = this._getMediaOrCropBox(this._page);
var cropX = cropOrMediaBox && cropOrMediaBox.length > 0 ? cropOrMediaBox[0] : 0;
var cropY = cropOrMediaBox && cropOrMediaBox.length > 1 ? cropOrMediaBox[1] : 0;
var count = points.length / 8;
for (var i = 0; i < count; i++) {
var x = points[4 + (i * 8)] - points[i * 8];
var y = points[5 + (i * 8)] - points[1 + (i * 8)];
var height = Math.sqrt((x * x) + (y * y));
x = points[6 + (i * 8)] - points[4 + (i * 8)];
y = points[7 + (i * 8)] - points[5 + (i * 8)];
var width = Math.sqrt((x * x) + (y * y));
var rect = {
x: points[i * 8] - cropX,
y: this._page.size.height - points[1 + (i * 8)] - cropY,
width: width,
height: height
};
collection.push(rect);
}
}
}
return collection;
}
return this._boundsCollection;
},
/**
* Sets the bounds collection of the annotation.
*
* @param {Array<Rectangle>} value bounds collection.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfRedactionAnnotation = page.annotations.at(0) as PdfRedactionAnnotation;
* // Sets the bounds collection of the annotation.
* annotation.boundsCollection = [{x: 50, y: 50, width: 100, height: 100}, {x: 201, y: 101, width: 61, height: 31}, {x: 101, y: 401, width: 61, height: 31}];
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
var _a;
if (!this._isLoaded && typeof value !== 'undefined') {
if (value.length > 0) {
this._quadPoints = new Array(value.length * 8);
(_a = this._boundsCollection).push.apply(_a, value);
}
else {
this._quadPoints = new Array(8);
this._boundsCollection = value;
}
this._isChanged = true;
}
if (this._isLoaded && typeof value !== 'undefined') {
var isChanged = false;
if (this.boundsCollection.length === value.length) {
for (var i = 0; i < value.length; i++) {
var rectA = value[i];
var rectB = this.boundsCollection[i];
if (rectA.x !== rectB.x || rectA.y !== rectB.y || rectA.width !== rectB.width || rectA.height !== rectB.height) {
isChanged = true;
break;
}
}
}
else {
isChanged = true;
}
if (isChanged) {
this._quadPoints = new Array(value.length * 8);
var pageHeight = this._page.size.height;
for (var i = 0; i < value.length; i++) {
var rect = value[i];
var base = i * 8;
this._quadPoints[base + 0] = rect.x;
this._quadPoints[base + 1] = pageHeight - rect.y;
this._quadPoints[base + 2] = rect.x + rect.width;
this._quadPoints[base + 3] = pageHeight - rect.y;
this._quadPoints[base + 4] = rect.x;
this._quadPoints[base + 5] = this._quadPoints[base + 1] - rect.height;
this._quadPoints[base + 6] = rect.x + rect.width;
this._quadPoints[base + 7] = this._quadPoints[base + 5];
}
this._dictionary.update('QuadPoints', this._quadPoints);
this._isChanged = true;
}
}
},
enumerable: true,
configurable: true
});
/**
* Loads a redaction annotation from the given page and dictionary, marks it as loaded, and initializes internal state.
*
* @private
* @param {PdfPage} page The page that contains the annotation.
* @param {_PdfDictionary} dictionary The source annotation dictionary.
* @returns {PdfRedactionAnnotation} The loaded redaction annotation instance.
*/
PdfRedactionAnnotation._load = function (page, dictionary) {
var annot = new PdfRedactionAnnotation();
annot._isLoaded = true;
annot._initialize(page, dictionary);
return annot;
};
/**
* Initializes the redaction annotation for the specified page and optional source dictionary by delegating to the base initializer.
*
* @private
* @param {PdfPage} page The page to associate with this annotation.
* @param {_PdfDictionary} [dictionary] Optional source dictionary to import from.
* @returns {void} No return value.
*/
PdfRedactionAnnotation.prototype._initialize = function (page, dictionary) {
_super.prototype._initialize.call(this, page, dictionary);
};
/**
* Finalizes setup: validates bounds, ensures BS defaults, updates QuadPoints when changed, optionally creates the redaction appearance, and updates the Rect entry.
*
* @private
* @param {boolean} isFlatten When true, prepares for flattening by creating appearance immediately if required.
* @returns {void} No return value.
*/
PdfRedactionAnnotation.prototype._postProcess = function (isFlatten) {
if (typeof this.bounds === 'undefined' || this.bounds === null) {
throw new Error('Bounds cannot be null or undefined');
}
var borderWidth;
if (this._dictionary.has('BS')) {
borderWidth = this.border.width;
}
else {
var dictionary = new _PdfDictionary(this._crossReference);
dictionary.set('Type', _PdfName.get('Border'));
this._dictionary.set('BS', dictionary);
}
if (typeof borderWidth === 'undefined') {
borderWidth = 1;
}
if (this._isChanged) {
this._setQuadPoints(this._page.size);
}
if (this._setAppearance || this._customTemplate.size > 0) {
this._appearanceTemplate = this._createRedactionAppearance(isFlatten);
}
this._dictionary.update('Rect', _updateBounds(this));
};
/**
* Builds or imports the redaction appearance based on load/flatten state and import status, applies matrix normalization when needed, and flattens or removes the annotation accordingly.
*
* @private
* @param {boolean} [isFlatten=false] When true, flattens the annotation into page content and removes it.
* @returns {void} No return value.
*/
PdfRedactionAnnotation.prototype._doPostProcess = function (isFlatten) {
if (isFlatten === void 0) { isFlatten = false; }
if (!this._isImported) {
if (this._isLoaded) {
this._appearanceTemplate = this._createRedactionAppearance(isFlatten);
}
else {
this._postProcess(isFlatten);
if (!this._appearanceTemplate) {
if (isFlatten) {
if (!this._dictionary.has('AP')) {
this._appearanceTemplate = this._createRedactionAppearance(isFlatten);
}
else {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
var appearanceStream = dictionary.get('N');
if (appearanceStream) {
var reference = dictionary.getRaw('N');
if (reference) {
appearanceStream.reference = reference;
}
this._appearanceTemplate = new PdfTemplate(appearanceStream, this._crossReference);
}
}
}
}
}
}
if (isFlatten && this._appearanceTemplate) {
var isNormalMatrix = this._validateTemplateMatrix(this._appearanceTemplate._content.dictionary);
if (!this._appearanceTemplate._content.dictionary.has('Matrix')) {
var box = this._appearanceTemplate._content.dictionary.getArray('BBox');
if (box) {
this._appearanceTemplate._content.dictionary.update('Matrix', [1, 0, 0, 1, -box[0], -box[1]]);
}
}
this._flattenAnnotationTemplate(this._appearanceTemplate, isNormalMatrix);
}
else if (isFlatten) {
this._page.annotations.remove(this);
}
}
};
/**
* Creates the redaction appearance; during non flatten flow, writes border and normal appearances to AP, or removes the annotation when flattening after creation.
*
* @private
* @param {boolean} isFlatten When true, prepares for flattening and may remove the annotation after creating the appearance.
* @returns {PdfTemplate} The normal (R) appearance template.
*/
PdfRedactionAnnotation.prototype._createRedactionAppearance = function (isFlatten) {
var normalTemplate = this._createNormalAppearance();
if (isFlatten) {
if (this._isLoaded && this._page !== null) {
this._page.annotations.remove(this);
}
}
else {
var borderTemplate = this._createBorderAppearance();
if (this._dictionary.has('AP')) {
var appearance_2 = this._dictionary.get('AP');
if (appearance_2 && appearance_2 instanceof _PdfDictionary) {
_removeDuplicateReference(appearance_2, this._crossReference, 'N');
_removeDuplicateReference(appearance_2, this._crossReference, 'R');
}
}
var appearance = void 0;
if (this._dictionary.has('AP')) {
appearance = this._dictionary.get('AP');
}
else {
var reference = this._crossReference._getNextReference();
appearance = new _PdfDictionary(this._crossReference);
this._crossReference._cacheMap.set(reference, appearance);
this._dictionary.update('AP', reference);
}
if (this._customTemplate.size > 0) {
normalTemplate = this._customTemplate.get('R');
this._drawCustomAppearance(appearance);
}
else {
borderTemplate._content.dictionary._updated = true;
var reference1 = this._crossReference._getNextReference();
this._crossReference._cacheMap.set(reference1, borderTemplate._content);
borderTemplate._content.reference = reference1;
appearance.set('N', reference1);
normalTemplate._content.dictionary._updated = true;
var reference = this._crossReference._getNextReference();
this._crossReference._cacheMap.set(reference, normalTemplate._content);
normalTemplate._content.reference = reference;
appearance.set('R', reference);
appearance._updated = true;
}
}
return normalTemplate;
};
/**
* Creates the border appearance template by drawing the redaction bounds with the configured pen/brush and optional opacity.
*
* @private
* @returns {PdfTemplate} The generated border (N) appearance template.
*/
PdfRedactionAnnotation.prototype._createBorderAppearance = function () {
var rectangle;
if (this.boundsCollection.length > 1) {
var pdfPath = new PdfPath();
for (var _i = 0, _a = this.boundsCollection; _i < _a.length; _i++) {
var bounds = _a[_i];
pdfPath.addRectangle(bounds);
}
var rect = pdfPath._getBounds();
rectangle = { x: rect[0], y: rect[1], width: rect[2], height: rect[3] };
this.bounds = rectangle;
}
else {
var singleBound = this.boundsCollection[0];
if (singleBound) {
rectangle = singleBound;
}
else {
rectangle = this.bounds;
}
}
var nativeRectangle = [0, 0, this.bounds.width, this.bounds.height];
var template = new PdfTemplate(nativeRectangle, this._crossReference);
var graphics = template.graphics;
var pen;
var brush;
if (this.border.width > 0 && this.borderColor) {
pen = new PdfPen(this.borderColor, this.border.width);
}
if (this.appearanceFillColor) {
brush = new PdfBrush(this.appearanceFillColor);
}
var effectiveBoundsCollection = (this.boundsCollection && this.boundsCollection.length > 0)
? this.boundsCollection
: [{ x: this.bounds.x, y: this.bounds.y, width: this.bounds.width, height: this.bounds.height }];
for (var _b = 0, effectiveBoundsCollection_1 = effectiveBoundsCollection; _b < effectiveBoundsCollection_1.length; _b++) {
var bounds = effectiveBoundsCollection_1[_b];
if (this.opacity < 1) {
var state = graphics.save();
graphics.setTransparency(this.opacity);
graphics.drawRectangle({ x: bounds.x - rectangle.x, y: bounds.y - rectangle.y,
width: bounds.width, height: bounds.height }, pen, brush);
graphics.restore(state);
}
else {
graphics.drawRectangle({ x: bounds.x - rectangle.x, y: bounds.y - rectangle.y,
width: bounds.width, height: bounds.height }, pen, brush);
}
}
return template;
};
/**
* Renders overlay text inside the provided rectangle across single or multiple bounds, honoring alignment and repeat settings.
*
* @private
* @param {PdfGraphics} graphics The graphics context used for drawing.
* @param {Rectangle} rectangle The reference rectangle for positioning overlay text.
* @returns {void} No return value.
*/
PdfRedactionAnnotation.prototype._drawText = function (graphics, rectangle) {
if (!this.overlayText) {
return;
}
if (!this.font) {
this.font = this._lineCaptionFont;
}
if (this._isLoaded) {
this._textAlignment = this.textAlignment;
}
var textColorBrush = this.textColor ? new PdfBrush(this.textColor) : new PdfBrush({ r: 128, g: 128, b: 128 });
var effectiveBoundsCollection = this.boundsCollection && this.boundsCollection.length > 0
? this.boundsCollection
: [{ x: this.bounds.x, y: this.bounds.y, width: this.bounds.width, height: this.bounds.height }];
var words = [];
var splitWords = this.overlayText.trim().split(/\s+/);
splitWords.forEach(function (w) {
if (w.length > 0) {
words.push(w);
}
});
var wordIndex = 0;
for (var _i = 0, effectiveBoundsCollection_2 = effectiveBoundsCollection; _i < effectiveBoundsCollection_2.length; _i++) {
var bounds = effectiveBoundsCollection_2[_i];
var rectX = bounds.x - rectangle.x;
var rectY = bounds.y - rectangle.y;
var maxWidth = bounds.width;
var maxHeight = bounds.height;
wordIndex = this._drawWrappedTextAligned(graphics, rectX, rectY, maxWidth, maxHeight, words, wordIndex, this._textAlignment, textColorBrush, this.repeatText);
if (!this.repeatText && wordIndex >= words.length) {
break;
}
}
};
PdfRedactionAnnotation.prototype._drawWrappedTextAligned = function (graphics, startX, startY, availableWidth, availableHeight, words, startIndex, alignment, brush, loopWhenExhausted) {
var lineHeight = this._getLineHeight();
var formatTopLeft = new PdfStringFormat(0, PdfVerticalAlignment.top);
var isSingleWord = words.length === 1;
var spaceChar = ' ';
var spaceWidth = this._getSpaceWidth();
var y = startY;
var idx = startIndex;
while (y + lineHeight <= startY + availableHeight) {
var lineWords = [];
var lineText = '';
var repeatedThisLine = 0;
while (true) { // eslint-disable-line
if (idx >= words.length) {
if (loopWhenExhausted) {
idx = 0;
repeatedThisLine++;
if (repeatedThisLine > 1 && lineWords.length === 0) {
break;
}
}
else {
break;
}
}
if (idx >= words.length) {
break;
}
var w = words[idx];
var candidate = lineWords.length === 0 ? w : (isSingleWord ? (lineText + w) : (lineText + spaceChar + w));
var candidateWidth = this._measureText(candidate);
if (candidateWidth <= availableWidth + 0.25) {
lineWords.push(w);
lineText = candidate;
idx++;
continue;
}
if (lineWords.length === 0) {
var chunk = this._breakWordToFit(w, availableWidth, this._measureText.bind(this));
if (chunk.text.length > 0) {
lineWords.push(chunk.text);
lineText = chunk.text;
}
if (chunk.remainder && chunk.remainder.length > 0) {
words[idx] = chunk.remainder;
}
else {
idx++;
}
}
break;
}
if (lineWords.length === 0) {
break;
}
var isLastLine = !loopWhenExhausted && (idx >= words.length);
if (alignment === PdfTextAlignment.right) {
var lineWidth = this._measureText(lineText);
var x = startX + Math.max(0, availableWidth - lineWidth);
graphics.drawString(lineText, this.font, { x: x, y: y, width: lineWidth, height: lineHeight }, null, brush, formatTopLeft);
}
else if (alignment === PdfTextAlignment.center) {
var lineWidth = this._measureText(lineText);
var x = startX + Math.max(0, (availableWidth - lineWidth) / 2);
graphics.drawString(lineText, this.font, { x: x, y: y, width: lineWidth, height: lineHeight }, null, brush, formatTopLeft);
}
else if (alignment === PdfTextAlignment.justify && !isLastLine && lineWords.length > 1 && !isSingleWord) {
var wordsWidth = 0;
for (var _i = 0, _a = lineWords; _i < _a.length; _i++) {
var w = _a[_i];
wordsWidth += this._measureText(w);
}
var extra = availableWidth - wordsWidth - (lineWords.length - 1) * spaceWidth;
if (extra < 0) {
extra = 0;
}
var extraPerGap = extra / (lineWords.length - 1);
var x = startX;
for (var i = 0; i < lineWords.length; i++) {
var w = lineWords[i];
var wWidth = this._measureText(w);
graphics.drawString(w, this.font, { x: x, y: y, width: wWidth, height: lineHeight }, null, brush, formatTopLeft);
x += wWidth;
if (i < lineWords.length - 1) {
x += spaceWidth + extraPerGap;
}
}
}
else {
graphics.drawString(lineText, this.font, { x: startX, y: y, width: Math.min(this._measureText(lineText), availableWidth), height: lineHeight }, null, brush, formatTopLeft);
}
y += lineHeight;
}
return idx;
};
PdfRedactionAnnotation.prototype._breakWordToFit = function (word, availableWidth, measure) {
if (!word) {
return { text: '', remainder: null };
}
var lo = 1;
var hLength = word.length;
var best = 0;
while (lo <= hLength) {
var mid = (lo + hLength) >> 1;
var part = word.slice(0, mid);
if (measure(part) <= availableWidth) {
best = mid;
lo = mid + 1;
}
else {
hLength = mid - 1;
}
}
var text = word.slice(0, best);
var remainder = best < word.length ? word.slice(best) : null;
return { text: text, remainder: remainder };
};
PdfRedactionAnnotation.prototype._measureText = function (text) {
return this.font.measureString(text, { width: 0, height: 0 }).width;
};
PdfRedactionAnnotation.prototype._getSpaceWidth = function () {
return this._measureText(' ');
};
PdfRedactionAnnotation.prototype._getLineHeight = function () {
return this.font._getHeight();
};
/**
* Creates the normal redaction appearance by drawing the specified bounds, applying transparency and page rotation, and rendering overlay text when present.
*
* @private
* @param {number} [index] Optional index of a specific bounds entry to render.
* @param {Rectangle} [rotatedBounds] Optional pre-rotated bounds to render.
* @param {PdfRotationAngle} [pageRotation] Optional page rotation to apply to the template.
* @returns {PdfTemplate} The generated normal appearance template.
*/
PdfRedactionAnnotation.prototype._createNormalAppearance = function (index, rotatedBounds, pageRotation) {
var pdfPath = new PdfPath();
var hasIndex = false;
var bounds;
if (rotatedBounds) {
bounds = rotatedBounds;
pdfPath.addRectangle(bounds);
hasIndex = typeof index === 'number' && index >= 0;
}
else if (typeof index === 'number' && index >= 0 && index < this.boundsCollection.length) {
bounds = this.boundsCollection[index];
pdfPath.addRectangle(bounds);
hasIndex = true;
}
else {
for (var _i = 0, _a = this.boundsCollection; _i < _a.length; _i++) {
var bounds_2 = _a[_i];
pdfPath.addRectangle(bounds_2);
}
}
var rect = pdfPath._getBounds();
if (rect[2] === 0 && rect[3] === 0) {
rect[0] = rotatedBounds ? rotatedBounds.x : this.bounds.x;
rect[1] = rotatedBounds ? rotatedBounds.y : this.bounds.y;
rect[2] = rotatedBounds ? rotatedBounds.width : this.bounds.width;
rect[3] = rotatedBounds ? rotatedBounds.height : this.bounds.height;
}
var rectangle = { x: rect[0], y: rect[1], width: rect[2], height: rect[3] };
this.bounds = rectangle;
var nativeRectangle = [0, 0, rectangle.width, rectangle.height];
var template = new PdfTemplate(nativeRectangle, this._crossReference);
var graphics = template.graphics;
var width = this.border.width / 2;
var widths = this.border.width;
var borderPen;
var backBrush;
if (this.borderColor && this.border.width > 0) {
borderPen = new PdfPen(this.borderColor, this.border.width);
}
if (this.innerColor) {
backBrush = new PdfBrush(this.innerColor);
}
var alphaState;
var shouldSetTransparency = this.opacity < 1;
if (shouldSetTransparency) {
alphaState = graphics.save();
graphics.setTransparency(this.opacity);
}
if (this.boundsCollection && this.boundsCollection.length > 0) {
if (hasIndex && bounds) {
graphics.drawRectangle({
x: bounds.x - rectangle.x,
y: bounds.y - rectangle.y,
width: bounds.width,
height: bounds.height
}, borderPen, backBrush);
}
else {
for (var _b = 0, _c = this.boundsCollection; _b < _c.length; _b++) {
var b = _c[_b];
graphics.drawRectangle({
x: b.x - rectangle.x,
y: b.y - rectangle.y,
width: b.width,
height: b.height
}, borderPen, backBrush);
}
}
}
else {
graphics.drawRectangle({
x: nativeRectangle[0] + width,
y: nativeRectangle[1] + width,
width: nativeRectangle[2] - widths,
height: nativeRectangle[3] - widths
}, borderPen, backBrush);
}
if (shouldSetTransparency && alphaState) {
graphics.restore(alphaState);
}
if (this.overlayText) {
var state = graphics.save();
var width_1 = nativeRectangle[2];
var height = nativeRectangle[3];
switch (pageRotation) {
case PdfRotationAngle.angle90:
graphics.rotateTransform(90);
graphics.translateTransform({ x: 0, y: -width_1 });
break;
case PdfRotationAngle.angle180:
graphics.rotateTransform(180);
graphics.translateTransform({ x: -width_1, y: -height });
break;
case PdfRotationAngle.angle270:
graphics.rotateTransform(270);
graphics.translateTransform({ x: -height, y: 0 });
break;
case PdfRotationAngle.angle0:
default:
break;
}
var rotatedRect = rectangle;
if (typeof pageRotation !== 'undefined' && pageRotation !== null &&
(pageRotation === PdfRotationAngle.angle90 ||
pageRotation === PdfRotationAngle.angle270)) {
rotatedRect.width = rectangle.height;
rotatedRect.height = rectangle.width;
}
this._drawText(graphics, rotatedRect);
graphics.restore(state);
}
return template;
};
return PdfRedactionAnnotation;
}(PdfComment));
export { PdfRedactionAnnotation };
/**
* `PdfRichMediaAnnotation` class represents the rich media annotation objects.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Access first page
* let page: PdfPage = document.getPage(0);
* // Access the annotation at index 0
* let annotation: PdfRichMediaAnnotation = page.annotations.at(0) as PdfRichMediaAnnotation;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
var PdfRichMediaAnnotation = /** @class */ (function (_super) {
__extends(PdfRichMediaAnnotation, _super);
/**
* Initializes a new instance of the `PdfRichMediaAnnotation` class.
*
* @private
*/
function PdfRichMediaAnnotation() {
var _this = _super.call(this) || this;
_this._type = _PdfAnnotationType.richMediaAnnotation;
return _this;
}
/**
* Creates a rich media annotation from the given page and dictionary and marks it as loaded.
*
* @private
* @param {PdfPage} page The page that contains the annotation.
* @param {_PdfDictionary} dictionary The source annotation dictionary.
* @returns {PdfRichMediaAnnotation} The loaded rich media annotation instance.
*/
PdfRichMediaAnnotation._load = function (page, dictionary) {
var annot = new PdfRichMediaAnnotation();
annot._isLoaded = true;
annot._initialize(page, dictionary);
return annot;
};
/**
* Initializes the annotation using the page and optional dictionary by invoking base initialization.
*
* @private
* @param {PdfPage} page The page to associate with this annotation.
* @param {_PdfDictionary} [dictionary] Optional source dictionary to import from.
* @returns {void} No return value.
*/
PdfRichMediaAnnotation.prototype._initialize = function (page, dictionary) {
_super.prototype._initialize.call(this, page, dictionary);
};
/**
* Performs post processing including flattening popups and appearance and removes the annotation if appearance is unavailable during flattening.
*
* @private
* @param {boolean} [isFlatten=false] When true, flattens the annotation using its appearance stream if present; otherwise removes it.
* @returns {void} No return value.
*/
PdfRichMediaAnnotation.prototype._doPostProcess = function (isFlatten) {
if (isFlatten === void 0) { isFlatten = false; }
if (typeof this.flattenPopups !== 'undefined' && this.flattenPopups) {
this._flattenPopUp();
}
if (isFlatten) {
var appearanceStream = void 0;
if (this._dictionary.has('AP')) {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
appearanceStream = dictionary.get('N');
var reference = dictionary.getRaw('N');
if (reference && appearanceStream) {
appearanceStream.reference = reference;
}
}
}
if (appearanceStream) {
var template = new PdfTemplate(appearanceStream, this._crossReference);
var isNormalMatrix = this._validateTemplateMatrix(template._content.dictionary);
this._flattenAnnotationTemplate(template, isNormalMatrix);
}
else {
this._removeAnnotation(this._page, this);
}
}
};
return PdfRichMediaAnnotation;
}(PdfAnnotation));
export { PdfRichMediaAnnotation };
/**
* `PdfWidgetAnnotation` class represents the widget annotation objects.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Access first page
* let page: PdfPage = document.getPage(0);
* // Access the annotation at index 0
* let annotation: PdfWidgetAnnotation = page.annotations.at(0) as PdfWidgetAnnotation;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
var PdfWidgetAnnotation = /** @class */ (function (_super) {
__extends(PdfWidgetAnnotation, _super);
/**
* Initializes a new instance of the `PdfWidgetAnnotation` class.
*
* @private
*/
function PdfWidgetAnnotation() {
var _this = _super.call(this) || this;
/**
* Enables automatic resizing of the widget to fit content.
*
* @private
*/
_this._isAutoResize = false;
/**
* Controls the visibility state of the form field/widget.
*
* @private
*/
_this._visibility = PdfFormFieldVisibility.visible;
/**
* Indicates whether a font has been explicitly set for the widget.
*
* @private
*/
_this._isFont = false;
/**
* When true, treats the background color as transparent.
*
* @private
*/
_this._isTransparentBackColor = false;
/**
* When true, treats the border color as transparent.
*
* @private
*/
_this._isTransparentBorderColor = false;
_this._isWidget = true;
_this._type = _PdfAnnotationType.widgetAnnotation;
return _this;
}
/**
* Parse an existing widget annotation.
*
* @private
* @param {_PdfDictionary} dictionary Widget dictionary.
* @param {_PdfCrossReference} crossReference PDF cross reference.
* @returns {PdfWidgetAnnotation} Widget.
*/
PdfWidgetAnnotation._load = function (dictionary, crossReference) {
var widget = new PdfWidgetAnnotation();
widget._isLoaded = true;
widget._dictionary = dictionary;
widget._crossReference = crossReference;
return widget;
};
Object.defineProperty(PdfWidgetAnnotation.prototype, "page", {
/**
* Gets the page object (Read only).
*
* @returns {PdfPage} page object.
*
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Access check box field
* let field: PdfCheckBoxField = document.form.fieldAt(0) as PdfCheckBoxField;
* // Access first item of check box field
* let item: PdfWidgetAnnotation = field.itemAt(0);
* // Gets the page object.
* let page: PdfPage = item.page;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
return this._getPage();
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfWidgetAnnotation.prototype, "color", {
/**
* Gets the fore color of the annotation.
*
* @returns {PdfColor} Color as R, G, B color array in between 0 to 255.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfWidgetAnnotation = page.annotations.at(0) as PdfWidgetAnnotation;
* // Gets the fore color of the annotation.
* let color: PdfColor = annotation.color;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._color === 'undefined' && this._defaultAppearance) {
this._color = this._da.color;
}
return this._color;
},
/**
* Sets the fore color of the annotation.
*
* @param {PdfColor} value Color as R, G, B color array in between 0 to 255.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfWidgetAnnotation = page.annotations.at(0) as PdfWidgetAnnotation;
* // Sets the fore color of the annotation.
* annotation.color = {r: 255, g: 255, b: 255};
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (typeof this.color === 'undefined' || this._color !== value) {
this._color = value;
}
var isNew = false;
if (!this._defaultAppearance) {
this._da = new _PdfDefaultAppearance('');
isNew = true;
}
if (isNew || this._da.color !== value) {
this._da.color = value;
this._dictionary.update('DA', this._da.toString());
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfWidgetAnnotation.prototype, "backColor", {
/**
* Gets the back color of the annotation.
*
* @returns {PdfColor} Color as R, G, B color array in between 0 to 255.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Access the text box field at index 0
* let field: PdfField = document.form.fieldAt(0);
* // Gets the back color of the annotation
* let backColor: PdfColor = field.itemAt(0).backColor;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
return this._parseBackColor();
},
/**
* Sets the back color of the annotation.
*
* @param {PdfColor} value Array with R, G, B color values in between 0 to 255.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Access the text box field at index 0
* let field: PdfField = document.form.fieldAt(0);
* // Sets the background color of the field item
* field.itemAt(0).backColor = {r: 255, g: 0, b: 0};
* // Sets the background color of the field item to transparent
* field.itemAt(1).backColor = {r: 0, g: 0, b: 0, isTransparent: true};
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
this._updateBackColor(value);
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfWidgetAnnotation.prototype, "_hasBackColor", {
/**
* Indicates whether a background color is defined for the annotation.
*
* @private
* @returns {boolean} as true or false.
*/
get: function () {
if (this._isLoaded) {
var mkDictionary = this._mkDictionary;
return (mkDictionary && mkDictionary.has('BG'));
}
else {
return !this._isTransparentBackColor;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfWidgetAnnotation.prototype, "_hasBorderColor", {
/**
* Indicates whether a border color is defined for the annotation.
*
* @private
* @returns {boolean} as true or false.
*/
get: function () {
if (this._isLoaded) {
var mkDictionary = this._mkDictionary;
return (mkDictionary && mkDictionary.has('BC'));
}
else {
return !this._isTransparentBorderColor;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfWidgetAnnotation.prototype, "borderColor", {
/**
* Gets the border color of the annotation.
*
* @returns {PdfColor} Color as R, G, B color array in between 0 to 255.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfWidgetAnnotation = page.annotations.at(0) as PdfWidgetAnnotation;
* // Gets the border color of the annotation.
* let borderColor: PdfColor = annotation.borderColor;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
return this._parseBorderColor();
},
/**
* Sets the border color of the annotation.
*
* @param {PdfColor} value Array with R, G, B color values in between 0 to 255.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfWidgetAnnotation = page.annotations.at(0) as PdfWidgetAnnotation;
* // Sets the border color of the annotation.
* annotation.borderColor = {r: 255, g: 255, b: 255};
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
this._updateBorderColor(value);
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfWidgetAnnotation.prototype, "rotate", {
/**
* Gets the rotation angle of the annotation.
*
* @returns {number} Rotation angle as number.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfWidgetAnnotation = page.annotations.at(0) as PdfWidgetAnnotation;
* // Gets the rotation angle of the annotation.
* let rotate: number = annotation.rotate;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._rotationAngle === 'undefined') {
if (this._mkDictionary && this._mkDictionary.has('R')) {
this._rotationAngle = this._mkDictionary.get('R');
}
else if (this._dictionary.has('R')) {
this._rotationAngle = this._dictionary.get('R');
}
}
return this._rotationAngle;
},
/**
* Sets the rotation angle of the annotation.
*
* @param {number} value Rotation angle as number.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfWidgetAnnotation = page.annotations.at(0) as PdfWidgetAnnotation;
* // Sets the rotation angle of the annotation.
* annotation.rotate = 90;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (typeof this.rotate === 'undefined' || this._rotationAngle !== value) {
if (typeof this._mkDictionary === 'undefined') {
this._dictionary.update('MK', new _PdfDictionary(this._crossReference));
}
this._mkDictionary.update('R', value);
this._rotationAngle = value;
this._dictionary._updated = true;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfWidgetAnnotation.prototype, "highlightMode", {
/**
* Gets the highlight mode of the annotation.
*
* @returns {PdfHighlightMode} Highlight mode.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfWidgetAnnotation = page.annotations.at(0) as PdfWidgetAnnotation;
* // Gets the highlight mode of the annotation.
* let highlightMode: PdfHighlightMode = annotation.highlightMode;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._highlightMode === 'undefined' && this._dictionary.has('H')) {
var mode = this._dictionary.get('H');
this._highlightMode = _mapHighlightMode(mode.name);
}
return this._highlightMode;
},
/**
* Sets the highlight mode of the annotation.
*
* @param {PdfHighlightMode} value Highlight mode.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfWidgetAnnotation = page.annotations.at(0) as PdfWidgetAnnotation;
* // Sets the highlight mode of the annotation.
* annotation.highlightMode = PdfHighlightMode.noHighlighting;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (this._highlightMode !== value) {
this._dictionary.update('H', _reverseMapHighlightMode(value));
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfWidgetAnnotation.prototype, "bounds", {
/**
* Gets the bounds of the annotation.
*
* @returns {Rectangle} Bounds.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfWidgetAnnotation = page.annotations.at(0) as PdfWidgetAnnotation;
* // Gets the bounds of the annotation
* let bounds: Rectangle = annotation.bounds;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (this._isLoaded && typeof this._bounds === 'undefined') {
this._bounds = _calculateBounds(this._dictionary, this._getPage());
}
if (typeof this._bounds === 'undefined' || this._bounds === null) {
this._bounds = { x: 0, y: 0, width: 0, height: 0 };
}
return this._bounds;
},
/**
* Sets the bounds of the annotation.
*
* @param {Rectangle} value Bounds
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfWidgetAnnotation = page.annotations.at(0) as PdfWidgetAnnotation;
* // Sets the bounds of the annotation
* annotation.bounds = {x: 0, y: 0, width: 50, height: 50};
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value.x === 0 && value.y === 0 && value.width === 0 && value.height === 0) {
throw new Error('Cannot set empty bounds');
}
this._bounds = value;
if (this._page && this._page._isNew && this._page._pageSettings) {
this._dictionary.update('Rect', _updateBounds(this));
}
else {
this._dictionary.update('Rect', _getUpdatedBounds([value.x, value.y, value.width, value.height], this._getPage()));
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfWidgetAnnotation.prototype, "textAlignment", {
/**
* Gets the text alignment of the annotation.
*
* @returns {PdfTextAlignment} Text alignment.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfWidgetAnnotation = page.annotations.at(0) as PdfWidgetAnnotation;
* // Gets the text alignment of the annotation.
* let textAlignment: PdfTextAlignment = annotation.textAlignment;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._textAlignment === 'undefined' && this._dictionary.has('Q')) {
this._textAlignment = this._dictionary.get('Q');
}
return this._textAlignment;
},
/**
* Sets the text alignment of the annotation.
*
* @param {PdfTextAlignment} value Text alignment.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfWidgetAnnotation = page.annotations.at(0) as PdfWidgetAnnotation;
* // Sets the text alignment of the annotation
* annotation.textAlignment = PdfTextAlignment.left;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (typeof this._textAlignment === 'undefined' || this._textAlignment !== value) {
this._dictionary.update('Q', value);
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfWidgetAnnotation.prototype, "visibility", {
/**
* Gets the visibility.
*
* @returns {PdfFormFieldVisibility} Field visibility option.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Access the form field at index 0
* let field: PdfField = document.form.fieldAt(0);
* // Gets the visibility
* let visibility: PdfFormFieldVisibility = field.itemAt(0).visibility;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
var value;
if (this._isLoaded) {
value = PdfFormFieldVisibility.visible;
var flag = PdfAnnotationFlag.default;
if (this._hasFlags) {
flag = this.flags;
var flagValue = 3;
if ((flag & PdfAnnotationFlag.hidden) === PdfAnnotationFlag.hidden) {
flagValue = 0;
}
if ((flag & PdfAnnotationFlag.noView) === PdfAnnotationFlag.noView) {
flagValue = 1;
}
if ((flag & PdfAnnotationFlag.print) !== PdfAnnotationFlag.print) {
flagValue &= 2;
}
switch (flagValue) {
case 0:
value = PdfFormFieldVisibility.hidden;
break;
case 1:
value = PdfFormFieldVisibility.hiddenPrintable;
break;
case 2:
value = PdfFormFieldVisibility.visibleNotPrintable;
break;
case 3:
value = PdfFormFieldVisibility.visible;
break;
}
}
else {
value = PdfFormFieldVisibility.visibleNotPrintable;
}
}
else {
return this._visibility;
}
return value;
},
/**
* Sets the visibility.
*
* @param {PdfFormFieldVisibility} value Visibility option.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Access the form field at index 0
* let field: PdfField = document.form.fieldAt(0);
* // Sets the visibility
* let field.itemAt(0).visibility = PdfFormFieldVisibility.hiddenPrintable;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (this._isLoaded) {
_updateVisibility(this._dictionary, value);
this._dictionary._updated = true;
}
else {
switch (value) {
case PdfFormFieldVisibility.hidden:
this.flags = PdfAnnotationFlag.hidden;
break;
case PdfFormFieldVisibility.hiddenPrintable:
this.flags = PdfAnnotationFlag.noView | PdfAnnotationFlag.print;
break;
case PdfFormFieldVisibility.visible:
this.flags = PdfAnnotationFlag.print;
break;
case PdfFormFieldVisibility.visibleNotPrintable:
this.flags = PdfAnnotationFlag.default;
break;
}
this._visibility = value;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfWidgetAnnotation.prototype, "font", {
/**
* Gets the font of the item.
*
* @returns {PdfFont} font.
*
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Access the form field at index 0
* let field: PdfTextBoxField = document.form.fieldAt(0) as PdfTextBoxField;
* // Get the first item of the field
* let item: PdfWidgetAnnotation = field.itemAt(0);
* // Gets the font of the item
* let font: PdfFont = item.font;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
var _this = this;
if (!this._pdfFont) {
var fontName = void 0;
if (this._crossReference) {
var form_1 = this._crossReference._document.form;
var fontData = this._obtainFontDetails();
var cacheKey = fontData.name + "_" + fontData.size + "_" + fontData.style;
if (form_1 && form_1._fontCache.has(cacheKey)) {
return form_1._fontCache.get(cacheKey);
}
if (form_1 && form_1._dictionary.has('DR')) {
var resources = form_1._dictionary.get('DR');
if (resources.has('Font')) {
var fonts = resources.get('Font');
if (fonts.has(fontData.name)) {
var fontDictionary = fonts.get(fontData.name);
if (fontDictionary && fontData.name && fontDictionary.has('BaseFont')) {
var baseFont = fontDictionary.get('BaseFont');
var textFontStyle = PdfFontStyle.regular;
if (baseFont) {
fontName = baseFont.name;
textFontStyle = _getFontStyle(baseFont.name);
if (fontName.includes('-')) {
fontName = fontName.substring(0, fontName.indexOf('-'));
}
if (this._dictionary.has('DA')) {
this._pdfFont = _obtainFontDetails(form_1, this);
}
else {
this._pdfFont = _mapFont(fontName, fontData.size, textFontStyle, this);
}
if (!form_1._fontCache.has(cacheKey)) {
form_1._fontCache.set(cacheKey, this._pdfFont);
}
}
}
}
}
}
if ((form_1 !== null && typeof form_1 !== 'undefined') && (this._pdfFont === null || typeof this._pdfFont === 'undefined') &&
form_1._parsedFields && form_1._parsedFields.size > 0) {
form_1._parsedFields.forEach(function (field) {
if (field instanceof PdfTextBoxField && field._kidsCount > 0) {
_this._pdfFont = _obtainFontDetails(form_1, _this, field);
}
});
if (!form_1._fontCache.has(cacheKey)) {
form_1._fontCache.set(cacheKey, this._pdfFont);
}
}
}
}
if ((this._pdfFont === null || typeof this._pdfFont === 'undefined') || (!this._isLoaded && this._pdfFont.size === 1)) {
this._pdfFont = this._circleCaptionFont;
}
return this._pdfFont;
},
/**
* Sets the font of the item.
*
* @param {PdfFont} value font.
*
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Access the form field at index 0
* let field: PdfTextBoxField = document.form.fieldAt(0) as PdfTextBoxField;
* // Get the first item of the field
* let item: PdfWidgetAnnotation = field.itemAt(0);
* // Set the font of the item
* item.font = new PdfStandardFont(PdfFontFamily.helvetica, 12, PdfFontStyle.bold);
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value && value instanceof PdfFont) {
this._pdfFont = value;
this._initializeFont(value);
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfWidgetAnnotation.prototype, "_defaultAppearance", {
/**
* Gets the cached default appearance from the annotation dictionary if available.
*
* @private
* @returns {_PdfDefaultAppearance} The parsed default appearance, if any.
*/
get: function () {
if (typeof this._da === 'undefined' && this._dictionary.has('DA')) {
var da = this._dictionary.get('DA');
if (da && da !== '') {
this._da = new _PdfDefaultAppearance(da);
}
}
return this._da;
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfWidgetAnnotation.prototype, "_mkDictionary", {
/**
* Gets the cached default appearance from the annotation dictionary if available.
*
* @private
* @returns {_PdfDefaultAppearance} The parsed default appearance, if any.
*/
get: function () {
var value;
if (this._dictionary.has('MK')) {
value = this._dictionary.get('MK');
}
return value;
},
enumerable: true,
configurable: true
});
/* eslint-disable */
/**
* Creates and initializes the widget annotation on the specified page with optional field linkage.
*
* @private
* @param {PdfPage} page The page on which to create the widget.
* @param {{x: number, y: number, width: number, height: number}} bounds The widget bounds in page coordinates. // eslint-disable-line
* @param {PdfField} [field] Optional form field to set as this widget's parent.
* @returns {_PdfDictionary} The created widget annotation dictionary.
*/
PdfWidgetAnnotation.prototype._create = function (page, bounds, field) {
this._page = page;
this._crossReference = page._crossReference;
this._ref = this._crossReference._getNextReference();
this._dictionary = new _PdfDictionary(this._crossReference);
this._crossReference._cacheMap.set(this._ref, this._dictionary);
this._dictionary._currentObj = this;
this._dictionary.objId = this._ref.toString();
this._dictionary.update('Type', _PdfName.get('Annot'));
this._dictionary.update('Subtype', _PdfName.get('Widget'));
this.flags |= PdfAnnotationFlag.print;
this._dictionary.update('P', page._ref);
page._addWidget(this._ref);
this.border = new PdfAnnotationBorder();
if (bounds) {
this.bounds = bounds;
}
if (field) {
this._field = field;
this._dictionary.update('Parent', this._field._ref);
}
return this._dictionary;
};
/* eslint-enable */
/**
* Performs post processing to recreate or use existing appearance and optionally flattens it to the page.
*
* @private
* @param {boolean} [isFlatten=false] When true, flattens the annotation appearance into page content.
* @param {boolean} [recreateAppearance=false] When true, attempts to recreate the appearance stream.
* @returns {void} No return value.
*/
PdfWidgetAnnotation.prototype._doPostProcess = function (isFlatten, recreateAppearance) {
if (isFlatten === void 0) { isFlatten = false; }
if (recreateAppearance === void 0) { recreateAppearance = false; }
if (isFlatten || recreateAppearance) {
var appearanceStream = void 0;
if (recreateAppearance || (isFlatten && !this._dictionary.has('AP'))) {
//appearanceStream = this._createAppearance();
}
if (!appearanceStream && this._dictionary.has('AP')) {
var dictionary = this._dictionary.get('AP');
if (dictionary && dictionary.has('N')) {
appearanceStream = dictionary.get('N');
var reference = dictionary.getRaw('N');
if (reference && appearanceStream) {
appearanceStream.reference = reference;
}
}
}
if (appearanceStream) {
var bounds = void 0;
if (isFlatten) {
var template = new PdfTemplate(appearanceStream, this._crossReference);
var page = this._getPage();
if (page) {
var graphics = page.graphics;
graphics.save();
if (page.rotation === PdfRotationAngle.angle90) {
graphics.translateTransform({ x: graphics._size.width, y: graphics._size.height });
graphics.rotateTransform(90);
}
else if (page.rotation === PdfRotationAngle.angle180) {
graphics.translateTransform({ x: graphics._size.width, y: graphics._size.height });
graphics.rotateTransform(-180);
}
else if (page.rotation === PdfRotationAngle.angle270) {
graphics.translateTransform({ x: graphics._size.width, y: graphics._size.height });
graphics.rotateTransform(270);
}
bounds = { x: this.bounds.x, y: this.bounds.y, width: template._size.width, height: template._size.height };
graphics.drawTemplate(template, bounds);
graphics.restore();
}
}
else {
var appearance = void 0;
if (this._dictionary.has('AP')) {
appearance = this._dictionary.get('AP');
}
else {
var reference_1 = this._crossReference._getNextReference();
appearance = new _PdfDictionary(this._crossReference);
this._crossReference._cacheMap.set(reference_1, appearance);
this._dictionary.update('AP', reference_1);
}
_removeDuplicateReference(appearance, this._crossReference, 'N');
var reference = this._crossReference._getNextReference();
this._crossReference._cacheMap.set(reference, appearanceStream);
appearance.update('N', reference);
}
}
this._dictionary._updated = false;
}
};
/**
* Initializes and registers the font in the document resources and updates default appearance.
*
* @private
* @param {PdfFont} font The font to register and apply to this widget.
* @returns {void} No return value.
*/
PdfWidgetAnnotation.prototype._initializeFont = function (font) {
this._pdfFont = font;
var document;
if (this._crossReference) {
document = this._crossReference._document;
var resource = void 0;
if (document) {
if (document.form._dictionary.has('DR')) {
resource = document.form._dictionary.get('DR');
}
else {
resource = new _PdfDictionary(this._crossReference);
}
}
var fontDict = void 0;
var isReference = false;
if (resource.has('Font')) {
var obj = resource.getRaw('Font'); // eslint-disable-line
if (obj && obj instanceof _PdfReference) {
isReference = true;
fontDict = this._crossReference._fetch(obj);
}
else if (obj instanceof _PdfDictionary) {
fontDict = obj;
}
}
if (!fontDict) {
fontDict = new _PdfDictionary(this._crossReference);
resource.update('Font', fontDict);
}
var keyName = _PdfName.get(_getNewGuidString());
var reference = this._crossReference._getNextReference();
this._crossReference._cacheMap.set(reference, this._pdfFont._dictionary);
if (font instanceof PdfTrueTypeFont) {
if (this._pdfFont._pdfFontInternals) {
this._crossReference._cacheMap.set(reference, this._pdfFont._pdfFontInternals);
}
}
else if (this._pdfFont._dictionary) {
this._crossReference._cacheMap.set(reference, this._pdfFont._dictionary);
}
fontDict.update(keyName.name, reference);
resource._updated = true;
document.form._dictionary.update('DR', resource);
document.form._dictionary._updated = true;
this._fontName = keyName.name;
var defaultAppearance = new _PdfDefaultAppearance();
defaultAppearance.fontName = this._fontName;
defaultAppearance.fontSize = this._pdfFont._size;
defaultAppearance.color = this.color ? this.color : { r: 0, g: 0, b: 0 };
this._dictionary.update('DA', defaultAppearance.toString());
if (isReference) {
resource._updated = true;
}
this._isFont = true;
}
};
/**
* Resolves and caches the owning page of the annotation from the document structure.
*
* @private
* @returns {PdfPage} The resolved page object, if found.
*/
PdfWidgetAnnotation.prototype._getPage = function () {
if (!this._page) {
var document_1;
if (this._crossReference) {
document_1 = this._crossReference._document;
}
var page = void 0;
if (this._dictionary.has('P')) {
var ref = this._dictionary.getRaw('P');
if (ref && document_1) {
for (var i = 0; i < document_1.pageCount; i++) {
var entry = document_1.getPage(i);
if (entry && entry._ref === ref) {
page = entry;
break;
}
}
}
}
if (!page && document_1 && this._ref) {
page = _findPage(document_1, this._ref);
}
this._page = page;
}
return this._page;
};
/**
* Updates the annotation rectangle before saving when bounds must be normalized to the page.
*
* @private
* @returns {void} No return value.
*/
PdfWidgetAnnotation.prototype._beginSave = function () {
if (!this._isLoaded && !this._page._isNew) {
var value = this._bounds;
this._dictionary.update('Rect', _getUpdatedBounds([value.x, value.y, value.width, value.height], this._page));
}
};
/**
* Parses and returns the background color from the appearance dictionary or defaults to white.
*
* @private
* @returns {PdfColor} The resolved background color.
*/
PdfWidgetAnnotation.prototype._parseBackColor = function () {
var value;
if ((this._isLoaded && this._hasBackColor) || (!this._isLoaded && !this._isTransparentBackColor)) {
if (typeof this._backColor === 'undefined') {
var dictionary = this._mkDictionary;
if (dictionary && dictionary.has('BG')) {
var colorArray = dictionary.getArray('BG');
if (colorArray) {
this._backColor = _parseColor(colorArray);
}
}
}
if (typeof this._backColor === 'undefined' || this._backColor === null) {
this._backColor = { r: 255, g: 255, b: 255 };
}
value = this._backColor;
}
return value;
};
/**
* Parses and returns the border color from the appearance dictionary or defaults to black.
*
* @private
* @returns {PdfColor} The resolved border color.
*/
PdfWidgetAnnotation.prototype._parseBorderColor = function () {
var value;
if ((this._isLoaded && this._hasBorderColor) || (!this._isLoaded && !this._isTransparentBorderColor)) {
if (typeof this._borderColor === 'undefined') {
var dictionary = this._mkDictionary;
if (dictionary && dictionary.has('BC')) {
var colorArray = dictionary.getArray('BC');
if (colorArray) {
this._borderColor = _parseColor(colorArray);
}
}
}
if (typeof this._borderColor === 'undefined' || this._borderColor === null) {
this._borderColor = { r: 0, g: 0, b: 0 };
}
value = this._borderColor;
}
return value;
};
/**
* Updates the background color state and appearance flags and optionally triggers field appearance regeneration.
*
* @private
* @param {PdfColor} value The new background color (set isTransparent to remove).
* @param {boolean} [setAppearance=false] When true, marks the parent field for appearance regeneration.
* @returns {void} No return value.
*/
PdfWidgetAnnotation.prototype._updateBackColor = function (value, setAppearance) {
if (setAppearance === void 0) { setAppearance = false; }
var isChanged = false;
if (value && value.isTransparent) {
this._isTransparentBackColor = true;
if (this._dictionary.has('BG')) {
delete this._dictionary._map.BG;
isChanged = true;
}
var mkDictionary = this._mkDictionary;
if (mkDictionary && mkDictionary.has('BG')) {
delete mkDictionary._map.BG;
this._dictionary._updated = true;
isChanged = true;
}
}
else {
this._isTransparentBackColor = false;
var bColor = void 0;
if (bColor) {
bColor = { r: this._backColor.r, g: this._backColor.g, b: this._backColor.b };
}
if (typeof this.backColor === 'undefined' || bColor !== value) {
if (typeof this._mkDictionary === 'undefined') {
this._dictionary.update('MK', new _PdfDictionary(this._crossReference));
}
this._mkDictionary.update('BG', [Number.parseFloat((value.r / 255).toFixed(3)),
Number.parseFloat((value.g / 255).toFixed(3)),
Number.parseFloat((value.b / 255).toFixed(3))]);
this._backColor = value;
this._dictionary._updated = true;
isChanged = true;
}
}
if (setAppearance && isChanged && this._field) {
this._field._setAppearance = true;
}
};
/**
* Updates the border color state and related border style entries in the appearance dictionary.
*
* @private
* @param {PdfColor} value The new border color (set isTransparent to remove).
* @returns {void} No return value.
*/
PdfWidgetAnnotation.prototype._updateBorderColor = function (value) {
if (value && value.isTransparent) {
this._isTransparentBorderColor = true;
if (this._dictionary.has('BC')) {
delete this._dictionary._map.BC;
}
var mkDictionary = this._mkDictionary;
if (mkDictionary && mkDictionary.has('BC')) {
delete mkDictionary._map.BC;
if (this._dictionary.has('BS')) {
var bsDictionary = this._dictionary.get('BS');
if (bsDictionary && bsDictionary.has('W')) {
delete bsDictionary._map.W;
}
}
this._dictionary._updated = true;
}
}
else {
this._isTransparentBorderColor = false;
var bColor = void 0;
if (this.borderColor) {
bColor = this.borderColor;
}
if (typeof this.borderColor === 'undefined' || bColor !== value) {
if (typeof this._mkDictionary === 'undefined') {
this._dictionary.update('MK', new _PdfDictionary(this._crossReference));
}
this._mkDictionary.update('BC', [Number.parseFloat((value.r / 255).toFixed(3)),
Number.parseFloat((value.g / 255).toFixed(3)),
Number.parseFloat((value.b / 255).toFixed(3))]);
this._borderColor = value;
this._dictionary._updated = true;
}
}
};
return PdfWidgetAnnotation;
}(PdfAnnotation));
export { PdfWidgetAnnotation };
/**
* `PdfStateItem` class represents the check box field item objects.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Access check box field
* let field: PdfCheckBoxField = document.form.fieldAt(0) as PdfCheckBoxField;
* // Access first item of check box field
* let item: PdfStateItem = field.itemAt(0) as PdfStateItem;
* // Sets the check box style as check
* item.style = PdfCheckBoxStyle.check;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
var PdfStateItem = /** @class */ (function (_super) {
__extends(PdfStateItem, _super);
/**
* Initializes a new instance of the `PdfStateItem` class.
*
* @private
*/
function PdfStateItem() {
var _this = _super.call(this) || this;
/**
* Stores the export value associated with the selected state.
*
* @private
*/
_this._exportValue = 'Yes';
return _this;
}
/**
* Parse an existing item of the field.
*
* @private
* @param {_PdfDictionary} dictionary Widget dictionary.
* @param {_PdfCrossReference} crossReference PDF cross reference.
* @param {PdfField} field Field object.
* @returns {PdfStateItem} Widget.
*/
PdfStateItem._load = function (dictionary, crossReference, field) {
var widget = new PdfStateItem();
widget._isLoaded = true;
widget._dictionary = dictionary;
widget._crossReference = crossReference;
widget._field = field;
return widget;
};
Object.defineProperty(PdfStateItem.prototype, "checked", {
/**
* Gets the flag to indicate whether the field item is checked or not.
*
* @returns {boolean} Checked or not.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Access check box field
* let field: PdfCheckBoxField = document.form.fieldAt(0) as PdfCheckBoxField;
* // Access first item of check box field
* let item: PdfStateItem = field.itemAt(0) as PdfStateItem;
* // Gets the flag to indicate whether the field item is checked or not.
* let checked: boolean = item.checked;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
return _checkField(this._dictionary);
},
/**
* Sets the flag to indicate whether the field item is checked or not.
*
* @param {boolean} value Checked or not.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Access check box field
* let field: PdfCheckBoxField = document.form.fieldAt(0) as PdfCheckBoxField;
* // Access first item of check box field
* let item: PdfStateItem = field.itemAt(0) as PdfStateItem;
* // Sets the style of the annotation
* item.checked = true;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (this.checked !== value) {
if (this._field) {
this._setCheckedStatus(value);
this._field._setAppearance = true;
}
if (this._exportValue) {
this._dictionary.update('AS', _PdfName.get(value ? this._exportValue : 'Off'));
}
else if (this._field && this._field._exportValue !== null && typeof this._field._exportValue !== 'undefined') {
this._dictionary.update('AS', _PdfName.get(value ? this._field._exportValue : 'Off'));
}
else {
this._dictionary.update('AS', _PdfName.get(value ? 'Yes' : 'Off'));
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfStateItem.prototype, "style", {
/**
* Gets the style of annotation.
*
* @returns {PdfCheckBoxStyle} Style of annotation.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Access check box field
* let field: PdfCheckBoxField = document.form.fieldAt(0) as PdfCheckBoxField;
* // Access first item of check box field
* let item: PdfStateItem = field.itemAt(0) as PdfStateItem;
* // Gets the style of the annotation
* let style: PdfCheckBoxStyle = item.style;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (this._isLoaded) {
var dictionary = this._mkDictionary;
if (dictionary && dictionary.has('CA')) {
this._style = _stringToStyle(dictionary.get('CA'));
}
else {
this._style = PdfCheckBoxStyle.check;
}
}
return this._style;
},
/**
* Sets the style of annotation.
*
* @param {PdfCheckBoxStyle} value Style of annotation.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Access check box field
* let field: PdfCheckBoxField = document.form.fieldAt(0) as PdfCheckBoxField;
* // Access first item of check box field
* let item: PdfStateItem = field.itemAt(0) as PdfStateItem;
* // Sets the style of the annotation
* item.style = PdfCheckBoxStyle.check;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (this.style !== value) {
this._style = value;
var dictionary = this._mkDictionary;
if (!dictionary) {
dictionary = new _PdfDictionary(this._crossReference);
this._dictionary.update('MK', dictionary);
}
dictionary.update('CA', _styleToString(value));
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfStateItem.prototype, "exportValue", {
/**
* Gets the export value of the check box field.
*
* @returns {string} Export value.
*
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Access the check box field
* let field: PdfCheckBoxField = document.form.fieldAt(0) as PdfCheckBoxField;
* // Access the first item of the check box field group
* let item: PdfStateItem = field.itemAt(0);
* // Gets the export value of the checkbox field.
* let text: sting = item.exportValue;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
return this._tryGetExportValue(this);
},
/**
* Sets the export value of the check box item.
*
* @param {string} value Export value.
*
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Access the check box field
* let field: PdfCheckBoxField = document.form.fieldAt(0) as PdfCheckBoxField;
* // Access the first item of the check box field group
* let item: PdfStateItem = field.itemAt(0);
* // Sets the export value of the checkbox field.
* item.exportValue = 'CheckBox';
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value !== '') {
this._exportValue = value;
}
if (this.checked) {
this._dictionary.update('AS', _PdfName.get(value));
this._setCheckedStatus(this.checked);
}
else {
this._dictionary.update('AS', _PdfName.get('Off'));
}
if (this._dictionary.has('AP')) {
var dictionary = this._dictionary.get('AP');
if (dictionary.has('N') || dictionary.has('D')) {
var oldValue = this._tryGetExportValue(this);
var newValue = value;
if (dictionary.has('N')) {
var normalDictionary = dictionary.get('N');
if (normalDictionary && normalDictionary.has(oldValue)) {
var reference = normalDictionary.getRaw(oldValue);
delete normalDictionary._map[oldValue]; // eslint-disable-line
normalDictionary.update(newValue, reference);
normalDictionary._updated = true;
}
}
if (dictionary.has('D')) {
var downDictionary = dictionary.get('D');
if (downDictionary && downDictionary.has(oldValue)) {
var reference = downDictionary.getRaw(oldValue);
delete downDictionary._map[oldValue]; // eslint-disable-line
downDictionary.update(newValue, reference);
downDictionary._updated = true;
}
}
}
}
this._dictionary._updated = true;
},
enumerable: true,
configurable: true
});
/**
* Sets the checked state and updates field and appearance dictionaries accordingly.
*
* @private
* @param {boolean} value Checked state to apply.
* @returns {void} No return value.
*/
PdfStateItem.prototype._setCheckedStatus = function (value) {
var check = value;
var fieldValue = this._tryGetExportValue(this);
this._unCheckOthers(this, fieldValue, value);
if (check) {
if (!fieldValue) {
fieldValue = 'Yes';
}
else {
this._exportValue = fieldValue;
}
this._field._dictionary.update('V', _PdfName.get(fieldValue));
this._field._dictionary.update('AS', _PdfName.get(fieldValue));
this._dictionary.update('AS', _PdfName.get(fieldValue));
this._dictionary.update('V', _PdfName.get(fieldValue));
}
else if (this._field._dictionary) {
if (this._field._dictionary.has('V')) {
var v = this._field._dictionary.get('V');
if (v && v.name === fieldValue) {
delete this._field._dictionary._map.V;
}
}
this._field._dictionary.update('AS', _PdfName.get('Off'));
}
};
/**
* Unchecks sibling items in the same field and ensures the current item remains checked when needed.
*
* @private
* @param {PdfStateItem} child The current item being toggled.
* @param {string} value The export value used to match siblings.
* @param {boolean} isChecked Whether the current item is checked.
* @returns {void} No return value.
*/
PdfStateItem.prototype._unCheckOthers = function (child, value, isChecked) {
if (!this._field._isUpdating) {
this._field._isUpdating = true;
var count = this._field.itemsCount;
for (var i = 0; i < count; ++i) {
var item = this._field.itemAt(i);
if (item) {
if (item !== child) {
var exportValue = this._tryGetExportValue(item);
item.checked = (exportValue === value && isChecked);
}
else if (!item.checked) {
item.checked = true;
}
}
}
}
};
/**
* Determines the export value of the widget from its appearance or state entries.
*
* @private
* @param {PdfStateItem} item Item to inspect.
* @returns {string} The resolved export value.
*/
PdfStateItem.prototype._tryGetExportValue = function (item) {
var itemValue = item._exportValue;
if (item._dictionary && item._dictionary.has('AP')) {
var apDictionary = item._dictionary.get('AP');
if (apDictionary && apDictionary.has('N')) {
var normalAppearance = apDictionary.get('N');
var keyList_1 = [];
normalAppearance.forEach(function (key, value) {
keyList_1.push(key);
});
if (keyList_1.length > 0) {
for (var i = 0; i < keyList_1.length; i++) {
var key = keyList_1[i];
if (key && key !== 'Off') {
itemValue = key;
break;
}
}
}
}
}
else if (item._dictionary && item._dictionary.has('AS')) {
var asValue = item._dictionary.get('AS');
if (asValue && asValue.name !== 'Off') {
itemValue = asValue.name;
}
}
return itemValue;
};
/**
* Draws the current state appearance onto the page and finalizes the annotation update state.
*
* @private
* @returns {void} No return value.
*/
PdfStateItem.prototype._doPostProcess = function () {
var style = this.checked ? _PdfCheckFieldState.checked : _PdfCheckFieldState.unchecked;
var template = _getStateTemplate(style, this);
if (template) {
var page = this._getPage();
if (page) {
var graphics = page.graphics;
graphics.save();
if (page.rotation === PdfRotationAngle.angle90) {
graphics.translateTransform({ x: graphics._size.width, y: graphics._size.height });
graphics.rotateTransform(90);
}
else if (page.rotation === PdfRotationAngle.angle180) {
graphics.translateTransform({ x: graphics._size.width, y: graphics._size.height });
graphics.rotateTransform(-180);
}
else if (page.rotation === PdfRotationAngle.angle270) {
graphics.translateTransform({ x: graphics._size.width, y: graphics._size.height });
graphics.rotateTransform(270);
}
graphics._sw._setTextRenderingMode(_TextRenderingMode.fill);
graphics.drawTemplate(template, this.bounds);
graphics.restore();
}
}
this._dictionary._updated = false;
};
/**
* Updates the appearance state entry based on the provided or inferred value.
*
* @private
* @param {string} [value] The appearance state to set; defaults to 'Yes' or 'Off'.
* @returns {void} No return value.
*/
PdfStateItem.prototype._postProcess = function (value) {
var field = this._field;
if (!value) {
value = (field && field.checked) ? 'Yes' : 'Off';
}
this._dictionary.update('AS', _PdfName.get(value));
};
/**
* Assigns the owning field, updates formatting, and registers this item as a kid of the field.
*
* @private
* @param {PdfField} field The parent field to associate.
* @returns {void} No return value.
*/
PdfStateItem.prototype._setField = function (field) {
this._field = field;
this._field._stringFormat = new PdfStringFormat(this.textAlignment, PdfVerticalAlignment.middle);
this._field._addToKid(this);
};
return PdfStateItem;
}(PdfWidgetAnnotation));
export { PdfStateItem };
/**
* `PdfRadioButtonListItem` class represents the radio button field item objects.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data);
* // Gets the first page of the document
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Access the PDF form
* let form: PdfForm = document.form;
* // Create a new radio button list field
* let field: PdfRadioButtonListField = new PdfRadioButtonListField(page, 'Age');
* // Create and add first item
* let first: PdfRadioButtonListItem = field.add('1-9', {x: 100, y: 140, width: 20, height: 20});
* // Create and add second item
* let second: PdfRadioButtonListItem = new PdfRadioButtonListItem('10-49', {x: 100, y: 170, width: 20, height: 20}, page);
* field.add(second);
* // Create and add third item
* let third: PdfRadioButtonListItem = new PdfRadioButtonListItem('50-59', {x: 100, y: 200, width: 20, height: 20}, field);
* field.add(third);
* // Sets selected index of the radio button list field
* field.selectedIndex = 0;
* // Add the field into PDF form
* form.add(field);
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
var PdfRadioButtonListItem = /** @class */ (function (_super) {
__extends(PdfRadioButtonListItem, _super);
function PdfRadioButtonListItem(value, bounds, item) {
var _this = _super.call(this) || this;
if (item && value && bounds) {
if (item instanceof PdfField) {
_this._initializeItem(value, bounds, item.page, item);
}
else {
_this._initializeItem(value, bounds, item);
}
}
return _this;
}
/**
* Parse an existing item of the field.
*
* @private
* @param {_PdfDictionary} dictionary Widget dictionary.
* @param {_PdfCrossReference} crossReference PDF cross reference.
* @param {PdfField} field Field object.
* @returns {PdfRadioButtonListItem} Widget.
*/
PdfRadioButtonListItem._load = function (dictionary, crossReference, field) {
var widget = new PdfRadioButtonListItem();
widget._isLoaded = true;
widget._dictionary = dictionary;
widget._crossReference = crossReference;
widget._field = field;
return widget;
};
Object.defineProperty(PdfRadioButtonListItem.prototype, "selected", {
/**
* Gets the flag to indicate whether the field item is selected or not.
*
* @returns {boolean} Selected or not.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data);
* // Gets the first page of the document
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Access the PDF form
* let form: PdfForm = document.form;
* // Create a new radio button list field
* let field: PdfRadioButtonListField = new PdfRadioButtonListField(page, 'Age');
* // Access first list field item
* let item: PdfRadioButtonListItem = field.itemAt(0);
* // Gets the flag to indicate whether the field item is selected or not.
* let selected: boolean = item.selected;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
return this._index === this._field.selectedIndex;
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfRadioButtonListItem.prototype, "value", {
/**
* Gets the value of the radio button list field item
*
* @returns {string} Value of the radio button list field item.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data);
* // Gets the first page of the document
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Access the PDF form
* let form: PdfForm = document.form;
* // Create a new radio button list field
* let field: PdfRadioButtonListField = new PdfRadioButtonListField(page, 'Age');
* // Access first list field item
* let item: PdfRadioButtonListItem = field.itemAt(0);
* // Gets the value of the radio button list field item
* let value: string = item.value;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (this._isLoaded && !this._optionValue) {
this._optionValue = _getItemValue(this._dictionary);
}
return this._optionValue;
},
/**
* Sets the value of the radio button list field item
*
* @param {string} option Value of the radio button list field item.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data);
* // Gets the first page of the document
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Access the PDF form
* let form: PdfForm = document.form;
* // Create a new radio button list field
* let field: PdfRadioButtonListField = new PdfRadioButtonListField(page, 'Age');
* // Access first list field item
* let item: PdfRadioButtonListItem = field.itemAt(0);
* // Sets the value of the radio button list field item
* item.value = '1-9';
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (option) {
this._optionValue = option;
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfRadioButtonListItem.prototype, "backColor", {
/**
* Gets the back color of the annotation.
*
* @returns {PdfColor} Color as R, G, B color array in between 0 to 255.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfWidgetAnnotation = page.annotations.at(0) as PdfWidgetAnnotation;
* // Gets the back color of the annotation
* let backColor: PdfColor = annotation.backColor;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
return this._parseBackColor();
},
/**
* Sets the back color of the annotation.
*
* @param {PdfColor} value Array with R, G, B color values in between 0 to 255.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data);
* // Gets the first page of the document
* let page: PdfPage = document.getPage(0);
* // Access the PDF form
* let form: PdfForm = document.form;
* // Access the radio button list field
* let field: PdfRadioButtonListField = form.fieldAt(0) as PdfRadioButtonListField;
* // Sets the back color of the radio button list item
* field.itemAt(0).backColor = {r: 255, g: 255, b: 255};
* // Sets the background color of the field item to transparent
* field.itemAt(1).backColor = {r: 0, g: 0, b: 0, isTransparent: true};
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
this._updateBackColor(value, true);
},
enumerable: true,
configurable: true
});
/* eslint-disable */
/**
* Initializes the radio button item with value, page, bounds, default styles, and optional parent field.
*
* @private
* @param {string} value The option/export value for this item.
* @param {any} bounds The item bounds on the page.
* @param {PdfPage} page The page where the item resides.
* @param {PdfField} [field] Optional field to register as parent.
* @returns {void} No return value.
*/
PdfRadioButtonListItem.prototype._initializeItem = function (value, bounds, page, field) {
this._optionValue = value;
this._page = page;
this._create(this._page, bounds, this._field);
this.textAlignment = PdfTextAlignment.left;
this._dictionary.update('MK', new _PdfDictionary(this._crossReference));
this._mkDictionary.update('BC', [0, 0, 0]);
this._mkDictionary.update('BG', [1, 1, 1]);
this.style = PdfCheckBoxStyle.circle;
this._dictionary.update('DA', '/TiRo 0 Tf 0 0 0 rg');
if (field) {
this._setField(field);
this._dictionary.update('Parent', field._ref);
}
};
/* eslint-enable */
/**
* Updates the appearance state to the provided value or turns it off when not selected.
*
* @private
* @param {string} [value] The appearance state or index string to set as selected.
* @returns {void} No return value.
*/
PdfRadioButtonListItem.prototype._postProcess = function (value) {
var field = this._field;
if (field) {
if (this.value === value || this._index.toString() === value) {
this._dictionary.update('AS', _PdfName.get(value));
}
else {
this._dictionary.update('AS', _PdfName.get('Off'));
}
}
};
return PdfRadioButtonListItem;
}(PdfStateItem));
export { PdfRadioButtonListItem };
/**
* `PdfListBoxItem` class represents the list and combo box field item objects.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data);
* // Gets the first page of the document
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Access the PDF form
* let form: PdfForm = document.form;
* // Create a new list box field
* let field: PdfListBoxField = new PdfListBoxField(page, 'list1', {x: 100, y: 60, width: 100, height: 50});
* // Add list items to the field.
* field.addItem(new PdfListFieldItem('English', 'English'));
* field.addItem(new PdfListFieldItem('French', 'French'));
* field.addItem(new PdfListFieldItem('German', 'German'));
* // Sets the selected index
* field.selectedIndex = 2;
* // Sets the flag indicates whether the list box allows multiple selections.
* field.multiSelect = true;
* // Add the field into PDF form
* form.add(field);
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
var PdfListFieldItem = /** @class */ (function (_super) {
__extends(PdfListFieldItem, _super);
function PdfListFieldItem(text, value, field) {
var _this = _super.call(this) || this;
if (text && value) {
_this._initializeItem(text, value, field);
}
return _this;
}
/**
* Parse an existing item of the field.
*
* @private
* @param {_PdfDictionary} dictionary Widget dictionary.
* @param {_PdfCrossReference} crossReference PDF cross reference.
* @param {PdfField} field Field object.
* @returns {PdfListFieldItem} Widget.
*/
PdfListFieldItem._load = function (dictionary, crossReference, field) {
var widget = new PdfListFieldItem();
widget._isLoaded = true;
widget._dictionary = dictionary;
widget._crossReference = crossReference;
widget._field = field;
return widget;
};
Object.defineProperty(PdfListFieldItem.prototype, "text", {
/**
* Gets the text of the annotation.
*
* @returns {string} Text.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data);
* // Gets the first page of the document
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Access the PDF form
* let form: PdfForm = document.form;
* // Create a new radio button list field
* let field: PdfListBoxField = form.fieldAt(0) as PdfListBoxField;
* // Access first list field item
* let item: PdfListFieldItem = field.itemAt(0);
* // Gets the text of the list field item
* let text: string = item.text;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
if (typeof this._text === 'undefined' &&
typeof this._field !== 'undefined' &&
(this._field instanceof PdfListBoxField || this._field instanceof PdfComboBoxField)) {
this._text = this._field._options[this._index][1];
}
return this._text;
},
/**
* Sets the text of the annotation.
*
* @param {string} value Text.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data);
* // Gets the first page of the document
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Access the PDF form
* let form: PdfForm = document.form;
* // Create a new radio button list field
* let field: PdfListBoxField = form.fieldAt(0) as PdfListBoxField;
* // Access first list field item
* let item: PdfListFieldItem = field.itemAt(0);
* // Sets the text of the list field item
* item.text = '1-9';
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (typeof value === 'string' &&
typeof this._field !== 'undefined' &&
(this._field instanceof PdfListBoxField || this._field instanceof PdfComboBoxField)) {
if (value !== this._field._options[this._index][1]) {
this._field._options[this._index][1] = value;
this._text = value;
this._field._dictionary._updated = true;
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfListFieldItem.prototype, "selected", {
/**
* Gets the flag to indicate whether the field item is selected or not (Read only).
*
* @returns {boolean} Selected or not.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data);
* // Gets the first page of the document
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Access the PDF form
* let form: PdfForm = document.form;
* // Create a new radio button list field
* let field: PdfListBoxField = form.fieldAt(0) as PdfListBoxField;
* // Access first list field item
* let item: PdfListFieldItem = field.itemAt(0);
* // Gets the flag to indicate whether the field item is selected or not.
* let selected: boolean = item.selected;
* // Save the document
* document.save('output.pdf');
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
return this._index === this._field.selectedIndex;
},
enumerable: true,
configurable: true
});
/**
* Initializes the list item with display text and value and optionally registers it with the owning list box field.
*
* @private
* @param {string} text The display text.
* @param {string} value The stored/export value.
* @param {PdfField} [field] The owning list/combobox field (registers when provided).
* @returns {void} No return value.
*/
PdfListFieldItem.prototype._initializeItem = function (text, value, field) {
this._text = text;
this._value = value;
if (field && field instanceof PdfListBoxField) {
field._addToOptions(this, field);
}
};
return PdfListFieldItem;
}(PdfStateItem));
export { PdfListFieldItem };
/**
* `PdfAnnotationCaption` class represents the caption text and properties of annotations.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Create and set annotation caption values
* annotation.caption = new PdfAnnotationCaption({cap: true, type: PdfLineCaptionType.inline, offset: {x: 10, y: 10}});
* // Destroy the document
* document.destroy();
* ```
*/
var PdfAnnotationCaption = /** @class */ (function () {
function PdfAnnotationCaption(options) {
if (options && 'cap' in options && options.cap !== null && typeof options.cap === 'boolean') {
this._cap = options.cap;
}
else {
this._cap = false;
}
if (options && 'type' in options && options.type !== null && typeof options.type !== 'undefined') {
this._type = options.type;
}
else {
this._type = PdfLineCaptionType.inline;
}
if (options && 'offset' in options && options.offset !== null && typeof options.offset !== 'undefined') {
this._offset = options.offset;
}
else {
this._offset = { x: 0, y: 0 };
}
}
Object.defineProperty(PdfAnnotationCaption.prototype, "cap", {
/**
* Gets the boolean flag indicating whether annotation has caption or not.
*
* @returns {boolean} Caption.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Gets the boolean flag indicating whether annotation has caption or not.
* let cap: boolean = annotation.caption.cap;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
return this._cap;
},
/**
* Sets the boolean flag indicating whether annotation has caption or not.
*
* @param {boolean} value Caption.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Sets the boolean flag indicating whether annotation has caption or not.
* annotation.caption.cap = true;
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value !== this._cap) {
this._cap = value;
if (this._dictionary) {
this._dictionary.update('Cap', value);
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfAnnotationCaption.prototype, "type", {
/**
* Gets the caption type of the annotation.
*
* @returns {PdfLineCaptionType} Caption type.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Gets the caption type of the annotation.
* let type: PdfLineCaptionType = annotation.caption.type;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
return this._type;
},
/**
* Sets the caption type of the annotation.
*
* @param {PdfLineCaptionType} value Caption type.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Sets the caption type of the annotation.
* annotation.caption.type = PdfLineCaptionType.inline;
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value !== this._type) {
this._type = value;
if (this._dictionary) {
this._dictionary.update('CP', _PdfName.get(value === PdfLineCaptionType.top ? 'Top' : 'Inline'));
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfAnnotationCaption.prototype, "offset", {
/**
* Gets the offset position of the annotation.
*
* @returns {Point} Caption offset.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Gets the offset position of the annotation.
* let offset: Point = annotation.caption.offset;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
return this._offset;
},
/**
* Sets the offset position of the annotation.
*
* @param {Point} value Caption offset.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Sets the offset position of the annotation.
* annotation.caption.offset = {x: 10, y: 10};
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value && !this._offset) {
this._offset = value;
this._dictionary.update('CO', [value.x, value.y]);
}
else if (value && this._offset && (value.x !== this._offset.x || value.y !== this._offset.y)) {
this._offset = value;
if (this._dictionary) {
this._dictionary.update('CO', [value.x, value.y]);
}
}
},
enumerable: true,
configurable: true
});
return PdfAnnotationCaption;
}());
export { PdfAnnotationCaption };
/**
* `PdfAnnotationLineEndingStyle` class represents the line ending styles of annotations.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Initializes a new instance of the `PdfAnnotationLineEndingStyle` class.
* annotation.lineEndingStyle = new PdfAnnotationLineEndingStyle({begin: PdfLineEndingStyle.openArrow, end: PdfLineEndingStyle.closeArrow});
* // Destroy the document
* document.destroy();
* ```
*/
var PdfAnnotationLineEndingStyle = /** @class */ (function () {
function PdfAnnotationLineEndingStyle(options) {
if (options && 'begin' in options && options.begin !== null && typeof options.begin !== 'undefined') {
this._begin = options.begin;
}
else {
this._begin = PdfLineEndingStyle.none;
}
if (options && 'end' in options && options.end !== null && typeof options.end !== 'undefined') {
this._end = options.end;
}
else {
this._begin = PdfLineEndingStyle.none;
}
}
Object.defineProperty(PdfAnnotationLineEndingStyle.prototype, "begin", {
/**
* Gets the begin line ending style of the annotation.
*
* @returns {PdfLineEndingStyle} Begin line ending style.
* `PdfAnnotationLineEndingStyle` class represents the line ending styles of annotations.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Gets the begin line ending style of the annotation.
* let begin: PdfLineEndingStyle = annotation.lineEndingStyle.begin;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
return this._begin;
},
/**
* Sets the begin line ending style of the annotation.
*
* @param {PdfLineEndingStyle} value Begin line ending style.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Initializes a new instance of the `PdfAnnotationLineEndingStyle` class.
* let lineEndingStyle = new PdfAnnotationLineEndingStyle();
* // Sets the begin line ending style of the annotation.
* lineEndingStyle.begin = PdfLineEndingStyle.openArrow;
* // Sets the end line ending style of the annotation.
* lineEndingStyle.end = PdfLineEndingStyle.closeArrow;
* // Sets the line ending style to the annotation
* annotation.lineEndingStyle = lineEndingStyle;
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value !== this._begin) {
this._begin = value;
if (this._dictionary) {
this._dictionary.update('LE', [_PdfName.get(_reverseMapEndingStyle(value)), _PdfName.get(_reverseMapEndingStyle(this._end))]);
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfAnnotationLineEndingStyle.prototype, "end", {
/**
* Gets the begin line ending style of the annotation.
*
* @returns {PdfLineEndingStyle} End line ending style.
* `PdfAnnotationLineEndingStyle` class represents the line ending styles of annotations.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Gets the end line ending style of the annotation.
* let end: PdfLineEndingStyle = annotation.lineEndingStyle.end;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
return this._end;
},
/**
* Sets the begin line ending style of the annotation.
*
* @param {PdfLineEndingStyle} value End line ending style.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Initializes a new instance of the `PdfAnnotationLineEndingStyle` class.
* let lineEndingStyle = new PdfAnnotationLineEndingStyle();
* // Sets the begin line ending style of the annotation.
* lineEndingStyle.begin = PdfLineEndingStyle.openArrow;
* // Sets the end line ending style of the annotation.
* lineEndingStyle.end = PdfLineEndingStyle.closeArrow;
* // Sets the line ending style to the annotation
* annotation.lineEndingStyle = lineEndingStyle;
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value !== this._end) {
this._end = value;
if (this._dictionary) {
this._dictionary.update('LE', [_PdfName.get(_reverseMapEndingStyle(this._begin)), _PdfName.get(_reverseMapEndingStyle(value))]);
}
}
},
enumerable: true,
configurable: true
});
return PdfAnnotationLineEndingStyle;
}());
export { PdfAnnotationLineEndingStyle };
/**
* `PdfInteractiveBorder` class represents the border of the field.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the PDF form field
* let field: PdfField = document.form.fieldAt(0);
* // Gets the width of the field border.
* let width: number = field.border.width;
* // Destroy the document
* document.destroy();
* ```
*/
var PdfInteractiveBorder = /** @class */ (function () {
function PdfInteractiveBorder(options) {
if (options && 'width' in options && options.width !== null && typeof options.width !== 'undefined') {
this._width = options.width;
}
else {
this._width = 1;
}
if (options && 'style' in options && options.style !== null && typeof options.style !== 'undefined') {
this._style = options.style;
}
else {
this._style = PdfBorderStyle.solid;
}
if (options && 'dash' in options && options.dash !== null && Array.isArray(options.dash)) {
this._dash = options.dash;
}
}
Object.defineProperty(PdfInteractiveBorder.prototype, "width", {
/**
* Gets the width of the field border.
*
* @returns {number} border width.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the PDF form field
* let field: PdfField = document.form.fieldAt(0);
* // Gets the width of the annotation border.
* let width: number = field.border.width;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
return this._width;
},
/**
* Sets the width of the field border.
*
* @param {number} value width.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the PDF form field
* let field: PdfField = document.form.fieldAt(0);
* // Initializes a new instance of the `PdfInteractiveBorder` class.
* let border: PdfInteractiveBorder = new PdfInteractiveBorder();
* //Sets the width of the annotation border.
* border.width = 10;
* //Sets the style of the annotation border.
* border.style = PdfBorderStyle.dashed;
* //Sets the dash pattern of the annotation border.
* border.dash = [1, 2, 1];
* // Sets the border to the PDF form field
* field.border = border;
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value !== this._width) {
this._width = value;
if (this._dictionary) {
var bs = this._dictionary.has('BS') ? this._dictionary.get('BS') : new _PdfDictionary(this._crossReference);
bs.update('Type', _PdfName.get('Border'));
bs.update('W', this._width);
bs.update('S', _mapBorderStyle(this._style));
if (this._dash) {
bs.update('D', this._dash);
}
this._dictionary.update('BS', bs);
this._dictionary._updated = true;
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfInteractiveBorder.prototype, "style", {
/**
* Gets the border line style of the field border.
*
* @returns {PdfBorderStyle} Border style.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the PDF form field
* let field: PdfField = document.form.fieldAt(0);
* // Gets the border line style of the annotation border.
* let style: PdfBorderStyle = field.border.style;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
return this._style;
},
/**
* Sets the border line style of the field border.
*
* @param {PdfBorderStyle} value Border style.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the PDF form field
* let field: PdfField = document.form.fieldAt(0);
* // Initializes a new instance of the `PdfInteractiveBorder` class.
* let border: PdfInteractiveBorder = new PdfInteractiveBorder();
* //Sets the width of the annotation border.
* border.width = 10;
* //Sets the style of the annotation border.
* border.style = PdfBorderStyle.dashed;
* //Sets the dash pattern of the annotation border.
* border.dash = [1, 2, 1];
* // Sets the border to the PDF form field
* field.border = border;
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value !== this._style) {
this._style = value;
if ((Array.isArray(this._dash) && this._dash.length === 0) || !this._dash) {
if (value === PdfBorderStyle.dot) {
this._dash = [1, 1];
}
else if (value === PdfBorderStyle.dashed) {
this._dash = [3, 1];
}
}
if (this._dictionary) {
var bs = this._dictionary.has('BS') ? this._dictionary.get('BS') : new _PdfDictionary(this._crossReference);
bs.update('Type', _PdfName.get('Border'));
bs.update('W', this._width);
bs.update('S', _mapBorderStyle(this._style));
if (this._dash) {
bs.update('D', this._dash);
}
this._dictionary.update('BS', bs);
this._dictionary._updated = true;
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfInteractiveBorder.prototype, "dash", {
/**
* Gets the dash pattern of the field border.
*
* @returns {Array<number>} Dash pattern.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the PDF form field
* let field: PdfField = document.form.fieldAt(0);
* // Gets the dash pattern of the field border.
* let dash: Array<number>= field.border.dash;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
return this._dash;
},
/**
* Sets the dash pattern of the field border.
*
* @param {Array<number>} value Dash pattern.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the PDF form field
* let field: PdfField = document.form.fieldAt(0);
* // Initializes a new instance of the `PdfInteractiveBorder` class.
* let border: PdfInteractiveBorder = new PdfInteractiveBorder();
* //Sets the width of the annotation border.
* border.width = 10;
* //Sets the style of the annotation border.
* border.style = PdfBorderStyle.dashed;
* //Sets the dash pattern of the annotation border.
* border.dash = [1, 2, 1];
* // Sets the border to the PDF form field
* field.border = border;
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (typeof this._dash === 'undefined' || _areNotEqual(value, this._dash)) {
this._dash = value;
if (this._dictionary) {
var bs = this._dictionary.has('BS') ? this._dictionary.get('BS') : new _PdfDictionary(this._crossReference);
bs.update('Type', _PdfName.get('Border'));
bs.update('W', this._width);
bs.update('S', _mapBorderStyle(this._style));
bs.update('D', this._dash);
this._dictionary.update('BS', bs);
this._dictionary._updated = true;
}
}
},
enumerable: true,
configurable: true
});
return PdfInteractiveBorder;
}());
export { PdfInteractiveBorder };
/**
* `PdfAnnotationBorder` class represents the border properties of annotations.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Initializes a new instance of the `PdfAnnotationBorder` class.
* let border: PdfAnnotationBorder = new PdfAnnotationBorder();
* //Sets the width of the annotation border.
* border.width = 10;
* //Sets the style of the annotation border.
* border.style = PdfBorderStyle.dashed;
* //Sets the dash pattern of the annotation border.
* border.dash = [1, 2, 1];
* // Sets the border to the PDF form field
* annotation.border = border;
* // Destroy the document
* document.destroy();
* ```
*/
var PdfAnnotationBorder = /** @class */ (function (_super) {
__extends(PdfAnnotationBorder, _super);
function PdfAnnotationBorder(options) {
var _this = _super.call(this, options) || this;
if (options !== null && typeof options !== 'undefined') {
if (options && 'hRadius' in options && options.hRadius !== null && typeof options.hRadius !== 'undefined') {
_this._hRadius = options.hRadius;
}
else {
_this._hRadius = 0;
}
if (options && 'vRadius' in options && options.vRadius !== null && typeof options.vRadius !== 'undefined') {
_this._vRadius = options.vRadius;
}
else {
_this._vRadius = 0;
}
}
return _this;
}
Object.defineProperty(PdfAnnotationBorder.prototype, "width", {
/**
* Gets the width of the annotation border.
*
* @returns {number} border width.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Gets the width of the annotation border.
* let width: number = annotation.border.width;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
return this._width;
},
/**
* Sets the width of the annotation border.
*
* @param {number} value width.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Initializes a new instance of the ` PdfAnnotationBorder ` class.
* let border: PdfAnnotationBorder = new PdfAnnotationBorder ();
* //Sets the width of the annotation border.
* border.width = 10;
* //Sets the style of the annotation border.
* border.style = PdfBorderStyle.dashed;
* //Sets the dash pattern of the annotation border.
* border.dash = [1, 2, 1];
* // Sets the border to the PDF form field
* annotation.border = border;
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value !== this._width) {
this._width = value;
if (this._dictionary) {
this._dictionary.update('Border', [this._hRadius, this._vRadius, this._width]);
var bs = this._dictionary.has('BS') ? this._dictionary.get('BS') : new _PdfDictionary(this._crossReference);
bs.update('Type', _PdfName.get('Border'));
bs.update('W', this._width);
bs.update('S', _mapBorderStyle(this._style));
if (this._dash) {
bs.update('D', this._dash);
}
this._dictionary.update('BS', bs);
this._dictionary._updated = true;
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfAnnotationBorder.prototype, "hRadius", {
/**
* Gets the horizontal radius of the annotation border.
*
* @returns {number} horizontal radius.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Gets the horizontal radius of the annotation border.
* let hRadius: number = annotation.border.hRadius;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
return this._hRadius;
},
/**
* Sets the horizontal radius of the annotation border.
*
* @param {number} value horizontal radius.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Initializes a new instance of the `PdfAnnotationBorder` class.
* let border: PdfAnnotationBorder = new PdfAnnotationBorder();
* //Sets the width of the annotation border.
* border.width = 10;
* // Sets the horizontal radius of the annotation border.
* border.hRadius = 2;
* //Sets the style of the annotation border.
* border.style = PdfBorderStyle.dashed;
* //Sets the dash pattern of the annotation border.
* border.dash = [1, 2, 1];
* // Sets the border to the PDF form field
* annotation.border = border;
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value !== this._hRadius) {
this._hRadius = value;
if (this._dictionary) {
this._dictionary.update('Border', [this._hRadius, this._vRadius, this._width]);
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfAnnotationBorder.prototype, "vRadius", {
/**
* Gets the vertical radius of the annotation border.
*
* @returns {number} vertical radius.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Gets the vertical radius of the annotation border.
* let vRadius: number = annotation.border.vRadius;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
return this._vRadius;
},
/**
* Sets the vertical radius of the annotation border.
*
* @param {number} value vertical radius.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfLineAnnotation = page.annotations.at(0) as PdfLineAnnotation;
* // Initializes a new instance of the `PdfAnnotationBorder` class.
* let border: PdfAnnotationBorder = new PdfAnnotationBorder();
* //Sets the width of the annotation border.
* border.width = 10;
* // Sets the vertical radius of the annotation border.
* border.vRadius = 2;
* //Sets the style of the annotation border.
* border.style = PdfBorderStyle.dashed;
* //Sets the dash pattern of the annotation border.
* border.dash = [1, 2, 1];
* // Sets the border to the PDF form field
* annotation.border = border;
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value !== this._vRadius) {
this._vRadius = value;
if (this._dictionary) {
this._dictionary.update('Border', [this._hRadius, this._vRadius, this._width]);
}
}
},
enumerable: true,
configurable: true
});
return PdfAnnotationBorder;
}(PdfInteractiveBorder));
export { PdfAnnotationBorder };
/**
* `PdfBorderEffect` class represents the border effects of annotations.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfSquareAnnotation = page.annotations.at(0) as PdfSquareAnnotation;
* // Initializes a new instance of the `PdfBorderEffect` class.
* let borderEffect: PdfBorderEffect = new PdfBorderEffect();
* // Sets the intensity of the annotation border.
* borderEffect.intensity = 2;
* // Sets the effect style of the annotation border.
* borderEffect.style = PdfBorderEffectStyle.cloudy;
* // Sets border effect to the annotation.
* annotation.borderEffect = borderEffect;
* // Destroy the document
* document.destroy();
* ```
*/
var PdfBorderEffect = /** @class */ (function () {
function PdfBorderEffect(arg) {
/**
* Cloudiness or intensity value for the border effect.
*
* @private
*/
this._intensity = 0;
if (typeof arg !== 'undefined' && arg !== null) {
if (arg instanceof _PdfDictionary) {
if (arg.has('BE')) {
var borderEffect = this._dictionary.get('BE');
if (borderEffect) {
if (borderEffect.has('I')) {
this._intensity = borderEffect.get('I');
}
if (borderEffect.has('S')) {
this._style = this._getBorderEffect(borderEffect.get('S'));
}
}
}
}
else {
if ('intensity' in arg && arg.intensity !== null && typeof arg.intensity !== 'undefined') {
this._intensity = arg.intensity;
}
if ('style' in arg && arg.style !== null && typeof arg.style !== 'undefined') {
this._style = arg.style;
}
this._dictionary = new _PdfDictionary();
this._dictionary.set('I', this._intensity);
this._dictionary.set('S', this._styleToEffect(this._style));
}
}
else {
this._dictionary = new _PdfDictionary();
this._dictionary.set('I', this._intensity);
this._dictionary.set('S', this._styleToEffect(this._style));
}
}
Object.defineProperty(PdfBorderEffect.prototype, "intensity", {
/**
* Gets the intensity of the annotation border.
*
* @returns {number} intensity.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfSquareAnnotation = page.annotations.at(0) as PdfSquareAnnotation;
* // Gets the intensity of the annotation border.
* let intensity: number = annotation.borderEffect.intensity;
* // Gets the effect style of the annotation border.
* let style: PdfBorderEffectStyle = annotation.borderEffect.style;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
return this._intensity;
},
/**
* Sets the intensity of the annotation border.
*
* @param {number} value intensity.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfSquareAnnotation = page.annotations.at(0) as PdfSquareAnnotation;
* // Initializes a new instance of the `PdfBorderEffect` class.
* let borderEffect: PdfBorderEffect = new PdfBorderEffect();
* // Sets the intensity of the annotation border.
* borderEffect.intensity = 2;
* // Sets the effect style of the annotation border.
* borderEffect.style = PdfBorderEffectStyle.cloudy;
* // Sets border effect to the annotation.
* annotation.borderEffect = borderEffect;
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value !== this._intensity) {
this._intensity = value;
if (this._dictionary) {
var bs = this._dictionary.has('BE') ? this._dictionary.get('BE') : new _PdfDictionary(this._crossReference);
bs.update('I', this._intensity);
bs.update('S', this._styleToEffect(this._style));
this._dictionary.update('BE', bs);
this._dictionary._updated = true;
}
this._dictionary._updated = true;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(PdfBorderEffect.prototype, "style", {
/**
* Gets the effect style of the annotation border.
*
* @returns {PdfBorderEffectStyle} effect style.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfSquareAnnotation = page.annotations.at(0) as PdfSquareAnnotation;
* // Gets the intensity of the annotation border.
* let intensity: number = annotation.borderEffect.intensity;
* // Gets the effect style of the annotation border.
* let style: PdfBorderEffectStyle = annotation.borderEffect.style;
* // Destroy the document
* document.destroy();
* ```
*/
get: function () {
return this._style;
},
/**
* Sets the effect style of the annotation border.
*
* @param {PdfBorderEffectStyle} value effect style.
* ```typescript
* // Load an existing PDF document
* let document: PdfDocument = new PdfDocument(data, password);
* // Get the first page
* let page: PdfPage = document.getPage(0) as PdfPage;
* // Get the first annotation of the page
* let annotation: PdfSquareAnnotation = page.annotations.at(0) as PdfSquareAnnotation;
* // Initializes a new instance of the `PdfBorderEffect` class.
* let borderEffect: PdfBorderEffect = new PdfBorderEffect();
* // Sets the intensity of the annotation border.
* borderEffect.intensity = 2;
* // Sets the effect style of the annotation border.
* borderEffect.style = PdfBorderEffectStyle.cloudy;
* // Sets border effect to the annotation.
* annotation.borderEffect = borderEffect;
* // Destroy the document
* document.destroy();
* ```
*/
set: function (value) {
if (value !== this._style) {
this._style = value;
if (this._dictionary) {
var bs = this._dictionary.has('BE') ?
this._dictionary.get('BE') :
new _PdfDictionary(this._crossReference);
bs.update('I', this._intensity);
bs.update('S', this._styleToEffect(this._style));
this._dictionary.update('BE', bs);
this._dictionary._updated = true;
}
}
},
enumerable: true,
configurable: true
});
/**
* Converts the border effect name into the corresponding border effect style.
*
* @private
* @param {string} value The raw border effect string (e.g., '/C' or other values).
* @returns {PdfBorderEffectStyle} The mapped border effect style.
*/
PdfBorderEffect.prototype._getBorderEffect = function (value) {
if (value === '/C') {
return PdfBorderEffectStyle.cloudy;
}
else {
return PdfBorderEffectStyle.solid;
}
};
/**
* Converts the border effect style into its corresponding string representation.
*
* @private
* @param {PdfBorderEffectStyle} value The border effect style to convert.
* @returns {string} The string representation for use in the annotation dictionary.
*/
PdfBorderEffect.prototype._styleToEffect = function (value) {
if (value === PdfBorderEffectStyle.cloudy) {
return 'C';
}
else {
return 'S';
}
};
return PdfBorderEffect;
}());
export { PdfBorderEffect };
/**
* Holds rendering parameters used for painting annotation appearances.
*
* @private
*/
var _PaintParameter = /** @class */ (function () {
function _PaintParameter() {
this.borderWidth = 1;
}
return _PaintParameter;
}());
export { _PaintParameter };
/**
* Represents a cloud arc segment used for cloudy border rendering.
*
* @private
*/
var _CloudStyleArc = /** @class */ (function () {
function _CloudStyleArc() {
this.startAngle = 0;
this.endAngle = 0;
}
return _CloudStyleArc;
}());